For the complete documentation index, see llms.txt. This page is also available as Markdown.

Multicast Transaction NACK Retransmission Protocol

Jeff Harris (jeff@lightweb.net)

Abstract

This BRC specifies the NACK-based retransmission and endpoint discovery protocol for the BSV multicast transaction distribution pipeline. It defines five UDP datagram formats — ADVERT, NACK, MISS, ACK, and THROTTLED — along with tier/preference-based endpoint selection, an escalation state machine, and configurable retransmit modes. The protocol operates on top of the BRC-124 data-plane and enables reliable gap recovery without requiring connection state at the ingress or listener tiers.

This BRC is licensed under the Open BSV License.

Motivation

The BRC-124 data-plane delivers BSV transactions over IPv6 multicast with best-effort semantics. Network congestion, interface buffer overflows, and MLD snooping transitions can cause individual frames to be lost. Because BRC-124 frames carry a stable per-flow HashKey and a monotonic SeqNum stamped by the ingress proxy, listeners can detect exactly which frame is missing without a central sequence authority.

This BRC adds the reliability layer that allows listeners to recover those gaps:

  1. Gap detection — listeners identify missing frames when a frame's SeqNum advances by more than 1 from the last-seen value for a given HashKey flow.

  2. NACK dispatch — listeners send a 64-byte NACK datagram to a retry endpoint identifying the missing frame by its flow (HashKey) and sequence number.

  3. ACK/MISS/THROTTLED responses — every served NACK receives a deterministic 16-byte response; ACK confirms retransmit dispatched, MISS triggers immediate escalation, and the optional THROTTLED signals honest congestion (hold and retry the same endpoint without escalating).

  4. Endpoint discovery — retry endpoints periodically multicast a 56-byte ADVERT beacon; listeners maintain a dynamic registry sorted by tier and preference, with no manual configuration required in well-connected deployments.

  5. Flood prevention — deduplication and fill-suppression mechanisms prevent retransmit storms at scale.

Specification

Common Message Preamble

All BRC-126 datagrams begin with a 7-byte preamble:

Offset
Size
Field
Description

0

4

Network Magic

0xE3E1F3E8 (BSV mainnet P2P magic)

4

2

Protocol Ver

0x02BF (703, BSV large-block baseline)

6

1

MsgType

Identifies the message type (see below)

The MsgType byte at offset 6 is in the same position as FrameVersion in BRC-124 data frames. Values 0x100x2F are reserved for BRC-126 control messages and are distinct from the data-frame version codes (0x010x07).

MsgType Values

MsgType
Name
Size
Direction

0x10

NACK

64 B

Listener → Retry endpoint

0x11

MISS

16 B

Retry endpoint → Listener

0x12

ACK

16 B

Retry endpoint → Listener

0x13

THROTTLED

16 B

Retry endpoint → Listener

0x20

ADVERT

56 B

Retry endpoint → Beacon group


ADVERT Wire Format (MsgType 0x20) — 56 bytes

Sent periodically by retry endpoints to the beacon multicast group. Listeners use it to build and maintain their endpoint registry.

Offset
Size
Field
Description

0

4

Network Magic

0xE3E1F3E8

4

2

Protocol Ver

0x02BF

6

1

MsgType

0x20 (ADVERT)

7

1

Scope

0x05 = site-local, 0x08 = org, 0x0E = global

8

16

NACKAddr

IPv6 unicast address listeners use for NACK requests

24

2

NACKPort

UDP port for NACK requests (default 9300)

26

1

Tier

Operator-assigned proximity tier; 0 = source-adjacent

27

1

Preference

Within-tier priority; higher = more preferred (default 128)

28

2

BeaconInterval

Beacon send interval in seconds; listeners TTL = 3 × this

30

2

Flags

Capability bitmask (see below)

32

4

InstanceID

CRC32c of hostname; stable across restarts

36

4

Reserved

Must be 0x00000000

40

16

Reserved

Must be all zeros; reserved for future capability bitmap

ADVERT Flags Bitmask

Bit
Name
Meaning

0x01

(reserved)

Unused; must be zero

0x02

HasParent

Endpoint forwards cache-miss NACKs to an upstream endpoint

0x04

Draining

Entering shutdown; listeners should stop routing new NACKs

0x08

UnicastRetransmit

Supports unicast frame delivery to the NACK source

0x10

MulticastRetransmit

Retransmits via multicast to the original shard group

HasParent: When set, the endpoint maintains a connection to a parent (higher-tier) endpoint and forwards NACKs on local cache miss. Listeners need only know their local tier; inter-tier forwarding is handled transparently.

