diff --git a/btcec/signature.go b/btcec/signature.go index cdd7cedfb8..8a8f8301b7 100644 --- a/btcec/signature.go +++ b/btcec/signature.go @@ -353,6 +353,10 @@ func recoverKeyFromSignature(curve *KoblitzCurve, sig *Signature, msg []byte, // step to prevent the jacobian conversion back and forth. Qx, Qy := curve.Add(sRx, sRy, minuseGx, minuseGy) + if Qx.Sign() == 0 && Qy.Sign() == 0 { + return nil, errors.New("point (Qx, Qy) equals the point at infinity") + } + return &PublicKey{ Curve: curve, X: Qx, diff --git a/mempool/mempool_test.go b/mempool/mempool_test.go index 96d5054417..de192781dc 100644 --- a/mempool/mempool_test.go +++ b/mempool/mempool_test.go @@ -560,7 +560,7 @@ func TestOrphanReject(t *testing.T) { // Ensure no transactions were reported as accepted. if len(acceptedTxns) != 0 { - t.Fatal("ProcessTransaction: reported %d accepted "+ + t.Fatalf("ProcessTransaction: reported %d accepted "+ "transactions from failed orphan attempt", len(acceptedTxns)) } diff --git a/mempool/policy.go b/mempool/policy.go index 7e97329319..1fe850797f 100644 --- a/mempool/policy.go +++ b/mempool/policy.go @@ -172,17 +172,10 @@ func checkPkScriptStandard(pkScript []byte, scriptClass txscript.ScriptClass) er return nil } -// isDust returns whether or not the passed transaction output amount is -// considered dust or not based on the passed minimum transaction relay fee. -// Dust is defined in terms of the minimum transaction relay fee. In -// particular, if the cost to the network to spend coins is more than 1/3 of the -// minimum transaction relay fee, it is considered dust. -func isDust(txOut *wire.TxOut, minRelayTxFee btcutil.Amount) bool { - // Unspendable outputs are considered dust. - if txscript.IsUnspendable(txOut.PkScript) { - return true - } - +// GetDustThreshold calculates the dust limit for a *wire.TxOut by taking the +// size of a typical spending transaction and multiplying it by 3 to account +// for the minimum dust relay fee of 3000sat/kvb. +func GetDustThreshold(txOut *wire.TxOut) int64 { // The total serialized size consists of the output and the associated // input script to redeem it. Since there is no input script // to redeem it yet, use the minimum size of a typical input script. @@ -253,6 +246,20 @@ func isDust(txOut *wire.TxOut, minRelayTxFee btcutil.Amount) bool { totalSize += 107 } + return 3 * int64(totalSize) +} + +// IsDust returns whether or not the passed transaction output amount is +// considered dust or not based on the passed minimum transaction relay fee. +// Dust is defined in terms of the minimum transaction relay fee. In +// particular, if the cost to the network to spend coins is more than 1/3 of the +// minimum transaction relay fee, it is considered dust. +func IsDust(txOut *wire.TxOut, minRelayTxFee btcutil.Amount) bool { + // Unspendable outputs are considered dust. + if txscript.IsUnspendable(txOut.PkScript) { + return true + } + // The output is considered dust if the cost to the network to spend the // coins is more than 1/3 of the minimum free transaction relay fee. // minFreeTxRelayFee is in Satoshi/KB, so multiply by 1000 to @@ -265,7 +272,7 @@ func isDust(txOut *wire.TxOut, minRelayTxFee btcutil.Amount) bool { // // The following is equivalent to (value/totalSize) * (1/3) * 1000 // without needing to do floating point math. - return txOut.Value*1000/(3*int64(totalSize)) < int64(minRelayTxFee) + return txOut.Value*1000/GetDustThreshold(txOut) < int64(minRelayTxFee) } // checkTransactionStandard performs a series of checks on a transaction to @@ -351,7 +358,7 @@ func checkTransactionStandard(tx *btcutil.Tx, height int32, // "dust". if scriptClass == txscript.NullDataTy { numNullDataOutputs++ - } else if isDust(txOut, minRelayTxFee) { + } else if IsDust(txOut, minRelayTxFee) { str := fmt.Sprintf("transaction output %d: payment "+ "of %d is dust", i, txOut.Value) return txRuleError(wire.RejectDust, str) diff --git a/mempool/policy_test.go b/mempool/policy_test.go index 9dd618ad6e..b9cdbac47a 100644 --- a/mempool/policy_test.go +++ b/mempool/policy_test.go @@ -204,7 +204,7 @@ func TestCheckPkScriptStandard(t *testing.T) { } } -// TestDust tests the isDust API. +// TestDust tests the IsDust API. func TestDust(t *testing.T) { pkScript := []byte{0x76, 0xa9, 0x21, 0x03, 0x2f, 0x7e, 0x43, 0x0a, 0xa4, 0xc9, 0xd1, 0x59, 0x43, 0x7e, 0x84, 0xb9, @@ -268,7 +268,7 @@ func TestDust(t *testing.T) { }, } for _, test := range tests { - res := isDust(&test.txOut, test.relayFee) + res := IsDust(&test.txOut, test.relayFee) if res != test.isDust { t.Fatalf("Dust test '%s' failed: want %v got %v", test.name, test.isDust, res) diff --git a/version.go b/version.go index f723b5c6e7..e9a86b3bad 100644 --- a/version.go +++ b/version.go @@ -18,7 +18,7 @@ const semanticAlphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr const ( appMajor uint = 0 appMinor uint = 22 - appPatch uint = 1 + appPatch uint = 2 // appPreRelease MUST only contain characters from semanticAlphabet // per the semantic versioning spec. diff --git a/wire/msgtx.go b/wire/msgtx.go index 1e2f69fad4..dbc379cf30 100644 --- a/wire/msgtx.go +++ b/wire/msgtx.go @@ -103,10 +103,9 @@ const ( maxWitnessItemsPerInput = 500000 // maxWitnessItemSize is the maximum allowed size for an item within - // an input's witness data. This number is derived from the fact that - // for script validation, each pushed item onto the stack must be less - // than 10k bytes. - maxWitnessItemSize = 11000 + // an input's witness data. This value is bounded by the largest + // possible block size, post segwit v1 (taproot). + maxWitnessItemSize = 4_000_000 ) // TxFlagMarker is the first byte of the FLAG field in a bitcoin tx @@ -114,16 +113,18 @@ const ( // transaction from one that would require a different parsing logic. // // Position of FLAG in a bitcoin tx message: -// ┌─────────┬────────────────────┬─────────────┬─────┐ -// │ VERSION │ FLAG │ TX-IN-COUNT │ ... │ -// │ 4 bytes │ 2 bytes (optional) │ varint │ │ -// └─────────┴────────────────────┴─────────────┴─────┘ +// +// ┌─────────┬────────────────────┬─────────────┬─────┐ +// │ VERSION │ FLAG │ TX-IN-COUNT │ ... │ +// │ 4 bytes │ 2 bytes (optional) │ varint │ │ +// └─────────┴────────────────────┴─────────────┴─────┘ // // Zooming into the FLAG field: -// ┌── FLAG ─────────────┬────────┐ -// │ TxFlagMarker (0x00) │ TxFlag │ -// │ 1 byte │ 1 byte │ -// └─────────────────────┴────────┘ +// +// ┌── FLAG ─────────────┬────────┐ +// │ TxFlagMarker (0x00) │ TxFlag │ +// │ 1 byte │ 1 byte │ +// └─────────────────────┴────────┘ const TxFlagMarker = 0x00 // TxFlag is the second byte of the FLAG field in a bitcoin tx message. @@ -586,8 +587,9 @@ func (msg *MsgTx) BtcDecode(r io.Reader, pver uint32, enc MessageEncoding) error // item itself. txin.Witness = make([][]byte, witCount) for j := uint64(0); j < witCount; j++ { - txin.Witness[j], err = readScript(r, pver, - maxWitnessItemSize, "script witness item") + txin.Witness[j], err = readScript( + r, pver, maxWitnessItemSize, "script witness item", + ) if err != nil { returnScriptBuffers() return err