Stale Tip Relay
Preamble
- BIP
- 332
- Layer
- Peer Services
- Title
- Stale Tip Relay
- Author
- Anthony Towns, w0xlt, Ram
- Status
- Draft
- Type
- Specification
- Assigned
- 2026-08-21
- License
- BSD-3-Clause
- Discussion
- 2026-07-29 https://gnusha.org/pi/bitcoindev/d92f1615-368b-4406-b326-a1799c72a555n@googlegroups.com/
- Version
- 0.1.0
- Requires
- 434
Abstract
Bitcoin miners sporadically produce stale blocks: valid blocks or valid block headers that do not become part of the node's active chain. This BIP defines a new optional peer-to-peer (P2P) staletip message for announcing recent stale chain tips to peers. The announcement includes the stale branch headers and whether the sender is willing to serve corresponding stale block data.
Motivation
Stale blocks are a potentially useful signal about the health of the network's block-relay layer. The rate at which they occur tracks how quickly new blocks reach the rest of the miners, and an elevated rate can be a symptom of a range of network-related problems – degraded or congested propagation, network partitions, or adversarial mining behavior such as selfish mining.
An added benefit is that when a stale block has the same cumulative proof of work as the active tip, the current active tip may be re-orged out in favor of a child of the stale block; having the block already downloaded (and possibly already validated) makes the reorg faster. The contents of stale blocks additionally reveal differences in block-creation policy between mining pools.
These benefits are not essential to the operation of the Bitcoin network, so this is proposed as an optional feature, with low performance demands and strict resource limits.
Specification
The key words "MUST", "MUST NOT", "REQUIRED", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119.
For the purposes of this document, "active chain" means the chain that a node has selected as its current best chain. A "stale branch" is a sequence of valid headers that descends from a known block but whose tip is not on the node's active chain. The "stale tip" is the last header in that branch.
The staletip Message
The staletip P2P message has the ASCII message type staletip and the following payload:
| Type | Name | Description |
|---|---|---|
uint256 |
fork_point |
The block hash used as the previous block hash of the first compressed header |
vector of CompressedHeader |
headers |
The headers forming a single stale branch after fork_point, in chain order |
bool |
have_block |
Whether the sender is willing to serve block data for the stale branch |
The fork_point MUST be known by the receiver and MUST be the predecessor of the first reconstructed header. In the common case, it is the last common block before the stale branch diverges from the receiver's active chain. It MAY be a later known stale-branch header if both peers are expected to already know that header; in that case the headers vector only contains the unknown suffix.
The headers field MUST describe a single linear branch. The first header immediately follows fork_point, and each subsequent header immediately follows the preceding header. The final header is the stale tip. A separate staletip message is required for each competing branch that the sender chooses to announce.
The headers vector is serialized as normal: encode the length of the vector as a 1, 3, 5 or 9 byte CompactSize, then serialize each member of the vector. Only minimally-encoded CompactSize values are supported.
The bool serialization is a single byte \x00 for false, and a single byte \x01 for true. Other encodings are malformed.
have_block set to true means the sender currently has, and is willing to serve through normal block download mechanisms, the full block data for the stale tip, which is the final header in this staletip message. A sender that sets have_block to true SHOULD additionally be willing to serve earlier blocks on the announced stale branch that it has. have_block set to false makes no claim about stale-branch block-data availability. A sender SHOULD NOT set have_block to true unless it expects a request for the stale tip block to succeed.
Because stale tips are very rare, this BIP does not reserve a 1-byte BIP 324 message type ID for the staletip message.
CompressedHeader Format
The CompressedHeader is a 48 byte structure equivalent to regular block header serialization, but omits the previous block's hash1. The fields are serialized exactly as the corresponding fields are serialized in a Bitcoin block header:
| Size | Name | Type | Description |
|---|---|---|---|
| 4 | version |
int32_t |
Block version information |
| 32 | merkle_root |
uint256 |
The Merkle root of the block's transactions |
| 4 | time |
uint32_t |
The block's timestamp |
| 4 | bits |
uint32_t |
The calculated difficulty target being used for this block |
| 4 | nonce |
uint32_t |
The nonce used to generate this block |
Protocol Constants
Implementations of this BIP use the following limits unless otherwise noted:
| Name | Value | Meaning |
|---|---|---|
MAX_STALETIP_HEADERS |
20 | Recommended maximum number of CompressedHeader entries in one staletip message |
STALETIP_RECENT_WINDOW |
1000 blocks | Recommended maximum distance from the receiver's active tip |
MAX_ADVERTISED_STALETIPS |
10 | Recommended maximum number of previously known stale tips advertised to a peer |
MAX_STALETIP_HEADERS is a resource-management limit2. The value of 20 is intended to cover the short stale branches useful for reorg detection while avoiding long-term tracking of persistent chain splits.
STALETIP_RECENT_WINDOW is a resource-management limit3. The 1000-block window is about seven days and balances limiting resource usage with allowing stale tips to propagate.
MAX_ADVERTISED_STALETIPS is a bandwidth limit4. Advertising up to 10 previously known stale tips, combined with the 20-header branch limit, keeps informing a new peer of known stale tips under 10kB. It does not limit how many stale tips a node retains, or how many newly learned tips it relays over the lifetime of a connection. Implementations MAY use stricter limits. A peer SHOULD NOT be punished solely because a single announcement exceeds local policy limits.
Staletip Feature Definition
This BIP defines a new BIP 434 feature id ("the staletip feature"):
BIP332
The staletip feature data MUST contain exactly one byte. This byte is a boolean, prefers_blocks, indicating whether the node advertising the feature prefers to collect the full block data associated with stale tips:
\x00: the node prefers header-only announcements and does not request that announcements be delayed until block data is available.\x01: the node prefers announcements that include availability of block data where practical.
Nodes receiving staletip feature data whose length is not exactly one byte, or whose byte is not \x00 or \x01, MUST ignore that peer's staletip feature advertisement. They SHOULD NOT disconnect solely because the feature data is not understood.
BIP 434 Negotiation
Nodes implementing this specification MUST use BIP 434 to negotiate support before sending any staletip messages.
Nodes MUST NOT send a staletip message to a peer unless that peer advertised a valid staletip feature during BIP 434 feature negotiation. Nodes SHOULD ignore staletip messages received from peers that did not advertise a valid staletip feature. Nodes MAY disconnect peers that repeatedly send such messages without negotiation.
Advertising the feature only signals willingness to receive staletip messages. It does not oblige a node to send them or to serve block data. A node MAY advertise the feature to receive stale tips while never sending any itself, for example a node that only collects stale tips for research.
Sending staletip Messages
Nodes implementing this BIP MAY send staletip messages to advertise recent stale tips they are aware of. If so:
- Nodes SHOULD send
staletipmessages advertising recent stale tips that they are aware of to peers that support thestaletipfeature. - Nodes SHOULD NOT advertise stale tips that violate header consensus rules (invalid version, invalid timestamps, invalid difficulty changes, insufficient proof of work).
- Nodes MUST NOT send
staletipmessages if they are not sure that thefork_pointis a block that their peer is aware of. This can be estimated by tracking the highest work blocks announced by the peer, and assuming the peer is treating that block as its active tip. Provided thefork_pointis an ancestor of that highest work block, the peer will be aware of thefork_point. - The
fork_pointSHOULD be chosen to minimise the number of entries in theheadersvector, while still being a block that the peer already has header information for. - Nodes MAY choose a
fork_pointbased on their own active chain, even if that results in theheadersvector repeating some headers that the peer already knows. - Nodes SHOULD NOT advertise stale tips whose tip height is more than
STALETIP_RECENT_WINDOWblocks behind the sender's active tip. - Nodes SHOULD NOT advertise stale branches longer than
MAX_STALETIP_HEADERSheaders. - Nodes SHOULD apply proof-of-work or chainwork thresholds sufficient to avoid using this message as a low-cost spam channel5.
- When informing a peer of stale tips that were already known when stale-tip relay with that peer began, nodes SHOULD advertise no more than
MAX_ADVERTISED_STALETIPSeligible tips. If more tips are eligible, nodes SHOULD select those with the greatest chainwork, preferring the most recently learned tip when chainwork is equal. Implementations MAY instead select a different subset, for example by sampling independently for each peer to increase the diversity of stale tips available across the network. This limit does not prevent relaying newly learned stale tips to an existing peer. - Nodes SHOULD avoid advertising the same tip to the same peer repeatedly via multiple
staletipmessages. - Nodes SHOULD respect the peer's
prefers_blockssetting. If a peer setsprefers_blocksto\x00, stale tips SHOULD be relayed to that peer promptly, without waiting to obtain block data. Conversely, for a peer that setsprefers_blocksto\x01, a node that does attempt to obtain block data SHOULD defer sending thestaletipmessage to that peer until it has obtained the relevant block data, unless doing so would substantially delay propagation. - Nodes that have the block data corresponding to the tip block (and will provide that data to peers that request it) SHOULD set
have_blockastrue. A sender that setshave_blocktotrueSHOULD additionally be willing to serve earlier blocks on the announced stale branch that it has. Nodes without the full tip block data, or that are unwilling to relay the data to peers, SHOULD sethave_blockasfalse.
Receiving staletip Messages
Nodes implementing this BIP MAY process staletip messages from peers to gain more knowledge about stale tips. If so:
- Nodes SHOULD reject messages whose payload cannot be parsed exactly as a
staletippayload, including non-minimally encodedCompactSizevalues, truncated data, invalid boolean values, or trailing bytes. Nodes MAY disconnect peers for malformed payloads. - Nodes SHOULD reject (ignore)
staletipmessages where thefork_pointis not known, and MAY disconnect peers that repeatedly send unknown fork points. Sending such a message violates the requirement above that senders MUST NOT sendstaletipmessages unless they are sure the receiver knows thefork_pointblock. - Nodes SHOULD reject messages where the
headersvector is empty, and MAY disconnect the sending peer if this occurs. - When processing a
staletipmessage, nodes MUST bound the resources they devote to it so that a denial-of-service vector is not created6. Enforcing theMAX_STALETIP_HEADERSandSTALETIP_RECENT_WINDOWlimits, together with implementation-specific storage limits, is one way to satisfy this requirement; nodes MAY apply stricter limits. - Nodes MAY ignore messages where the
headersvector contains more thanMAX_STALETIP_HEADERSentries, or MAY partially process headers until local limits are reached. - Nodes SHOULD ignore messages whose stale tip is not recent according to local policy, for example more than
STALETIP_RECENT_WINDOWblocks behind the receiver's active tip. - Nodes MAY ignore messages that violate local denial-of-service checks, or MAY partially process headers until local limits are reached. Nodes SHOULD NOT disconnect or otherwise punish a peer solely because a single message exceeds local policy limits. Nodes MAY rate-limit or disconnect peers that repeatedly send messages exceeding those limits.
- After receiving a
staletipmessage that passes local denial-of-service checks, nodes SHOULD reconstruct the block headers from theCompressedHeaderencoding and validate the headers. - Nodes SHOULD ignore any headers found to be invalid, and SHOULD NOT disconnect or otherwise punish a peer solely for a single invalid announcement. Nodes MAY rate-limit or disconnect peers that repeatedly announce invalid headers7.
- If
have_blockistrue, nodes that prefer to collect the full block data SHOULD request missing block data for the announced stale branch in the normal way, for example by walking back from the reconstructed stale tip toward a known block and sendinggetdatamessages for missing blocks. - Nodes that receive a new stale tip SHOULD announce that tip to their peers that negotiated the
staletipfeature, subject to local relay policy. Nodes SHOULD NOT announce the same stale tip to the same peer more than once, and SHOULD NOT announce a stale tip to a peer from which they have already received an announcement of that tip.
Nodes in initial block download SHOULD NOT announce stale tips, and MAY ignore received staletip messages, until they are close enough to the active network tip for stale-tip recency checks to be meaningful.
If a received staletip branch has more cumulative proof of work than the receiver's current active chain, the receiver SHOULD process the reconstructed headers through its normal header-processing logic. Such a branch may cease to be stale from the receiver's perspective.
Active Tip Announcements
In order for peers to send useful staletip messages, they must be able to track which block is your active tip in order to deduce whether you already know the fork point corresponding to new stale tips.
Currently, many node implementations make a small optimisation in their block announcement handling that conflicts with this requirement: they will not announce a block to a peer if they have already processed an announcement for the same block from that peer at the time they validate the block. That said, due to delays in obtaining block data and validating the block, it is usually the case that two well-connected peers will announce the same new block to each other.
Nodes implementing this BIP SHOULD always announce their new active tip to all peers. To minimise additional bandwidth, they MAY do so via an inv message rather than a headers or compact block message.
Reconstructing Headers
Headers may be reconstructed from a staletip message via the following algorithm:
prev_hash = staletip.fork_point
for compressed_header in staletip.headers:
header = BlockHeader(
version = compressed_header.version,
previous_block_hash = prev_hash,
merkle_root = compressed_header.merkle_root,
time = compressed_header.time,
bits = compressed_header.bits,
nonce = compressed_header.nonce
)
prev_hash = hash(header)
Headers are reconstructed in chain order, beginning with the header immediately following fork_point and ending with the stale tip.
Optionality
Node software implementing this BIP SHOULD provide a configuration option to disable it entirely. Implementations MAY provide separate options for relaying stale headers and for requesting or serving stale block data.
Rationale
This proposal treats stale-tip relay as a negotiated peer service because stale tips are useful but not required for normal participation in the Bitcoin network. A node can fully validate the active chain, relay blocks, and serve peers without ever learning about stale branches that did not become part of its active chain. Negotiating support avoids imposing bandwidth, storage, privacy, or implementation complexity on nodes that do not use this information.
The feature uses BIP 434 negotiation instead of a protocol-version bump or opportunistic transmission of a new message. A protocol-version bump would unnecessarily coordinate this feature with unrelated P2P changes and would imply broader capability than is actually needed. Sending a new post-handshake message without feature-specific negotiation would rely on every peer safely ignoring unknown messages. BIP 434 provides a narrower capability signal: peers only send staletip messages after the receiver has advertised support for this specific feature.
A separate staletip message is used instead of reusing headers, inv, or block relay. Existing relay messages are primarily active-chain mechanisms and do not communicate the extra information needed here: that the branch is believed to be stale, which known block should be used as the reconstruction base, and whether the sender expects stale branch block data to be available. Reusing existing messages would either overload their meaning or require receivers to infer stale-tip intent from context. A dedicated message keeps the behavior explicit and allows implementations to apply separate resource, privacy, and relay policies.
The protocol is announcement-based rather than request-based. An alternative would be to define messages for requesting known stale tips from a peer, but that would add more state, more peer-specific behavior, and a possible query amplification surface for a feature whose events are expected to be rare. Simple announcements are sufficient for the main use cases: faster preparation for near-tip reorgs and passive measurement of stale-block propagation.
The message includes a fork_point followed by compressed headers because the previous-block hash in each header is redundant once the fork point is known. This saves 32 bytes per header while preserving the normal block-header fields needed for validation. More aggressive compression of nVersion, nTime, nBits, or nonce was not chosen because those fields are consensus-relevant and chain-dependent. Compressing them would add implementation complexity and increase the risk of divergent reconstruction behavior for relatively small additional savings.
The fork_point is required to be known by the receiver so that the message can be processed without an extra round trip. Allowing the fork point to be either an active-chain block or an already-known stale-branch header lets senders avoid resending headers the peer is expected to know. Requiring the fork point to be the exact divergence point from the active chain would be simpler conceptually, but less efficient when both peers already know part of the stale branch.
The branch length limit of 20 headers is a deliberate resource bound. Stale branches relevant to near-tip reorg handling are expected to be short, and longer branches can be handled by normal header synchronization if they become important. The limit keeps each message small, bounds validation work, and prevents staletip from becoming a cheap bulk-header relay mechanism.
The recency and advertised-tip limits are recommendations rather than strict wire requirements because different nodes have different goals. A monitoring node may advertise more stale tips for measurement, while a resource-constrained node may advertise fewer or ignore them entirely. Selecting the greatest-chainwork tips prioritizes branches most likely to become relevant to a reorganization, while randomizing the selection independently for each peer can improve network-wide availability when more tips are eligible than can be advertised. Treating these limits as local policy allows implementations to differ without making honest peers appear malformed or misbehaving.
Invalid or locally unacceptable stale-tip announcements are generally ignored rather than punished. Stale-tip relay is inherently race-prone: peers may have different active tips, different retained stale headers, or different local resource policies. Disconnecting peers for these cases would risk penalizing honest nodes during exactly the network conditions where stale tips are most likely to appear.
The have_block flag is a compact signal that block data for the announced stale branch may be available from the sender. The tip block is the minimum object described by have_block, because it is the final header in the announcement and the block most immediately useful for reorg preparation and block-policy analysis. Receivers may also request earlier missing blocks on the announced branch. Describing availability for every block in the branch would make the message larger and more complex; peers can instead request missing blocks through normal block download and retry with other announcers if requests fail.
No one-byte BIP 324 message type is assigned for staletip. BIP 324 short message identifiers save the 12-byte ASCII command overhead for messages that are sent frequently. Stale-tip announcements are expected to be rare, and each announcement already carries at least a 32-byte fork point and one 48-byte compressed header, so the bandwidth saved by replacing the staletip command name with a one-byte identifier would be negligible. Since the one-byte identifier space is limited, it is better reserved for messages that are common enough for the per-message saving to matter.
The test-network guidance is stricter because test networks have weaker anti-spam properties than mainnet. Signet headers cannot be fully validated without the block data containing the signature, and testnet difficulty rules can make low-work stale headers cheap to produce. The specification therefore leaves room for implementations to disable the feature on test networks or apply stronger relay policy there than they would on mainnet.
Test Networks
Making this feature available on test networks raises additional concerns, as they are less protected by proof of work, and thus may have a larger attack surface for denial of service issues. As a result, node software implementing this BIP MAY choose to do so only for mainnet.
Signet
The default signet is expected to reorg roughly once per day, with a branch of random length. Stale tips are therefore common on signet rather than rare, and a stale branch may be longer than MAX_STALETIP_HEADERS. Such a branch will not be relayed via staletip; nodes fall back to normal header synchronisation for it, and implementations MAY raise the limit on signet.
The signet network is designed around the assumption that all valid blocks are signed, and thus much lower proof of work is needed. However, because the block signatures are included in the coinbase transaction, they cannot be verified if only the block's headers are available. As such, when implementing this BIP for signet:
- Nodes MUST NOT send
staletipmessages when they do not have the corresponding block data needed to verify the signet signature. - Nodes MAY disconnect peers that send a
staletipmessage withhave_blockset tofalse. - Nodes SHOULD set
prefers_blocksto\x01when negotiating the feature, as they will always need to download the full block data for a stale tip to validate the signature.
In addition, when the difficulty is low, it is possible that varying the nBits field of a valid block will generate another valid block (see #33266). As such:
- Nodes SHOULD consider variant headers, where the previous block and Merkle root are both the same, to be duplicates, and only advertise the first seen variant as a stale tip.
While nodes MAY also deduplicate such variant headers when receiving them via staletip messages, if they do not perform the same deduplication logic when receiving such headers via standard headers or block relay, that provides little protection. Deduplicating when sending staletip messages is primarily aimed at avoiding nodes implementing this BIP from being used to amplify attacks.
Only variant tips need to be deduplicated: it is possible, though unlikely, that valid signed blocks may be descendants of variant blocks. These blocks will not themselves be variants, as they will have different previous blocks.
Testnet3 and Testnet4
While testnet3 and testnet4 blocks are proof-of-work based like mainnet, they both allow for low difficulty blocks:
- testnet3 allows minimum difficulty blocks when a block's timestamp is 20 minutes after the previous block's timestamp, and resets the difficulty on an ongoing basis if this occurs for the last block in a retarget period.
- testnet4 updates these rules, as specified in BIP 94, basing the difficulty calculation for the first block in a new retarget period on the difficulty of the first block in the previous retarget period, rather than the previous block, avoiding a reset.
As a result, nodes could see many valid stale tips with minimum difficulty, either due to such tips being created with long timestamps, or, on testnet3, because the difficulty has been reset. To avoid this scenario, when implementing this BIP on testnet3 or testnet4:
- Nodes SHOULD only advertise stale tips when the stale tip itself has a difficulty greater than the minimum difficulty.
- Nodes MAY advertise stale tips only when the stale tip itself has a difficulty greater than some higher threshold, for example 1,000,000.
Backward Compatibility
This BIP introduces a new P2P message (staletip) and relies on BIP 434 for feature negotiation to avoid impacting nodes that do not support this BIP. Nodes MUST NOT send staletip messages to peers that have not negotiated the staletip feature.
Nodes that do not support this BIP may still see more frequent notifications of when their peers update to a new active tip, if implementations choose to make active-tip inv announcements to all peers rather than only to peers that negotiated the staletip feature.
Privacy Impact
Sharing stale tips raises several potential privacy concerns.
The first concern is fingerprinting. A node's behaviour when negotiating and sharing stale tips may make it easier for peers to distinguish that node from others on the network, perhaps allowing attackers to relate a node's onion address with its IPv4 address. The BIP 434 feature advertisement itself, the prefers_blocks value, active-tip announcement behaviour, and stale-tip relay timing are all potentially fingerprintable. Since stale tips are expected to propagate fairly efficiently and consistently, and to remain rare, this is not expected to be a significant problem in practice. For users that remain concerned, disabling stale tip relay entirely is probably the best approach.
The second concern is for miners with private transaction pools. In that case, miners have a selection of transactions that they wish to mine themselves without giving other miners the opportunity to compete with them, only publishing them when they construct a block with valid proof-of-work that includes them. Relaying those transactions via staletip announcements will largely be harmful to a private transaction pool operator, as it will not help them win the stale block race. It will only allow nodes to reorg slightly faster if they do win, but if they lose the stale block race it will make their private transactions available to competing miners. This is a particular concern if the reason for the block being stale is due to inefficiencies in updating ASIC miners to a new work target, in which case there is almost no chance of winning the stale block race. As such, miners operating private transaction pools should probably disable stale tip relay entirely on the nodes they use for processing their mined blocks.
Reference Implementation
A prototype implementation is available at:
- Bitcoin Core branch: https://github.com/w0xlt/bitcoin/tree/staletip-v4
Test Vectors
Signet Stale Branch (19 blocks)
This serialization test vector is from signet, where a 19-block stale branch occurred at height 287767-287785. Because this vector has have_block set to false, it is not an example of a Signet staletip message that conforming nodes should relay under the Signet-specific rules above.
| Field | Value |
|---|---|
| Network | Signet |
| Fork point height | 287766 |
| Fork point hash | 00000012602fde2eaf33a90523f42fb07ca854c1d26108782dc4592a80507e1c |
| Stale tip height | 287785 |
| Stale tip hash | 0000000024ff924ff932668d497bba7da9157559a68d9c87d2f28d22e5e4a001 |
| Branch length | 19 |
have_block |
false |
Serialized staletip payload (946 bytes):
1c7e50802a59c42d780861d2c154a87cb02ff42305a933af2ede2f60120000001300000020
67aa2937b235e209f1ad40f37b17dcad8ca02d1fb9cf4c4928902eab3ff853a6cda16e6916
58151d81ad7b0400000020721ab6f36042842bab4583f98e15181b646c47c7b9dfb07a204c
4e5152e54e97fda46e691658151dd2dcec1800000020ddc6b628101b404f78d446591a623e
12bb7e7cd2ae1593d0cc6ef082e19fa81014a66e691658151d46070e10000000208be5b960
7b20ac0163b885881aa6018ef60a5637b93a9cd85981515a169a31c36aab6e691658151de4
e10600000000206c974ef806b2e6a21cc9a53fedcbd5d5e203b4929a1bd7c5859ec77d0a75
5c1d64ae6e691658151d2a2e130e0000002039505fa2ee91f5e5b2540b4a9a7f02ed58d79f
c387412cf2520a39ee16bf435f6eb16e691658151db29c830a00000020411bce69cda2b239
c74faea1f0cfaceabd90377114dc0ace14e2a58858cd4f9a91b46e691658151d4c2d3f0500
00002096464a2ec42fea8419a5c6adcc41ca7dc3f53461cd0afc880f76498aa8eedbf993b5
6e691658151d5e99700b00000020c3cad611ee3c7bffec3f80fc83f68192ca0a86e8c89050
f8353480310d080caf08b76e691658151dbc61a6150000002079e36b5a06bb5a524a2f5bad
6725451613c354cbf64f9a0283f77fe90782d59fcbba6e691658151d6c669300000000204c
69fd467818994e7ff885181e7451d23869a7fd19447dad7a95398077ed7774dcba6e691658
151dc9c7ff02000000208ea9a871b12cd45226ab6df280ec46b8c9ca196b98dc8adc27718c
ab333e19a50abc6e691658151df6bae902000000209c182979424a5c85d55d5bddbf3b9421
b01b7810edf95ad2529552dd2eec80848ebd6e691658151d439e5c0000000020cfb9f6d164
3613dfdd23a6e1eabadac38c392f985f5dc05b00ef682c428922c96cbe6e691658151d278b
4d1400000020eea983b8d64947368de4f7626531a3134d18f20a8d87462ba011a4f56a53b6
ac4fbf6e691658151ddae8640800000020140bc70b1a3282fbebf9d48ff40a9b73ab7c76ad
522799cee73315e9c21aab50dcc06e691658151dedaae90f000000209b91a056fe089429f2
ba4298e764acb4177249ce7d68e6883836f70d1d9218b355c16e691658151d28a432060000
0020b26e80c6a12cc4595556d2318fda564ced5d2a526c7b77f57a9897a56c10539056c16e
691658151dc64fb50000000020369d36495749c96d36260d839abfa703a611aad7b3016342
ef05d0412f42221e6ac56e691658151d8f8bfb0f00
Payload breakdown:
- Bytes 0-31:
fork_point(uint256, little-endian) - Byte 32: vector length (
0x13= 19) - Bytes 33-944: 19
CompressedHeaderentries (48 bytes each) - Byte 945:
have_block(0x00=false)
BCH Fork Headers (18 blocks)
This test vector uses mainnet headers from the BCH fork. Blocks 478559-478576 have valid Bitcoin headers meeting proof-of-work requirements, but are invalid Bitcoin blocks because block 478559 exceeds the 1MB block size limit. Block 478577 changed difficulty under BCH's Emergency Difficulty Adjustment rules, making it an invalid Bitcoin header as well.
| Field | Value |
|---|---|
| Network | Mainnet |
| Fork point height | 478558 |
| Fork point hash | 0000000000000000011865af4122fe3b144e2cbeea86142e8ff2fb4107352d43 |
| Stale tip height | 478576 |
| Stale tip hash | 000000000000000001416af072f8989829f4c60a1a9658e1cec08411798e4ffa |
| Branch length | 18 |
have_block |
false |
Serialized staletip payload (898 bytes):
432d350741fbf28f2e1486eabe2c4e143bfe2241af65180100000000000000001200000020
abaa4bd8a48c1c6bc08ee39b66065e5e9484304cab8b56d5eed3e40b1ac996c899c4805935
47011822ca4ae80000002082afc8ef7eb41a4ecac1fea46983742e491f804ad662e3745ab9
c6c4297d8a0862c980593547011840a772cb0200002058874e50628fdf83aeea4e8cbc7ade
946e9ba14bcb1d8ffb28c3daf8ade84df65fca805935470118e2f5100300000020111b85f9
d3b969a1f7ff3d50af08893c500edfc5623b96dbeab6daf16a5164a40ace805935470118c4
f4240a0000002040a045063b551b61d6a1c9db6d3231e2d7403185bbb2332ae1f66db24aac
7fa288d8805935470118f15dd76b0000002070cb14529e8757c359c2e8b1e987f6eee6fbc4
472ee9ad4a2e5df6905c19d6d70bed80593547011885ae00d0000000209653314c1d73e463
0bb485fb25ce7a2583cec7c3ccfc27a6d24163be1e9fb19530f4805935470118f17ad2c500
000020cdf48b8e7ac6bf3a51d1878ee3ff7e6fd0022926dd69cc5cc8d9126e77c4dba809f5
8059354701188114e83600000020890cf1dc60edbf0fd4fb667f28ac785849c031d8b24d5e
5a0af56ee2bd8a739bf51081593547011812f32a9600000020ff5244613ad20fdc39b7ee6f
4fbc7016432d2dbf45c2a950c59665b39c3954b5b525815935470118aa790d6600000020ae
ed520e7c1693de5cfe7531e7d3e73dff7858b09cb6e1ec29229a75c3da2b92453e81593547
011830a4314d000000202e4a4054e64c3f5810c23ec0144d9793aab2d5a7d77d1660eee24d
3d55e8b715b543815935470118da1c00e00000002073152af68778a98fd984a158aeb29d28
e094e23c3a7dff02260c345791e52498c3fb8159354701188d5abed90000002022606e744a
29f9d4a67ff1fcd2f0e31300ddbd145f8f1db8a68270bfbde77dd88fff8159354701186af1
75f8000000209f5db27969fecc0ef71503279069b2df981ba545592a7b425f353b5060e77f
3e7e13825935470118da70378e000000202f0d316b08350f5cd998c6a11762d10adb9f951b
5f79ce2a073f8187c05f561f1b1c8259354701184834c62300000020cf8fc3bad8dad139a3
dd6a30481d87e1f760122573168002cc9ef7a58fc53ad387848259354701188a3b54f70000
00200eae92d9b46d81a011a79726a802d4eb195a7af8b70a09b0e115c391968c50d51c8a82
5935470118cd786d1300
Payload breakdown:
- Bytes 0-31:
fork_point(uint256, little-endian) - Byte 32: vector length (
0x12= 18) - Bytes 33-896: 18
CompressedHeaderentries (48 bytes each) - Byte 897:
have_block(0x00=false)
Copyright
This BIP is licensed under the 3-clause BSD license.
Omitting the previous block hash from each header saves 32 bytes per header (40%), as this field can be reconstructed from the preceding headers in the message. This does not apply to the first header, which is why the fork point must be included explicitly. This BIP does not attempt to omit
nBitsor compressnTimeornVersion, because reconstructing those fields is significantly more complicated for comparatively much less potential gain.↩︎Limiting the branch length to 20 headers avoids nodes being burdened with tracking deliberate chain splits. When incompatible consensus rules are enforced, the majority chain need not continue sharing the minority's fork beyond a short window. Twenty blocks is sufficient to capture the short-term stale blocks useful for reorg detection, while avoiding long-term tracking of persistent chain splits.↩︎
A window of 1000 blocks (about 7 days) provides a reasonable balance between limiting resource usage, and maximising propagation potential. By limiting the distance to the tip to being no older than the previous retarget period, we ensure that the difficulty of creating a stale block is comparable to creating a new tip, making it uneconomical to use this as a spamming mechanism. By choosing a longer period, we provide the opportunity for nodes interested in stale block data for research purposes plenty of opportunity to obtain the data. In particular, many nodes will tend to discover it through the periodic blocks-only connections (see Bitcoin Core PR #19858).↩︎
Limiting stale branches to 20 headers bounds the per-message size to under 1kB. Combining this with a default limit of 10 previously known stale tips advertised to a peer ensures that the initial relay bandwidth is under 10kB. Restricting relay to recent tips whose proof of work is comparable to the active chain makes stale-tip spam costly on mainnet.↩︎
Limiting stale branches to 20 headers bounds the per-message size to under 1kB. Combining this with a default limit of 10 previously known stale tips advertised to a peer ensures that the initial relay bandwidth is under 10kB. Restricting relay to recent tips whose proof of work is comparable to the active chain makes stale-tip spam costly on mainnet.↩︎
Limiting stale branches to 20 headers bounds the per-message size to under 1kB. Combining this with a default limit of 10 previously known stale tips advertised to a peer ensures that the initial relay bandwidth is under 10kB. Restricting relay to recent tips whose proof of work is comparable to the active chain makes stale-tip spam costly on mainnet.↩︎
Ignoring rather than punishing allows nodes to apply different limits for what stale tips they accept. If one node uses stricter limits than its peers, this avoids the risk that honest announcements from those peers will cause disconnection and potentially network partitions. This is also consistent with how invalid headers are handled.↩︎