Beersy
BRC-132

Multicast Subtree Data Frame Format

Knowing a exists is not the same as having the transaction hashes in it. This defines a frame carrying those contents to everyone subscribed, so nobody has to request them.

Jeff Harrischanged 30 Jul 20267 min read
SubtreeIDMsgTypePayloadLenhashes+fees0

Summary

Why
Reconstructing and verifying a block's Merkle subtree, or assembling a block, required retrieving every individual transaction rather than the subtree's contents as a unit.
What
BRC-132 defines a multicast wire frame (version 0x05) that carries the full transaction hash list, and optionally fee and size, for a Merkle subtree.
How
A sender fills a 92-byte header (identical layout to BRC-124 but with a and MsgType instead of a TxID) followed by a payload of either bare transaction hashes or hash+fee+size nodes plus a conflict list, sends it to the GroupSubtreeDataAnnounce multicast group, and lets the existing BRC-130 fragmentation and

What this lets you do

  • Send full transaction hash lists for a Merkle subtree over multicast
  • Send per-transaction fee and size data alongside hashes with FullNodes mode
  • Rebuild a subtree's Merkle tree locally without fetching each transaction
  • Fragment and reassemble oversized subtree payloads using BRC-130
  • Verify received subtree contents against the SubtreeID

Written by claude-sonnet-5 from the specification text. Where the two differ, the original is correct.

Reference for an AI

Everything an assistant needs to answer questions about BRC-132 accurately, including what it depends on.

The specification

Abstract

This BRC defines frame version 0x05 for distributing complete Merkle contents — transaction hashes and optional per-transaction metadata — over the IPv6 multicast fabric. Subtree data frames are delivered to all subscribers via the dedicated GroupSubtreeDataAnnounce multicast group (FF0X::B:FFFB), independently of the per-shard groups used for individual transaction distribution.

This BRC is licensed under the Open BSV License.

Motivation

The multicast fabric distributes individual transactions shard-by-shard (BRC-124) and block-level metadata (BRC-131). BRC-132 fills the remaining gap: delivering the contents of each Merkle subtree so that subscribers can:

  1. Reconstruct the subtree Merkle tree locally.
  2. Verify block inclusion without fetching individual transactions.
  3. Power block-assembly tooling and downstream analytics without per-transaction retrieval.

BRC-132 complements BRC-127, which maps to for shard-level filtering. BRC-127 announces where a subtree lives; BRC-132 delivers what it contains.

Specification

Multicast Group

Subtree data frames are sent to the GroupSubtreeDataAnnounce group (index 0xFFFB):

IndexScopeCompressed AddressConstant
0xFFFBsiteFF05::B:FFFBGroupSubtreeDataAnnounce
0xFFFBorgFF08::B:FFFBGroupSubtreeDataAnnounce
0xFFFBglobalFF0E::B:FFFBGroupSubtreeDataAnnounce

Scope selection follows the GroupBeacon pattern defined in BRC-129. Operators select one or more scopes via the -announce-scope flag on listening components.

Addresses are shown in (FF0x) form; under SSM, substitute the FF3x prefix per BRC-129 (FF3E::B:FFFB for inter-domain scope, SSM-only per RFC 8815). The frame format and NACK/fragmentation paths are unchanged. Under SSM, receivers (S,G)-join using the subtree-data source (the emitting proxy, senderIPv6); the source set is distributed per BRC-129 (data-plane sources via the shard ).

Frame Header Format (92 bytes)

The BRC-132 header is layout-identical to the BRC-124 header. All infrastructure components that inspect Magic, , or SeqNum read correct values at the same offsets. The header is read using the same 44+48 two-step protocol as BRC-124 and BRC-131.

OffsetSizeAlignFieldValue /
04Network Magic0xE3E1F3E8 (BSV mainnet P2P magic)
42Protocol Ver0x02BF (703, BSV large-block baseline)
61Frame Version0x05 — BRC-132 subtree data
71MsgType0x01 = HashesOnly, 0x02 = FullNodes
8328BSubtreeIDSHA-256 of the subtree (content ID)
4088BHashKeyXXH64(senderIPv6 ∥ 0xFFFB ∥ SubtreeID); proxy-stamped
4888BSeqNumMonotonic counter per (sender, SubtreeID); proxy-stamped
56328BLayoutPad32All zeros; retained for uniform HeaderSize = 92
8848BPayloadLenPayload size in bytes (uint32 BE)
92*PayloadMsgType-specific subtree data (see §Payload Format)

Key distinctions from BRC-124:

  • Byte 7 carries MsgType rather than Reserved = 0x00.
  • Bytes 8–39 carry SubtreeID (the Merkle root), not a TxID.
  • LayoutPad32 (bytes 56–87) is always zero. SubtreeID already serves as content identifier and flow scope; no secondary field is needed. The field is retained so that HeaderSize = 92 remains uniform across V2/V4/V5.
  • HashKey is computed as XXH64(senderIPv6 ∥ 0xFFFB ∥ SubtreeID). Each distinct subtree from the same sender has an independent sequence stream, so loss in one subtree does not create false gaps in another.

MsgType Values

