From f523d4ccaa5f34a2f761f16a05f5d6e6665b1168 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Sun, 9 Oct 2022 17:03:31 -0700 Subject: [PATCH] wire: remove erroneous witness size check in wire parsing In this commit, we fix a bug that would cause nodes to be unable to parse a given block from the wire. The block would be properly accepted if fed in via other mechanisms. The issue here is that the old checks for the maximum witness size, circa segwit v0 where placed in the wire package _as well_ as the tx engine. This check should only be in the engine, since it's properly gated by other related scrip validation flags. The fix itself is simple: limit witnesses only based on the maximum block size in bytes, or ~4MB. --- blockchain/weight.go | 2 +- wire/msgtx.go | 30 ++++++++++++++++-------------- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/blockchain/weight.go b/blockchain/weight.go index 5a6f257be5..1b691f0086 100644 --- a/blockchain/weight.go +++ b/blockchain/weight.go @@ -7,9 +7,9 @@ package blockchain import ( "fmt" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcd/btcutil" ) const ( diff --git a/wire/msgtx.go b/wire/msgtx.go index 917a142e6e..c289cd7e0b 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