lnwallet: update testSignOutputUsingTweaks to exercise new key derivation
This commit is contained in:
parent
9edc335049
commit
eca8dd1076
@ -1130,62 +1130,85 @@ func testTransactionSubscriptions(miner *rpctest.Harness, w *lnwallet.LightningW
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func testSignOutputPrivateTweak(r *rpctest.Harness, w *lnwallet.LightningWallet, t *testing.T) {
|
func testSignOutputUsingTweaks(r *rpctest.Harness,
|
||||||
t.Logf("Running private tweak test")
|
alice, _ *lnwallet.LightningWallet, t *testing.T) {
|
||||||
|
|
||||||
// We'd like to test the ability of the wallet's Signer implementation
|
// We'd like to test the ability of the wallet's Signer implementation
|
||||||
// to be able to sign with a private key derived from tweaking the
|
// to be able to sign with a private key derived from tweaking the
|
||||||
// specific public key. This scenario exercises the case when the
|
// specific public key. This scenario exercises the case when the
|
||||||
// wallet needs to sign for a sweep of a revoked output.
|
// wallet needs to sign for a sweep of a revoked output, or just claim
|
||||||
|
// any output that pays to a tweaked key.
|
||||||
|
|
||||||
// First, generate a new public key under th control of the wallet,
|
// First, generate a new public key under the control of the wallet,
|
||||||
// then generate a revocation key using it.
|
// then generate a revocation key using it.
|
||||||
pubkey, err := w.NewRawKey()
|
pubKey, err := alice.NewRawKey()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to obtain public key: %v", err)
|
t.Fatalf("unable to obtain public key: %v", err)
|
||||||
}
|
}
|
||||||
revocation := bytes.Repeat([]byte{2}, 32)
|
|
||||||
revocationKey := lnwallet.DeriveRevocationPubkey(pubkey, revocation)
|
|
||||||
|
|
||||||
// With the revocation key generated, create a pkScript that pays to
|
// As we'd like to test both single tweak, and double tweak spends,
|
||||||
// the revocation key using a simple p2wkh script.
|
// we'll generate a commitment pre-image, then derive a revocation key
|
||||||
pubkeyHash := btcutil.Hash160(revocationKey.SerializeCompressed())
|
// and single tweak from that.
|
||||||
revokeAddr, err := btcutil.NewAddressWitnessPubKeyHash(pubkeyHash,
|
commitPreimage := bytes.Repeat([]byte{2}, 32)
|
||||||
|
commitSecret, commitPoint := btcec.PrivKeyFromBytes(btcec.S256(),
|
||||||
|
commitPreimage)
|
||||||
|
|
||||||
|
revocationKey := lnwallet.DeriveRevocationPubkey(pubKey, commitPoint)
|
||||||
|
commitTweak := lnwallet.SingleTweakBytes(commitPoint, pubKey)
|
||||||
|
|
||||||
|
tweakedPub := lnwallet.TweakPubKey(pubKey, commitPoint)
|
||||||
|
|
||||||
|
// As we'd like to test both single and double tweaks, we'll repeat
|
||||||
|
// the same set up twice. The first will use a regular single tweak,
|
||||||
|
// and the second will use a double tweak.
|
||||||
|
baseKey := pubKey
|
||||||
|
for i := 0; i < 2; i++ {
|
||||||
|
var tweakedKey *btcec.PublicKey
|
||||||
|
if i == 0 {
|
||||||
|
tweakedKey = tweakedPub
|
||||||
|
} else {
|
||||||
|
tweakedKey = revocationKey
|
||||||
|
}
|
||||||
|
|
||||||
|
// Using the given key for the current iteration, we'll
|
||||||
|
// generate a regular p2wkh from that.
|
||||||
|
pubkeyHash := btcutil.Hash160(tweakedKey.SerializeCompressed())
|
||||||
|
keyAddr, err := btcutil.NewAddressWitnessPubKeyHash(pubkeyHash,
|
||||||
&chaincfg.SimNetParams)
|
&chaincfg.SimNetParams)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to create addr: %v", err)
|
t.Fatalf("unable to create addr: %v", err)
|
||||||
}
|
}
|
||||||
revokeScript, err := txscript.PayToAddrScript(revokeAddr)
|
keyScript, err := txscript.PayToAddrScript(keyAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to generate script: %v", err)
|
t.Fatalf("unable to generate script: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// With the script fully assemebld, instruct the wallet to fund the
|
// With the script fully assembled, instruct the wallet to fund
|
||||||
// output with a newly creaed transaction.
|
// the output with a newly created transaction.
|
||||||
revokeOutput := &wire.TxOut{
|
newOutput := &wire.TxOut{
|
||||||
Value: btcutil.SatoshiPerBitcoin,
|
Value: btcutil.SatoshiPerBitcoin,
|
||||||
PkScript: revokeScript,
|
PkScript: keyScript,
|
||||||
}
|
}
|
||||||
txid, err := w.SendOutputs([]*wire.TxOut{revokeOutput})
|
txid, err := alice.SendOutputs([]*wire.TxOut{newOutput})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to create output: %v", err)
|
t.Fatalf("unable to create output: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Query for the transaction generated above so we can located the
|
// Query for the transaction generated above so we can located
|
||||||
// index of our output.
|
// the index of our output.
|
||||||
tx, err := r.Node.GetRawTransaction(txid)
|
tx, err := r.Node.GetRawTransaction(txid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to query for tx: %v", err)
|
t.Fatalf("unable to query for tx: %v", err)
|
||||||
}
|
}
|
||||||
var outputIndex uint32
|
var outputIndex uint32
|
||||||
if bytes.Equal(tx.MsgTx().TxOut[0].PkScript, revokeScript) {
|
if bytes.Equal(tx.MsgTx().TxOut[0].PkScript, keyScript) {
|
||||||
outputIndex = 0
|
outputIndex = 0
|
||||||
} else {
|
} else {
|
||||||
outputIndex = 1
|
outputIndex = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
/// WIth the index located, we can create a transaction spending the
|
// With the index located, we can create a transaction spending
|
||||||
//referenced output.
|
// the referenced output.
|
||||||
sweepTx := wire.NewMsgTx(2)
|
sweepTx := wire.NewMsgTx(2)
|
||||||
sweepTx.AddTxIn(&wire.TxIn{
|
sweepTx.AddTxIn(&wire.TxIn{
|
||||||
PreviousOutPoint: wire.OutPoint{
|
PreviousOutPoint: wire.OutPoint{
|
||||||
@ -1193,43 +1216,57 @@ func testSignOutputPrivateTweak(r *rpctest.Harness, w *lnwallet.LightningWallet,
|
|||||||
Index: outputIndex,
|
Index: outputIndex,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
sweepTx.AddTxOut(&wire.TxOut{
|
||||||
|
Value: 1000,
|
||||||
|
PkScript: keyScript,
|
||||||
|
})
|
||||||
|
|
||||||
// Now we can populate the sign descriptor which we'll use to generate
|
// Now we can populate the sign descriptor which we'll use to
|
||||||
// the signature. Within the descriptor we set the private tweak value
|
// generate the signature. Within the descriptor we set the
|
||||||
// as the key in the script is derived based on this tweak value and
|
// private tweak value as the key in the script is derived
|
||||||
// the key we originally generated above.
|
// based on this tweak value and the key we originally
|
||||||
|
// generated above.
|
||||||
signDesc := &lnwallet.SignDescriptor{
|
signDesc := &lnwallet.SignDescriptor{
|
||||||
PubKey: pubkey,
|
PubKey: baseKey,
|
||||||
PrivateTweak: revocation,
|
WitnessScript: keyScript,
|
||||||
WitnessScript: revokeScript,
|
Output: newOutput,
|
||||||
Output: revokeOutput,
|
|
||||||
HashType: txscript.SigHashAll,
|
HashType: txscript.SigHashAll,
|
||||||
SigHashes: txscript.NewTxSigHashes(sweepTx),
|
SigHashes: txscript.NewTxSigHashes(sweepTx),
|
||||||
InputIndex: 0,
|
InputIndex: 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
// With the descriptor created, we use it to generate a signature, then
|
// If this is the first, loop, we'll use the generated single
|
||||||
// manually create a valid witness stack we'll use for signing.
|
// tweak, otherwise, we'll use the double tweak.
|
||||||
spendSig, err := w.Signer.SignOutputRaw(sweepTx, signDesc)
|
if i == 0 {
|
||||||
|
signDesc.SingleTweak = commitTweak
|
||||||
|
} else {
|
||||||
|
signDesc.DoubleTweak = commitSecret
|
||||||
|
}
|
||||||
|
|
||||||
|
// With the descriptor created, we use it to generate a
|
||||||
|
// signature, then manually create a valid witness stack we'll
|
||||||
|
// use for signing.
|
||||||
|
spendSig, err := alice.Cfg.Signer.SignOutputRaw(sweepTx, signDesc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to generate signature: %v", err)
|
t.Fatalf("unable to generate signature: %v", err)
|
||||||
}
|
}
|
||||||
witness := make([][]byte, 2)
|
witness := make([][]byte, 2)
|
||||||
witness[0] = append(spendSig, byte(txscript.SigHashAll))
|
witness[0] = append(spendSig, byte(txscript.SigHashAll))
|
||||||
witness[1] = revocationKey.SerializeCompressed()
|
witness[1] = tweakedKey.SerializeCompressed()
|
||||||
sweepTx.TxIn[0].Witness = witness
|
sweepTx.TxIn[0].Witness = witness
|
||||||
|
|
||||||
// Finally, attempt to validate the completed transaction. This should
|
// Finally, attempt to validate the completed transaction. This
|
||||||
// succeed if the wallet was able to properly generate the proper
|
// should succeed if the wallet was able to properly generate
|
||||||
// private key.
|
// the proper private key.
|
||||||
vm, err := txscript.NewEngine(revokeScript,
|
vm, err := txscript.NewEngine(keyScript,
|
||||||
sweepTx, 0, txscript.StandardVerifyFlags, nil,
|
sweepTx, 0, txscript.StandardVerifyFlags, nil,
|
||||||
nil, int64(btcutil.SatoshiPerBitcoin))
|
nil, int64(btcutil.SatoshiPerBitcoin))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to create engine: %v", err)
|
t.Fatalf("unable to create engine: %v", err)
|
||||||
}
|
}
|
||||||
if err := vm.Execute(); err != nil {
|
if err := vm.Execute(); err != nil {
|
||||||
t.Fatalf("revocation spend invalid: %v", err)
|
t.Fatalf("spend #%v is invalid: %v", i, err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user