Beacon group addresses are derived from the shard address scheme using the reserved control-plane index 0xFFFD:

Scope
Beacon Group

Site (0x05)

FF05::B:FFFD

Org (0x08)

FF08::B:FFFD

Global (0x0E)

FF0E::B:FFFD

Addresses use the IANA-aligned layout: bytes 0–1 carry the scope prefix, bytes 2–11 are zero (IANA 96-bit boundary), bytes 12–13 carry the IANA Bitcoin group-id (0x000B), and bytes 14–15 carry the group index. Operators MAY override the group-id via -mc-group-id.


NACK Wire Format (MsgType 0x10) — 64 bytes

Sent by a listener to a retry endpoint when a gap is detected. Identifies the missing frame by its flow (HashKey) and sequence number range. For current single-frame retrieval, StartSeq == EndSeq; range requests (StartSeq < EndSeq) are reserved for future use.

Offset
Size
Field
Description

0

4

Magic

0xE3E1F3E8

4

2

ProtoVer

0x02BF

6

1

MsgType

0x10 (NACK)

7

1

Flags

Bit 0 (0x01) = Proxied; bits 1–7 reserved, must be 0

8

8

HashKey

Stable per-flow XXH64 identifier; from BRC-124 frame bytes 40–47

16

8

StartSeq

First missing SeqNum (inclusive)

24

8

EndSeq

Last missing SeqNum (inclusive); equals StartSeq for single-frame retrieval

32

32

SubtreeID

32-byte batch identifier; from BRC-124 frame bytes 56–87; zeros = unset

The listener opens a per-request ephemeral UDP socket ([::]:0), sends the NACK, and waits up to 300 ms for a single response (MISS or ACK).

HashKey (offset 8) is the HashKey field from the BRC-124 frame, computed as XXH64(senderIPv6 ∥ groupIdx ∥ subtreeID). It uniquely identifies the flow. The retry endpoint uses HashKey as a per-flow rate-limiting key (NACK storm cap). A value of 0 bypasses the per-flow check.

StartSeq / EndSeq (offsets 16/24) specify the range of missing sequence numbers. For current single-frame retrieval, StartSeq == EndSeq. The retry endpoint looks up the frame using the 16-byte cache key HashKey ∥ StartSeq.

SubtreeID (offset 32) is carried for informational purposes; the cache key is HashKey ∥ SeqNum and does not require SubtreeID for disambiguation.

Flags / Proxied (offset 7, bit 0x01) marks a NACK that an endpoint issued on behalf of a downstream multicast domain (cross-domain proxying — see NACK Proxying). An endpoint receiving a NACK with this bit set MUST serve it from its own cache but MUST NOT re-proxy it, bounding any proxy chain to a single hop. The bit was previously reserved and is ignored by legacy endpoints, which simply never re-proxy.


NACK Proxying (cross-domain recovery)

