input: pass input.Signature to multisig spend
Modifies SpendMultiSig to accept input.Signature, so that we can ultimately assert the size of multisig witnesses.
This commit is contained in:
parent
0f94b8dc62
commit
f2b6e2af04
@ -4,7 +4,6 @@ import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
|
||||
"github.com/btcsuite/btcd/txscript"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/btcsuite/btcutil"
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
@ -510,11 +509,15 @@ func (c *channelCloser) ProcessCloseMsg(msg lnwire.Message) ([]lnwire.Message, b
|
||||
// transaction! We'll craft the final closing transaction so
|
||||
// we can broadcast it to the network.
|
||||
matchingSig := c.priorFeeOffers[remoteProposedFee].Signature
|
||||
localSigBytes := matchingSig.ToSignatureBytes()
|
||||
localSig := append(localSigBytes, byte(txscript.SigHashAll))
|
||||
localSig, err := matchingSig.ToSignature()
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
remoteSigBytes := closeSignedMsg.Signature.ToSignatureBytes()
|
||||
remoteSig := append(remoteSigBytes, byte(txscript.SigHashAll))
|
||||
remoteSig, err := closeSignedMsg.Signature.ToSignature()
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
closeTx, _, err := c.cfg.channel.CompleteCooperativeClose(
|
||||
localSig, remoteSig, c.localDeliveryScript,
|
||||
|
@ -96,7 +96,9 @@ func GenFundingPkScript(aPub, bPub []byte, amt int64) ([]byte, *wire.TxOut, erro
|
||||
|
||||
// SpendMultiSig generates the witness stack required to redeem the 2-of-2 p2wsh
|
||||
// multi-sig output.
|
||||
func SpendMultiSig(witnessScript, pubA, sigA, pubB, sigB []byte) [][]byte {
|
||||
func SpendMultiSig(witnessScript, pubA []byte, sigA Signature,
|
||||
pubB []byte, sigB Signature) [][]byte {
|
||||
|
||||
witness := make([][]byte, 4)
|
||||
|
||||
// When spending a p2wsh multi-sig script, rather than an OP_0, we add
|
||||
@ -108,11 +110,11 @@ func SpendMultiSig(witnessScript, pubA, sigA, pubB, sigB []byte) [][]byte {
|
||||
// ensure the signatures appear on the Script Virtual Machine stack in
|
||||
// the correct order.
|
||||
if bytes.Compare(pubA, pubB) == 1 {
|
||||
witness[1] = sigB
|
||||
witness[2] = sigA
|
||||
witness[1] = append(sigB.Serialize(), byte(txscript.SigHashAll))
|
||||
witness[2] = append(sigA.Serialize(), byte(txscript.SigHashAll))
|
||||
} else {
|
||||
witness[1] = sigA
|
||||
witness[2] = sigB
|
||||
witness[1] = append(sigA.Serialize(), byte(txscript.SigHashAll))
|
||||
witness[2] = append(sigB.Serialize(), byte(txscript.SigHashAll))
|
||||
}
|
||||
|
||||
// Finally, add the preimage as the last witness element.
|
||||
|
@ -5065,17 +5065,21 @@ func (lc *LightningChannel) getSignedCommitTx() (*wire.MsgTx, error) {
|
||||
// for the transaction.
|
||||
localCommit := lc.channelState.LocalCommitment
|
||||
commitTx := localCommit.CommitTx.Copy()
|
||||
theirSig := append(localCommit.CommitSig, byte(txscript.SigHashAll))
|
||||
|
||||
// With this, we then generate the full witness so the caller can
|
||||
// broadcast a fully signed transaction.
|
||||
lc.signDesc.SigHashes = txscript.NewTxSigHashes(commitTx)
|
||||
ourSigRaw, err := lc.Signer.SignOutputRaw(commitTx, lc.signDesc)
|
||||
theirSig, err := btcec.ParseDERSignature(
|
||||
localCommit.CommitSig, btcec.S256(),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ourSig := append(ourSigRaw.Serialize(), byte(txscript.SigHashAll))
|
||||
// With this, we then generate the full witness so the caller can
|
||||
// broadcast a fully signed transaction.
|
||||
lc.signDesc.SigHashes = txscript.NewTxSigHashes(commitTx)
|
||||
ourSig, err := lc.Signer.SignOutputRaw(commitTx, lc.signDesc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// With the final signature generated, create the witness stack
|
||||
// required to spend from the multi-sig output.
|
||||
@ -6017,7 +6021,8 @@ func (lc *LightningChannel) CreateCloseProposal(proposedFee btcutil.Amount,
|
||||
//
|
||||
// NOTE: The passed local and remote sigs are expected to be fully complete
|
||||
// signatures including the proper sighash byte.
|
||||
func (lc *LightningChannel) CompleteCooperativeClose(localSig, remoteSig []byte,
|
||||
func (lc *LightningChannel) CompleteCooperativeClose(
|
||||
localSig, remoteSig input.Signature,
|
||||
localDeliveryScript, remoteDeliveryScript []byte,
|
||||
proposedFee btcutil.Amount) (*wire.MsgTx, btcutil.Amount, error) {
|
||||
|
||||
@ -6070,8 +6075,10 @@ func (lc *LightningChannel) CompleteCooperativeClose(localSig, remoteSig []byte,
|
||||
SerializeCompressed()
|
||||
theirKey := lc.channelState.RemoteChanCfg.MultiSigKey.PubKey.
|
||||
SerializeCompressed()
|
||||
witness := input.SpendMultiSig(lc.signDesc.WitnessScript, ourKey,
|
||||
localSig, theirKey, remoteSig)
|
||||
witness := input.SpendMultiSig(
|
||||
lc.signDesc.WitnessScript, ourKey, localSig, theirKey,
|
||||
remoteSig,
|
||||
)
|
||||
closeTx.TxIn[0].Witness = witness
|
||||
|
||||
// Validate the finalized transaction to ensure the output script is
|
||||
|
@ -616,7 +616,6 @@ func TestCooperativeChannelClosure(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("unable to create alice coop close proposal: %v", err)
|
||||
}
|
||||
aliceCloseSig := append(aliceSig.Serialize(), byte(txscript.SigHashAll))
|
||||
|
||||
bobFee := bobChannel.CalcFee(bobFeeRate)
|
||||
bobSig, _, _, err := bobChannel.CreateCloseProposal(
|
||||
@ -625,14 +624,13 @@ func TestCooperativeChannelClosure(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("unable to create bob coop close proposal: %v", err)
|
||||
}
|
||||
bobCloseSig := append(bobSig.Serialize(), byte(txscript.SigHashAll))
|
||||
|
||||
// With the proposals created, both sides should be able to properly
|
||||
// process the other party's signature. This indicates that the
|
||||
// transaction is well formed, and the signatures verify.
|
||||
aliceCloseTx, _, err := bobChannel.CompleteCooperativeClose(
|
||||
bobCloseSig, aliceCloseSig, bobDeliveryScript,
|
||||
aliceDeliveryScript, bobFee,
|
||||
bobSig, aliceSig, bobDeliveryScript, aliceDeliveryScript,
|
||||
bobFee,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to complete alice cooperative close: %v", err)
|
||||
@ -640,8 +638,8 @@ func TestCooperativeChannelClosure(t *testing.T) {
|
||||
bobCloseSha := aliceCloseTx.TxHash()
|
||||
|
||||
bobCloseTx, _, err := aliceChannel.CompleteCooperativeClose(
|
||||
aliceCloseSig, bobCloseSig, aliceDeliveryScript,
|
||||
bobDeliveryScript, aliceFee,
|
||||
aliceSig, bobSig, aliceDeliveryScript, bobDeliveryScript,
|
||||
aliceFee,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to complete bob cooperative close: %v", err)
|
||||
@ -2054,24 +2052,25 @@ func TestCooperativeCloseDustAdherence(t *testing.T) {
|
||||
// balances. As a result, performing a cooperative closure now result
|
||||
// in both sides having an output within the closure transaction.
|
||||
aliceFee := btcutil.Amount(aliceChannel.CalcFee(aliceFeeRate)) + 1000
|
||||
aliceSig, _, _, err := aliceChannel.CreateCloseProposal(aliceFee,
|
||||
aliceDeliveryScript, bobDeliveryScript)
|
||||
aliceSig, _, _, err := aliceChannel.CreateCloseProposal(
|
||||
aliceFee, aliceDeliveryScript, bobDeliveryScript,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to close channel: %v", err)
|
||||
}
|
||||
aliceCloseSig := append(aliceSig.Serialize(), byte(txscript.SigHashAll))
|
||||
|
||||
bobFee := btcutil.Amount(bobChannel.CalcFee(bobFeeRate)) + 1000
|
||||
bobSig, _, _, err := bobChannel.CreateCloseProposal(bobFee,
|
||||
bobDeliveryScript, aliceDeliveryScript)
|
||||
bobSig, _, _, err := bobChannel.CreateCloseProposal(
|
||||
bobFee, bobDeliveryScript, aliceDeliveryScript,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to close channel: %v", err)
|
||||
}
|
||||
bobCloseSig := append(bobSig.Serialize(), byte(txscript.SigHashAll))
|
||||
|
||||
closeTx, _, err := bobChannel.CompleteCooperativeClose(
|
||||
bobCloseSig, aliceCloseSig,
|
||||
bobDeliveryScript, aliceDeliveryScript, bobFee)
|
||||
bobSig, aliceSig, bobDeliveryScript, aliceDeliveryScript,
|
||||
bobFee,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to accept channel close: %v", err)
|
||||
}
|
||||
@ -2093,23 +2092,24 @@ func TestCooperativeCloseDustAdherence(t *testing.T) {
|
||||
|
||||
// Attempt another cooperative channel closure. It should succeed
|
||||
// without any issues.
|
||||
aliceSig, _, _, err = aliceChannel.CreateCloseProposal(aliceFee,
|
||||
aliceDeliveryScript, bobDeliveryScript)
|
||||
aliceSig, _, _, err = aliceChannel.CreateCloseProposal(
|
||||
aliceFee, aliceDeliveryScript, bobDeliveryScript,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to close channel: %v", err)
|
||||
}
|
||||
aliceCloseSig = append(aliceSig.Serialize(), byte(txscript.SigHashAll))
|
||||
|
||||
bobSig, _, _, err = bobChannel.CreateCloseProposal(bobFee,
|
||||
bobDeliveryScript, aliceDeliveryScript)
|
||||
bobSig, _, _, err = bobChannel.CreateCloseProposal(
|
||||
bobFee, bobDeliveryScript, aliceDeliveryScript,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to close channel: %v", err)
|
||||
}
|
||||
bobCloseSig = append(bobSig.Serialize(), byte(txscript.SigHashAll))
|
||||
|
||||
closeTx, _, err = bobChannel.CompleteCooperativeClose(
|
||||
bobCloseSig, aliceCloseSig,
|
||||
bobDeliveryScript, aliceDeliveryScript, bobFee)
|
||||
bobSig, aliceSig, bobDeliveryScript, aliceDeliveryScript,
|
||||
bobFee,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to accept channel close: %v", err)
|
||||
}
|
||||
@ -2141,7 +2141,6 @@ func TestCooperativeCloseDustAdherence(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("unable to close channel: %v", err)
|
||||
}
|
||||
aliceCloseSig = append(aliceSig.Serialize(), byte(txscript.SigHashAll))
|
||||
|
||||
bobSig, _, _, err = bobChannel.CreateCloseProposal(
|
||||
bobFee, bobDeliveryScript, aliceDeliveryScript,
|
||||
@ -2149,11 +2148,11 @@ func TestCooperativeCloseDustAdherence(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("unable to close channel: %v", err)
|
||||
}
|
||||
bobCloseSig = append(bobSig.Serialize(), byte(txscript.SigHashAll))
|
||||
|
||||
closeTx, _, err = bobChannel.CompleteCooperativeClose(
|
||||
bobCloseSig, aliceCloseSig,
|
||||
bobDeliveryScript, aliceDeliveryScript, bobFee)
|
||||
bobSig, aliceSig, bobDeliveryScript, aliceDeliveryScript,
|
||||
bobFee,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to accept channel close: %v", err)
|
||||
}
|
||||
|
@ -98,7 +98,7 @@ func newChannelTestCtx(chanSize int64) (*channelTestCtx, error) {
|
||||
}
|
||||
|
||||
sigHashes := txscript.NewTxSigHashes(commitTx)
|
||||
aliceSig, err := txscript.RawTxInWitnessSignature(
|
||||
aliceSigRaw, err := txscript.RawTxInWitnessSignature(
|
||||
commitTx, sigHashes, 0, chanSize,
|
||||
multiSigScript, txscript.SigHashAll, alicePriv,
|
||||
)
|
||||
@ -106,7 +106,14 @@ func newChannelTestCtx(chanSize int64) (*channelTestCtx, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
bobSig, err := txscript.RawTxInWitnessSignature(
|
||||
aliceSig, err := btcec.ParseDERSignature(
|
||||
aliceSigRaw, btcec.S256(),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
bobSigRaw, err := txscript.RawTxInWitnessSignature(
|
||||
commitTx, sigHashes, 0, chanSize,
|
||||
multiSigScript, txscript.SigHashAll, bobPriv,
|
||||
)
|
||||
@ -114,6 +121,13 @@ func newChannelTestCtx(chanSize int64) (*channelTestCtx, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
bobSig, err := btcec.ParseDERSignature(
|
||||
bobSigRaw, btcec.S256(),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
commitTx.TxIn[0].Witness = input.SpendMultiSig(
|
||||
multiSigScript, alicePub.SerializeCompressed(), aliceSig,
|
||||
bobPub.SerializeCompressed(), bobSig,
|
||||
|
@ -1,7 +1,6 @@
|
||||
package lnwallet
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
@ -81,6 +80,19 @@ var (
|
||||
},
|
||||
LockTime: 5,
|
||||
}
|
||||
|
||||
// A valid, DER-encoded signature (taken from btcec unit tests).
|
||||
testSigBytes = []byte{
|
||||
0x30, 0x44, 0x02, 0x20, 0x4e, 0x45, 0xe1, 0x69,
|
||||
0x32, 0xb8, 0xaf, 0x51, 0x49, 0x61, 0xa1, 0xd3,
|
||||
0xa1, 0xa2, 0x5f, 0xdf, 0x3f, 0x4f, 0x77, 0x32,
|
||||
0xe9, 0xd6, 0x24, 0xc6, 0xc6, 0x15, 0x48, 0xab,
|
||||
0x5f, 0xb8, 0xcd, 0x41, 0x02, 0x20, 0x18, 0x15,
|
||||
0x22, 0xec, 0x8e, 0xca, 0x07, 0xde, 0x48, 0x60,
|
||||
0xa4, 0xac, 0xdd, 0x12, 0x90, 0x9d, 0x83, 0x1c,
|
||||
0xc5, 0x6c, 0xbb, 0xac, 0x46, 0x22, 0x08, 0x22,
|
||||
0x21, 0xa8, 0x76, 0x8d, 0x1d, 0x09,
|
||||
}
|
||||
)
|
||||
|
||||
// CreateTestChannels creates to fully populated channels to be used within
|
||||
@ -257,7 +269,7 @@ func CreateTestChannels(chanType channeldb.ChannelType) (
|
||||
CommitFee: commitFee,
|
||||
FeePerKw: btcutil.Amount(feePerKw),
|
||||
CommitTx: aliceCommitTx,
|
||||
CommitSig: bytes.Repeat([]byte{1}, 71),
|
||||
CommitSig: testSigBytes,
|
||||
}
|
||||
bobCommit := channeldb.ChannelCommitment{
|
||||
CommitHeight: 0,
|
||||
@ -266,7 +278,7 @@ func CreateTestChannels(chanType channeldb.ChannelType) (
|
||||
CommitFee: commitFee,
|
||||
FeePerKw: btcutil.Amount(feePerKw),
|
||||
CommitTx: bobCommitTx,
|
||||
CommitSig: bytes.Repeat([]byte{1}, 71),
|
||||
CommitSig: testSigBytes,
|
||||
}
|
||||
|
||||
var chanIDBytes [8]byte
|
||||
|
Loading…
Reference in New Issue
Block a user