From c81e0a3ebb570e9f6d9f2e5f358da4b110807eed Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Fri, 18 Nov 2016 15:23:26 -0800 Subject: [PATCH] lnwallet: convert CommitSpendRevoke+CommitSpendNoDelay to use Signer This commit converts the rearming two commitment spend functions to use the lnwallet.Signer interface directly rather than manually manage private keys during the signing process. This commit is in preparation for implementation of fully automated revoked uncooperative closure detection and retribution. --- lnwallet/channel_test.go | 12 +++++++++++- lnwallet/script_utils.go | 28 +++++++++++----------------- lnwallet/script_utils_test.go | 31 ++++++++++++++++++++++++++----- 3 files changed, 48 insertions(+), 23 deletions(-) diff --git a/lnwallet/channel_test.go b/lnwallet/channel_test.go index 5bd96b79..87d90e3c 100644 --- a/lnwallet/channel_test.go +++ b/lnwallet/channel_test.go @@ -70,7 +70,17 @@ func (m *mockSigner) SignOutputRaw(tx *wire.MsgTx, signDesc *SignDescriptor) ([] return sig[:len(sig)-1], nil } func (m *mockSigner) ComputeInputScript(tx *wire.MsgTx, signDesc *SignDescriptor) (*InputScript, error) { - return nil, nil + + witnessScript, err := txscript.WitnessScript(tx, signDesc.SigHashes, + signDesc.InputIndex, signDesc.Output.Value, signDesc.Output.PkScript, + txscript.SigHashAll, m.key, true) + if err != nil { + return nil, err + } + + return &InputScript{ + Witness: witnessScript, + }, nil } type mockNotfier struct { diff --git a/lnwallet/script_utils.go b/lnwallet/script_utils.go index c3cf907e..0e578270 100644 --- a/lnwallet/script_utils.go +++ b/lnwallet/script_utils.go @@ -639,16 +639,13 @@ func CommitSpendTimeout(signer Signer, signDesc *SignDescriptor, return witnessStack, nil } -// commitSpendRevoke constructs a valid witness allowing a node to sweep the +// CommitSpendRevoke constructs a valid witness allowing a node to sweep the // settled output of a malicious counter-party who broadcasts a revoked // commitment transaction. -func commitSpendRevoke(commitScript []byte, outputAmt btcutil.Amount, - revocationPriv *btcec.PrivateKey, sweepTx *wire.MsgTx) (wire.TxWitness, error) { +func CommitSpendRevoke(signer Signer, signDesc *SignDescriptor, + sweepTx *wire.MsgTx) (wire.TxWitness, error) { - hashCache := txscript.NewTxSigHashes(sweepTx) - sweepSig, err := txscript.RawTxInWitnessSignature( - sweepTx, hashCache, 0, int64(outputAmt), commitScript, - txscript.SigHashAll, revocationPriv) + sweepSig, err := signer.SignOutputRaw(sweepTx, signDesc) if err != nil { return nil, err } @@ -656,29 +653,26 @@ func commitSpendRevoke(commitScript []byte, outputAmt btcutil.Amount, // Place a 1 as the first item in the evaluated witness stack to // force script execution to the revocation clause. witnessStack := wire.TxWitness(make([][]byte, 3)) - witnessStack[0] = sweepSig + witnessStack[0] = append(sweepSig, byte(txscript.SigHashAll)) witnessStack[1] = []byte{1} - witnessStack[2] = commitScript + witnessStack[2] = signDesc.WitnessScript return witnessStack, nil } -// commitSpendNoDelay constructs a valid witness allowing a node to spend their +// CommitSpendNoDelay constructs a valid witness allowing a node to spend their // settled no-delay output on the counter-party's commitment transaction. -func commitSpendNoDelay(commitScript []byte, outputAmt btcutil.Amount, - commitPriv *btcec.PrivateKey, sweepTx *wire.MsgTx) (wire.TxWitness, error) { +func CommitSpendNoDelay(signer Signer, signDesc *SignDescriptor, + sweepTx *wire.MsgTx) (wire.TxWitness, error) { // This is just a regular p2wkh spend which looks something like: // * witness: - hashCache := txscript.NewTxSigHashes(sweepTx) - witness, err := txscript.WitnessScript(sweepTx, hashCache, 0, - int64(outputAmt), commitScript, txscript.SigHashAll, - commitPriv, true) + inputScript, err := signer.ComputeInputScript(sweepTx, signDesc) if err != nil { return nil, err } - return wire.TxWitness(witness), nil + return wire.TxWitness(inputScript.Witness), nil } // DeriveRevocationPubkey derives the revocation public key given the diff --git a/lnwallet/script_utils_test.go b/lnwallet/script_utils_test.go index 8aaa7539..eda916c8 100644 --- a/lnwallet/script_utils_test.go +++ b/lnwallet/script_utils_test.go @@ -107,11 +107,21 @@ func TestCommitmentSpendValidation(t *testing.T) { } // Next, we'll test bob spending with the derived revocation key to - // simulate the scenario when alice broadcasts this commitmen + // simulate the scenario when alice broadcasts this commitment // transaction after it's been revoked. revokePrivKey := DeriveRevocationPrivKey(bobKeyPriv, revocationPreimage) - bobWitnessSpend, err := commitSpendRevoke(delayScript, channelBalance, - revokePrivKey, sweepTx) + bobRevokeSigner := &mockSigner{revokePrivKey} + signDesc = &SignDescriptor{ + WitnessScript: delayScript, + SigHashes: txscript.NewTxSigHashes(sweepTx), + Output: &wire.TxOut{ + Value: int64(channelBalance), + }, + HashType: txscript.SigHashAll, + InputIndex: 0, + } + bobWitnessSpend, err := CommitSpendRevoke(bobRevokeSigner, signDesc, + sweepTx) if err != nil { t.Fatalf("unable to generate revocation witness: %v", err) } @@ -128,12 +138,23 @@ func TestCommitmentSpendValidation(t *testing.T) { // Finally, we test bob sweeping his output as normal in the case that // alice broadcasts this commitment transaction. + bobSigner := &mockSigner{bobKeyPriv} bobScriptp2wkh, err := commitScriptUnencumbered(bobKeyPub) if err != nil { t.Fatalf("unable to create bob p2wkh script: %v", err) } - bobRegularSpend, err := commitSpendNoDelay(bobScriptp2wkh, - channelBalance, bobKeyPriv, sweepTx) + signDesc = &SignDescriptor{ + WitnessScript: bobScriptp2wkh, + SigHashes: txscript.NewTxSigHashes(sweepTx), + Output: &wire.TxOut{ + Value: int64(channelBalance), + PkScript: bobScriptp2wkh, + }, + HashType: txscript.SigHashAll, + InputIndex: 0, + } + bobRegularSpend, err := CommitSpendNoDelay(bobSigner, signDesc, + sweepTx) if err != nil { t.Fatalf("unable to create bob regular spend: %v", err) }