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"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/btcsuite/btcd/txscript"
|
|
||||||
"github.com/btcsuite/btcd/wire"
|
"github.com/btcsuite/btcd/wire"
|
||||||
"github.com/btcsuite/btcutil"
|
"github.com/btcsuite/btcutil"
|
||||||
"github.com/davecgh/go-spew/spew"
|
"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
|
// transaction! We'll craft the final closing transaction so
|
||||||
// we can broadcast it to the network.
|
// we can broadcast it to the network.
|
||||||
matchingSig := c.priorFeeOffers[remoteProposedFee].Signature
|
matchingSig := c.priorFeeOffers[remoteProposedFee].Signature
|
||||||
localSigBytes := matchingSig.ToSignatureBytes()
|
localSig, err := matchingSig.ToSignature()
|
||||||
localSig := append(localSigBytes, byte(txscript.SigHashAll))
|
if err != nil {
|
||||||
|
return nil, false, err
|
||||||
|
}
|
||||||
|
|
||||||
remoteSigBytes := closeSignedMsg.Signature.ToSignatureBytes()
|
remoteSig, err := closeSignedMsg.Signature.ToSignature()
|
||||||
remoteSig := append(remoteSigBytes, byte(txscript.SigHashAll))
|
if err != nil {
|
||||||
|
return nil, false, err
|
||||||
|
}
|
||||||
|
|
||||||
closeTx, _, err := c.cfg.channel.CompleteCooperativeClose(
|
closeTx, _, err := c.cfg.channel.CompleteCooperativeClose(
|
||||||
localSig, remoteSig, c.localDeliveryScript,
|
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
|
// SpendMultiSig generates the witness stack required to redeem the 2-of-2 p2wsh
|
||||||
// multi-sig output.
|
// 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)
|
witness := make([][]byte, 4)
|
||||||
|
|
||||||
// When spending a p2wsh multi-sig script, rather than an OP_0, we add
|
// 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
|
// ensure the signatures appear on the Script Virtual Machine stack in
|
||||||
// the correct order.
|
// the correct order.
|
||||||
if bytes.Compare(pubA, pubB) == 1 {
|
if bytes.Compare(pubA, pubB) == 1 {
|
||||||
witness[1] = sigB
|
witness[1] = append(sigB.Serialize(), byte(txscript.SigHashAll))
|
||||||
witness[2] = sigA
|
witness[2] = append(sigA.Serialize(), byte(txscript.SigHashAll))
|
||||||
} else {
|
} else {
|
||||||
witness[1] = sigA
|
witness[1] = append(sigA.Serialize(), byte(txscript.SigHashAll))
|
||||||
witness[2] = sigB
|
witness[2] = append(sigB.Serialize(), byte(txscript.SigHashAll))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finally, add the preimage as the last witness element.
|
// Finally, add the preimage as the last witness element.
|
||||||
|
@ -5065,17 +5065,21 @@ func (lc *LightningChannel) getSignedCommitTx() (*wire.MsgTx, error) {
|
|||||||
// for the transaction.
|
// for the transaction.
|
||||||
localCommit := lc.channelState.LocalCommitment
|
localCommit := lc.channelState.LocalCommitment
|
||||||
commitTx := localCommit.CommitTx.Copy()
|
commitTx := localCommit.CommitTx.Copy()
|
||||||
theirSig := append(localCommit.CommitSig, byte(txscript.SigHashAll))
|
|
||||||
|
|
||||||
// With this, we then generate the full witness so the caller can
|
theirSig, err := btcec.ParseDERSignature(
|
||||||
// broadcast a fully signed transaction.
|
localCommit.CommitSig, btcec.S256(),
|
||||||
lc.signDesc.SigHashes = txscript.NewTxSigHashes(commitTx)
|
)
|
||||||
ourSigRaw, err := lc.Signer.SignOutputRaw(commitTx, lc.signDesc)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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
|
// With the final signature generated, create the witness stack
|
||||||
// required to spend from the multi-sig output.
|
// 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
|
// NOTE: The passed local and remote sigs are expected to be fully complete
|
||||||
// signatures including the proper sighash byte.
|
// signatures including the proper sighash byte.
|
||||||
func (lc *LightningChannel) CompleteCooperativeClose(localSig, remoteSig []byte,
|
func (lc *LightningChannel) CompleteCooperativeClose(
|
||||||
|
localSig, remoteSig input.Signature,
|
||||||
localDeliveryScript, remoteDeliveryScript []byte,
|
localDeliveryScript, remoteDeliveryScript []byte,
|
||||||
proposedFee btcutil.Amount) (*wire.MsgTx, btcutil.Amount, error) {
|
proposedFee btcutil.Amount) (*wire.MsgTx, btcutil.Amount, error) {
|
||||||
|
|
||||||
@ -6070,8 +6075,10 @@ func (lc *LightningChannel) CompleteCooperativeClose(localSig, remoteSig []byte,
|
|||||||
SerializeCompressed()
|
SerializeCompressed()
|
||||||
theirKey := lc.channelState.RemoteChanCfg.MultiSigKey.PubKey.
|
theirKey := lc.channelState.RemoteChanCfg.MultiSigKey.PubKey.
|
||||||
SerializeCompressed()
|
SerializeCompressed()
|
||||||
witness := input.SpendMultiSig(lc.signDesc.WitnessScript, ourKey,
|
witness := input.SpendMultiSig(
|
||||||
localSig, theirKey, remoteSig)
|
lc.signDesc.WitnessScript, ourKey, localSig, theirKey,
|
||||||
|
remoteSig,
|
||||||
|
)
|
||||||
closeTx.TxIn[0].Witness = witness
|
closeTx.TxIn[0].Witness = witness
|
||||||
|
|
||||||
// Validate the finalized transaction to ensure the output script is
|
// Validate the finalized transaction to ensure the output script is
|
||||||
|
@ -616,7 +616,6 @@ func TestCooperativeChannelClosure(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to create alice coop close proposal: %v", err)
|
t.Fatalf("unable to create alice coop close proposal: %v", err)
|
||||||
}
|
}
|
||||||
aliceCloseSig := append(aliceSig.Serialize(), byte(txscript.SigHashAll))
|
|
||||||
|
|
||||||
bobFee := bobChannel.CalcFee(bobFeeRate)
|
bobFee := bobChannel.CalcFee(bobFeeRate)
|
||||||
bobSig, _, _, err := bobChannel.CreateCloseProposal(
|
bobSig, _, _, err := bobChannel.CreateCloseProposal(
|
||||||
@ -625,14 +624,13 @@ func TestCooperativeChannelClosure(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to create bob coop close proposal: %v", err)
|
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
|
// With the proposals created, both sides should be able to properly
|
||||||
// process the other party's signature. This indicates that the
|
// process the other party's signature. This indicates that the
|
||||||
// transaction is well formed, and the signatures verify.
|
// transaction is well formed, and the signatures verify.
|
||||||
aliceCloseTx, _, err := bobChannel.CompleteCooperativeClose(
|
aliceCloseTx, _, err := bobChannel.CompleteCooperativeClose(
|
||||||
bobCloseSig, aliceCloseSig, bobDeliveryScript,
|
bobSig, aliceSig, bobDeliveryScript, aliceDeliveryScript,
|
||||||
aliceDeliveryScript, bobFee,
|
bobFee,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to complete alice cooperative close: %v", err)
|
t.Fatalf("unable to complete alice cooperative close: %v", err)
|
||||||
@ -640,8 +638,8 @@ func TestCooperativeChannelClosure(t *testing.T) {
|
|||||||
bobCloseSha := aliceCloseTx.TxHash()
|
bobCloseSha := aliceCloseTx.TxHash()
|
||||||
|
|
||||||
bobCloseTx, _, err := aliceChannel.CompleteCooperativeClose(
|
bobCloseTx, _, err := aliceChannel.CompleteCooperativeClose(
|
||||||
aliceCloseSig, bobCloseSig, aliceDeliveryScript,
|
aliceSig, bobSig, aliceDeliveryScript, bobDeliveryScript,
|
||||||
bobDeliveryScript, aliceFee,
|
aliceFee,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to complete bob cooperative close: %v", err)
|
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
|
// balances. As a result, performing a cooperative closure now result
|
||||||
// in both sides having an output within the closure transaction.
|
// in both sides having an output within the closure transaction.
|
||||||
aliceFee := btcutil.Amount(aliceChannel.CalcFee(aliceFeeRate)) + 1000
|
aliceFee := btcutil.Amount(aliceChannel.CalcFee(aliceFeeRate)) + 1000
|
||||||
aliceSig, _, _, err := aliceChannel.CreateCloseProposal(aliceFee,
|
aliceSig, _, _, err := aliceChannel.CreateCloseProposal(
|
||||||
aliceDeliveryScript, bobDeliveryScript)
|
aliceFee, aliceDeliveryScript, bobDeliveryScript,
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to close channel: %v", err)
|
t.Fatalf("unable to close channel: %v", err)
|
||||||
}
|
}
|
||||||
aliceCloseSig := append(aliceSig.Serialize(), byte(txscript.SigHashAll))
|
|
||||||
|
|
||||||
bobFee := btcutil.Amount(bobChannel.CalcFee(bobFeeRate)) + 1000
|
bobFee := btcutil.Amount(bobChannel.CalcFee(bobFeeRate)) + 1000
|
||||||
bobSig, _, _, err := bobChannel.CreateCloseProposal(bobFee,
|
bobSig, _, _, err := bobChannel.CreateCloseProposal(
|
||||||
bobDeliveryScript, aliceDeliveryScript)
|
bobFee, bobDeliveryScript, aliceDeliveryScript,
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to close channel: %v", err)
|
t.Fatalf("unable to close channel: %v", err)
|
||||||
}
|
}
|
||||||
bobCloseSig := append(bobSig.Serialize(), byte(txscript.SigHashAll))
|
|
||||||
|
|
||||||
closeTx, _, err := bobChannel.CompleteCooperativeClose(
|
closeTx, _, err := bobChannel.CompleteCooperativeClose(
|
||||||
bobCloseSig, aliceCloseSig,
|
bobSig, aliceSig, bobDeliveryScript, aliceDeliveryScript,
|
||||||
bobDeliveryScript, aliceDeliveryScript, bobFee)
|
bobFee,
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to accept channel close: %v", err)
|
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
|
// Attempt another cooperative channel closure. It should succeed
|
||||||
// without any issues.
|
// without any issues.
|
||||||
aliceSig, _, _, err = aliceChannel.CreateCloseProposal(aliceFee,
|
aliceSig, _, _, err = aliceChannel.CreateCloseProposal(
|
||||||
aliceDeliveryScript, bobDeliveryScript)
|
aliceFee, aliceDeliveryScript, bobDeliveryScript,
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to close channel: %v", err)
|
t.Fatalf("unable to close channel: %v", err)
|
||||||
}
|
}
|
||||||
aliceCloseSig = append(aliceSig.Serialize(), byte(txscript.SigHashAll))
|
|
||||||
|
|
||||||
bobSig, _, _, err = bobChannel.CreateCloseProposal(bobFee,
|
bobSig, _, _, err = bobChannel.CreateCloseProposal(
|
||||||
bobDeliveryScript, aliceDeliveryScript)
|
bobFee, bobDeliveryScript, aliceDeliveryScript,
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to close channel: %v", err)
|
t.Fatalf("unable to close channel: %v", err)
|
||||||
}
|
}
|
||||||
bobCloseSig = append(bobSig.Serialize(), byte(txscript.SigHashAll))
|
|
||||||
|
|
||||||
closeTx, _, err = bobChannel.CompleteCooperativeClose(
|
closeTx, _, err = bobChannel.CompleteCooperativeClose(
|
||||||
bobCloseSig, aliceCloseSig,
|
bobSig, aliceSig, bobDeliveryScript, aliceDeliveryScript,
|
||||||
bobDeliveryScript, aliceDeliveryScript, bobFee)
|
bobFee,
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to accept channel close: %v", err)
|
t.Fatalf("unable to accept channel close: %v", err)
|
||||||
}
|
}
|
||||||
@ -2141,7 +2141,6 @@ func TestCooperativeCloseDustAdherence(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to close channel: %v", err)
|
t.Fatalf("unable to close channel: %v", err)
|
||||||
}
|
}
|
||||||
aliceCloseSig = append(aliceSig.Serialize(), byte(txscript.SigHashAll))
|
|
||||||
|
|
||||||
bobSig, _, _, err = bobChannel.CreateCloseProposal(
|
bobSig, _, _, err = bobChannel.CreateCloseProposal(
|
||||||
bobFee, bobDeliveryScript, aliceDeliveryScript,
|
bobFee, bobDeliveryScript, aliceDeliveryScript,
|
||||||
@ -2149,11 +2148,11 @@ func TestCooperativeCloseDustAdherence(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to close channel: %v", err)
|
t.Fatalf("unable to close channel: %v", err)
|
||||||
}
|
}
|
||||||
bobCloseSig = append(bobSig.Serialize(), byte(txscript.SigHashAll))
|
|
||||||
|
|
||||||
closeTx, _, err = bobChannel.CompleteCooperativeClose(
|
closeTx, _, err = bobChannel.CompleteCooperativeClose(
|
||||||
bobCloseSig, aliceCloseSig,
|
bobSig, aliceSig, bobDeliveryScript, aliceDeliveryScript,
|
||||||
bobDeliveryScript, aliceDeliveryScript, bobFee)
|
bobFee,
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to accept channel close: %v", err)
|
t.Fatalf("unable to accept channel close: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -98,7 +98,7 @@ func newChannelTestCtx(chanSize int64) (*channelTestCtx, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sigHashes := txscript.NewTxSigHashes(commitTx)
|
sigHashes := txscript.NewTxSigHashes(commitTx)
|
||||||
aliceSig, err := txscript.RawTxInWitnessSignature(
|
aliceSigRaw, err := txscript.RawTxInWitnessSignature(
|
||||||
commitTx, sigHashes, 0, chanSize,
|
commitTx, sigHashes, 0, chanSize,
|
||||||
multiSigScript, txscript.SigHashAll, alicePriv,
|
multiSigScript, txscript.SigHashAll, alicePriv,
|
||||||
)
|
)
|
||||||
@ -106,7 +106,14 @@ func newChannelTestCtx(chanSize int64) (*channelTestCtx, error) {
|
|||||||
return nil, err
|
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,
|
commitTx, sigHashes, 0, chanSize,
|
||||||
multiSigScript, txscript.SigHashAll, bobPriv,
|
multiSigScript, txscript.SigHashAll, bobPriv,
|
||||||
)
|
)
|
||||||
@ -114,6 +121,13 @@ func newChannelTestCtx(chanSize int64) (*channelTestCtx, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bobSig, err := btcec.ParseDERSignature(
|
||||||
|
bobSigRaw, btcec.S256(),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
commitTx.TxIn[0].Witness = input.SpendMultiSig(
|
commitTx.TxIn[0].Witness = input.SpendMultiSig(
|
||||||
multiSigScript, alicePub.SerializeCompressed(), aliceSig,
|
multiSigScript, alicePub.SerializeCompressed(), aliceSig,
|
||||||
bobPub.SerializeCompressed(), bobSig,
|
bobPub.SerializeCompressed(), bobSig,
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package lnwallet
|
package lnwallet
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
@ -81,6 +80,19 @@ var (
|
|||||||
},
|
},
|
||||||
LockTime: 5,
|
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
|
// CreateTestChannels creates to fully populated channels to be used within
|
||||||
@ -257,7 +269,7 @@ func CreateTestChannels(chanType channeldb.ChannelType) (
|
|||||||
CommitFee: commitFee,
|
CommitFee: commitFee,
|
||||||
FeePerKw: btcutil.Amount(feePerKw),
|
FeePerKw: btcutil.Amount(feePerKw),
|
||||||
CommitTx: aliceCommitTx,
|
CommitTx: aliceCommitTx,
|
||||||
CommitSig: bytes.Repeat([]byte{1}, 71),
|
CommitSig: testSigBytes,
|
||||||
}
|
}
|
||||||
bobCommit := channeldb.ChannelCommitment{
|
bobCommit := channeldb.ChannelCommitment{
|
||||||
CommitHeight: 0,
|
CommitHeight: 0,
|
||||||
@ -266,7 +278,7 @@ func CreateTestChannels(chanType channeldb.ChannelType) (
|
|||||||
CommitFee: commitFee,
|
CommitFee: commitFee,
|
||||||
FeePerKw: btcutil.Amount(feePerKw),
|
FeePerKw: btcutil.Amount(feePerKw),
|
||||||
CommitTx: bobCommitTx,
|
CommitTx: bobCommitTx,
|
||||||
CommitSig: bytes.Repeat([]byte{1}, 71),
|
CommitSig: testSigBytes,
|
||||||
}
|
}
|
||||||
|
|
||||||
var chanIDBytes [8]byte
|
var chanIDBytes [8]byte
|
||||||
|
Loading…
Reference in New Issue
Block a user