BRC-132 Transactions

Multicast Subtree Data Frame Format

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 indi

Jeff Harris (jeff@lightweb.net)

How it connects

Relationships

Authoritative content mirror

Full upstream text

View source
Rendered from transactions/0132.md at the indexed upstream commit

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:

  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 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):

Index Scope Compressed Address Constant
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.

Addresses are shown in ASM (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 manifest).

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.

Offset Size Align Field Value / Notes
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 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

MsgType Constant Node Size Description
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)

Offset Size Field Description
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

Offset Size Field
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

Offset Size Field
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 = 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 size Fragments
~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

Condition Action
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

Name Value Hex Description
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