A retry endpoint serving a downstream multicast domain (one fed by a listener's multicast egress rather than directly by the ingress proxy) can only cache what the listener actually emitted. A frame the listener never put on the downstream wire — egress send error, interface flap, or in-fabric loss — is missed identically by the downstream endpoint and every downstream consumer, so a downstream-only cache cannot repair it. NACK proxying recovers such frames from an upstream endpoint that received them directly from the ingress proxy:

  1. A downstream consumer NACKs the downstream endpoint, which suffers a local cache miss and returns MISS immediately.

  2. The downstream endpoint forwards the NACK to a statically configured upstream endpoint with the Proxied flag set (0x01). Recovery is asynchronous ("cache-warm"); no NACK worker is held waiting.

  3. The upstream endpoint serves the proxied NACK from its cache. Because the requester (the downstream endpoint) is not joined to the upstream shard groups, the frame is returned by unicast to the NACK source — a proxied NACK is always served a unicast copy regardless of the upstream's advertised retransmit mode.

  4. The downstream endpoint re-caches the recovered frame (keyed HashKey ∥ SeqNum, per-FrameVer TTL) and multicast-retransmits it into the downstream domain; the consumer's gap auto-fills via Tracker.Fill().

One-hop bound. The Proxied flag prevents an upstream endpoint from re-proxying, so any proxy chain is at most one hop. Upstream discovery is by static configuration, because a separated downstream domain generally cannot receive upstream multicast ADVERT beacons. The HasParent ADVERT flag (0x02) signals that an endpoint has an upstream parent configured. When several downstream endpoints run with proxying enabled against a shared cache backend, an in-flight claim deduplicates the upstream NACKs so only one endpoint recovers each gap.


MISS Response (MsgType 0x11) — 16 bytes

Sent unicast to the NACK source when the requested frame is not in the endpoint's cache. On receipt, the listener advances immediately to the next endpoint (no backoff delay).

Offset
Size
Field
Description

0

4

Magic

0xE3E1F3E8

4

2

ProtoVer

0x02BF

6

1

MsgType

0x11 (MISS)

7

1

Flags

Reserved; must be 0x00

8

8

SeqNum

Always 0 on MISS


ACK Response (MsgType 0x12) — 16 bytes

Sent unicast to the NACK source when the frame was found and retransmit dispatched. On receipt, the listener cancels the gap entry immediately.

Offset
Size
Field
Description

0

4

Magic

0xE3E1F3E8

4

2

ProtoVer

0x02BF

6

1

MsgType

0x12 (ACK)

7

1

Flags

0x01 = multicast sent; 0x02 = unicast sent

8

8

SeqNum

SeqNum of the retransmitted frame (from BRC-124 bytes 48–55)

The listener uses the SeqNum echo to confirm the gap entry matches before cancelling it.


THROTTLED Response (MsgType 0x13) — 16 bytes

Sent unicast to the NACK source when the request was rejected by a congestion-control tier that limits per-gap or per-flow request rate (see Flood Prevention). It is a flow-control signal, not a failure: the endpoint is healthy, and for a per-gap throttle a retransmit for this exact gap was likely just served and is propagating over the multicast data plane. On receipt a listener MUST hold the gap for the hinted backoff and retry the same endpoint; it MUST NOT escalate to another endpoint and MUST NOT count the throttle as a recovery failure.

Offset
Size
Field
Description

0

4

Magic

0xE3E1F3E8

4

2

ProtoVer

0x02BF

6

1

MsgType

0x13 (THROTTLED)

7

1

Flags

Bits 0-3 = backoff bucket; 4-7 reserved

8

8

SeqNum

Echo of the throttled request's StartSeq

Backoff hint. The suggested hold is ThrottleHintBase << bucket, where ThrottleHintBase = 125 ms and bucket is the Flags low nibble. Endpoints SHOULD use bucket 2 (~500 ms) for a per-gap throttle and bucket 3 (~1 s) for a per-flow throttle. Listeners SHOULD apply jitter (e.g. uniform over [hold/2, hold]) to de-synchronise and MAY clamp the hold to a local maximum. The gap's absolute TTL remains the upper bound; a multicast repair cancels the gap regardless.

Emission rules.

  • THROTTLED is OPTIONAL and SHOULD default to disabled; it is a load-shedding refinement for high-fan-out deployments.

  • An endpoint MUST NOT send THROTTLED for a flood-tier (per-source) rejection: that tier sheds abusive or spoofed-source load, and answering it would permit reflection. (The 16-byte response is smaller than the 64-byte NACK, so the protocol is never a bandwidth amplifier regardless.)

  • An endpoint that does not implement THROTTLED stays silent; the listener falls back to timeout + backoff.

  • A listener that does not recognise 0x13 treats it as an unparseable response (timeout-equivalent), so emission is backward-compatible.


Tier / Preference Model

Retry endpoints are organised into tiers representing proximity to the transaction source, and assigned a preference within each tier.

Tier
Meaning

0

Same AS as bitcoin-shard-proxy (source-adjacent)

1

One AS boundary from source

N

N AS hops from source

0xFF

Static seed (no beacon received; lowest priority)

Endpoints discovered via ADVERT carry their operator-assigned Tier (0–254) and Preference (0–255). Endpoints registered via static configuration seed the registry at Tier=0xFF, Preference=0.

Listeners sort the endpoint registry by (Tier ASC, Preference DESC). NACK dispatch always selects the head of the sorted list; on MISS or timeout, the listener advances to the next position.

Escalation State Machine

  • ACK received: Cancel gap entry. No further NACKs sent for this gap.

  • MISS received: Advance to next endpoint at same tier by Preference; if tier exhausted, move to next tier; retry immediately.

  • Timeout: Apply exponential backoff (capped at nack-backoff-max); retry on next sweeper tick.

  • THROTTLED received: Hold the gap for the hinted backoff and retry the same endpoint. Do not escalate and do not count it as a recovery failure — it is congestion control (see THROTTLED Response).

  • Multicast fill: The data-plane receive goroutine calls Tracker.Fill() independently; gap cancelled regardless of NACK state.


Beacon Scopes

Three scope bytes are defined for the ADVERT wire format. The reference implementation's -beacon-scope flag accepts site, global, or both (sends to site + global simultaneously):

Scope
Scope byte
Beacon group
Use case

Site (0x05)

0x05

FF05::B:FFFD

Intra-site discovery; all listeners join at startup

Org (0x08)

0x08

FF08::B:FFFD

Organisation-wide discovery for multi-site AS

Global (0x0E)

0x0E

FF0E::B:FFFD

Inter-AS discovery via MP-BGP MVPN / MSDP

Scope byte 0xFF is used in ADVERT datagrams when the sender intends to cover both site and global simultaneously (sends two ADVERTs). Listeners parse the scope byte from each individual datagram.

To cover multiple scopes, run separate endpoint instances each configured with a different -beacon-scope value. Each scope can use independent Tier and Preference tuning.

Listeners compute TTL as 3 × BeaconInterval. An endpoint not heard for that duration is evicted from the registry. Static seeds (-retry-endpoints) are never evicted.


Configurable Retransmit Modes

Retransmit behavior is controlled by flags on the retry endpoint:

Flag
Default
Effect

-retransmit-multicast

true

Retransmit frame to original multicast shard group

-retransmit-unicast

false

Retransmit frame unicast to NACK source

-suppress-miss

false

Do not send MISS response on cache miss

-suppress-ack

false

Do not send ACK response on cache hit

Deployment profiles:

  • On-fabric (default): -retransmit-multicast=true — all listeners on the fabric receive the retransmit simultaneously.

  • Edge / unicast: -retransmit-unicast=true -retransmit-multicast=false — for listeners not on the multicast fabric.

  • High-volume: -suppress-ack=true — reduces per-frame ACK traffic; MISS responses are preserved for escalation correctness.


Flood Prevention

Mechanism
Component
Effect

Cache TTL (60 s)

Retry endpoint

Frames expire naturally; bounds retransmit window

Tracker.Fill()

Listener

Multicast repair cancels all pending NACKs for a gap

Jitter hold-off

Listener

Randomised delay before first NACK suppresses correlated duplicates

Exponential backoff

Listener

Reduces NACK rate on persistent or repeated gaps

MaxRetries + GapTTL

Listener

Gap entries evicted after retry exhaustion or absolute deadline

THROTTLED hint

Retry endpoint

Tells throttled listeners to hold (vs. timeout + escalate), cutting NACK load on honest congestion; IP flood tier stays silent


Examples

ADVERT Datagram (56 bytes)

A site-scope endpoint at fd20::24, port 9300, Tier 0, Preference 128, 60-second interval, multicast retransmit enabled:

NACK Datagram (64 bytes)

Single-frame retrieval: missing frame for flow HashKey=0xA1B2C3D400000001, SeqNum=1235:

MISS Response (16 bytes)

ACK Response (16 bytes)

Frame found and retransmitted via multicast:


References


Constants Reference

Name
Value
Hex
Description

MagicBSV

3823236072

0xE3E1F3E8

BSV mainnet P2P magic

ProtoVer

703

0x02BF

Protocol version

MsgTypeNACK

16

0x10

NACK request

MsgTypeMISS

17

0x11

MISS response

MsgTypeACK

18

0x12

ACK response

MsgTypeADVERT

32

0x20

Endpoint advertisement beacon

ScopeSite

5

0x05

Site-local beacon scope

ScopeOrg

8

0x08

Organisation beacon scope

ScopeGlobal

14

0x0E

Global beacon scope

NACKSize

64

0x40

NACK datagram size in bytes

FlagProxied

1

0x01

NACK flag: proxied, one-hop downstream

FlagMulticastSent

1

0x01

ACK flag: multicast retransmit sent

FlagUnicastSent

2

0x02

ACK flag: unicast retransmit sent

FlagHasParent

2

0x02

ADVERT flag: upstream endpoint set

FlagDraining

4

0x04

ADVERT flag: endpoint is draining

FlagUnicastRetransmit

8

0x08

ADVERT flag: unicast retransmit

FlagMcastRetransmit

16

0x10

ADVERT flag: multicast retransmit

GroupBeacon

65533

0xFFFD

Control-plane beacon group index

DefaultNACKPort

9300

0x2454

Default NACK/ADVERT UDP port

DefaultBeaconInterval

60

Default ADVERT send interval (s)

DefaultCacheTTL

60

Default frame cache TTL (s)

TierStaticSeed

255

0xFF

Tier assigned to static seed endpoints

Last updated

Was this helpful?