input/size: assert witness size constants
This commit introduces a new test case that asserts all of the witness size constants currently in the codebase. We also reintroduce the AcceptedHtlcSuccessWitnessSize and OfferedHtlcTimeoutWitnessSize constants that were recently removed for the sake of completeness. In asserting the witnes sizes, there were three uncovered discrepancies: * OfferedHtlcSuccessWitnessSize overestimated by about 30% because it included an extra signature in the calculation. * ToLocalPenaltyWitnessSize was underestimated by one byte, because it was missing the length byte for the OP_TRUE. This has implications the watchtower protocol since the client and server are assumed to share the same weight estimates used for signing. This commit keeps the current behavior, with the intention of rolling out negotiation for which weight estimate to use for a given session. * AcceptedHtlcScriptSize was underestimated by one byte because it was missing a length byte for the value 32 pushed on the stack when asserting the preimage's length. This affects all AcceptedHtlc* witness sizes.
This commit is contained in:
parent
f2b6e2af04
commit
c1b9b272cd
113
input/size.go
113
input/size.go
@ -1,12 +1,8 @@
|
|||||||
package input
|
package input
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"math/big"
|
|
||||||
|
|
||||||
"github.com/btcsuite/btcd/blockchain"
|
"github.com/btcsuite/btcd/blockchain"
|
||||||
"github.com/btcsuite/btcd/btcec"
|
|
||||||
"github.com/btcsuite/btcd/wire"
|
"github.com/btcsuite/btcd/wire"
|
||||||
"github.com/lightningnetwork/lnd/keychain"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -94,7 +90,7 @@ const (
|
|||||||
// - OP_CHECKMULTISIG: 1 byte
|
// - OP_CHECKMULTISIG: 1 byte
|
||||||
MultiSigSize = 1 + 1 + 33 + 1 + 33 + 1 + 1
|
MultiSigSize = 1 + 1 + 33 + 1 + 33 + 1 + 1
|
||||||
|
|
||||||
// WitnessSize 222 bytes
|
// MultiSigWitnessSize 222 bytes
|
||||||
// - NumberOfWitnessElements: 1 byte
|
// - NumberOfWitnessElements: 1 byte
|
||||||
// - NilLength: 1 byte
|
// - NilLength: 1 byte
|
||||||
// - sigAliceLength: 1 byte
|
// - sigAliceLength: 1 byte
|
||||||
@ -103,7 +99,7 @@ const (
|
|||||||
// - sigBob: 73 bytes
|
// - sigBob: 73 bytes
|
||||||
// - WitnessScriptLength: 1 byte
|
// - WitnessScriptLength: 1 byte
|
||||||
// - WitnessScript (MultiSig)
|
// - WitnessScript (MultiSig)
|
||||||
WitnessSize = 1 + 1 + 1 + 73 + 1 + 73 + 1 + MultiSigSize
|
MultiSigWitnessSize = 1 + 1 + 1 + 73 + 1 + 73 + 1 + MultiSigSize
|
||||||
|
|
||||||
// InputSize 41 bytes
|
// InputSize 41 bytes
|
||||||
// - PreviousOutPoint:
|
// - PreviousOutPoint:
|
||||||
@ -177,7 +173,7 @@ const (
|
|||||||
BaseCommitmentTxWeight = witnessScaleFactor * BaseCommitmentTxSize
|
BaseCommitmentTxWeight = witnessScaleFactor * BaseCommitmentTxSize
|
||||||
|
|
||||||
// WitnessCommitmentTxWeight 224 weight
|
// WitnessCommitmentTxWeight 224 weight
|
||||||
WitnessCommitmentTxWeight = WitnessHeaderSize + WitnessSize
|
WitnessCommitmentTxWeight = WitnessHeaderSize + MultiSigWitnessSize
|
||||||
|
|
||||||
// BaseAnchorCommitmentTxSize 225 + 43 * num-htlc-outputs bytes
|
// BaseAnchorCommitmentTxSize 225 + 43 * num-htlc-outputs bytes
|
||||||
// - Version: 4 bytes
|
// - Version: 4 bytes
|
||||||
@ -264,14 +260,15 @@ const (
|
|||||||
// - witness_script (to_local_script)
|
// - witness_script (to_local_script)
|
||||||
ToLocalTimeoutWitnessSize = 1 + 1 + 73 + 1 + 1 + ToLocalScriptSize
|
ToLocalTimeoutWitnessSize = 1 + 1 + 73 + 1 + 1 + ToLocalScriptSize
|
||||||
|
|
||||||
// ToLocalPenaltyWitnessSize 156 bytes
|
// ToLocalPenaltyWitnessSize 157 bytes
|
||||||
// - number_of_witness_elements: 1 byte
|
// - number_of_witness_elements: 1 byte
|
||||||
// - revocation_sig_length: 1 byte
|
// - revocation_sig_length: 1 byte
|
||||||
// - revocation_sig: 73 bytes
|
// - revocation_sig: 73 bytes
|
||||||
|
// - OP_TRUE_length: 1 byte
|
||||||
// - OP_TRUE: 1 byte
|
// - OP_TRUE: 1 byte
|
||||||
// - witness_script_length: 1 byte
|
// - witness_script_length: 1 byte
|
||||||
// - witness_script (to_local_script)
|
// - witness_script (to_local_script)
|
||||||
ToLocalPenaltyWitnessSize = 1 + 1 + 73 + 1 + 1 + ToLocalScriptSize
|
ToLocalPenaltyWitnessSize = 1 + 1 + 73 + 1 + 1 + 1 + ToLocalScriptSize
|
||||||
|
|
||||||
// ToRemoteConfirmedScriptSize 37 bytes
|
// ToRemoteConfirmedScriptSize 37 bytes
|
||||||
// - OP_DATA: 1 byte
|
// - OP_DATA: 1 byte
|
||||||
@ -289,7 +286,7 @@ const (
|
|||||||
// - witness_script (to_remote_delayed_script)
|
// - witness_script (to_remote_delayed_script)
|
||||||
ToRemoteConfirmedWitnessSize = 1 + 1 + 73 + 1 + ToRemoteConfirmedScriptSize
|
ToRemoteConfirmedWitnessSize = 1 + 1 + 73 + 1 + ToRemoteConfirmedScriptSize
|
||||||
|
|
||||||
// AcceptedHtlcScriptSize 142 bytes
|
// AcceptedHtlcScriptSize 143 bytes
|
||||||
// - OP_DUP: 1 byte
|
// - OP_DUP: 1 byte
|
||||||
// - OP_HASH160: 1 byte
|
// - OP_HASH160: 1 byte
|
||||||
// - OP_DATA: 1 byte (RIPEMD160(SHA256(revocationkey)) length)
|
// - OP_DATA: 1 byte (RIPEMD160(SHA256(revocationkey)) length)
|
||||||
@ -302,6 +299,7 @@ const (
|
|||||||
// - remotekey: 33 bytes
|
// - remotekey: 33 bytes
|
||||||
// - OP_SWAP: 1 byte
|
// - OP_SWAP: 1 byte
|
||||||
// - OP_SIZE: 1 byte
|
// - OP_SIZE: 1 byte
|
||||||
|
// - OP_DATA: 1 byte (32 length)
|
||||||
// - 32: 1 byte
|
// - 32: 1 byte
|
||||||
// - OP_EQUAL: 1 byte
|
// - OP_EQUAL: 1 byte
|
||||||
// - OP_IF: 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_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_DROP: 1 byte // but it is just an upper bound used for fee estimation in any case.
|
||||||
// - OP_ENDIF: 1 byte
|
// - 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
|
33 + 5*1 + 4 + 8*1
|
||||||
|
|
||||||
// AcceptedHtlcTimeoutWitnessSize 219
|
// AcceptedHtlcTimeoutWitnessSize 219
|
||||||
@ -349,6 +347,20 @@ const (
|
|||||||
// - witness_script (accepted_htlc_script)
|
// - witness_script (accepted_htlc_script)
|
||||||
AcceptedHtlcPenaltyWitnessSize = 1 + 1 + 73 + 1 + 33 + 1 + AcceptedHtlcScriptSize
|
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
|
// OfferedHtlcScriptSize 136 bytes
|
||||||
// - OP_DUP: 1 byte
|
// - OP_DUP: 1 byte
|
||||||
// - OP_HASH160: 1 byte
|
// - OP_HASH160: 1 byte
|
||||||
@ -386,18 +398,27 @@ const (
|
|||||||
// - OP_ENDIF: 1 byte
|
// - OP_ENDIF: 1 byte
|
||||||
OfferedHtlcScriptSize = 3*1 + 20 + 5*1 + 33 + 10*1 + 33 + 5*1 + 20 + 7*1
|
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
|
// - number_of_witness_elements: 1 byte
|
||||||
// - nil_length: 1 byte
|
|
||||||
// - receiver_sig_length: 1 byte
|
// - receiver_sig_length: 1 byte
|
||||||
// - receiver_sig: 73 bytes
|
// - receiver_sig: 73 bytes
|
||||||
// - sender_sig_length: 1 byte
|
|
||||||
// - sender_sig: 73 bytes
|
|
||||||
// - payment_preimage_length: 1 byte
|
// - payment_preimage_length: 1 byte
|
||||||
// - payment_preimage: 32 bytes
|
// - payment_preimage: 32 bytes
|
||||||
// - witness_script_length: 1 byte
|
// - witness_script_length: 1 byte
|
||||||
// - witness_script (offered_htlc_script)
|
// - 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
|
// OfferedHtlcPenaltyWitnessSize 246 bytes
|
||||||
// - number_of_witness_elements: 1 byte
|
// - number_of_witness_elements: 1 byte
|
||||||
@ -408,53 +429,25 @@ const (
|
|||||||
// - witness_script_length: 1 byte
|
// - witness_script_length: 1 byte
|
||||||
// - witness_script (offered_htlc_script)
|
// - witness_script (offered_htlc_script)
|
||||||
OfferedHtlcPenaltyWitnessSize = 1 + 1 + 73 + 1 + 33 + 1 + OfferedHtlcScriptSize
|
OfferedHtlcPenaltyWitnessSize = 1 + 1 + 73 + 1 + 33 + 1 + OfferedHtlcScriptSize
|
||||||
)
|
|
||||||
|
|
||||||
type dummySignature struct{}
|
// AnchorScriptSize 40 bytes
|
||||||
|
// - pubkey_length: 1 byte
|
||||||
func (d *dummySignature) Serialize() []byte {
|
// - pubkey: 33 bytes
|
||||||
// Always return worst-case signature length, excluding the one byte
|
// - OP_CHECKSIG: 1 byte
|
||||||
// sighash flag.
|
// - OP_IFDUP: 1 byte
|
||||||
return make([]byte, 73-1)
|
// - OP_NOTIF: 1 byte
|
||||||
}
|
// - OP_16: 1 byte
|
||||||
|
// - OP_CSV 1 byte
|
||||||
// dummySigner is a fake signer used for size (upper bound) calculations.
|
// - OP_ENDIF: 1 byte
|
||||||
type dummySigner struct {
|
AnchorScriptSize = 1 + 33 + 6*1
|
||||||
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) (Signature, error) {
|
|
||||||
|
|
||||||
return &dummySignature{}, 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,
|
|
||||||
)
|
|
||||||
|
|
||||||
// AnchorWitnessSize 116 bytes
|
// 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
|
// EstimateCommitTxWeight estimate commitment transaction weight depending on
|
||||||
|
@ -1,15 +1,45 @@
|
|||||||
package input_test
|
package input_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"math/big"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/btcsuite/btcd/blockchain"
|
"github.com/btcsuite/btcd/blockchain"
|
||||||
|
"github.com/btcsuite/btcd/btcec"
|
||||||
"github.com/btcsuite/btcd/chaincfg"
|
"github.com/btcsuite/btcd/chaincfg"
|
||||||
"github.com/btcsuite/btcd/txscript"
|
"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/lightningnetwork/lnd/input"
|
"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
|
// TestTxWeightEstimator tests that transaction weight estimates are calculated
|
||||||
@ -204,7 +234,7 @@ func TestTxWeightEstimator(t *testing.T) {
|
|||||||
for j := 0; j < test.numP2PKHInputs; j++ {
|
for j := 0; j < test.numP2PKHInputs; j++ {
|
||||||
weightEstimate.AddP2PKHInput()
|
weightEstimate.AddP2PKHInput()
|
||||||
|
|
||||||
signature := make([]byte, 73)
|
signature := make([]byte, maxDERSignatureSize+1)
|
||||||
compressedPubKey := make([]byte, 33)
|
compressedPubKey := make([]byte, 33)
|
||||||
scriptSig, err := txscript.NewScriptBuilder().AddData(signature).
|
scriptSig, err := txscript.NewScriptBuilder().AddData(signature).
|
||||||
AddData(compressedPubKey).Script()
|
AddData(compressedPubKey).Script()
|
||||||
@ -217,7 +247,7 @@ func TestTxWeightEstimator(t *testing.T) {
|
|||||||
for j := 0; j < test.numP2WKHInputs; j++ {
|
for j := 0; j < test.numP2WKHInputs; j++ {
|
||||||
weightEstimate.AddP2WKHInput()
|
weightEstimate.AddP2WKHInput()
|
||||||
|
|
||||||
signature := make([]byte, 73)
|
signature := make([]byte, maxDERSignatureSize+1)
|
||||||
compressedPubKey := make([]byte, 33)
|
compressedPubKey := make([]byte, 33)
|
||||||
witness := wire.TxWitness{signature, compressedPubKey}
|
witness := wire.TxWitness{signature, compressedPubKey}
|
||||||
tx.AddTxIn(&wire.TxIn{Witness: witness})
|
tx.AddTxIn(&wire.TxIn{Witness: witness})
|
||||||
@ -232,7 +262,7 @@ func TestTxWeightEstimator(t *testing.T) {
|
|||||||
for j := 0; j < test.numNestedP2WKHInputs; j++ {
|
for j := 0; j < test.numNestedP2WKHInputs; j++ {
|
||||||
weightEstimate.AddNestedP2WKHInput()
|
weightEstimate.AddNestedP2WKHInput()
|
||||||
|
|
||||||
signature := make([]byte, 73)
|
signature := make([]byte, maxDERSignatureSize+1)
|
||||||
compressedPubKey := make([]byte, 33)
|
compressedPubKey := make([]byte, 33)
|
||||||
witness := wire.TxWitness{signature, compressedPubKey}
|
witness := wire.TxWitness{signature, compressedPubKey}
|
||||||
scriptSig, err := txscript.NewScriptBuilder().AddData(p2wkhScript).
|
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
|
type maxDERSignature struct{}
|
||||||
// unchanged.
|
|
||||||
func TestSizes(t *testing.T) {
|
func (s *maxDERSignature) Serialize() []byte {
|
||||||
if input.AnchorWitnessSize != 116 {
|
// Always return worst-case signature length, excluding the one byte
|
||||||
t.Fatal("unexpected anchor witness size")
|
// 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)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -321,7 +321,7 @@ func (s *Server) SignOutputRaw(ctx context.Context, in *SignReq) (*SignResp, err
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
resp.RawSigs[i] = sig
|
resp.RawSigs[i] = sig.Serialize()
|
||||||
}
|
}
|
||||||
|
|
||||||
return resp, nil
|
return resp, nil
|
||||||
|
@ -15,7 +15,7 @@ var (
|
|||||||
input.HtlcOfferedRemoteTimeout,
|
input.HtlcOfferedRemoteTimeout,
|
||||||
input.WitnessKeyHash,
|
input.WitnessKeyHash,
|
||||||
}
|
}
|
||||||
expectedWeight = int64(1462)
|
expectedWeight = int64(1463)
|
||||||
expectedSummary = "0000000000000000000000000000000000000000000000000000000000000000:10 (CommitmentTimeLock), " +
|
expectedSummary = "0000000000000000000000000000000000000000000000000000000000000000:10 (CommitmentTimeLock), " +
|
||||||
"0000000000000000000000000000000000000000000000000000000000000001:11 (HtlcAcceptedSuccessSecondLevel), " +
|
"0000000000000000000000000000000000000000000000000000000000000001:11 (HtlcAcceptedSuccessSecondLevel), " +
|
||||||
"0000000000000000000000000000000000000000000000000000000000000002:12 (HtlcOfferedRemoteTimeout), " +
|
"0000000000000000000000000000000000000000000000000000000000000002:12 (HtlcOfferedRemoteTimeout), " +
|
||||||
|
@ -225,6 +225,12 @@ func (p *JusticeDescriptor) assembleJusticeTxn(txWeight int64,
|
|||||||
// CreateJusticeTxn computes the justice transaction that sweeps a breaching
|
// CreateJusticeTxn computes the justice transaction that sweeps a breaching
|
||||||
// commitment transaction. The justice transaction is constructed by assembling
|
// commitment transaction. The justice transaction is constructed by assembling
|
||||||
// the witnesses using data provided by the client in a prior state update.
|
// 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) {
|
func (p *JusticeDescriptor) CreateJusticeTxn() (*wire.MsgTx, error) {
|
||||||
var (
|
var (
|
||||||
sweepInputs = make([]*breachedInput, 0, 2)
|
sweepInputs = make([]*breachedInput, 0, 2)
|
||||||
@ -256,7 +262,13 @@ func (p *JusticeDescriptor) CreateJusticeTxn() (*wire.MsgTx, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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)
|
sweepInputs = append(sweepInputs, toLocalInput)
|
||||||
|
|
||||||
// If the justice kit specifies that we have to sweep the to-remote
|
// 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.
|
// Compute the weight estimate for our justice transaction.
|
||||||
var weightEstimate input.TxWeightEstimator
|
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.AddWitnessInput(input.P2WKHWitnessSize)
|
||||||
weightEstimate.AddP2WKHOutput()
|
weightEstimate.AddP2WKHOutput()
|
||||||
if blobType.Has(blob.FlagReward) {
|
if blobType.Has(blob.FlagReward) {
|
||||||
|
@ -141,7 +141,14 @@ func (t *backupTask) bindSession(session *wtdb.ClientSessionBody) error {
|
|||||||
// Next, add the contribution from the inputs that are present on this
|
// Next, add the contribution from the inputs that are present on this
|
||||||
// breach transaction.
|
// breach transaction.
|
||||||
if t.toLocalInput != nil {
|
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 {
|
if t.toRemoteInput != nil {
|
||||||
weightEstimate.AddWitnessInput(input.P2WKHWitnessSize)
|
weightEstimate.AddWitnessInput(input.P2WKHWitnessSize)
|
||||||
|
Loading…
Reference in New Issue
Block a user