feat(rpc-gateway): SLOT_UDP_BIND — raw-shred UDP slot fast path#391
Merged
Conversation
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a third optional source to the
slotSubscribemultiplex: a UDPlistener 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:portis set, the gateway spawns a tokioUdpSocketloop that reads bytes 65..73 as a little-endian u64 andfeeds it into the same
DeliveredWindowdedup the WS and gRPCsources share.
The slot offset is part of the Solana shred wire protocol (=
solana_ledger::shred::wire::get_slot); we re-implement the readinline so the gateway does not depend on the heavy
solana-ledgercrate.
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
:20000proxy listener uses.Env + ansible
SLOT_UDP_BIND=host:port— read inmain.rs, plumbed throughGatewayBuilder.slot_udp_bind.rpc_gateway_slot_udp_bindrendered into thesystemd unit only when non-empty.
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-portscomma-list. Plus an nftables allowlist on the bind port.
Test plan
cargo test -p slv-rpc-gateway --lib— 53 passed (5 newUDP tests + 48 existing unchanged)
cargo build --release -p slv-rpc-gateway— cleannftables allowlist + VPS bench to confirm UDP source wins
slots vs the existing gRPC + WS sources.