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