Skip to content

feat(rpc-gateway): SLOT_UDP_BIND — raw-shred UDP slot fast path#391

Merged
POPPIN-FUMI merged 1 commit into
mainfrom
feat/udp-direct-slot-source
May 19, 2026
Merged

feat(rpc-gateway): SLOT_UDP_BIND — raw-shred UDP slot fast path#391
POPPIN-FUMI merged 1 commit into
mainfrom
feat/udp-direct-slot-source

Conversation

@POPPIN-FUMI
Copy link
Copy Markdown
Contributor

Summary

Adds a third optional source to the slotSubscribe multiplex: a UDP
listener that reads the slot field directly from the Solana shred
header (offset 65, u64 LE), bypassing the gRPC proxy's decode +
serialize round-trip. Estimated savings: ~150–450 µs per slot.

How

When SLOT_UDP_BIND=host:port is set, the gateway spawns a tokio
UdpSocket loop that reads bytes 65..73 as a little-endian u64 and
feeds it into the same DeliveredWindow dedup the WS and gRPC
sources share.

The slot offset is part of the Solana shred wire protocol (=
solana_ledger::shred::wire::get_slot); we re-implement the read
inline so the gateway does not depend on the heavy solana-ledger
crate.

Security

Gateway does NOT verify shred signatures. Spoofing protection
relies on a strict nftables source-IP allowlist at the bind port,
in the same shape the existing :20000 proxy listener uses.

Env + ansible

  • SLOT_UDP_BIND=host:port — read in main.rs, plumbed through
    GatewayBuilder.slot_udp_bind.
  • Inventory var rpc_gateway_slot_udp_bind rendered into the
    systemd unit only when non-empty.
  • SKILL.md cascade table updated.

Deployment prerequisite (= no code in this PR)

To get any actual data on the UDP path, the upstream shred sender
(local jito-shredstream-proxy and/or stake-validator forwarder)
needs to include the gateway's UDP address in its --dest-ip-ports
comma-list. Plus an nftables allowlist on the bind port.

Test plan

  • cargo test -p slv-rpc-gateway --lib — 53 passed (5 new
    UDP tests + 48 existing unchanged)
  • cargo build --release -p slv-rpc-gateway — clean
  • CI green on this PR
  • After merge: deploy + reconfigure upstream senders +
    nftables allowlist + VPS bench to confirm UDP source wins
    slots vs the existing gRPC + WS sources.

Adds a third optional source to the `slotSubscribe` multiplex:
a UDP listener that reads the slot field directly from the Solana
shred header (offset 65, u64 LE), bypassing the gRPC proxy's decode
and serialize round-trip.  Estimated savings: ~150–450 µs per slot.

## How

When `SLOT_UDP_BIND=host:port` is set, the gateway spawns a tokio
`UdpSocket` loop that:
  - calls `recv_from` for each incoming packet,
  - reads bytes 65..73 as a little-endian u64 (= the slot field),
  - feeds it into the same `DeliveredWindow` dedup that the WS and
    gRPC sources share.

The slot offset is part of the Solana shred wire protocol (= what
`solana_ledger::shred::wire::get_slot` reads); we re-implement the
read inline so the gateway does not depend on the heavy
`solana-ledger` crate (which would pull in tens of MB of transitive
deps).

## Security

The gateway does NOT verify shred signatures.  Spoofing protection
relies on a strict source-IP allowlist (nftables) at the bind port,
in the same shape the existing shredstream-bench's `:20000` already
uses.

## Behaviour

- Zero-slot packets are dropped (= sentinel used by
  `slotsUpdatesSubscribe` probes and by zero-padded noise).
- Packets shorter than 73 bytes are dropped (can't hold the slot
  field).
- The multiplex activates whenever ANY of WS-URLs / gRPC URL /
  UDP bind is configured — the UDP-only configuration is valid.
- Other constructors (`slot_subscribe`, `first_shred`) default
  `udp_bind: None` and are unchanged for callers.

## Env + ansible

- `SLOT_UDP_BIND=host:port` — read in `main.rs`, passed through
  `GatewayBuilder.slot_udp_bind`.
- Inventory var `rpc_gateway_slot_udp_bind` rendered into the
  systemd unit only when non-empty.
- SKILL.md cascade table updated.

## Deployment prerequisite

To get any actual data on the UDP path, the upstream shred sender
(the local `jito-shredstream-proxy` and/or the stake-validator
forwarder) needs to include the gateway's UDP address in its
`--dest-ip-ports` comma-list.  Plus an nftables allowlist on the
bind port.  Both are operator config — no new code or sender
changes are in this PR.

## Tests

- 5 new unit tests in `ws::slot_source::tests`:
  - `parse_shred_slot_reads_offset_65_le` (canonical byte layout)
  - `parse_shred_slot_rejects_short_packets` (boundary)
  - `parse_shred_slot_rejects_zero_slot` (sentinel)
  - `first_shred_multiplex_stores_udp_bind` (ctor wiring)
  - `udp_shred_loop_delivers_unique_slots_through_dedup` (tokio
    end-to-end via `deliver()` — verifies dedup integration)
- 48 existing tests pass unchanged (one signature change in
  `first_shred_multiplex` propagated to two existing call sites).
- `cargo build --release` clean.
@POPPIN-FUMI POPPIN-FUMI merged commit 73e28d1 into main May 19, 2026
3 checks passed
@POPPIN-FUMI POPPIN-FUMI deleted the feat/udp-direct-slot-source branch May 19, 2026 18:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant