> For the complete documentation index, see [llms.txt](https://hub.bsvblockchain.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://hub.bsvblockchain.org/brc/transactions/0130.md).

# Multicast Transaction Frame Fragmentation

Jeff Harris (<jeff@lightweb.net>)

## Abstract

This BRC specifies a fragmentation extension to the BRC-124 Multicast Transaction Frame Format. When a BSV transaction payload exceeds the path MTU available on a multicast fabric, the proxy decomposes the payload into a sequence of fixed-size fragment datagrams. Listeners reassemble the fragments and verify the reconstructed payload against the transaction ID before forwarding. The fragment header is a strict superset of the BRC-124 header, enabling mixed-version infrastructure to identify and discard fragment frames it cannot process.

## Copyright

This BRC is licensed under the Open BSV License.

## Motivation

BSV transactions can be arbitrarily large. The 1500-byte Ethernet MTU imposes a hard limit on single-datagram UDP delivery; transactions exceeding \~1300 bytes of payload after IPv6 and UDP overhead cannot be transported in a single BRC-124 frame without IP fragmentation, which is unreliable on multicast paths and disabled by default on many fabrics.

Rather than rely on IP-layer fragmentation (which requires receiver kernel reassembly and breaks on many switch configurations), BRC-130 performs fragmentation at the application layer:

1. The proxy slices the payload into *k* equal-sized chunks and emits *k* independent UDP datagrams.
2. Each datagram carries a complete BRC-130 header that is layout-compatible with BRC-124, allowing existing firewall rules, packet classifiers, and traffic monitors to inspect the frame header fields.
3. Listeners reassemble fragments keyed on the Transaction ID and verify the result with SHA256d before forwarding.

## Specification

### Fragment Header Format (104 bytes)

A BRC-130 fragment datagram consists of a 104-byte header followed by the fragment data. All multi-byte integers are big-endian.

| Offset | Size | Align | Field          | Description                                               |
| ------ | ---- | ----- | -------------- | --------------------------------------------------------- |
| 0      | 4    | —     | Network Magic  | 0xE3E1F3E8 (BSV mainnet P2P magic)                        |
| 4      | 2    | —     | Protocol Ver   | 0x02BF (703, BSV large-block baseline)                    |
| 6      | 1    | —     | Frame Version  | 0x03 (BRC-130 fragment)                                   |
| 7      | 1    | —     | MsgType        | Carried-through MsgType (byte 7); 0x00 for BRC-124/128    |
| 8      | 32   | 8B    | Transaction ID | SHA256d(reassembled payload); same on every fragment      |
| 40     | 8    | 8B    | HashKey        | XXH64(senderIPv6 ∥ groupIdx ∥ subtreeID); per-flow        |
| 48     | 8    | 8B    | SeqNum         | Per-flow monotonic counter; independent per fragment      |
| 56     | 32   | 8B    | Subtree ID     | 32-byte batch identifier; zeros = unset                   |
| 88     | 4    | 8B    | PayloadLen     | Size of this fragment's data bytes (uint32 BE)            |
| 92     | 4    | 4B    | OrigPayloadLen | Total unfragmented payload length (uint32 BE)             |
| 96     | 2    | 2B    | FragIndex      | 0-based index of this fragment (uint16 BE)                |
| 98     | 2    | 2B    | FragTotal      | Total number of fragments in this transaction (uint16 BE) |
| 100    | 1    | —     | OrigFrameVer   | Original FrameVer before fragmentation; 0x00 ⇒ 0x02       |
| 101    | 3    | —     | Reserved       | Must be 0x000000                                          |
| 104    | \*   | —     | Fragment data  | Slice of the original payload (PayloadLen bytes)          |

Bytes 0–91 are **layout-identical** to a BRC-124 frame header (`FrameVer=0x03` and the byte-7 `MsgType` excepted). Existing infrastructure that inspects the Transaction ID, HashKey, SeqNum, or Subtree ID fields in a BRC-124 header will read correct values from a BRC-130 datagram at the same offsets.

### Field Definitions

#### Network Magic (bytes 0–3)

`0xE3E1F3E8` — identical to BRC-124. Enables BSV firewall rules and monitoring tools to classify fragment datagrams without modification.

#### Protocol Version (bytes 4–5)

`0x02BF` — identical to BRC-124. Informational; receivers do not validate it.

#### Frame Version (byte 6)

`0x03` — identifies this datagram as a BRC-130 fragment. Infrastructure that does not implement BRC-130 reassembly must silently discard datagrams with this version byte.

#### MsgType (byte 7)

The frame-type `MsgType` carried through from byte 7 of the original (pre-fragmentation) frame, so reassembly can reconstruct it. For fragmented BRC-124/128 transaction frames this byte is `0x00` (their byte 7 is reserved); for fragmented BRC-131 block frames it is `0x01`/`0x02` and for BRC-132 subtree frames `0x01`/`0x02`. Together with `OrigFrameVer` (byte 100) it fully restores the original header bytes 6–7 on reassembly.

#### Transaction ID (bytes 8–39)

The 32-byte double-SHA256 hash of the complete unfragmented payload:

```
TxID = SHA256(SHA256(reassembled_payload))
```

The same TxID appears on every fragment of a transaction. It serves as both the reassembly key and the integrity proof: after reassembly, the listener must verify `SHA256(SHA256(payload)) == TxID`.

#### HashKey (bytes 40–47)

An 8-byte stable per-flow identifier, computed by the proxy as:

```
HashKey = XXH64(senderIPv6[16B] ∥ groupIdx[4B BE] ∥ subtreeID[32B])
```

`XXH64` is the 64-bit xxHash algorithm (`github.com/cespare/xxhash/v2`). HashKey is the same for every BRC-124 and BRC-130 frame emitted by the same (sender, multicast-group, subtree-batch) flow. Senders set this field to 0; the proxy stamps it in-place.

**Note:** For fragment datagrams, the proxy stamps an **independent** HashKey and SeqNum per fragment (i.e., each fragment is treated as a separate frame for gap-tracking purposes). This allows retransmission of individual lost fragments via the standard BRC-126 NACK mechanism without changes to the retry endpoint.

#### SeqNum (bytes 48–55)

An 8-byte per-flow monotonic counter, starting at 1. The proxy increments the per-flow counter independently for each fragment datagram. Listeners detect gaps at the fragment granularity, enabling single-fragment retransmission.

Senders set SeqNum to 0; the proxy stamps it before forwarding.

#### Subtree ID (bytes 56–87)

Identical to BRC-124. A 32-byte batch identifier shared by all transactions belonging to the same subtree (BRC-119 STUMP root). All-zero bytes indicate the field is unset.

#### PayloadLen (bytes 88–91)

The number of fragment data bytes carried by **this datagram** — not the total original payload length. Equals `min(fragDataSize, origPayloadLen - fragIndex * fragDataSize)` for the last fragment, and `fragDataSize` for all prior fragments.

#### OrigPayloadLen (bytes 92–95)

The total length of the unfragmented payload in bytes. All fragments of the same transaction carry the same `OrigPayloadLen` value. Receivers use this to allocate a reassembly buffer of exactly the correct size.

#### FragIndex (bytes 96–97)

The 0-based index of this fragment within the transaction. Values range from `0` to `FragTotal - 1`.

#### FragTotal (bytes 98–99)

The total number of fragments into which the payload was divided. All fragments of the same transaction carry the same `FragTotal` value. Must be ≥ 1. `FragTotal = 1` is valid and means the payload was not split (degenerate case, used only for testing).

#### OrigFrameVer (byte 100)

The `FrameVer` of the original frame before fragmentation (`0x02` BRC-124/128, `0x04` BRC-131, `0x05` BRC-132, `0x06` BRC-134). A value of `0x00` defaults to `0x02` (BRC-124). Listeners use it — together with the byte-7 `MsgType` — to reconstruct the correct synthetic frame on reassembly.

#### Reserved (bytes 101–103)

Must be `0x000000`. Reserved for future protocol extensions.

### Fragment Data (byte 104 onward)

The slice of the original payload bytes corresponding to this fragment:

```
fragment[i].data = payload[i * fragDataSize : (i+1) * fragDataSize]
```

The last fragment carries the remaining bytes, which may be shorter than `fragDataSize`.

### Fragment Data Size

The fragment data size (`fragDataSize`) is derived from the configured path MTU:

```
fragDataSize = pathMTU - IPv6HeaderSize - UDPHeaderSize - BRC130HeaderSize
             = pathMTU - 40 - 8 - 104
             = pathMTU - 152
```

For standard Ethernet (pathMTU = 1500): `fragDataSize = 1348 bytes`.\
For jumbo frames (pathMTU = 9000): `fragDataSize = 8848 bytes`.

### Reassembly

A listener reassembles a fragmented transaction as follows:

1. **Slot allocation.** On receipt of the first fragment for a TxID, allocate a reassembly slot containing a `OrigPayloadLen`-byte buffer, a received-fragment bitmask of `FragTotal` bits, and a TTL timer.
2. **Fragment placement.** Copy fragment data into the buffer at `offset = fragIndex * fragDataSize`. Mark the fragment index as received.
3. **Completion check.** When all `FragTotal` fragment indices are marked received, proceed to verification.
4. **Hash verification.** Compute `SHA256(SHA256(buffer))` and compare to the TxID. If they differ, drop the slot and increment `bsl_reassembly_hash_mismatch_total`.
5. **Delivery.** Construct a synthetic BRC-124 frame (FrameVer = 0x02) carrying the reassembled payload and the TxID, HashKey, SeqNum, and SubtreeID from the first fragment received. Route the frame through the normal filter → egress → gap-tracking path.
6. **TTL eviction.** If a slot's TTL expires before all fragments arrive, discard the partial buffer and increment `bsl_reassembly_abandoned_total`. The default TTL is 10 seconds.
7. **Slot limits.** A reassembly buffer implementation may enforce a maximum number of concurrent slots (default: 4096). When the limit is reached, the oldest incomplete slot is evicted to make room for the new TxID.
8. **Duplicate fragments.** Duplicate fragments (same TxID + FragIndex) are silently ignored.

### Reassembly Metrics

Listeners implementing BRC-130 reassembly expose the following Prometheus counters:

| Metric                               | Description                                           |
| ------------------------------------ | ----------------------------------------------------- |
| `bsl_reassembly_started_total`       | New reassembly slots opened (first fragment received) |
| `bsl_reassembly_completed_total`     | Reassemblies completed and delivered downstream       |
| `bsl_reassembly_abandoned_total`     | Slots evicted due to TTL expiry or max-slots eviction |
| `bsl_reassembly_hash_mismatch_total` | Reassembled payloads that failed SHA256d verification |

### Error Handling

| Condition                      | Action                                      |
| ------------------------------ | ------------------------------------------- |
| Fragment version byte ≠ 0x03   | Not a BRC-130 datagram; decode as BRC-124   |
| Bad magic                      | Silent drop                                 |
| FragIndex ≥ FragTotal          | Silent drop (malformed fragment)            |
| FragTotal = 0                  | Silent drop (malformed)                     |
| OrigPayloadLen = 0             | Silent drop                                 |
| PayloadLen > fragDataSize      | Silent drop                                 |
| Datagram shorter than header   | Silent drop                                 |
| Hash mismatch after reassembly | Drop slot; increment hash\_mismatch counter |
| TTL expiry                     | Drop slot; increment abandoned counter      |

## Examples

### Two-Fragment Transaction (1500-byte path MTU)

A 2000-byte transaction payload is split into two fragments under a 1500-byte path MTU (`fragDataSize = 1348`):

**Fragment 0 (1452 bytes on wire):**

```
// BRC-130 header (104 bytes)
E3E1F3E8          // Network Magic
02BF              // Protocol Version
03                // Frame Version (BRC-130)
00                // Reserved
<32B TxID>        // SHA256d of full payload
<8B HashKey>      // XXH64(senderIPv6 ∥ groupIdx ∥ subtreeID)
<8B SeqNum>       // e.g. 0x0000000000000001
<32B SubtreeID>
00000544          // PayloadLen = 1348 (0x544)
000007D0          // OrigPayloadLen = 2000 (0x7D0)
0000              // FragIndex = 0
0002              // FragTotal = 2
00                // OrigFrameVer (0x00 = BRC-124)
000000            // Reserved

// Fragment data (1348 bytes: payload[0:1348])
```

**Fragment 1 (756 bytes on wire):**

```
// BRC-130 header (104 bytes)
E3E1F3E8
02BF
03
00
<32B TxID>        // Same TxID as fragment 0
<8B HashKey>      // Same flow HashKey
<8B SeqNum>       // e.g. 0x0000000000000002
<32B SubtreeID>
0000028C          // PayloadLen = 652 (0x28C; last fragment: 2000 - 1348 = 652)
000007D0          // OrigPayloadLen = 2000
0001              // FragIndex = 1
0002              // FragTotal = 2
00                // OrigFrameVer (0x00 = BRC-124)
000000            // Reserved

// Fragment data (652 bytes: payload[1348:2000])
```

## Compatibility

* **BRC-12 (FrameVer 0x01) receivers:** Must discard datagrams with FrameVer 0x03.
* **BRC-124 (FrameVer 0x02) receivers:** Must discard datagrams with FrameVer 0x03. BRC-130 fragments will not parse as valid BRC-124 frames because the `PayloadLen` field carries the fragment data size, not the full transaction length.
* **BRC-130 receivers:** Implement the reassembly procedure above and deliver a synthetic BRC-124 frame to downstream consumers.

The BRC-130 header is intentionally layout-compatible with BRC-124 at bytes 0–91 so that packet classifiers, firewall rules, and monitoring tools that inspect common header fields (magic, version, TxID, HashKey, SeqNum, SubtreeID) work correctly on fragment datagrams without modification.

## References

* [BRC-12: Raw Transaction Format](/brc/transactions/0012.md) — Payload format for BSV transactions
* [BRC-124: Multicast Transaction Frame Format](/brc/transactions/0124.md) — Base frame format extended by this BRC
* [BRC-119: SubTree Unified Merkle Path (STUMP) Format](/brc/transactions/0119.md) — Defines the Subtree ID concept

## Constants Reference

| Name                | Value | Hex    | Description                        |
| ------------------- | ----- | ------ | ---------------------------------- |
| FrameVerV3          | 3     | 0x03   | BRC-130 fragment frame version     |
| HeaderSizeV3        | 104   | 0x68   | BRC-130 header size in bytes       |
| IPv6HeaderSize      | 40    | 0x28   | IPv6 header overhead               |
| UDPHeaderSize       | 8     | 0x08   | UDP header overhead                |
| MinPathMTU          | 1280  | 0x500  | IPv6 minimum MTU (RFC 8200)        |
| EthernetMTU         | 1500  | 0x5DC  | Standard Ethernet MTU              |
| JumboMTU            | 9000  | 0x2328 | Jumbo frame MTU                    |
| DefaultFragDataSize | 1348  | 0x544  | fragDataSize at 1500-byte path MTU |


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://hub.bsvblockchain.org/brc/transactions/0130.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