MsgTypeConstantNode SizeDescription
0x01SubtreeMsgHashesOnly32 bytesTxHashes only (network transfer format)
0x02SubtreeMsgFullNodes48 bytesTxHash + Fee + Size per node

Any other MsgType value causes the frame to be rejected with ErrBadSubtreeMsg.

Payload Format

Both MsgType variants share a 24-byte metadata prefix followed by N node entries and a conflict set.

Common Prefix (24 bytes)

OffsetSizeFieldDescription
08TotalFeesAggregate fee sum for the subtree (uint64 BE)
88TotalSizeBytesAggregate serialised tx size (uint64 BE, bytes)
168NodeCountNumber of transaction nodes (uint64 BE)

MsgType 0x01 — HashesOnly

OffsetSizeField
2432 × NTxHashes
24 + 32N8ConflictCount (uint64 BE)
24 + 32N + 832 × MConflictHashes

Maximum size at 1M nodes, 0 conflicts: 24 + 32 × 1,048,576 + 8 ≈ 32 MB.

MsgType 0x02 — FullNodes

OffsetSizeField
2448 × NNodes: TxHash (32B) ∥ Fee (8B BE) ∥ Size (8B BE)
24 + 48N8ConflictCount (uint64 BE)
24 + 48N + 832 × MConflictHashes

Maximum size at 1M nodes, 0 conflicts: 24 + 48 × 1,048,576 + 8 ≈ 48 MB.

Fragmentation

Payloads of 32–48 MB exceed any path MTU. The proxy fragments each BRC-132 frame using BRC-130:

  • OrigFrameVer = 0x05 in each BRC-130 fragment header (byte 100).
  • MsgType is preserved in fragment header byte 7 (same pattern as BRC-131 fragmentBlock).
  • Fragment reassembly is keyed by SubtreeID (bytes 8–39), matching the TxID slot used by BRC-124 fragments.
  • SHA256d hash verification does not apply — SubtreeID is a Merkle root, not a payload double-hash. The verifyHash flag must be false for V5 reassembly slots.
  • Optional post-reassembly Merkle-root verification is available (see §Merkle Verification).

Fragment counts at MTU 9000 (fragDataSize = 8848 bytes):

Subtree sizeFragments
~32 MB (HashesOnly, 1M nodes)~3,793
~48 MB (FullNodes, 1M nodes)~5,689

Both fit within the uint16 FragTotal limit of 65,535.

Sequence Tracking and Retransmission

BRC-132 frames participate in the same NACK-based reliability mechanism as BRC-124 and BRC-131:

  • The proxy stamps HashKey and SeqNum in-place before forwarding. Each (senderIPv6, SubtreeID) pair owns an independent monotonic sequence stream.
  • If SeqNum is already non-zero on arrival, the frame is forwarded verbatim (pre-stamped path).
  • Listeners detect gaps on the (HashKey, 0xFFFB, SubtreeID) flow and dispatch BRC-126 NACKs to retry endpoints.
  • Retry endpoints join FF0X::B:FFFB and cache BRC-132 frames and BRC-130 fragments (OrigFrameVer = 0x05) by HashKey ∥ SeqNum. On NACK, the frame is retransmitted to FF0X::B:FFFB. The retry endpoint TTL for BRC-132 frames defaults to 120 s (compared to 60 s for transaction frames) to accommodate large reassembly windows.

Merkle Verification

After reassembly, optional Merkle-root recomputation verifies the SubtreeID:

  • Enabled by -subtree-data-verify-merkle / SUBTREE_DATA_VERIFY_MERKLE=true on the listener.
  • The listener decodes the payload into nodes and computes SHA256d pairwise up the binary tree, then compares the root to SubtreeID.
  • Computationally significant at 1M nodes (~1M double-SHA256 operations); disabled by default.
  • On mismatch: drop the reassembly slot; increment bsl_reassembly_merkle_mismatch_total.

Error Handling

ConditionAction
raw[6] != 0x05Not BRC-132; handled by other decoders
Bad magicSilent drop
Unknown MsgTypeDrop; ErrBadSubtreeMsg
PayloadLen exceeds bufferDrop; io.ErrUnexpectedEOF
Datagram shorter than 92 bytesDrop; ErrTooShort
SeqNum == 0Frame not proxy-stamped; listener discards
Merkle mismatch (optional)Drop; bsl_reassembly_merkle_mismatch_total++

Constants Reference

NameValueHexDescription
FrameVerV550x05BRC-132 subtree data frame version
SubtreeMsgHashesOnly10x01MsgType: TxHashes only (32B per node)
SubtreeMsgFullNodes20x02MsgType: TxHash + Fee + Size (48B per node)
GroupSubtreeDataAnnounce655310xFFFBSubtree data multicast group index
HeaderSize920x5CBRC-132 header size (identical to BRC-124)
SubtreeDataPayloadHeaderSize240x18Fixed metadata prefix size
SubtreeNodeHashSize320x20Node size in HashesOnly payload
SubtreeNodeFullSize480x30Node size in FullNodes payload

References

Was this helpful?

Search Beersy

Search standards by number, title, author or topic