From 37dffb225a495af38f86bbcb8bd47ef3d74c8556 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Sun, 5 Apr 2020 17:06:14 -0700 Subject: [PATCH] input: introduce Signature iface This commit introduces the Signature interface which will be used by our witness construction methods instead of passing in raw byte slices. This will be used later to inject various kinds of mock signatures, e.g. 73-byte signatures for simulating worst-case witness weight. --- input/script_utils.go | 15 +++++++++++---- input/script_utils_test.go | 18 ++++++++++++++---- lnwallet/channel.go | 15 ++++++++++++--- 3 files changed, 37 insertions(+), 11 deletions(-) diff --git a/input/script_utils.go b/input/script_utils.go index d8f80f31..56bfbe97 100644 --- a/input/script_utils.go +++ b/input/script_utils.go @@ -23,6 +23,13 @@ var ( SequenceLockTimeSeconds = uint32(1 << 22) ) +// Signature is an interface for objects that can populate signatures during +// witness construction. +type Signature interface { + // Serialize returns a DER-encoded ECDSA signature. + Serialize() []byte +} + // WitnessScriptHash generates a pay-to-witness-script-hash public key script // paying to a version 0 witness program paying to the passed redeem script. func WitnessScriptHash(witnessScript []byte) ([]byte, error) { @@ -343,7 +350,7 @@ func SenderHtlcSpendRedeem(signer Signer, signDesc *SignDescriptor, // HTLC to activate the time locked covenant clause of a soon to be expired // HTLC. This script simply spends the multi-sig output using the // pre-generated HTLC timeout transaction. -func SenderHtlcSpendTimeout(receiverSig []byte, +func SenderHtlcSpendTimeout(receiverSig Signature, receiverSigHash txscript.SigHashType, signer Signer, signDesc *SignDescriptor, htlcTimeoutTx *wire.MsgTx) ( wire.TxWitness, error) { @@ -359,7 +366,7 @@ func SenderHtlcSpendTimeout(receiverSig []byte, // original OP_CHECKMULTISIG. witnessStack := wire.TxWitness(make([][]byte, 5)) witnessStack[0] = nil - witnessStack[1] = append(receiverSig, byte(receiverSigHash)) + witnessStack[1] = append(receiverSig.Serialize(), byte(receiverSigHash)) witnessStack[2] = append(sweepSig, byte(signDesc.HashType)) witnessStack[3] = nil witnessStack[4] = signDesc.WitnessScript @@ -508,7 +515,7 @@ func ReceiverHTLCScript(cltvExpiry uint32, senderHtlcKey, // signed has a relative timelock delay enforced by its sequence number. This // delay give the sender of the HTLC enough time to revoke the output if this // is a breach commitment transaction. -func ReceiverHtlcSpendRedeem(senderSig []byte, +func ReceiverHtlcSpendRedeem(senderSig Signature, senderSigHash txscript.SigHashType, paymentPreimage []byte, signer Signer, signDesc *SignDescriptor, htlcSuccessTx *wire.MsgTx) ( wire.TxWitness, error) { @@ -527,7 +534,7 @@ func ReceiverHtlcSpendRedeem(senderSig []byte, // order to consume the extra pop within OP_CHECKMULTISIG. witnessStack := wire.TxWitness(make([][]byte, 5)) witnessStack[0] = nil - witnessStack[1] = append(senderSig, byte(senderSigHash)) + witnessStack[1] = append(senderSig.Serialize(), byte(senderSigHash)) witnessStack[2] = append(sweepSig, byte(signDesc.HashType)) witnessStack[3] = paymentPreimage witnessStack[4] = signDesc.WitnessScript diff --git a/input/script_utils_test.go b/input/script_utils_test.go index be1e2d0f..a76183dc 100644 --- a/input/script_utils_test.go +++ b/input/script_utils_test.go @@ -226,7 +226,7 @@ func TestHTLCSenderSpendValidation(t *testing.T) { htlcOutput *wire.TxOut sweepTxSigHashes *txscript.TxSigHashes senderCommitTx, sweepTx *wire.MsgTx - bobRecvrSig []byte + bobRecvrSig *btcec.Signature bobSigHash txscript.SigHashType ) @@ -303,10 +303,15 @@ func TestHTLCSenderSpendValidation(t *testing.T) { SigHashes: sweepTxSigHashes, InputIndex: 0, } - bobRecvrSig, err = bobSigner.SignOutputRaw(sweepTx, &bobSignDesc) + bobSigBytes, err := bobSigner.SignOutputRaw(sweepTx, &bobSignDesc) if err != nil { t.Fatalf("unable to generate alice signature: %v", err) } + + bobRecvrSig, err = btcec.ParseDERSignature(bobSigBytes, btcec.S256()) + if err != nil { + t.Fatalf("unable to parse signature: %v", err) + } } testCases := []struct { @@ -622,7 +627,7 @@ func TestHTLCReceiverSpendValidation(t *testing.T) { htlcOutput *wire.TxOut receiverCommitTx, sweepTx *wire.MsgTx sweepTxSigHashes *txscript.TxSigHashes - aliceSenderSig []byte + aliceSenderSig *btcec.Signature aliceSigHash txscript.SigHashType ) @@ -695,10 +700,15 @@ func TestHTLCReceiverSpendValidation(t *testing.T) { SigHashes: sweepTxSigHashes, InputIndex: 0, } - aliceSenderSig, err = aliceSigner.SignOutputRaw(sweepTx, &aliceSignDesc) + aliceSigBytes, err := aliceSigner.SignOutputRaw(sweepTx, &aliceSignDesc) if err != nil { t.Fatalf("unable to generate alice signature: %v", err) } + + aliceSenderSig, err = btcec.ParseDERSignature(aliceSigBytes, btcec.S256()) + if err != nil { + t.Fatalf("unable to parse signature: %v", err) + } } // TODO(roasbeef): modify valid to check precise script errors? diff --git a/lnwallet/channel.go b/lnwallet/channel.go index c9ca227d..11eb1159 100644 --- a/lnwallet/channel.go +++ b/lnwallet/channel.go @@ -5459,11 +5459,16 @@ func newOutgoingHtlcResolution(signer input.Signer, InputIndex: 0, } + htlcSig, err := btcec.ParseDERSignature(htlc.Signature, btcec.S256()) + if err != nil { + return nil, err + } + // With the sign desc created, we can now construct the full witness // for the timeout transaction, and populate it as well. sigHashType := HtlcSigHashType(chanType) timeoutWitness, err := input.SenderHtlcSpendTimeout( - htlc.Signature, sigHashType, signer, &timeoutSignDesc, timeoutTx, + htlcSig, sigHashType, signer, &timeoutSignDesc, timeoutTx, ) if err != nil { return nil, err @@ -5585,14 +5590,18 @@ func newIncomingHtlcResolution(signer input.Signer, InputIndex: 0, } + htlcSig, err := btcec.ParseDERSignature(htlc.Signature, btcec.S256()) + if err != nil { + return nil, err + } + // Next, we'll construct the full witness needed to satisfy the input of // the success transaction. Don't specify the preimage yet. The preimage // will be supplied by the contract resolver, either directly or when it // becomes known. sigHashType := HtlcSigHashType(chanType) successWitness, err := input.ReceiverHtlcSpendRedeem( - htlc.Signature, sigHashType, nil, signer, &successSignDesc, - successTx, + htlcSig, sigHashType, nil, signer, &successSignDesc, successTx, ) if err != nil { return nil, err