Merge pull request #4172 from cfromknecht/witness-size
input: assert witness size constants
This commit is contained in:
commit
8c2647de6b
@ -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,
|
||||
@ -589,7 +592,7 @@ func (c *channelCloser) proposeCloseSigned(fee btcutil.Amount) (*lnwire.ClosingS
|
||||
// party responds we'll be able to decide if we've agreed on fees or
|
||||
// not.
|
||||
c.lastFeeProposal = fee
|
||||
parsedSig, err := lnwire.NewSigFromRawSignature(rawSig)
|
||||
parsedSig, err := lnwire.NewSigFromSignature(rawSig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/btcsuite/btcd/btcec"
|
||||
"github.com/btcsuite/btcd/txscript"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/lightningnetwork/lnd/chainntnfs"
|
||||
@ -15,12 +16,22 @@ import (
|
||||
"github.com/lightningnetwork/lnd/lnwallet"
|
||||
)
|
||||
|
||||
type dummySignature struct{}
|
||||
|
||||
func (s *dummySignature) Serialize() []byte {
|
||||
return []byte{}
|
||||
}
|
||||
|
||||
func (s *dummySignature) Verify(_ []byte, _ *btcec.PublicKey) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
type mockSigner struct {
|
||||
}
|
||||
|
||||
func (m *mockSigner) SignOutputRaw(tx *wire.MsgTx,
|
||||
signDesc *input.SignDescriptor) ([]byte, error) {
|
||||
return nil, nil
|
||||
signDesc *input.SignDescriptor) (input.Signature, error) {
|
||||
return &dummySignature{}, nil
|
||||
}
|
||||
|
||||
func (m *mockSigner) ComputeInputScript(tx *wire.MsgTx,
|
||||
@ -145,8 +156,8 @@ func TestHtlcTimeoutResolver(t *testing.T) {
|
||||
timeout: true,
|
||||
txToBroadcast: func() (*wire.MsgTx, error) {
|
||||
witness, err := input.SenderHtlcSpendTimeout(
|
||||
nil, txscript.SigHashAll, signer,
|
||||
fakeSignDesc, sweepTx,
|
||||
&dummySignature{}, txscript.SigHashAll,
|
||||
signer, fakeSignDesc, sweepTx,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -165,9 +176,9 @@ func TestHtlcTimeoutResolver(t *testing.T) {
|
||||
timeout: false,
|
||||
txToBroadcast: func() (*wire.MsgTx, error) {
|
||||
witness, err := input.ReceiverHtlcSpendRedeem(
|
||||
nil, txscript.SigHashAll,
|
||||
fakePreimageBytes, signer,
|
||||
fakeSignDesc, sweepTx,
|
||||
&dummySignature{}, txscript.SigHashAll,
|
||||
fakePreimageBytes, signer, fakeSignDesc,
|
||||
sweepTx,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -23,6 +23,7 @@ import (
|
||||
"github.com/go-errors/errors"
|
||||
"github.com/lightningnetwork/lnd/chainntnfs"
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/input"
|
||||
"github.com/lightningnetwork/lnd/lnpeer"
|
||||
"github.com/lightningnetwork/lnd/lntest/wait"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
@ -96,7 +97,7 @@ type mockSigner struct {
|
||||
}
|
||||
|
||||
func (n *mockSigner) SignMessage(pubKey *btcec.PublicKey,
|
||||
msg []byte) (*btcec.Signature, error) {
|
||||
msg []byte) (input.Signature, error) {
|
||||
|
||||
if !pubKey.IsEqual(n.privKey.PubKey()) {
|
||||
return nil, fmt.Errorf("unknown public key")
|
||||
|
@ -254,7 +254,8 @@ type fundingConfig struct {
|
||||
//
|
||||
// TODO(roasbeef): should instead pass on this responsibility to a
|
||||
// distinct sub-system?
|
||||
SignMessage func(pubKey *btcec.PublicKey, msg []byte) (*btcec.Signature, error)
|
||||
SignMessage func(pubKey *btcec.PublicKey,
|
||||
msg []byte) (input.Signature, error)
|
||||
|
||||
// CurrentNodeAnnouncement should return the latest, fully signed node
|
||||
// announcement from the backing Lightning Network node.
|
||||
@ -1726,7 +1727,7 @@ func (f *fundingManager) continueFundingAccept(resCtx *reservationWithCtx,
|
||||
PendingChannelID: pendingChanID,
|
||||
FundingPoint: *outPoint,
|
||||
}
|
||||
fundingCreated.CommitSig, err = lnwire.NewSigFromRawSignature(sig)
|
||||
fundingCreated.CommitSig, err = lnwire.NewSigFromSignature(sig)
|
||||
if err != nil {
|
||||
fndgLog.Errorf("Unable to parse signature: %v", err)
|
||||
f.failFundingFlow(resCtx.peer, pendingChanID, err)
|
||||
@ -1775,14 +1776,21 @@ func (f *fundingManager) handleFundingCreated(fmsg *fundingCreatedMsg) {
|
||||
fndgLog.Infof("completing pending_id(%x) with ChannelPoint(%v)",
|
||||
pendingChanID[:], fundingOut)
|
||||
|
||||
commitSig, err := fmsg.msg.CommitSig.ToSignature()
|
||||
if err != nil {
|
||||
fndgLog.Errorf("unable to parse signature: %v", err)
|
||||
f.failFundingFlow(fmsg.peer, pendingChanID, err)
|
||||
return
|
||||
}
|
||||
|
||||
// With all the necessary data available, attempt to advance the
|
||||
// funding workflow to the next stage. If this succeeds then the
|
||||
// funding transaction will broadcast after our next message.
|
||||
// CompleteReservationSingle will also mark the channel as 'IsPending'
|
||||
// in the database.
|
||||
commitSig := fmsg.msg.CommitSig.ToSignatureBytes()
|
||||
completeChan, err := resCtx.reservation.CompleteReservationSingle(
|
||||
&fundingOut, commitSig)
|
||||
&fundingOut, commitSig,
|
||||
)
|
||||
if err != nil {
|
||||
// TODO(roasbeef): better error logging: peerID, channelID, etc.
|
||||
fndgLog.Errorf("unable to complete single reservation: %v", err)
|
||||
@ -1837,7 +1845,7 @@ func (f *fundingManager) handleFundingCreated(fmsg *fundingCreatedMsg) {
|
||||
// With their signature for our version of the commitment transaction
|
||||
// verified, we can now send over our signature to the remote peer.
|
||||
_, sig := resCtx.reservation.OurSignatures()
|
||||
ourCommitSig, err := lnwire.NewSigFromRawSignature(sig)
|
||||
ourCommitSig, err := lnwire.NewSigFromSignature(sig)
|
||||
if err != nil {
|
||||
fndgLog.Errorf("unable to parse signature: %v", err)
|
||||
f.failFundingFlow(fmsg.peer, pendingChanID, err)
|
||||
@ -1950,7 +1958,13 @@ func (f *fundingManager) handleFundingSigned(fmsg *fundingSignedMsg) {
|
||||
// The remote peer has responded with a signature for our commitment
|
||||
// transaction. We'll verify the signature for validity, then commit
|
||||
// the state to disk as we can now open the channel.
|
||||
commitSig := fmsg.msg.CommitSig.ToSignatureBytes()
|
||||
commitSig, err := fmsg.msg.CommitSig.ToSignature()
|
||||
if err != nil {
|
||||
fndgLog.Errorf("Unable to parse signature: %v", err)
|
||||
f.failFundingFlow(fmsg.peer, pendingChanID, err)
|
||||
return
|
||||
}
|
||||
|
||||
completeChan, err := resCtx.reservation.CompleteReservation(
|
||||
nil, commitSig,
|
||||
)
|
||||
|
@ -334,7 +334,9 @@ func createTestFundingManager(t *testing.T, privKey *btcec.PrivateKey,
|
||||
Wallet: lnw,
|
||||
Notifier: chainNotifier,
|
||||
FeeEstimator: estimator,
|
||||
SignMessage: func(pubKey *btcec.PublicKey, msg []byte) (*btcec.Signature, error) {
|
||||
SignMessage: func(pubKey *btcec.PublicKey,
|
||||
msg []byte) (input.Signature, error) {
|
||||
|
||||
return testSig, nil
|
||||
},
|
||||
SendAnnouncement: func(msg lnwire.Message,
|
||||
@ -474,7 +476,7 @@ func recreateAliceFundingManager(t *testing.T, alice *testNode) {
|
||||
Notifier: oldCfg.Notifier,
|
||||
FeeEstimator: oldCfg.FeeEstimator,
|
||||
SignMessage: func(pubKey *btcec.PublicKey,
|
||||
msg []byte) (*btcec.Signature, error) {
|
||||
msg []byte) (input.Signature, error) {
|
||||
return testSig, nil
|
||||
},
|
||||
SendAnnouncement: func(msg lnwire.Message,
|
||||
|
@ -852,7 +852,9 @@ type mockSigner struct {
|
||||
key *btcec.PrivateKey
|
||||
}
|
||||
|
||||
func (m *mockSigner) SignOutputRaw(tx *wire.MsgTx, signDesc *input.SignDescriptor) ([]byte, error) {
|
||||
func (m *mockSigner) SignOutputRaw(tx *wire.MsgTx,
|
||||
signDesc *input.SignDescriptor) (input.Signature, error) {
|
||||
|
||||
amt := signDesc.Output.Value
|
||||
witnessScript := signDesc.WitnessScript
|
||||
privKey := m.key
|
||||
@ -877,7 +879,7 @@ func (m *mockSigner) SignOutputRaw(tx *wire.MsgTx, signDesc *input.SignDescripto
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return sig[:len(sig)-1], nil
|
||||
return btcec.ParseDERSignature(sig[:len(sig)-1], btcec.S256())
|
||||
}
|
||||
func (m *mockSigner) ComputeInputScript(tx *wire.MsgTx, signDesc *input.SignDescriptor) (*input.Script, error) {
|
||||
|
||||
|
@ -23,6 +23,17 @@ 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
|
||||
|
||||
// Verify return true if the ECDSA signature is valid for the passed
|
||||
// message digest under the provided public key.
|
||||
Verify([]byte, *btcec.PublicKey) bool
|
||||
}
|
||||
|
||||
// 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) {
|
||||
@ -85,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
|
||||
@ -97,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.
|
||||
@ -283,7 +296,7 @@ func SenderHtlcSpendRevokeWithKey(signer Signer, signDesc *SignDescriptor,
|
||||
// manner in order to encode the revocation contract into a sig+key
|
||||
// pair.
|
||||
witnessStack := wire.TxWitness(make([][]byte, 3))
|
||||
witnessStack[0] = append(sweepSig, byte(signDesc.HashType))
|
||||
witnessStack[0] = append(sweepSig.Serialize(), byte(signDesc.HashType))
|
||||
witnessStack[1] = revokeKey.SerializeCompressed()
|
||||
witnessStack[2] = signDesc.WitnessScript
|
||||
|
||||
@ -332,7 +345,7 @@ func SenderHtlcSpendRedeem(signer Signer, signDesc *SignDescriptor,
|
||||
// generated above under the receiver's public key, and the payment
|
||||
// pre-image.
|
||||
witnessStack := wire.TxWitness(make([][]byte, 3))
|
||||
witnessStack[0] = append(sweepSig, byte(signDesc.HashType))
|
||||
witnessStack[0] = append(sweepSig.Serialize(), byte(signDesc.HashType))
|
||||
witnessStack[1] = paymentPreimage
|
||||
witnessStack[2] = signDesc.WitnessScript
|
||||
|
||||
@ -343,7 +356,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,8 +372,8 @@ func SenderHtlcSpendTimeout(receiverSig []byte,
|
||||
// original OP_CHECKMULTISIG.
|
||||
witnessStack := wire.TxWitness(make([][]byte, 5))
|
||||
witnessStack[0] = nil
|
||||
witnessStack[1] = append(receiverSig, byte(receiverSigHash))
|
||||
witnessStack[2] = append(sweepSig, byte(signDesc.HashType))
|
||||
witnessStack[1] = append(receiverSig.Serialize(), byte(receiverSigHash))
|
||||
witnessStack[2] = append(sweepSig.Serialize(), byte(signDesc.HashType))
|
||||
witnessStack[3] = nil
|
||||
witnessStack[4] = signDesc.WitnessScript
|
||||
|
||||
@ -508,7 +521,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,8 +540,8 @@ 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[2] = append(sweepSig, byte(signDesc.HashType))
|
||||
witnessStack[1] = append(senderSig.Serialize(), byte(senderSigHash))
|
||||
witnessStack[2] = append(sweepSig.Serialize(), byte(signDesc.HashType))
|
||||
witnessStack[3] = paymentPreimage
|
||||
witnessStack[4] = signDesc.WitnessScript
|
||||
|
||||
@ -555,7 +568,7 @@ func ReceiverHtlcSpendRevokeWithKey(signer Signer, signDesc *SignDescriptor,
|
||||
// witness stack in order to force script execution to the HTLC
|
||||
// revocation clause.
|
||||
witnessStack := wire.TxWitness(make([][]byte, 3))
|
||||
witnessStack[0] = append(sweepSig, byte(signDesc.HashType))
|
||||
witnessStack[0] = append(sweepSig.Serialize(), byte(signDesc.HashType))
|
||||
witnessStack[1] = revokeKey.SerializeCompressed()
|
||||
witnessStack[2] = signDesc.WitnessScript
|
||||
|
||||
@ -620,7 +633,7 @@ func ReceiverHtlcSpendTimeout(signer Signer, signDesc *SignDescriptor,
|
||||
}
|
||||
|
||||
witnessStack := wire.TxWitness(make([][]byte, 3))
|
||||
witnessStack[0] = append(sweepSig, byte(signDesc.HashType))
|
||||
witnessStack[0] = append(sweepSig.Serialize(), byte(signDesc.HashType))
|
||||
witnessStack[1] = nil
|
||||
witnessStack[2] = signDesc.WitnessScript
|
||||
|
||||
@ -725,7 +738,7 @@ func HtlcSpendSuccess(signer Signer, signDesc *SignDescriptor,
|
||||
// witness script), in order to force execution to the second portion
|
||||
// of the if clause.
|
||||
witnessStack := wire.TxWitness(make([][]byte, 3))
|
||||
witnessStack[0] = append(sweepSig, byte(signDesc.HashType))
|
||||
witnessStack[0] = append(sweepSig.Serialize(), byte(signDesc.HashType))
|
||||
witnessStack[1] = nil
|
||||
witnessStack[2] = signDesc.WitnessScript
|
||||
|
||||
@ -750,7 +763,7 @@ func HtlcSpendRevoke(signer Signer, signDesc *SignDescriptor,
|
||||
// witness script), in order to force execution to the revocation
|
||||
// clause in the second level HTLC script.
|
||||
witnessStack := wire.TxWitness(make([][]byte, 3))
|
||||
witnessStack[0] = append(sweepSig, byte(signDesc.HashType))
|
||||
witnessStack[0] = append(sweepSig.Serialize(), byte(signDesc.HashType))
|
||||
witnessStack[1] = []byte{1}
|
||||
witnessStack[2] = signDesc.WitnessScript
|
||||
|
||||
@ -781,7 +794,7 @@ func HtlcSecondLevelSpend(signer Signer, signDesc *SignDescriptor,
|
||||
// witness script), in order to force execution to the second portion
|
||||
// of the if clause.
|
||||
witnessStack := wire.TxWitness(make([][]byte, 3))
|
||||
witnessStack[0] = append(sweepSig, byte(txscript.SigHashAll))
|
||||
witnessStack[0] = append(sweepSig.Serialize(), byte(txscript.SigHashAll))
|
||||
witnessStack[1] = nil
|
||||
witnessStack[2] = signDesc.WitnessScript
|
||||
|
||||
@ -885,7 +898,7 @@ func CommitSpendTimeout(signer Signer, signDesc *SignDescriptor,
|
||||
// place an empty byte in order to ensure our script is still valid
|
||||
// from the PoV of nodes that are enforcing minimal OP_IF/OP_NOTIF.
|
||||
witnessStack := wire.TxWitness(make([][]byte, 3))
|
||||
witnessStack[0] = append(sweepSig, byte(signDesc.HashType))
|
||||
witnessStack[0] = append(sweepSig.Serialize(), byte(signDesc.HashType))
|
||||
witnessStack[1] = nil
|
||||
witnessStack[2] = signDesc.WitnessScript
|
||||
|
||||
@ -910,7 +923,7 @@ func CommitSpendRevoke(signer Signer, signDesc *SignDescriptor,
|
||||
// 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] = append(sweepSig, byte(signDesc.HashType))
|
||||
witnessStack[0] = append(sweepSig.Serialize(), byte(signDesc.HashType))
|
||||
witnessStack[1] = []byte{1}
|
||||
witnessStack[2] = signDesc.WitnessScript
|
||||
|
||||
@ -944,7 +957,7 @@ func CommitSpendNoDelay(signer Signer, signDesc *SignDescriptor,
|
||||
// exact same as a regular p2wkh witness, depending on the value of the
|
||||
// tweakless bool.
|
||||
witness := make([][]byte, 2)
|
||||
witness[0] = append(sweepSig, byte(signDesc.HashType))
|
||||
witness[0] = append(sweepSig.Serialize(), byte(signDesc.HashType))
|
||||
|
||||
switch tweakless {
|
||||
// If we're tweaking the key, then we use the tweaked public key as the
|
||||
@ -1021,7 +1034,7 @@ func CommitSpendToRemoteConfirmed(signer Signer, signDesc *SignDescriptor,
|
||||
// Finally, we'll manually craft the witness. The witness here is the
|
||||
// signature and the redeem script.
|
||||
witnessStack := make([][]byte, 2)
|
||||
witnessStack[0] = append(sweepSig, byte(signDesc.HashType))
|
||||
witnessStack[0] = append(sweepSig.Serialize(), byte(signDesc.HashType))
|
||||
witnessStack[1] = signDesc.WitnessScript
|
||||
|
||||
return witnessStack, nil
|
||||
@ -1077,7 +1090,7 @@ func CommitSpendAnchor(signer Signer, signDesc *SignDescriptor,
|
||||
|
||||
// The witness here is just a signature and the redeem script.
|
||||
witnessStack := make([][]byte, 2)
|
||||
witnessStack[0] = append(sweepSig, byte(signDesc.HashType))
|
||||
witnessStack[0] = append(sweepSig.Serialize(), byte(signDesc.HashType))
|
||||
witnessStack[1] = signDesc.WitnessScript
|
||||
|
||||
return witnessStack, nil
|
||||
|
@ -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,17 @@ func TestHTLCSenderSpendValidation(t *testing.T) {
|
||||
SigHashes: sweepTxSigHashes,
|
||||
InputIndex: 0,
|
||||
}
|
||||
bobRecvrSig, err = bobSigner.SignOutputRaw(sweepTx, &bobSignDesc)
|
||||
bobSig, err := bobSigner.SignOutputRaw(sweepTx, &bobSignDesc)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to generate alice signature: %v", err)
|
||||
}
|
||||
|
||||
bobRecvrSig, err = btcec.ParseDERSignature(
|
||||
bobSig.Serialize(), btcec.S256(),
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to parse signature: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
testCases := []struct {
|
||||
@ -622,7 +629,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 +702,17 @@ func TestHTLCReceiverSpendValidation(t *testing.T) {
|
||||
SigHashes: sweepTxSigHashes,
|
||||
InputIndex: 0,
|
||||
}
|
||||
aliceSenderSig, err = aliceSigner.SignOutputRaw(sweepTx, &aliceSignDesc)
|
||||
aliceSig, err := aliceSigner.SignOutputRaw(sweepTx, &aliceSignDesc)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to generate alice signature: %v", err)
|
||||
}
|
||||
|
||||
aliceSenderSig, err = btcec.ParseDERSignature(
|
||||
aliceSig.Serialize(), btcec.S256(),
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to parse signature: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(roasbeef): modify valid to check precise script errors?
|
||||
|
@ -14,7 +14,8 @@ type Signer interface {
|
||||
// according to the data within the passed SignDescriptor.
|
||||
//
|
||||
// NOTE: The resulting signature should be void of a sighash byte.
|
||||
SignOutputRaw(tx *wire.MsgTx, signDesc *SignDescriptor) ([]byte, error)
|
||||
SignOutputRaw(tx *wire.MsgTx,
|
||||
signDesc *SignDescriptor) (Signature, error)
|
||||
|
||||
// ComputeInputScript generates a complete InputIndex for the passed
|
||||
// transaction with the signature as defined within the passed
|
||||
|
107
input/size.go
107
input/size.go
@ -1,12 +1,8 @@
|
||||
package input
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
|
||||
"github.com/btcsuite/btcd/blockchain"
|
||||
"github.com/btcsuite/btcd/btcec"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/lightningnetwork/lnd/keychain"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -94,7 +90,7 @@ const (
|
||||
// - OP_CHECKMULTISIG: 1 byte
|
||||
MultiSigSize = 1 + 1 + 33 + 1 + 33 + 1 + 1
|
||||
|
||||
// WitnessSize 222 bytes
|
||||
// MultiSigWitnessSize 222 bytes
|
||||
// - NumberOfWitnessElements: 1 byte
|
||||
// - NilLength: 1 byte
|
||||
// - sigAliceLength: 1 byte
|
||||
@ -103,7 +99,7 @@ const (
|
||||
// - sigBob: 73 bytes
|
||||
// - WitnessScriptLength: 1 byte
|
||||
// - WitnessScript (MultiSig)
|
||||
WitnessSize = 1 + 1 + 1 + 73 + 1 + 73 + 1 + MultiSigSize
|
||||
MultiSigWitnessSize = 1 + 1 + 1 + 73 + 1 + 73 + 1 + MultiSigSize
|
||||
|
||||
// InputSize 41 bytes
|
||||
// - PreviousOutPoint:
|
||||
@ -177,7 +173,7 @@ const (
|
||||
BaseCommitmentTxWeight = witnessScaleFactor * BaseCommitmentTxSize
|
||||
|
||||
// WitnessCommitmentTxWeight 224 weight
|
||||
WitnessCommitmentTxWeight = WitnessHeaderSize + WitnessSize
|
||||
WitnessCommitmentTxWeight = WitnessHeaderSize + MultiSigWitnessSize
|
||||
|
||||
// BaseAnchorCommitmentTxSize 225 + 43 * num-htlc-outputs bytes
|
||||
// - Version: 4 bytes
|
||||
@ -264,14 +260,15 @@ const (
|
||||
// - witness_script (to_local_script)
|
||||
ToLocalTimeoutWitnessSize = 1 + 1 + 73 + 1 + 1 + ToLocalScriptSize
|
||||
|
||||
// ToLocalPenaltyWitnessSize 156 bytes
|
||||
// ToLocalPenaltyWitnessSize 157 bytes
|
||||
// - number_of_witness_elements: 1 byte
|
||||
// - revocation_sig_length: 1 byte
|
||||
// - revocation_sig: 73 bytes
|
||||
// - OP_TRUE_length: 1 byte
|
||||
// - OP_TRUE: 1 byte
|
||||
// - witness_script_length: 1 byte
|
||||
// - witness_script (to_local_script)
|
||||
ToLocalPenaltyWitnessSize = 1 + 1 + 73 + 1 + 1 + ToLocalScriptSize
|
||||
ToLocalPenaltyWitnessSize = 1 + 1 + 73 + 1 + 1 + 1 + ToLocalScriptSize
|
||||
|
||||
// ToRemoteConfirmedScriptSize 37 bytes
|
||||
// - OP_DATA: 1 byte
|
||||
@ -289,7 +286,7 @@ const (
|
||||
// - witness_script (to_remote_delayed_script)
|
||||
ToRemoteConfirmedWitnessSize = 1 + 1 + 73 + 1 + ToRemoteConfirmedScriptSize
|
||||
|
||||
// AcceptedHtlcScriptSize 142 bytes
|
||||
// AcceptedHtlcScriptSize 143 bytes
|
||||
// - OP_DUP: 1 byte
|
||||
// - OP_HASH160: 1 byte
|
||||
// - OP_DATA: 1 byte (RIPEMD160(SHA256(revocationkey)) length)
|
||||
@ -302,6 +299,7 @@ const (
|
||||
// - remotekey: 33 bytes
|
||||
// - OP_SWAP: 1 byte
|
||||
// - OP_SIZE: 1 byte
|
||||
// - OP_DATA: 1 byte (32 length)
|
||||
// - 32: 1 byte
|
||||
// - OP_EQUAL: 1 byte
|
||||
// - OP_IF: 1 byte
|
||||
@ -327,7 +325,7 @@ const (
|
||||
// - OP_CSV: 1 byte // HTLC script types. The size won't be correct in all cases,
|
||||
// - OP_DROP: 1 byte // but it is just an upper bound used for fee estimation in any case.
|
||||
// - OP_ENDIF: 1 byte
|
||||
AcceptedHtlcScriptSize = 3*1 + 20 + 5*1 + 33 + 7*1 + 20 + 4*1 +
|
||||
AcceptedHtlcScriptSize = 3*1 + 20 + 5*1 + 33 + 8*1 + 20 + 4*1 +
|
||||
33 + 5*1 + 4 + 8*1
|
||||
|
||||
// AcceptedHtlcTimeoutWitnessSize 219
|
||||
@ -349,6 +347,20 @@ const (
|
||||
// - witness_script (accepted_htlc_script)
|
||||
AcceptedHtlcPenaltyWitnessSize = 1 + 1 + 73 + 1 + 33 + 1 + AcceptedHtlcScriptSize
|
||||
|
||||
// AcceptedHtlcSuccessWitnessSize 322 bytes
|
||||
// - number_of_witness_elements: 1 byte
|
||||
// - nil_length: 1 byte
|
||||
// - sig_alice_length: 1 byte
|
||||
// - sig_alice: 73 bytes
|
||||
// - sig_bob_length: 1 byte
|
||||
// - sig_bob: 73 bytes
|
||||
// - preimage_length: 1 byte
|
||||
// - preimage: 32 bytes
|
||||
// - witness_script_length: 1 byte
|
||||
// - witness_script (accepted_htlc_script)
|
||||
AcceptedHtlcSuccessWitnessSize = 1 + 1 + 1 + 73 + 1 + 73 + 1 + 32 + 1 +
|
||||
AcceptedHtlcScriptSize
|
||||
|
||||
// OfferedHtlcScriptSize 136 bytes
|
||||
// - OP_DUP: 1 byte
|
||||
// - OP_HASH160: 1 byte
|
||||
@ -386,18 +398,27 @@ const (
|
||||
// - OP_ENDIF: 1 byte
|
||||
OfferedHtlcScriptSize = 3*1 + 20 + 5*1 + 33 + 10*1 + 33 + 5*1 + 20 + 7*1
|
||||
|
||||
// OfferedHtlcSuccessWitnessSize 320 bytes
|
||||
// OfferedHtlcSuccessWitnessSize 245 bytes
|
||||
// - number_of_witness_elements: 1 byte
|
||||
// - nil_length: 1 byte
|
||||
// - receiver_sig_length: 1 byte
|
||||
// - receiver_sig: 73 bytes
|
||||
// - sender_sig_length: 1 byte
|
||||
// - sender_sig: 73 bytes
|
||||
// - payment_preimage_length: 1 byte
|
||||
// - payment_preimage: 32 bytes
|
||||
// - witness_script_length: 1 byte
|
||||
// - witness_script (offered_htlc_script)
|
||||
OfferedHtlcSuccessWitnessSize = 1 + 1 + 1 + 73 + 1 + 73 + 1 + 32 + 1 + OfferedHtlcScriptSize
|
||||
OfferedHtlcSuccessWitnessSize = 1 + 1 + 73 + 1 + 32 + 1 + OfferedHtlcScriptSize
|
||||
|
||||
// OfferedHtlcTimeoutWitnessSize 285 bytes
|
||||
// - number_of_witness_elements: 1 byte
|
||||
// - nil_length: 1 byte
|
||||
// - sig_alice_length: 1 byte
|
||||
// - sig_alice: 73 bytes
|
||||
// - sig_bob_length: 1 byte
|
||||
// - sig_bob: 73 bytes
|
||||
// - nil_length: 1 byte
|
||||
// - witness_script_length: 1 byte
|
||||
// - witness_script (offered_htlc_script)
|
||||
OfferedHtlcTimeoutWitnessSize = 1 + 1 + 1 + 73 + 1 + 73 + 1 + 1 + OfferedHtlcScriptSize
|
||||
|
||||
// OfferedHtlcPenaltyWitnessSize 246 bytes
|
||||
// - number_of_witness_elements: 1 byte
|
||||
@ -408,47 +429,25 @@ const (
|
||||
// - witness_script_length: 1 byte
|
||||
// - witness_script (offered_htlc_script)
|
||||
OfferedHtlcPenaltyWitnessSize = 1 + 1 + 73 + 1 + 33 + 1 + OfferedHtlcScriptSize
|
||||
)
|
||||
|
||||
// dummySigner is a fake signer used for size (upper bound) calculations.
|
||||
type dummySigner struct {
|
||||
Signer
|
||||
}
|
||||
|
||||
// SignOutputRaw generates a signature for the passed transaction according to
|
||||
// the data within the passed SignDescriptor.
|
||||
func (s *dummySigner) SignOutputRaw(tx *wire.MsgTx, signDesc *SignDescriptor) (
|
||||
[]byte, error) {
|
||||
|
||||
// Always return worst-case signature length, excluding the one byte
|
||||
// sighash flag.
|
||||
return make([]byte, 73-1), nil
|
||||
}
|
||||
|
||||
var (
|
||||
// dummyPubKey is a pubkey used in script size calculation.
|
||||
dummyPubKey = btcec.PublicKey{
|
||||
X: &big.Int{},
|
||||
Y: &big.Int{},
|
||||
}
|
||||
|
||||
// dummyAnchorScript is a script used for size calculation.
|
||||
dummyAnchorScript, _ = CommitScriptAnchor(&dummyPubKey)
|
||||
|
||||
// dummyAnchorWitness is a witness used for size calculation.
|
||||
dummyAnchorWitness, _ = CommitSpendAnchor(
|
||||
&dummySigner{},
|
||||
&SignDescriptor{
|
||||
KeyDesc: keychain.KeyDescriptor{
|
||||
PubKey: &dummyPubKey,
|
||||
},
|
||||
WitnessScript: dummyAnchorScript,
|
||||
},
|
||||
nil,
|
||||
)
|
||||
// AnchorScriptSize 40 bytes
|
||||
// - pubkey_length: 1 byte
|
||||
// - pubkey: 33 bytes
|
||||
// - OP_CHECKSIG: 1 byte
|
||||
// - OP_IFDUP: 1 byte
|
||||
// - OP_NOTIF: 1 byte
|
||||
// - OP_16: 1 byte
|
||||
// - OP_CSV 1 byte
|
||||
// - OP_ENDIF: 1 byte
|
||||
AnchorScriptSize = 1 + 33 + 6*1
|
||||
|
||||
// AnchorWitnessSize 116 bytes
|
||||
AnchorWitnessSize = dummyAnchorWitness.SerializeSize()
|
||||
// - number_of_witnes_elements: 1 byte
|
||||
// - signature_length: 1 byte
|
||||
// - signature: 73 bytes
|
||||
// - witness_script_length: 1 byte
|
||||
// - witness_script (anchor_script)
|
||||
AnchorWitnessSize = 1 + 1 + 73 + 1 + AnchorScriptSize
|
||||
)
|
||||
|
||||
// EstimateCommitTxWeight estimate commitment transaction weight depending on
|
||||
|
@ -1,15 +1,45 @@
|
||||
package input_test
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
"github.com/btcsuite/btcd/blockchain"
|
||||
"github.com/btcsuite/btcd/btcec"
|
||||
"github.com/btcsuite/btcd/chaincfg"
|
||||
"github.com/btcsuite/btcd/txscript"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/btcsuite/btcutil"
|
||||
|
||||
"github.com/lightningnetwork/lnd/input"
|
||||
"github.com/lightningnetwork/lnd/keychain"
|
||||
)
|
||||
|
||||
const (
|
||||
testCSVDelay = (1 << 31) - 1
|
||||
|
||||
testCLTVExpiry = 500000000
|
||||
|
||||
// maxDERSignatureSize is the largest possible DER-encoded signature
|
||||
// without the trailing sighash flag.
|
||||
maxDERSignatureSize = 72
|
||||
)
|
||||
|
||||
var (
|
||||
testPubkeyBytes = make([]byte, 33)
|
||||
|
||||
testHash160 = make([]byte, 20)
|
||||
testPreimage = make([]byte, 32)
|
||||
|
||||
// testPubkey is a pubkey used in script size calculation.
|
||||
testPubkey = &btcec.PublicKey{
|
||||
X: &big.Int{},
|
||||
Y: &big.Int{},
|
||||
}
|
||||
|
||||
testPrivkey, _ = btcec.PrivKeyFromBytes(btcec.S256(), make([]byte, 32))
|
||||
|
||||
testTx = wire.NewMsgTx(2)
|
||||
)
|
||||
|
||||
// TestTxWeightEstimator tests that transaction weight estimates are calculated
|
||||
@ -204,7 +234,7 @@ func TestTxWeightEstimator(t *testing.T) {
|
||||
for j := 0; j < test.numP2PKHInputs; j++ {
|
||||
weightEstimate.AddP2PKHInput()
|
||||
|
||||
signature := make([]byte, 73)
|
||||
signature := make([]byte, maxDERSignatureSize+1)
|
||||
compressedPubKey := make([]byte, 33)
|
||||
scriptSig, err := txscript.NewScriptBuilder().AddData(signature).
|
||||
AddData(compressedPubKey).Script()
|
||||
@ -217,7 +247,7 @@ func TestTxWeightEstimator(t *testing.T) {
|
||||
for j := 0; j < test.numP2WKHInputs; j++ {
|
||||
weightEstimate.AddP2WKHInput()
|
||||
|
||||
signature := make([]byte, 73)
|
||||
signature := make([]byte, maxDERSignatureSize+1)
|
||||
compressedPubKey := make([]byte, 33)
|
||||
witness := wire.TxWitness{signature, compressedPubKey}
|
||||
tx.AddTxIn(&wire.TxIn{Witness: witness})
|
||||
@ -232,7 +262,7 @@ func TestTxWeightEstimator(t *testing.T) {
|
||||
for j := 0; j < test.numNestedP2WKHInputs; j++ {
|
||||
weightEstimate.AddNestedP2WKHInput()
|
||||
|
||||
signature := make([]byte, 73)
|
||||
signature := make([]byte, maxDERSignatureSize+1)
|
||||
compressedPubKey := make([]byte, 33)
|
||||
witness := wire.TxWitness{signature, compressedPubKey}
|
||||
scriptSig, err := txscript.NewScriptBuilder().AddData(p2wkhScript).
|
||||
@ -281,10 +311,537 @@ func TestTxWeightEstimator(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestSizes guards calculated constants to make sure their values remain
|
||||
// unchanged.
|
||||
func TestSizes(t *testing.T) {
|
||||
if input.AnchorWitnessSize != 116 {
|
||||
t.Fatal("unexpected anchor witness size")
|
||||
type maxDERSignature struct{}
|
||||
|
||||
func (s *maxDERSignature) Serialize() []byte {
|
||||
// Always return worst-case signature length, excluding the one byte
|
||||
// sighash flag.
|
||||
return make([]byte, maxDERSignatureSize)
|
||||
}
|
||||
|
||||
func (s *maxDERSignature) Verify(_ []byte, _ *btcec.PublicKey) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// dummySigner is a fake signer used for size (upper bound) calculations.
|
||||
type dummySigner struct {
|
||||
input.Signer
|
||||
}
|
||||
|
||||
// SignOutputRaw generates a signature for the passed transaction according to
|
||||
// the data within the passed SignDescriptor.
|
||||
func (s *dummySigner) SignOutputRaw(tx *wire.MsgTx,
|
||||
signDesc *input.SignDescriptor) (input.Signature, error) {
|
||||
|
||||
return &maxDERSignature{}, nil
|
||||
}
|
||||
|
||||
type witnessSizeTest struct {
|
||||
name string
|
||||
expSize int
|
||||
genWitness func(t *testing.T) wire.TxWitness
|
||||
}
|
||||
|
||||
var witnessSizeTests = []witnessSizeTest{
|
||||
{
|
||||
name: "funding",
|
||||
expSize: input.MultiSigWitnessSize,
|
||||
genWitness: func(t *testing.T) wire.TxWitness {
|
||||
witnessScript, _, err := input.GenFundingPkScript(
|
||||
testPubkeyBytes, testPubkeyBytes, 1,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
return input.SpendMultiSig(
|
||||
witnessScript,
|
||||
testPubkeyBytes, &maxDERSignature{},
|
||||
testPubkeyBytes, &maxDERSignature{},
|
||||
)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "to local timeout",
|
||||
expSize: input.ToLocalTimeoutWitnessSize,
|
||||
genWitness: func(t *testing.T) wire.TxWitness {
|
||||
witnessScript, err := input.CommitScriptToSelf(
|
||||
testCSVDelay, testPubkey, testPubkey,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
signDesc := &input.SignDescriptor{
|
||||
WitnessScript: witnessScript,
|
||||
}
|
||||
|
||||
witness, err := input.CommitSpendTimeout(
|
||||
&dummySigner{}, signDesc, testTx,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
return witness
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "to local revoke",
|
||||
expSize: input.ToLocalPenaltyWitnessSize,
|
||||
genWitness: func(t *testing.T) wire.TxWitness {
|
||||
witnessScript, err := input.CommitScriptToSelf(
|
||||
testCSVDelay, testPubkey, testPubkey,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
signDesc := &input.SignDescriptor{
|
||||
WitnessScript: witnessScript,
|
||||
}
|
||||
|
||||
witness, err := input.CommitSpendRevoke(
|
||||
&dummySigner{}, signDesc, testTx,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
return witness
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "to remote confirmed",
|
||||
expSize: input.ToRemoteConfirmedWitnessSize,
|
||||
genWitness: func(t *testing.T) wire.TxWitness {
|
||||
witScript, err := input.CommitScriptToRemoteConfirmed(
|
||||
testPubkey,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
signDesc := &input.SignDescriptor{
|
||||
WitnessScript: witScript,
|
||||
KeyDesc: keychain.KeyDescriptor{
|
||||
PubKey: testPubkey,
|
||||
},
|
||||
}
|
||||
|
||||
witness, err := input.CommitSpendToRemoteConfirmed(
|
||||
&dummySigner{}, signDesc, testTx,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
return witness
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "anchor",
|
||||
expSize: input.AnchorWitnessSize,
|
||||
genWitness: func(t *testing.T) wire.TxWitness {
|
||||
witScript, err := input.CommitScriptAnchor(
|
||||
testPubkey,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
signDesc := &input.SignDescriptor{
|
||||
WitnessScript: witScript,
|
||||
KeyDesc: keychain.KeyDescriptor{
|
||||
PubKey: testPubkey,
|
||||
},
|
||||
}
|
||||
|
||||
witness, err := input.CommitSpendAnchor(
|
||||
&dummySigner{}, signDesc, testTx,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
return witness
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "anchor anyone",
|
||||
expSize: 43,
|
||||
genWitness: func(t *testing.T) wire.TxWitness {
|
||||
witScript, err := input.CommitScriptAnchor(
|
||||
testPubkey,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
witness, _ := input.CommitSpendAnchorAnyone(witScript)
|
||||
|
||||
return witness
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "offered htlc revoke",
|
||||
expSize: input.OfferedHtlcPenaltyWitnessSize - 3,
|
||||
genWitness: func(t *testing.T) wire.TxWitness {
|
||||
witScript, err := input.SenderHTLCScript(
|
||||
testPubkey, testPubkey, testPubkey,
|
||||
testHash160, false,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
signDesc := &input.SignDescriptor{
|
||||
WitnessScript: witScript,
|
||||
KeyDesc: keychain.KeyDescriptor{
|
||||
PubKey: testPubkey,
|
||||
},
|
||||
DoubleTweak: testPrivkey,
|
||||
}
|
||||
|
||||
witness, err := input.SenderHtlcSpendRevoke(
|
||||
&dummySigner{}, signDesc, testTx,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
return witness
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "offered htlc revoke confirmed",
|
||||
expSize: input.OfferedHtlcPenaltyWitnessSize,
|
||||
genWitness: func(t *testing.T) wire.TxWitness {
|
||||
hash := make([]byte, 20)
|
||||
|
||||
witScript, err := input.SenderHTLCScript(
|
||||
testPubkey, testPubkey, testPubkey,
|
||||
hash, true,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
signDesc := &input.SignDescriptor{
|
||||
WitnessScript: witScript,
|
||||
KeyDesc: keychain.KeyDescriptor{
|
||||
PubKey: testPubkey,
|
||||
},
|
||||
DoubleTweak: testPrivkey,
|
||||
}
|
||||
|
||||
witness, err := input.SenderHtlcSpendRevoke(
|
||||
&dummySigner{}, signDesc, testTx,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
return witness
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "offered htlc timeout",
|
||||
expSize: input.OfferedHtlcTimeoutWitnessSize - 3,
|
||||
genWitness: func(t *testing.T) wire.TxWitness {
|
||||
witScript, err := input.SenderHTLCScript(
|
||||
testPubkey, testPubkey, testPubkey,
|
||||
testHash160, false,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
signDesc := &input.SignDescriptor{
|
||||
WitnessScript: witScript,
|
||||
}
|
||||
|
||||
witness, err := input.SenderHtlcSpendTimeout(
|
||||
&maxDERSignature{}, txscript.SigHashAll,
|
||||
&dummySigner{}, signDesc, testTx,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
return witness
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "offered htlc timeout confirmed",
|
||||
expSize: input.OfferedHtlcTimeoutWitnessSize,
|
||||
genWitness: func(t *testing.T) wire.TxWitness {
|
||||
witScript, err := input.SenderHTLCScript(
|
||||
testPubkey, testPubkey, testPubkey,
|
||||
testHash160, true,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
signDesc := &input.SignDescriptor{
|
||||
WitnessScript: witScript,
|
||||
}
|
||||
|
||||
witness, err := input.SenderHtlcSpendTimeout(
|
||||
&maxDERSignature{}, txscript.SigHashAll,
|
||||
&dummySigner{}, signDesc, testTx,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
return witness
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "offered htlc success",
|
||||
expSize: input.OfferedHtlcSuccessWitnessSize - 3,
|
||||
genWitness: func(t *testing.T) wire.TxWitness {
|
||||
witScript, err := input.SenderHTLCScript(
|
||||
testPubkey, testPubkey, testPubkey,
|
||||
testHash160, false,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
signDesc := &input.SignDescriptor{
|
||||
WitnessScript: witScript,
|
||||
}
|
||||
|
||||
witness, err := input.SenderHtlcSpendRedeem(
|
||||
&dummySigner{}, signDesc, testTx, testPreimage,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
return witness
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "offered htlc success confirmed",
|
||||
expSize: input.OfferedHtlcSuccessWitnessSize,
|
||||
genWitness: func(t *testing.T) wire.TxWitness {
|
||||
witScript, err := input.SenderHTLCScript(
|
||||
testPubkey, testPubkey, testPubkey,
|
||||
testHash160, true,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
signDesc := &input.SignDescriptor{
|
||||
WitnessScript: witScript,
|
||||
}
|
||||
|
||||
witness, err := input.SenderHtlcSpendRedeem(
|
||||
&dummySigner{}, signDesc, testTx, testPreimage,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
return witness
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "accepted htlc revoke",
|
||||
expSize: input.AcceptedHtlcPenaltyWitnessSize - 3,
|
||||
genWitness: func(t *testing.T) wire.TxWitness {
|
||||
witScript, err := input.ReceiverHTLCScript(
|
||||
testCLTVExpiry, testPubkey, testPubkey,
|
||||
testPubkey, testHash160, false,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
signDesc := &input.SignDescriptor{
|
||||
WitnessScript: witScript,
|
||||
KeyDesc: keychain.KeyDescriptor{
|
||||
PubKey: testPubkey,
|
||||
},
|
||||
DoubleTweak: testPrivkey,
|
||||
}
|
||||
|
||||
witness, err := input.ReceiverHtlcSpendRevoke(
|
||||
&dummySigner{}, signDesc, testTx,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
return witness
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "accepted htlc revoke confirmed",
|
||||
expSize: input.AcceptedHtlcPenaltyWitnessSize,
|
||||
genWitness: func(t *testing.T) wire.TxWitness {
|
||||
witScript, err := input.ReceiverHTLCScript(
|
||||
testCLTVExpiry, testPubkey, testPubkey,
|
||||
testPubkey, testHash160, true,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
signDesc := &input.SignDescriptor{
|
||||
WitnessScript: witScript,
|
||||
KeyDesc: keychain.KeyDescriptor{
|
||||
PubKey: testPubkey,
|
||||
},
|
||||
DoubleTweak: testPrivkey,
|
||||
}
|
||||
|
||||
witness, err := input.ReceiverHtlcSpendRevoke(
|
||||
&dummySigner{}, signDesc, testTx,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
return witness
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "accepted htlc timeout",
|
||||
expSize: input.AcceptedHtlcTimeoutWitnessSize - 3,
|
||||
genWitness: func(t *testing.T) wire.TxWitness {
|
||||
|
||||
witScript, err := input.ReceiverHTLCScript(
|
||||
testCLTVExpiry, testPubkey, testPubkey,
|
||||
testPubkey, testHash160, false,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
signDesc := &input.SignDescriptor{
|
||||
WitnessScript: witScript,
|
||||
}
|
||||
|
||||
witness, err := input.ReceiverHtlcSpendTimeout(
|
||||
&dummySigner{}, signDesc, testTx,
|
||||
testCLTVExpiry,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
return witness
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "accepted htlc timeout confirmed",
|
||||
expSize: input.AcceptedHtlcTimeoutWitnessSize,
|
||||
genWitness: func(t *testing.T) wire.TxWitness {
|
||||
witScript, err := input.ReceiverHTLCScript(
|
||||
testCLTVExpiry, testPubkey, testPubkey,
|
||||
testPubkey, testHash160, true,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
signDesc := &input.SignDescriptor{
|
||||
WitnessScript: witScript,
|
||||
}
|
||||
|
||||
witness, err := input.ReceiverHtlcSpendTimeout(
|
||||
&dummySigner{}, signDesc, testTx,
|
||||
testCLTVExpiry,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
return witness
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "accepted htlc success",
|
||||
expSize: input.AcceptedHtlcSuccessWitnessSize - 3,
|
||||
genWitness: func(t *testing.T) wire.TxWitness {
|
||||
witScript, err := input.ReceiverHTLCScript(
|
||||
testCLTVExpiry, testPubkey, testPubkey,
|
||||
testPubkey, testHash160, false,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
signDesc := &input.SignDescriptor{
|
||||
WitnessScript: witScript,
|
||||
KeyDesc: keychain.KeyDescriptor{
|
||||
PubKey: testPubkey,
|
||||
},
|
||||
}
|
||||
|
||||
witness, err := input.ReceiverHtlcSpendRedeem(
|
||||
&maxDERSignature{}, txscript.SigHashAll,
|
||||
testPreimage, &dummySigner{}, signDesc, testTx,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
return witness
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "accepted htlc success confirmed",
|
||||
expSize: input.AcceptedHtlcSuccessWitnessSize,
|
||||
genWitness: func(t *testing.T) wire.TxWitness {
|
||||
witScript, err := input.ReceiverHTLCScript(
|
||||
testCLTVExpiry, testPubkey, testPubkey,
|
||||
testPubkey, testHash160, true,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
signDesc := &input.SignDescriptor{
|
||||
WitnessScript: witScript,
|
||||
KeyDesc: keychain.KeyDescriptor{
|
||||
PubKey: testPubkey,
|
||||
},
|
||||
}
|
||||
|
||||
witness, err := input.ReceiverHtlcSpendRedeem(
|
||||
&maxDERSignature{}, txscript.SigHashAll,
|
||||
testPreimage, &dummySigner{}, signDesc, testTx,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
return witness
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// TestWitnessSizes asserts the correctness of our magic witness constants.
|
||||
// Witnesses involving signatures will have maxDERSignatures injected so that we
|
||||
// can determine upper bounds for the witness sizes. These constants are
|
||||
// predominately used for fee estimation, so we want to be certain that we
|
||||
// aren't under estimating or our transactions could get stuck.
|
||||
func TestWitnessSizes(t *testing.T) {
|
||||
for _, test := range witnessSizeTests {
|
||||
test := test
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
size := test.genWitness(t).SerializeSize()
|
||||
if size != test.expSize {
|
||||
t.Fatalf("size mismatch, want: %v, got: %v",
|
||||
test.expSize, size)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -50,7 +50,9 @@ type MockSigner struct {
|
||||
|
||||
// SignOutputRaw generates a signature for the passed transaction according to
|
||||
// the data within the passed SignDescriptor.
|
||||
func (m *MockSigner) SignOutputRaw(tx *wire.MsgTx, signDesc *SignDescriptor) ([]byte, error) {
|
||||
func (m *MockSigner) SignOutputRaw(tx *wire.MsgTx,
|
||||
signDesc *SignDescriptor) (Signature, error) {
|
||||
|
||||
pubkey := signDesc.KeyDesc.PubKey
|
||||
switch {
|
||||
case signDesc.SingleTweak != nil:
|
||||
@ -72,7 +74,7 @@ func (m *MockSigner) SignOutputRaw(tx *wire.MsgTx, signDesc *SignDescriptor) ([]
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return sig[:len(sig)-1], nil
|
||||
return btcec.ParseDERSignature(sig[:len(sig)-1], btcec.S256())
|
||||
}
|
||||
|
||||
// ComputeInputScript generates a complete InputIndex for the passed transaction
|
||||
|
@ -321,7 +321,7 @@ func (s *Server) SignOutputRaw(ctx context.Context, in *SignReq) (*SignResp, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp.RawSigs[i] = sig
|
||||
resp.RawSigs[i] = sig.Serialize()
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
|
@ -225,7 +225,7 @@ func maybeTweakPrivKey(signDesc *input.SignDescriptor,
|
||||
//
|
||||
// This is a part of the WalletController interface.
|
||||
func (b *BtcWallet) SignOutputRaw(tx *wire.MsgTx,
|
||||
signDesc *input.SignDescriptor) ([]byte, error) {
|
||||
signDesc *input.SignDescriptor) (input.Signature, error) {
|
||||
|
||||
witnessScript := signDesc.WitnessScript
|
||||
|
||||
@ -256,7 +256,7 @@ func (b *BtcWallet) SignOutputRaw(tx *wire.MsgTx,
|
||||
}
|
||||
|
||||
// Chop off the sighash flag at the end of the signature.
|
||||
return sig[:len(sig)-1], nil
|
||||
return btcec.ParseDERSignature(sig[:len(sig)-1], btcec.S256())
|
||||
}
|
||||
|
||||
// ComputeInputScript generates a complete InputScript for the passed
|
||||
@ -358,7 +358,7 @@ var _ input.Signer = (*BtcWallet)(nil)
|
||||
//
|
||||
// NOTE: This is a part of the MessageSigner interface.
|
||||
func (b *BtcWallet) SignMessage(pubKey *btcec.PublicKey,
|
||||
msg []byte) (*btcec.Signature, error) {
|
||||
msg []byte) (input.Signature, error) {
|
||||
|
||||
// First attempt to fetch the private key which corresponds to the
|
||||
// specified public key.
|
||||
|
@ -3402,7 +3402,7 @@ func (lc *LightningChannel) SignNextCommitment() (lnwire.Sig, []lnwire.Sig, []ch
|
||||
close(cancelChan)
|
||||
return sig, htlcSigs, nil, err
|
||||
}
|
||||
sig, err = lnwire.NewSigFromRawSignature(rawSig)
|
||||
sig, err = lnwire.NewSigFromSignature(rawSig)
|
||||
if err != nil {
|
||||
close(cancelChan)
|
||||
return sig, htlcSigs, nil, err
|
||||
@ -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, 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.
|
||||
@ -5459,11 +5463,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 +5594,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
|
||||
@ -5941,7 +5954,8 @@ func NewLocalForceCloseSummary(chanState *channeldb.OpenChannel, signer input.Si
|
||||
// settle any in flight.
|
||||
func (lc *LightningChannel) CreateCloseProposal(proposedFee btcutil.Amount,
|
||||
localDeliveryScript []byte,
|
||||
remoteDeliveryScript []byte) ([]byte, *chainhash.Hash, btcutil.Amount, error) {
|
||||
remoteDeliveryScript []byte) (input.Signature, *chainhash.Hash,
|
||||
btcutil.Amount, error) {
|
||||
|
||||
lc.Lock()
|
||||
defer lc.Unlock()
|
||||
@ -6007,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) {
|
||||
|
||||
@ -6060,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, 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, 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, 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, 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, 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, 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, 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, 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,
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/btcsuite/btcutil"
|
||||
"github.com/btcsuite/btcwallet/wallet/txauthor"
|
||||
"github.com/lightningnetwork/lnd/input"
|
||||
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
|
||||
)
|
||||
|
||||
@ -292,7 +293,7 @@ type MessageSigner interface {
|
||||
// that corresponds to the passed public key. If the target private key
|
||||
// is unable to be found, then an error will be returned. The actual
|
||||
// digest signed is the double SHA-256 of the passed message.
|
||||
SignMessage(pubKey *btcec.PublicKey, msg []byte) (*btcec.Signature, error)
|
||||
SignMessage(pubKey *btcec.PublicKey, msg []byte) (input.Signature, error)
|
||||
}
|
||||
|
||||
// WalletDriver represents a "driver" for a particular concrete
|
||||
|
@ -38,6 +38,7 @@ import (
|
||||
"github.com/lightningnetwork/lnd/channeldb/kvdb"
|
||||
"github.com/lightningnetwork/lnd/input"
|
||||
"github.com/lightningnetwork/lnd/keychain"
|
||||
"github.com/lightningnetwork/lnd/lntest/wait"
|
||||
"github.com/lightningnetwork/lnd/lnwallet"
|
||||
"github.com/lightningnetwork/lnd/lnwallet/btcwallet"
|
||||
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
|
||||
@ -1590,7 +1591,7 @@ func txFromOutput(tx *wire.MsgTx, signer input.Signer, fromPubKey,
|
||||
return nil, fmt.Errorf("unable to generate signature: %v", err)
|
||||
}
|
||||
witness := make([][]byte, 2)
|
||||
witness[0] = append(spendSig, byte(txscript.SigHashAll))
|
||||
witness[0] = append(spendSig.Serialize(), byte(txscript.SigHashAll))
|
||||
witness[1] = fromPubKey.SerializeCompressed()
|
||||
tx1.TxIn[0].Witness = witness
|
||||
|
||||
@ -1975,7 +1976,7 @@ func testSignOutputUsingTweaks(r *rpctest.Harness,
|
||||
t.Fatalf("unable to generate signature: %v", err)
|
||||
}
|
||||
witness := make([][]byte, 2)
|
||||
witness[0] = append(spendSig, byte(txscript.SigHashAll))
|
||||
witness[0] = append(spendSig.Serialize(), byte(txscript.SigHashAll))
|
||||
witness[1] = tweakedKey.SerializeCompressed()
|
||||
sweepTx.TxIn[0].Witness = witness
|
||||
|
||||
@ -3062,18 +3063,22 @@ func runTests(t *testing.T, walletDriver *lnwallet.WalletDriver,
|
||||
defer bitcoind.Process.Kill()
|
||||
|
||||
// Wait for the bitcoind instance to start up.
|
||||
time.Sleep(time.Second)
|
||||
|
||||
host := fmt.Sprintf("127.0.0.1:%d", rpcPort)
|
||||
chainConn, err := chain.NewBitcoindConn(
|
||||
netParams, host, "weks", "weks", zmqBlockHost,
|
||||
zmqTxHost, 100*time.Millisecond,
|
||||
var chainConn *chain.BitcoindConn
|
||||
err = wait.NoError(func() error {
|
||||
chainConn, err = chain.NewBitcoindConn(
|
||||
netParams, host, "weks", "weks",
|
||||
zmqBlockHost, zmqTxHost,
|
||||
100*time.Millisecond,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to establish connection to "+
|
||||
"bitcoind: %v", err)
|
||||
return err
|
||||
}
|
||||
if err := chainConn.Start(); err != nil {
|
||||
|
||||
return chainConn.Start()
|
||||
}, 10*time.Second)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to establish connection to "+
|
||||
"bitcoind: %v", err)
|
||||
}
|
||||
|
@ -134,8 +134,8 @@ type ChannelReservation struct {
|
||||
theirFundingInputScripts []*input.Script
|
||||
|
||||
// Our signature for their version of the commitment transaction.
|
||||
ourCommitmentSig []byte
|
||||
theirCommitmentSig []byte
|
||||
ourCommitmentSig input.Signature
|
||||
theirCommitmentSig input.Signature
|
||||
|
||||
ourContribution *ChannelContribution
|
||||
theirContribution *ChannelContribution
|
||||
@ -538,7 +538,9 @@ func (r *ChannelReservation) TheirContribution() *ChannelContribution {
|
||||
//
|
||||
// NOTE: These signatures will only be populated after a call to
|
||||
// .ProcessContribution()
|
||||
func (r *ChannelReservation) OurSignatures() ([]*input.Script, []byte) {
|
||||
func (r *ChannelReservation) OurSignatures() ([]*input.Script,
|
||||
input.Signature) {
|
||||
|
||||
r.RLock()
|
||||
defer r.RUnlock()
|
||||
return r.ourFundingInputScripts, r.ourCommitmentSig
|
||||
@ -558,7 +560,7 @@ func (r *ChannelReservation) OurSignatures() ([]*input.Script, []byte) {
|
||||
// confirmations. Once the method unblocks, a LightningChannel instance is
|
||||
// returned, marking the channel available for updates.
|
||||
func (r *ChannelReservation) CompleteReservation(fundingInputScripts []*input.Script,
|
||||
commitmentSig []byte) (*channeldb.OpenChannel, error) {
|
||||
commitmentSig input.Signature) (*channeldb.OpenChannel, error) {
|
||||
|
||||
// TODO(roasbeef): add flag for watch or not?
|
||||
errChan := make(chan error, 1)
|
||||
@ -585,7 +587,7 @@ func (r *ChannelReservation) CompleteReservation(fundingInputScripts []*input.Sc
|
||||
// called as a response to a single funder channel, only a commitment signature
|
||||
// will be populated.
|
||||
func (r *ChannelReservation) CompleteReservationSingle(fundingPoint *wire.OutPoint,
|
||||
commitSig []byte) (*channeldb.OpenChannel, error) {
|
||||
commitSig input.Signature) (*channeldb.OpenChannel, error) {
|
||||
|
||||
errChan := make(chan error, 1)
|
||||
completeChan := make(chan *channeldb.OpenChannel, 1)
|
||||
@ -608,7 +610,9 @@ func (r *ChannelReservation) CompleteReservationSingle(fundingPoint *wire.OutPoi
|
||||
//
|
||||
// NOTE: These attributes will be unpopulated before a call to
|
||||
// .CompleteReservation().
|
||||
func (r *ChannelReservation) TheirSignatures() ([]*input.Script, []byte) {
|
||||
func (r *ChannelReservation) TheirSignatures() ([]*input.Script,
|
||||
input.Signature) {
|
||||
|
||||
r.RLock()
|
||||
defer r.RUnlock()
|
||||
return r.theirFundingInputScripts, r.theirCommitmentSig
|
||||
|
@ -205,7 +205,7 @@ func (s *SigPool) poolWorker() {
|
||||
}
|
||||
}
|
||||
|
||||
sig, err := lnwire.NewSigFromRawSignature(rawSig)
|
||||
sig, err := lnwire.NewSigFromSignature(rawSig)
|
||||
select {
|
||||
case sigMsg.Resp <- SignJobResp{
|
||||
Sig: sig,
|
||||
|
@ -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
|
||||
|
@ -215,7 +215,7 @@ type addCounterPartySigsMsg struct {
|
||||
|
||||
// This should be 1/2 of the signatures needed to successfully spend our
|
||||
// version of the commitment transaction.
|
||||
theirCommitmentSig []byte
|
||||
theirCommitmentSig input.Signature
|
||||
|
||||
// This channel is used to return the completed channel after the wallet
|
||||
// has completed all of its stages in the funding process.
|
||||
@ -240,7 +240,7 @@ type addSingleFunderSigsMsg struct {
|
||||
|
||||
// theirCommitmentSig are the 1/2 of the signatures needed to
|
||||
// successfully spend our version of the commitment transaction.
|
||||
theirCommitmentSig []byte
|
||||
theirCommitmentSig input.Signature
|
||||
|
||||
// This channel is used to return the completed channel after the wallet
|
||||
// has completed all of its stages in the funding process.
|
||||
@ -1406,18 +1406,13 @@ func (l *LightningWallet) handleFundingCounterPartySigs(msg *addCounterPartySigs
|
||||
|
||||
// Verify that we've received a valid signature from the remote party
|
||||
// for our version of the commitment transaction.
|
||||
theirCommitSig := msg.theirCommitmentSig
|
||||
sig, err := btcec.ParseSignature(theirCommitSig, btcec.S256())
|
||||
if err != nil {
|
||||
msg.err <- err
|
||||
msg.completeChan <- nil
|
||||
return
|
||||
} else if !sig.Verify(sigHash, theirKey.PubKey) {
|
||||
if !msg.theirCommitmentSig.Verify(sigHash, theirKey.PubKey) {
|
||||
msg.err <- fmt.Errorf("counterparty's commitment signature is invalid")
|
||||
msg.completeChan <- nil
|
||||
return
|
||||
}
|
||||
res.partialState.LocalCommitment.CommitSig = theirCommitSig
|
||||
theirCommitSigBytes := msg.theirCommitmentSig.Serialize()
|
||||
res.partialState.LocalCommitment.CommitSig = theirCommitSigBytes
|
||||
|
||||
// Funding complete, this entry can be removed from limbo.
|
||||
l.limboMtx.Lock()
|
||||
@ -1566,19 +1561,14 @@ func (l *LightningWallet) handleSingleFunderSigs(req *addSingleFunderSigsMsg) {
|
||||
|
||||
// Verify that we've received a valid signature from the remote party
|
||||
// for our version of the commitment transaction.
|
||||
sig, err := btcec.ParseSignature(req.theirCommitmentSig, btcec.S256())
|
||||
if err != nil {
|
||||
req.err <- err
|
||||
req.completeChan <- nil
|
||||
return
|
||||
}
|
||||
if !sig.Verify(sigHash, theirKey.PubKey) {
|
||||
if !req.theirCommitmentSig.Verify(sigHash, theirKey.PubKey) {
|
||||
req.err <- fmt.Errorf("counterparty's commitment signature " +
|
||||
"is invalid")
|
||||
req.completeChan <- nil
|
||||
return
|
||||
}
|
||||
chanState.LocalCommitment.CommitSig = req.theirCommitmentSig
|
||||
theirCommitSigBytes := req.theirCommitmentSig.Serialize()
|
||||
chanState.LocalCommitment.CommitSig = theirCommitSigBytes
|
||||
|
||||
// With their signature for our version of the commitment transactions
|
||||
// verified, we can now generate a signature for their version,
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/btcsuite/btcd/btcec"
|
||||
"github.com/lightningnetwork/lnd/input"
|
||||
)
|
||||
|
||||
// Sig is a fixed-sized ECDSA signature. Unlike Bitcoin, we use fixed sized
|
||||
@ -64,7 +65,7 @@ func NewSigFromRawSignature(sig []byte) (Sig, error) {
|
||||
|
||||
// NewSigFromSignature creates a new signature as used on the wire, from an
|
||||
// existing btcec.Signature.
|
||||
func NewSigFromSignature(e *btcec.Signature) (Sig, error) {
|
||||
func NewSigFromSignature(e input.Signature) (Sig, error) {
|
||||
if e == nil {
|
||||
return Sig{}, fmt.Errorf("cannot decode empty signature")
|
||||
}
|
||||
|
4
mock.go
4
mock.go
@ -33,7 +33,7 @@ type mockSigner struct {
|
||||
}
|
||||
|
||||
func (m *mockSigner) SignOutputRaw(tx *wire.MsgTx,
|
||||
signDesc *input.SignDescriptor) ([]byte, error) {
|
||||
signDesc *input.SignDescriptor) (input.Signature, error) {
|
||||
amt := signDesc.Output.Value
|
||||
witnessScript := signDesc.WitnessScript
|
||||
privKey := m.key
|
||||
@ -58,7 +58,7 @@ func (m *mockSigner) SignOutputRaw(tx *wire.MsgTx,
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return sig[:len(sig)-1], nil
|
||||
return btcec.ParseDERSignature(sig[:len(sig)-1], btcec.S256())
|
||||
}
|
||||
|
||||
func (m *mockSigner) ComputeInputScript(tx *wire.MsgTx,
|
||||
|
@ -6,6 +6,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/btcsuite/btcd/btcec"
|
||||
"github.com/lightningnetwork/lnd/input"
|
||||
"github.com/lightningnetwork/lnd/lnwallet"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"github.com/lightningnetwork/lnd/netann"
|
||||
@ -17,7 +18,7 @@ type mockSigner struct {
|
||||
}
|
||||
|
||||
func (m *mockSigner) SignMessage(pk *btcec.PublicKey,
|
||||
msg []byte) (*btcec.Signature, error) {
|
||||
msg []byte) (input.Signature, error) {
|
||||
|
||||
if m.err != nil {
|
||||
return nil, m.err
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
|
||||
"github.com/btcsuite/btcd/btcec"
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/lightningnetwork/lnd/input"
|
||||
"github.com/lightningnetwork/lnd/lnwallet"
|
||||
)
|
||||
|
||||
@ -31,7 +32,7 @@ func NewNodeSigner(key *btcec.PrivateKey) *NodeSigner {
|
||||
// resident node's private key. If the target public key is _not_ the node's
|
||||
// private key, then an error will be returned.
|
||||
func (n *NodeSigner) SignMessage(pubKey *btcec.PublicKey,
|
||||
msg []byte) (*btcec.Signature, error) {
|
||||
msg []byte) (input.Signature, error) {
|
||||
|
||||
// If this isn't our identity public key, then we'll exit early with an
|
||||
// error as we can't sign with this key.
|
||||
@ -41,12 +42,12 @@ func (n *NodeSigner) SignMessage(pubKey *btcec.PublicKey,
|
||||
|
||||
// Otherwise, we'll sign the dsha256 of the target message.
|
||||
digest := chainhash.DoubleHashB(msg)
|
||||
sign, err := n.privKey.Sign(digest)
|
||||
sig, err := n.privKey.Sign(digest)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("can't sign the message: %v", err)
|
||||
}
|
||||
|
||||
return sign, nil
|
||||
return sig, nil
|
||||
}
|
||||
|
||||
// SignCompact signs a double-sha256 digest of the msg parameter under the
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/btcsuite/btcd/btcec"
|
||||
"github.com/lightningnetwork/lnd/input"
|
||||
"github.com/lightningnetwork/lnd/lnwallet"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
)
|
||||
@ -11,7 +12,7 @@ import (
|
||||
// SignAnnouncement signs any type of gossip message that is announced on the
|
||||
// network.
|
||||
func SignAnnouncement(signer lnwallet.MessageSigner, pubKey *btcec.PublicKey,
|
||||
msg lnwire.Message) (*btcec.Signature, error) {
|
||||
msg lnwire.Message) (input.Signature, error) {
|
||||
|
||||
var (
|
||||
data []byte
|
||||
|
16
peer_test.go
16
peer_test.go
@ -96,7 +96,7 @@ func TestPeerChannelClosureAcceptFeeResponder(t *testing.T) {
|
||||
t.Fatalf("error creating close proposal: %v", err)
|
||||
}
|
||||
|
||||
parsedSig, err := lnwire.NewSigFromRawSignature(initiatorSig)
|
||||
parsedSig, err := lnwire.NewSigFromSignature(initiatorSig)
|
||||
if err != nil {
|
||||
t.Fatalf("error parsing signature: %v", err)
|
||||
}
|
||||
@ -184,7 +184,7 @@ func TestPeerChannelClosureAcceptFeeInitiator(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("unable to create close proposal: %v", err)
|
||||
}
|
||||
parsedSig, err := lnwire.NewSigFromRawSignature(closeSig)
|
||||
parsedSig, err := lnwire.NewSigFromSignature(closeSig)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to parse signature: %v", err)
|
||||
}
|
||||
@ -296,7 +296,7 @@ func TestPeerChannelClosureFeeNegotiationsResponder(t *testing.T) {
|
||||
t.Fatalf("error creating close proposal: %v", err)
|
||||
}
|
||||
|
||||
parsedSig, err := lnwire.NewSigFromRawSignature(initiatorSig)
|
||||
parsedSig, err := lnwire.NewSigFromSignature(initiatorSig)
|
||||
if err != nil {
|
||||
t.Fatalf("error parsing signature: %v", err)
|
||||
}
|
||||
@ -340,7 +340,7 @@ func TestPeerChannelClosureFeeNegotiationsResponder(t *testing.T) {
|
||||
t.Fatalf("error creating close proposal: %v", err)
|
||||
}
|
||||
|
||||
parsedSig, err = lnwire.NewSigFromRawSignature(initiatorSig)
|
||||
parsedSig, err = lnwire.NewSigFromSignature(initiatorSig)
|
||||
if err != nil {
|
||||
t.Fatalf("error parsing signature: %v", err)
|
||||
}
|
||||
@ -385,7 +385,7 @@ func TestPeerChannelClosureFeeNegotiationsResponder(t *testing.T) {
|
||||
t.Fatalf("error creating close proposal: %v", err)
|
||||
}
|
||||
|
||||
parsedSig, err = lnwire.NewSigFromRawSignature(initiatorSig)
|
||||
parsedSig, err = lnwire.NewSigFromSignature(initiatorSig)
|
||||
if err != nil {
|
||||
t.Fatalf("error parsing signature: %v", err)
|
||||
}
|
||||
@ -477,7 +477,7 @@ func TestPeerChannelClosureFeeNegotiationsInitiator(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("unable to create close proposal: %v", err)
|
||||
}
|
||||
parsedSig, err := lnwire.NewSigFromRawSignature(closeSig)
|
||||
parsedSig, err := lnwire.NewSigFromSignature(closeSig)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to parse signature: %v", err)
|
||||
}
|
||||
@ -543,7 +543,7 @@ func TestPeerChannelClosureFeeNegotiationsInitiator(t *testing.T) {
|
||||
t.Fatalf("error creating close proposal: %v", err)
|
||||
}
|
||||
|
||||
parsedSig, err = lnwire.NewSigFromRawSignature(responderSig)
|
||||
parsedSig, err = lnwire.NewSigFromSignature(responderSig)
|
||||
if err != nil {
|
||||
t.Fatalf("error parsing signature: %v", err)
|
||||
}
|
||||
@ -589,7 +589,7 @@ func TestPeerChannelClosureFeeNegotiationsInitiator(t *testing.T) {
|
||||
t.Fatalf("error creating close proposal: %v", err)
|
||||
}
|
||||
|
||||
parsedSig, err = lnwire.NewSigFromRawSignature(responderSig)
|
||||
parsedSig, err = lnwire.NewSigFromSignature(responderSig)
|
||||
if err != nil {
|
||||
t.Fatalf("error parsing signature: %v", err)
|
||||
}
|
||||
|
@ -980,7 +980,7 @@ func newServer(listenAddrs []net.Addr, chanDB *channeldb.DB,
|
||||
Notifier: cc.chainNotifier,
|
||||
FeeEstimator: cc.feeEstimator,
|
||||
SignMessage: func(pubKey *btcec.PublicKey,
|
||||
msg []byte) (*btcec.Signature, error) {
|
||||
msg []byte) (input.Signature, error) {
|
||||
|
||||
if pubKey.IsEqual(privKey.PubKey()) {
|
||||
return s.nodeSigner.SignMessage(pubKey, msg)
|
||||
|
@ -6,6 +6,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/btcsuite/btcd/btcec"
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/lightningnetwork/lnd/chainntnfs"
|
||||
@ -18,13 +19,23 @@ var (
|
||||
mockChainHeight = int32(100)
|
||||
)
|
||||
|
||||
type dummySignature struct{}
|
||||
|
||||
func (s *dummySignature) Serialize() []byte {
|
||||
return []byte{}
|
||||
}
|
||||
|
||||
func (s *dummySignature) Verify(_ []byte, _ *btcec.PublicKey) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
type mockSigner struct {
|
||||
}
|
||||
|
||||
func (m *mockSigner) SignOutputRaw(tx *wire.MsgTx,
|
||||
signDesc *input.SignDescriptor) ([]byte, error) {
|
||||
signDesc *input.SignDescriptor) (input.Signature, error) {
|
||||
|
||||
return []byte{}, nil
|
||||
return &dummySignature{}, nil
|
||||
}
|
||||
|
||||
func (m *mockSigner) ComputeInputScript(tx *wire.MsgTx,
|
||||
|
@ -15,7 +15,7 @@ var (
|
||||
input.HtlcOfferedRemoteTimeout,
|
||||
input.WitnessKeyHash,
|
||||
}
|
||||
expectedWeight = int64(1462)
|
||||
expectedWeight = int64(1463)
|
||||
expectedSummary = "0000000000000000000000000000000000000000000000000000000000000000:10 (CommitmentTimeLock), " +
|
||||
"0000000000000000000000000000000000000000000000000000000000000001:11 (HtlcAcceptedSuccessSecondLevel), " +
|
||||
"0000000000000000000000000000000000000000000000000000000000000002:12 (HtlcOfferedRemoteTimeout), " +
|
||||
|
@ -225,6 +225,12 @@ func (p *JusticeDescriptor) assembleJusticeTxn(txWeight int64,
|
||||
// CreateJusticeTxn computes the justice transaction that sweeps a breaching
|
||||
// commitment transaction. The justice transaction is constructed by assembling
|
||||
// the witnesses using data provided by the client in a prior state update.
|
||||
//
|
||||
// NOTE: An older version of ToLocalPenaltyWitnessSize underestimated the size
|
||||
// of the witness by one byte, which could cause the signature(s) to break if
|
||||
// the tower is reconstructing with the newer constant because the output values
|
||||
// might differ. This method retains that original behavior to not invalidate
|
||||
// historical signatures.
|
||||
func (p *JusticeDescriptor) CreateJusticeTxn() (*wire.MsgTx, error) {
|
||||
var (
|
||||
sweepInputs = make([]*breachedInput, 0, 2)
|
||||
@ -256,7 +262,13 @@ func (p *JusticeDescriptor) CreateJusticeTxn() (*wire.MsgTx, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
weightEstimate.AddWitnessInput(input.ToLocalPenaltyWitnessSize)
|
||||
|
||||
// An older ToLocalPenaltyWitnessSize constant used to underestimate the
|
||||
// size by one byte. The diferrence in weight can cause different output
|
||||
// values on the sweep transaction, so we mimic the original bug to
|
||||
// avoid invalidating signatures by older clients.
|
||||
weightEstimate.AddWitnessInput(input.ToLocalPenaltyWitnessSize - 1)
|
||||
|
||||
sweepInputs = append(sweepInputs, toLocalInput)
|
||||
|
||||
// If the justice kit specifies that we have to sweep the to-remote
|
||||
|
@ -144,7 +144,13 @@ func testJusticeDescriptor(t *testing.T, blobType blob.Type) {
|
||||
|
||||
// Compute the weight estimate for our justice transaction.
|
||||
var weightEstimate input.TxWeightEstimator
|
||||
weightEstimate.AddWitnessInput(input.ToLocalPenaltyWitnessSize)
|
||||
|
||||
// An older ToLocalPenaltyWitnessSize constant used to underestimate the
|
||||
// size by one byte. The diferrence in weight can cause different output
|
||||
// values on the sweep transaction, so we mimic the original bug and
|
||||
// create signatures using the original weight estimate.
|
||||
weightEstimate.AddWitnessInput(input.ToLocalPenaltyWitnessSize - 1)
|
||||
|
||||
weightEstimate.AddWitnessInput(input.P2WKHWitnessSize)
|
||||
weightEstimate.AddP2WKHOutput()
|
||||
if blobType.Has(blob.FlagReward) {
|
||||
@ -262,7 +268,7 @@ func testJusticeDescriptor(t *testing.T, blobType blob.Type) {
|
||||
toRemoteSigRaw := toRemoteWitness[0][:len(toRemoteWitness[0])-1]
|
||||
|
||||
// Convert the DER to-local sig into a fixed-size signature.
|
||||
toLocalSig, err := lnwire.NewSigFromRawSignature(toLocalSigRaw)
|
||||
toLocalSig, err := lnwire.NewSigFromSignature(toLocalSigRaw)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to parse to-local signature: %v", err)
|
||||
}
|
||||
@ -310,7 +316,7 @@ func testJusticeDescriptor(t *testing.T, blobType blob.Type) {
|
||||
|
||||
// Construct the test's to-local witness.
|
||||
justiceTxn.TxIn[0].Witness = make([][]byte, 3)
|
||||
justiceTxn.TxIn[0].Witness[0] = append(toLocalSigRaw,
|
||||
justiceTxn.TxIn[0].Witness[0] = append(toLocalSigRaw.Serialize(),
|
||||
byte(txscript.SigHashAll))
|
||||
justiceTxn.TxIn[0].Witness[1] = []byte{1}
|
||||
justiceTxn.TxIn[0].Witness[2] = toLocalScript
|
||||
|
@ -141,7 +141,14 @@ func (t *backupTask) bindSession(session *wtdb.ClientSessionBody) error {
|
||||
// Next, add the contribution from the inputs that are present on this
|
||||
// breach transaction.
|
||||
if t.toLocalInput != nil {
|
||||
weightEstimate.AddWitnessInput(input.ToLocalPenaltyWitnessSize)
|
||||
// An older ToLocalPenaltyWitnessSize constant used to
|
||||
// underestimate the size by one byte. The diferrence in weight
|
||||
// can cause different output values on the sweep transaction,
|
||||
// so we mimic the original bug and create signatures using the
|
||||
// original weight estimate.
|
||||
weightEstimate.AddWitnessInput(
|
||||
input.ToLocalPenaltyWitnessSize - 1,
|
||||
)
|
||||
}
|
||||
if t.toRemoteInput != nil {
|
||||
weightEstimate.AddWitnessInput(input.P2WKHWitnessSize)
|
||||
|
@ -30,7 +30,7 @@ func NewMockSigner() *MockSigner {
|
||||
// in the sign descriptor. The returned signature is the raw DER-encoded
|
||||
// signature without the signhash flag.
|
||||
func (s *MockSigner) SignOutputRaw(tx *wire.MsgTx,
|
||||
signDesc *input.SignDescriptor) ([]byte, error) {
|
||||
signDesc *input.SignDescriptor) (input.Signature, error) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
@ -50,7 +50,7 @@ func (s *MockSigner) SignOutputRaw(tx *wire.MsgTx,
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return sig[:len(sig)-1], nil
|
||||
return btcec.ParseDERSignature(sig[:len(sig)-1], btcec.S256())
|
||||
}
|
||||
|
||||
// ComputeInputScript is not implemented.
|
||||
|
Loading…
Reference in New Issue
Block a user