Multicast Transaction Bundle Frame Format
Sending many tiny transactions as separate packets spends more on overhead than on content. This packs the ones heading the same way into a single frame.
Summary
- Why
- Sending each small transaction as its own multicast packet wastes forwarding capacity because packet-rate, not byte-rate, is the real cost of fan-out.
- What
- BRC-142 is a wire format that packs multiple small BSV transactions bound for the same shard group into a single multicast datagram.
- How
- A coalescing node groups transactions bound for the same shard group and subtree into a bundle header plus length-prefixed member list, and the receiving edge decoalesces it back into individual BRC-124 or BRC-128 frames (or raw BRC-12/BRC-30 transactions) before delivering to consumers.
What this lets you do
- Pack many small transactions into one multicast datagram
- Mix raw and Extended Format transactions in the same bundle
- Skip carrying per-member transaction IDs and let receivers recompute them
- Retransmit a lost bundle as a whole using existing NACK machinery
- Re-bucket a bundle when shard-bit width changes mid-flight
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-142 accurately, including what it depends on.
The specification
Abstract
This BRC specifies a coalescing extension to the BRC-124 and BRC-128 Multicast Transaction Frame Formats. A bundle packs many small BSV transactions — standard (BRC-12 raw) or Extended Format (BRC-30 EF) — that share one shard group and subtree into a single datagram, so a payload that would otherwise cross a multicast fabric as N small packets crosses it as one. It is the inverse of BRC-130 fragmentation, which splits one oversized transaction across many datagrams. Bundling reduces packets-per-second — the dominant per-packet forwarding cost of multicast fan-out — without changing transaction semantics.
Copyright
This BRC is licensed under the Open BSV License.
Motivation
Basic BSV payments are small — a typical pay-to-public-key-hash (P2PKH) transaction is only ~200 bytes — even though Bitcoin script imposes no such limit and many transactions are far larger. A large share of fabric traffic is therefore small-packet, and multicast fan-out cost is dominated by packets-per-second, not bandwidth: each replicated packet carries a per-packet forwarding cost largely independent of its size. A node that already forwards individual BRC-124/128 frames can pack many same-destination transactions into one datagram, cutting the packet rate it imposes on every downstream hop while carrying the same transactions. Bundling is an operator-side optimization: senders need not participate, and a node may bundle, or not, without coordination.
Specification
Bundle Header Format (66 bytes)
A bundle is identified by Frame Version 0x08. Unlike BRC-130, a bundle header
is not layout-compatible with BRC-124 — a bundle has no single Transaction
ID. All multi-byte integers are big-endian.
| Offset | Size | Field | Description |
|---|---|---|---|
| 0 | 4 | Network Magic | 0xE3E1F3E8 (BSV mainnet P2P magic) |
| 4 | 2 | Protocol Ver | 0x02BF (703) |
| 6 | 1 | Frame Version | 0x08 (BRC-142 bundle) |
| 7 | 1 | Flags | bit0 = TxIDsPresent (per-member Transaction ID present, all-or-none); bits 1–7 reserved (0) |
| 8 | 32 | Subtree ID | The single 32-byte subtree shared by all members; zeros = unset |
| 40 | 8 | HashKey | XXH64(senderIPv6 ∥ groupIdx ∥ subtreeID); the bundle flow identity |
| 48 | 8 | SeqNum | Per-flow monotonic counter, starts at 1; 0 = unset |
| 56 | 2 | GroupIdx | Shard group index this bundle was built for (uint16 BE) |
| 58 | 1 | ShardBits | Shard-bit width GroupIdx was computed at (1–12); pins the generation |
| 59 | 1 | Reserved | 0x00 |
| 60 | 2 | TxCount | Number of members (uint16 BE) |
| 62 | 4 | PayloadLen | Total byte length of the member section that follows (uint32 BE) |
| 66 | * | Member section | TxCount members (below) |
Member Format
The header is followed by TxCount length-prefixed members:
| Offset (relative) | Size | Field | Description |
|---|---|---|---|
| 0 | 2 | TxLen | Member transaction byte length (uint16 BE) |
| 2 | 32 | TxID | Present only when Flags.TxIDsPresent; raw 256-bit TxID |
| 2 or 34 | TxLen | Tx | Serialised BSV transaction — BRC-12 raw or BRC-30 Extended Format |
TxLenis a fixed uint16: a member must fit one datagram, so 16 bits suffices; a transaction that would exceed the path MTU is ineligible and uses BRC-130.- The per-member Transaction ID is optional (the
TxIDsPresentflag) because it is recomputable from the transaction, so carrying it is redundant wire data — and at 32 bytes per member it is a real density cost on small payments (~14% fewer members for a ~200-byte P2PKH tx), working against the packing this format exists for. Omit it by default and let receivers recomputeSHA256d(Tx). Carry it (set the flag) when a receiver needs the id without recompute — line-rate dedup or accounting — or for Extended Format members, whose canonical id is the hash of the de-extended base transaction (not of the EF bytes) and so cannot be cheaply recomputed. It is not a retransmission aid. - A member is a transaction in BRC-12 (raw) or BRC-30 (Extended Format) serialization; an EF member self-identifies by its 6-byte marker (payload bytes 4–9), so the two may be mixed in one bundle with no per-member type flag. The bundle carries only the transaction bytes — the egress format is the downstream consumer's contract, not the bundle's. On decoalesce the edge re-emits each member in the consumer's format: as a multicast frame — BRC-124 (raw) or BRC-128 (Extended Format), both Frame Version 0x02 — or in the transaction's own BRC-12 / BRC-30 format.
- Parsers read members until
PayloadLenbytes are consumed;TxCountis a cross-check.
Group, Subtree, and Flow Identity
Every member of a bundle satisfies GroupIndex(member TxID) == GroupIdx at
ShardBits (BRC-129) and carries the bundle's Subtree ID. A bundle is therefore
a single (sender, group, subtree) flow with one HashKey and one monotonic
SeqNum, exactly as a BRC-124 frame. This lets a bundle reuse the BRC-126
retransmission machinery unchanged: gap detection and NACK operate on the bundle
SeqNum stream.
A bundle is transport-agnostic: the on-wire bytes are identical under Any-Source
(ASM) and Source-Specific (SSM) multicast. Addressing, scopes, and the SSM
(S,G) join and source-discovery model are those of the underlying shard group
in BRC-129; the bundle's source is the coalescing node
(senderIPv6, the first HashKey ingredient), so a receiver joins the same
(S,G) it would for the group's BRC-124 frames.
GroupIdx and ShardBits are carried explicitly, rather than derived from
member Transaction IDs, so any node can classify and re-bucket a bundle
deterministically during a BRC-139 shard-bit transition — when the active
ShardBits, and therefore the group a Transaction ID maps to, is changing.
Coalescing and Decoalescing
A coalescing node buckets input frames by (group, subtree) and packs each
bucket into bundles, starting a new bundle when the next member would exceed the
path MTU or TxCount = 65535. A bundle never exceeds the path MTU and never
fragments: BRC-142 and BRC-130 are mutually exclusive per datagram. Coalescing
is bounded so a partial bundle is not held indefinitely — the bound (a maximum
delay or a batch window) is implementation-defined — and is opt-in, at an
implementation-defined granularity (per node or per flow; latency-sensitive
relay opts out).
Decoalescing splits a bundle back into individual transactions in the downstream consumer's format — each re-emitted as a multicast frame (BRC-124 for a raw transaction or BRC-128 for an Extended Format one, both Frame Version 0x02) or in the transaction's own BRC-12 / BRC-30 format. The default is edge-decoalesce: the fabric carries bundles and the edge node splits them before per-consumer delivery, leaving the consumer contract unchanged. Each emitted frame inherits the bundle's Subtree ID, carries its own (carried or recomputed) Transaction ID, and is assigned a per-transaction SeqNum on the egress flow. A consumer MAY instead opt to receive bundles directly.
Retransmission
The retransmission unit is the whole bundle. A lost bundle is a datagram the
receiver never saw, so it can only request the bundle by its SeqNum, not a
member within it. A retry endpoint caches and retransmits a bundle keyed on
(HashKey, SeqNum) exactly as a BRC-124 frame.
Re-bucketing
A relay forwarding a bundle into a domain or generation running a different
ShardBits MUST re-bucket it: decoalesce and re-coalesce at the target
ShardBits (learned from the BRC-139 manifest), routing each member to its
correct group, preserving the Subtree ID, and re-stamping the flow HashKey and
SeqNum. A relay MUST NOT deliver a bundle to a subscriber whose interest is
finer than the bundle's ShardBits without re-bucketing, since that subscriber
would receive — and, on loss, re-request — transactions outside its interest.
Error Handling
| Condition | Action |
|---|---|
| Frame Version ≠ 0x08 | Not a bundle; decode per its version |
| Bad magic | Silent drop |
| Datagram shorter than 66-byte header | Silent drop |
| PayloadLen exceeds datagram remainder | Silent drop (truncated) |
| Member runs past PayloadLen | Silent drop (malformed) |
| Member group ≠ GroupIdx at ShardBits | Encoder invariant — origin MUST pack only same-group members (not decoder-enforced) |
Compatibility
- BRC-12 (0x01) and BRC-124/128 (0x02) receivers MUST discard datagrams with Frame Version 0x08; a bundle does not parse as a single-transaction frame.
- BRC-142 receivers implement decoalescing (or re-bucketing, at a relay) and deliver individual transactions downstream — as multicast frames (BRC-124/128, 0x02) or in the transaction's base BRC-12 / BRC-30 format, per the consumer's contract — preserving existing consumer behaviour.
- Network Magic and Protocol Version are at the BRC-124 offsets, so firewall rules and classifiers matching those still recognise the datagram. The Transaction ID, HashKey, and SeqNum offsets differ from BRC-124, so a classifier reading those fields must branch on Frame Version 0x08.
References
- BRC-12: Raw Transaction Format — raw member payload and base egress format
- BRC-124: Multicast Transaction Frame Format — base frame coalesced by this BRC
- BRC-30: Transaction Extended Format (EF) — EF member payload and base egress format
- BRC-128: Multicast Extended Transaction Frame Format — Extended Format members
- BRC-126: Multicast Transaction NACK Retransmission Protocol — bundle-unit retransmission
- BRC-129: IPv6 Multicast Group Address Assignments — group/subtree addressing
- BRC-130: Multicast Transaction Frame Fragmentation — the inverse; mutually exclusive per datagram
- BRC-139: Multicast Shard Manifest Announcement Protocol — ShardBits/generation coordination
Constants Reference
| Name | Value | Hex | Description |
|---|---|---|---|
| FrameVerBundle | 8 | 0x08 | BRC-142 bundle frame version |
| BundleHeaderSize | 66 | 0x42 | Bundle header size in bytes |
| FlagTxIDsPresent | 1 | 0x01 | Flags bit 0: per-member TxIDs present |
| MaxMembers | 65535 | 0xFFFF | TxCount ceiling (uint16) |
| MaxMemberTxLen | 65535 | 0xFFFF | Largest member transaction (uint16) |