Add support for newly named Bitcoin Core script-test result tokens and
skip taproot placeholder rows that are already covered by
TestTaprootReferenceTests.
In this commit, we fix a policy-level divergence with Bitcoin Core when
handling OP_CODESEPARATOR inside unexecuted OP_IF branches in non-segwit
scripts with the ScriptVerifyConstScriptCode flag.
Bitcoin Core's EvalScript (interpreter.cpp:474-476) places the
SCRIPT_VERIFY_CONST_SCRIPTCODE check for OP_CODESEPARATOR before the
fExec branch-execution gate, causing it to fire unconditionally on every
OP_CODESEPARATOR encountered during script iteration -- even inside
OP_FALSE OP_IF ... OP_ENDIF envelopes.
Previously, btcd's equivalent check lived inside the opcodeCodeSeparator
handler, which was never reached for opcodes in unexecuted branches due
to the early return in executeOpcode that skips non-conditional opcodes
when isBranchExecuting() is false. This meant a script like:
OP_FALSE OP_IF OP_CODESEPARATOR OP_ENDIF <validation>
would be rejected by Bitcoin Core's mempool but accepted by btcd's.
The fix moves the check before the branch-execution gate in
executeOpcode, matching Bitcoin Core's structure. This follows the
existing pattern in btcd where isOpcodeDisabled and isOpcodeAlwaysIllegal
checks already fire regardless of branch execution state.
Note: SCRIPT_VERIFY_CONST_SCRIPTCODE is purely a policy flag (included
in STANDARD_SCRIPT_VERIFY_FLAGS but not MANDATORY_SCRIPT_VERIFY_FLAGS),
so this was not a consensus divergence. Both implementations would accept
such transactions if mined in a block.
Found via differential fuzzing by Bruno from bitcoinfuzz.
Update the expected error strings in recoveryTests to match the new
error message format introduced by the secp256k1 v4.4.0 upgrade.
Also replace reflect.DeepEqual with a string-based errorStringEqual
helper to avoid type mismatches between fmt.Errorf and wrapped errors,
and drop the now-unused "reflect" import.
The new version exposes Signature.S(), giving direct access to the S
scalar without re-parsing the DER bytes. This enables a cleaner
implementation of the VerifyLowS helper added in this branch.
This commit replaces the parsing of a JSON string with a simple
prefix/suffix replacement of the quotes. That is much faster than
allocating memory for a JSON parser.
Where possible, we also directly decode the hex with a decoder to
further reduce the number of allocations.
Address review feedback on the peer add/done race fix:
Add three direct unit tests in server_test.go that exercise the fix
without the full server or rpctest harness:
- TestOnVerAckDoubleCall: call OnVerAck twice on the same serverPeer,
assert no panic and verAckCh remains closed.
- TestPeerLifecycleOrdering: verack before disconnect emits peerAdd
then peerDone in order.
- TestPeerLifecycleSimultaneousReady: both verAckCh and Peer.Done()
ready before the handler runs; assert peerDone always arrives and
peerAdd, if emitted, precedes it (100 iterations).
Harden integration tests in sync_race_test.go:
- Check fakePeerConn errors via require.NoError instead of discarding.
- Extract dialAndSendVersion helper for TestPreVerackDisconnect;
check all errors instead of silently continuing.
- Fix comment wording ("produces" -> "is expected to produce").
Add NewHashFromStrStrict and DecodeStrict for callers that must
parse full txids or block hashes exactly.
Keep NewHashFromStr and Decode lenient for compatibility, but add
NOTE docs steering typical parsing to the strict helpers.
Add tests for the new strict behavior and preserve coverage for the
existing lenient short and odd hex behavior.
As we introduced a new MaxProtocolMessageLength, MsgReject max size
should also be lowered to MaxProtocolMessageLength.
If this isn't lowered and if we ever have a MsgReject message that is
bigger than MaxProtocolMessageLength, then the MaxPayloadLength() check
on the message will pass but it won't serialize in functions
WriteMessageWithEncodingN() and WriteV2MessageN() as both of these
functions have a separate check that each message isn't greater than
MaxProtocolMessageLength.
Go's net.ParseIP stores IPv4 addresses as 16-byte IPv4-mapped IPv6
addresses (::ffff:x.x.x.x). NetAddressV2FromBytes dispatches on
address length, so these 16-byte addresses were incorrectly matched
as IPv6 and serialized with networkID 0x02 (IPv6) instead of 0x01
(IPv4). BIP-155 doesn't forbid this, but Bitcoin Core silently drops
them anyway (undocumented, naturally). Detect IPv4-mapped IPv6
addresses and extract the 4-byte IPv4 address with the correct
networkID.
Add a test case that passes a 16-byte IPv4-mapped IPv6 address
(::ffff:127.0.0.1) to NetAddressV2FromBytes and asserts that it
is recognized as IPv4 with networkID 0x01, not IPv6 with 0x02.
Revert MaxMessagePayload to 32MB and introduce MaxProtocolMessageLength
(~4MB) for p2p network message size enforcement. This mirrors Bitcoin
Core's separation between MAX_SIZE (32MB serialization bound) and
MAX_PROTOCOL_MESSAGE_LENGTH (~4MB network limit) introduced in
bitcoin/bitcoin#5843.
The previous commit reduced MaxMessagePayload to 4MB, but that constant
is also used as a serialization bound for deriving maxTxInPerMessage,
maxTxOutPerMessage, and variable-length string limits in contexts beyond
network messages (e.g. database deserialization via MsgTx.Deserialize).
While consensus limits keep real values well below the 4MB-derived
bounds, conflating the two constants is architecturally incorrect and
diverges from Bitcoin Core's design.
The new MaxProtocolMessageLength is now enforced in all four network
read/write paths: WriteMessageN, WriteMessageWithEncodingN,
ReadMessageWithEncodingN, and ReadV2MessageN (which previously had no
overall message size check).
In this commit, we remove the localhost-only restriction for sync peer
candidates on regtest and simnet. Previously, isSyncCandidate rejected
any regtest peer not on 127.0.0.1 or localhost, which prevented IBD
when nodes run in Docker containers on bridge networks (e.g. 172.18.0.x).
We also replace fragile pointer-equality checks against global chaincfg
params with value-based Name field comparisons, and extend the exception
to simnet since it has the same local-only usage pattern.
In this commit, we fix `IsRoutable` to correctly reject IPv6 addresses
whose first 16-bit group is zero (i.e., in the `0000::/16` reserved
block per RFC 4291). Differential fuzzing between btcd and Bitcoin Core
revealed that addresses like `0:9881:8181:8181:fe00🅰️9e:9801` were
slipping through as routable when they shouldn't be.
We add a new `zero6Net` (`0000::/16`) definition alongside the existing
`zero4Net`, and introduce an `IsZero` helper that checks both. The /16
prefix width is intentional: the broader /8 reservation would
incorrectly catch allocated sub-ranges like `0064:ff9b::/96` (RFC 6052,
NAT64). We also carve out an exception for RFC 6145 translated IPv4
addresses (`::ffff:0:0:0/96`), which live within `0000::/16` but are
valid for routing.
Test coverage includes the original bug report address, various
zero-prefix IPv6 addresses, the RFC 6145 exclusion, and corresponding
`GroupKey` entries to confirm they land in the "unroutable" bucket.
Fixes#2431
html/template automatically HTML-escapes special characters to prevent
XSS, which can silently corrupt arbitrary script data. Since the output
is binary script bytes and not HTML, this escaping provides no benefit
and might breaks correctness.
Add a recoverFromPanic method that catches panics in peer goroutines,
logs the error with a stack trace, and disconnects the offending peer
instead of crashing the entire node. This provides defense-in-depth
against future unknown panics in message parsing or handling.
Protect two goroutine boundaries:
- The negotiation goroutine in start(), which handles pre-handshake
message decoding via BtcDecode.
- The inHandler goroutine, which processes all post-handshake messages.
Refactor inHandler cleanup from manual end-of-function calls to
defer-based cleanup, ensuring close(p.inQuit) always runs even on
panic, which prevents stallHandler from hanging.
In this commit, we add TestReadMessageTrailingBytes which constructs a
valid version message with 4 garbage bytes appended to the payload. The
wire frame uses a correct checksum over the full dirty payload so that
the checksum validation passes, but the new trailing-bytes check in
readMessageWithEncodingNInternal catches the unconsumed bytes and
returns a MessageError.
In this commit, we add a strictness check to
readMessageWithEncodingNInternal that verifies all payload bytes were
consumed by BtcDecode. After BtcDecode returns, the remaining length of
the payload buffer is checked, and if any bytes remain unconsumed, the
message is rejected with a MessageError.
Previously, the payload buffer was passed to BtcDecode without any
post-decode validation, meaning any bytes beyond what BtcDecode consumed
were silently ignored. This check ensures wire message payloads are
exactly the size needed for the decoded message, tightening our
conformance to the expected wire format.
Add a bounds check against the remaining slab capacity so oversized
witness items return a decode error. Add a regression test for witness
items that overflow the decode slab.
This issue was discovered through differential fuzzing between btcd and
Bitcoin Core.
IPv4-mapped IPv6 addresses (::ffff:0:0/96, RFC 4291) sent with networkID
0x02 (IPv6) in addrv2 messages are now properly rejected. Per BIP155,
these addresses should use networkID 0x01 (IPv4) instead. This aligns
btcd's behavior with Bitcoin Core's addrv2 handling.
Changes:
- Add ipv4MappedPrefix constant for the ::ffff:0:0/96 prefix
- Add isIPv4Mapped() helper function to detect these addresses
- Update readNetAddressV2() to skip IPv4-mapped addresses with IPv6 networkID
- Add comprehensive test coverage for IPv4-mapped address detection
This issue was discovered through differential fuzzing between btcd and
Bitcoin Core.
Add detection and filtering of IPv6 ORCHIDv2 addresses as defined by
RFC7343 (2001:20::/28). These addresses are overlay routable
cryptographic hash identifiers and should not be treated as routable
peer addresses, consistent with Bitcoin Core's behavior.
Changes:
- Add rfc7343Net variable for the 2001:20::/28 address block
- Add IsRFC7343() function to detect ORCHIDv2 addresses
- Update IsRoutable() to exclude RFC7343 addresses
- Add comprehensive test coverage for RFC7343 detection
- Fix incorrect error message in TestIPTypes (IsRFC1918 -> IsRFC6145)
Verify that startSync skips header download and directly requests
blocks when the header chain is already caught up to the peer's
height but the block chain lags behind.
ince we now utilize ProcessBlockHeaders, we change the startSync
function to utilize the block index for downloading blocks/headers
instead of using the headerList in SyncManager.
This tests that after two nodes diverge and reconnect, the shorter
node downloads blocks starting from the fork point rather than its
current height. It verifies the reorg completes, both nodes
converge, and the orphaned fork appears as a side chain via
getchaintips.