Multicast Subtree Data Frame Format
Jeff Harris (jeff@lightweb.net)
Abstract
This BRC defines frame version 0x05 for distributing complete Merkle subtree 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.
Copyright
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:
Reconstruct the subtree Merkle tree locally.
Verify block inclusion without fetching individual transactions.
Power block-assembly tooling and downstream analytics without per-transaction retrieval.
BRC-132 complements BRC-127, which maps SubtreeIDs to GroupIDs 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):
0xFFFB
site
FF05::B:FFFB
GroupSubtreeDataAnnounce
0xFFFB
org
FF08::B:FFFB
GroupSubtreeDataAnnounce
0xFFFB
global
FF0E::B:FFFB
GroupSubtreeDataAnnounce
Scope selection follows the GroupBeacon pattern defined in BRC-129. Operators select one or more scopes via the -announce-scope flag on listening components.
Frame Header Format (92 bytes)
The BRC-132 header is layout-identical to the BRC-124 header. All infrastructure components that inspect Magic, HashKey, 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.
0
4
—
Network Magic
0xE3E1F3E8 (BSV mainnet P2P magic)
4
2
—
Protocol Ver
0x02BF (703, BSV large-block baseline)
6
1
—
Frame Version
0x05 — BRC-132 subtree data
7
1
—
MsgType
0x01 = HashesOnly, 0x02 = FullNodes
8
32
8B
SubtreeID
SHA-256 Merkle root of the subtree (content ID)
40
8
8B
HashKey
XXH64(senderIPv6 ∥ 0xFFFB ∥ SubtreeID); proxy-stamped
48
8
8B
SeqNum
Monotonic counter per (sender, SubtreeID); proxy-stamped
56
32
8B
LayoutPad32
All zeros; retained for uniform HeaderSize = 92
88
4
8B
PayloadLen
Payload size in bytes (uint32 BE)
92
*
—
Payload
MsgType-specific subtree data (see §Payload Format)
Key distinctions from BRC-124:
Byte 7 carries
MsgTyperather thanReserved = 0x00.Bytes 8–39 carry
SubtreeID(the Merkle root), not aTxID.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 thatHeaderSize = 92remains uniform across V2/V4/V5.HashKeyis computed asXXH64(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
0x01
SubtreeMsgHashesOnly
32 bytes
TxHashes only (network transfer format)
0x02
SubtreeMsgFullNodes
48 bytes
TxHash + 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)
0
8
TotalFees
Aggregate fee sum for the subtree (uint64 BE)
8
8
TotalSizeBytes
Aggregate serialised tx size (uint64 BE, bytes)
16
8
NodeCount
Number of transaction nodes (uint64 BE)
MsgType 0x01 — HashesOnly
24
32 × N
TxHashes
24 + 32N
8
ConflictCount (uint64 BE)
24 + 32N + 8
32 × M
ConflictHashes
Maximum size at 1M nodes, 0 conflicts: 24 + 32 × 1,048,576 + 8 ≈ 32 MB.
MsgType 0x02 — FullNodes
24
48 × N
Nodes: TxHash (32B) ∥ Fee (8B BE) ∥ Size (8B BE)
24 + 48N
8
ConflictCount (uint64 BE)
24 + 48N + 8
32 × M
ConflictHashes
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 = 0x05in each BRC-130 fragment header (byte 100).MsgTypeis preserved in fragment header byte 7 (same pattern as BRC-131fragmentBlock).Fragment reassembly is keyed by SubtreeID (bytes 8–39), matching the
TxIDslot used by BRC-124 fragments.SHA256d hash verification does not apply — SubtreeID is a Merkle root, not a payload double-hash. The
verifyHashflag must befalsefor V5 reassembly slots.Optional post-reassembly Merkle-root verification is available (see §Merkle Verification).
Fragment counts at MTU 9000 (fragDataSize = 8848 bytes):
~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
HashKeyandSeqNumin-place before forwarding. Each(senderIPv6, SubtreeID)pair owns an independent monotonic sequence stream.If
SeqNumis 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:FFFBand cache BRC-132 frames and BRC-130 fragments (OrigFrameVer = 0x05) byHashKey ∥ SeqNum. On NACK, the frame is retransmitted toFF0X::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=trueon 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
raw[6] != 0x05
Not BRC-132; handled by other decoders
Bad magic
Silent drop
Unknown MsgType
Drop; ErrBadSubtreeMsg
PayloadLen exceeds buffer
Drop; io.ErrUnexpectedEOF
Datagram shorter than 92 bytes
Drop; ErrTooShort
SeqNum == 0
Frame not proxy-stamped; listener discards
Merkle mismatch (optional)
Drop; bsl_reassembly_merkle_mismatch_total++
Constants Reference
FrameVerV5
5
0x05
BRC-132 subtree data frame version
SubtreeMsgHashesOnly
1
0x01
MsgType: TxHashes only (32B per node)
SubtreeMsgFullNodes
2
0x02
MsgType: TxHash + Fee + Size (48B per node)
GroupSubtreeDataAnnounce
65531
0xFFFB
Subtree data multicast group index
HeaderSize
92
0x5C
BRC-132 header size (identical to BRC-124)
SubtreeDataPayloadHeaderSize
24
0x18
Fixed metadata prefix size
SubtreeNodeHashSize
32
0x20
Node size in HashesOnly payload
SubtreeNodeFullSize
48
0x30
Node size in FullNodes payload
References
BRC-119: SubTree Unified Merkle Path (STUMP) Format — SubtreeID definition and Merkle subtree structure
BRC-124: Multicast Transaction Frame Format — Base header layout reused by BRC-132
BRC-126: BSV Multicast NACK Retransmission Protocol — NACK-based reliability used for subtree frame retransmission
BRC-127: Multicast Subtree Group Announcement Frame Format — SubtreeID→GroupID metadata; distinct from BRC-132 data delivery
BRC-129: IPv6 Multicast Group Address Assignments — Group index allocations;
0xFFFB= GroupSubtreeDataAnnounceBRC-130: Multicast Frame Fragmentation — Fragmentation for large subtree payloads;
OrigFrameVer = 0x05BRC-131: Block Announcement Protocol —
FrameVerV4pattern followed by BRC-132
Last updated
Was this helpful?

