sof
sof is the SOF observer/runtime crate.
It is built for low-latency Solana data ingest, local runtime-derived signals, and services that need infrastructure-style control over replay, control-plane freshness, and bounded multicore packet handling.
Core responsibilities:
- shred ingestion (direct UDP, relay, optional gossip bootstrap)
- optional shred verification
- dataset reconstruction and transaction extraction
- plugin-driven event hooks for custom logic
- local transaction commitment status tagging (
processed/confirmed/finalized) without RPC dependency
At a Glance
- Embed SOF directly inside a Tokio application
- Attach
PluginorRuntimeExtensionconsumers - Run with built-in UDP ingress or external kernel-bypass ingress
- Treat SOF as a local market-data and control-plane engine, not just a passive observer
- Use packet-worker and dataset-worker fanout to keep multi-core hosts busy under sustained shred load
- Consume local slot/reorg/transaction/account-touch signals
- Use the replayable derived-state feed for restart-safe stateful consumers
- Apply typed gossip and ingest tuning profiles instead of env-string bundles
- Keep more runtime work on borrowed/shared data instead of eagerly allocating owned transaction or dataset payload copies
- Drop duplicate or conflicting shred observations before they can re-emit duplicate dataset or transaction events downstream
Install
Optional gossip bootstrap support at compile time:
= { = "0.12.0", = ["gossip-bootstrap"] }
Optional external kernel-bypass ingress support:
= { = "0.12.0", = ["kernel-bypass"] }
The bundled sof-solana-gossip backend defaults to SOF's lightweight in-memory duplicate/conflict
path. The heavier ledger-backed duplicate-shred tooling remains available behind the vendored
crate's explicit solana-ledger feature.
Semantic Shred Dedupe
SOF now treats shred dedupe as a semantic correctness boundary, not just a packet-cache hint.
- One shared semantic shred registry is used across both ingest and canonical emission stages.
- Exact repeats are dropped before they can waste verify/FEC/reassembly work.
- Conflicting repeats are also suppressed before they can re-emit duplicate downstream events.
- The HFT/observer contract is that normal downstream consumers should not need their own duplicate shred suppression logic.
The shared registry publishes runtime telemetry for:
- current and max retained shred identities
- current and max eviction-queue depth
- capacity-driven vs expiry-driven evictions
- ingress duplicate/conflict drops
- canonical duplicate/conflict drops
Those metrics are intended to help tune SOF_SHRED_DEDUP_CAPACITY and
SOF_SHRED_DEDUP_TTL_MS under real traffic instead of guessing.
Quick Start
Run the bundled runtime example:
With gossip bootstrap:
Basic programmatic setup:
use ;
async
Runtime API
Embed directly in Tokio:
use ObserverRuntime;
async
Or use programmatic setup:
use SocketAddr;
use ;
async
When SOF_OBSERVABILITY_BIND (or RuntimeSetup::with_observability_bind_addr) is set, the
packaged runtime also serves:
/metrics/healthz/readyz
Or apply one typed gossip/ingest profile instead of stringly env overrides:
use ;
use ;
async
Linux busy-poll is available as an explicit host-side experiment when you want to trade CPU efficiency for steadier UDP receive behavior:
use ObserverRuntime;
use ;
async
With external kernel-bypass ingress, feed RawPacketBatch values through SOF's ingress queue:
async
Run the kernel-bypass ingress metrics example for 180 seconds:
SOF_KERNEL_BYPASS_EXAMPLE_DURATION_SECS=180 \
Run the same example against live Solana gossip traffic (real chain data):
SOF_KERNEL_BYPASS_EXAMPLE_SOURCE=gossip \
SOF_KERNEL_BYPASS_EXAMPLE_DURATION_SECS=180 \
RUST_LOG=info \
Run AF_XDP external-ingress example (requires Linux, AF_XDP-capable NIC setup, and privileges to create XDP sockets/programs):
SOF_AF_XDP_IFACE=enp17s0 \
SOF_AF_XDP_EXAMPLE_DURATION_SECS=180 \
Notes for high-ingest runs:
- The example configures
SOF_PORT_RANGE=12000-12100andSOF_GOSSIP_PORT=8001. - It defaults live gossip mode to
SOF_INGEST_QUEUE_MODE=lockfreewithSOF_INGEST_QUEUE_CAPACITY=262144. - The bundled gossip backend also exposes
SOF_GOSSIP_CONSUME_THREADS,SOF_GOSSIP_LISTEN_THREADS,SOF_GOSSIP_SOCKET_CONSUME_PARALLEL_PACKET_THRESHOLD,SOF_GOSSIP_LISTEN_PARALLEL_BATCH_THRESHOLD,SOF_GOSSIP_LISTEN_PARALLEL_MESSAGE_THRESHOLD, andSOF_GOSSIP_STATS_INTERVAL_SECSfor host-specific tuning. SOF_UDP_DROP_ON_CHANNEL_FULLonly applies to SOF's built-in UDP receiver path (non-external ingress).- Queue mode is configurable with
SOF_INGEST_QUEUE_MODE:bounded(default): Tokio bounded channel.unbounded: Tokio unbounded channel (no backpressure drops; memory grows with load).lockfree: lock-freeArrayQueuering + async wakeups.
- Ring/bounded capacity is configurable with
SOF_INGEST_QUEUE_CAPACITY(default16384).
Plugin Quickstart
use async_trait;
use ;
;
async
For sparse plugin subscriptions, prefer PluginConfig::new().with_*() so the enabled hooks stand
out clearly. Use a raw PluginConfig { .. } literal only when many flags are enabled and the full
shape is easier to scan.
For low-latency transaction consumers, prefer the explicit inline path:
use async_trait;
use ;
;
async
TransactionDispatchMode::Inline is an explicit delivery contract for on_transaction.
SOF now tries to dispatch that hook as soon as an anchored contiguous dataset prefix
contains one full serialized transaction for the plugin that asked for it, instead of
waiting for the whole dataset by default. If the runtime still cannot anchor the dataset
prefix early, inline dispatch falls back to the completed-dataset point for that tx.
If other plugins or subsystems still need deferred dataset processing, SOF can deliver
the inline transaction hook first and then continue the same dataset through the
standard dataset-worker path for those remaining consumers.
When observability is enabled, SOF exports exact inline latency counters:
sof_inline_transaction_plugin_first_shred_lag_us_totalsof_latest_inline_transaction_plugin_first_shred_lag_ussof_max_inline_transaction_plugin_first_shred_lag_ussof_inline_transaction_plugin_last_shred_lag_us_totalsof_latest_inline_transaction_plugin_last_shred_lag_ussof_max_inline_transaction_plugin_last_shred_lag_ussof_inline_transaction_plugin_completed_dataset_lag_us_totalsof_latest_inline_transaction_plugin_completed_dataset_lag_ussof_max_inline_transaction_plugin_completed_dataset_lag_us
Those track, respectively:
- first observed shred that contributes to the inline tx path -> inline
on_transactioncallback start - last observed shred required to dispatch the inline tx -> inline
on_transactioncallback start - inline dispatch-ready timestamp -> inline
on_transactioncallback start
RuntimeExtension Quickstart
use async_trait;
use ;
use ObserverRuntime;
;
async
Plugin Hooks
Current hook set:
on_raw_packeton_shredon_dataseton_transactionon_account_touchon_slot_statuson_reorgon_recent_blockhashon_cluster_topology(gossip-bootstrap mode)on_leader_schedule(gossip-bootstrap mode)
on_transaction events include:
commitment_statusconfirmed_slotfinalized_slot
These commitment fields are derived from local shred-stream slot progress (depth-based), not RPC polling.
on_account_touch events include transaction-derived static account-key sets:
account_keyswritable_account_keysreadonly_account_keyslookup_table_account_keys
This hook is for account discovery/invalidation. It is not a validator post-write account-update feed.
Derived-State Consumers
SOF also exposes a replayable derived-state feed intended for stateful official extensions and local consumers that need:
- retained feed continuity
- checkpoint persistence
- replay-based recovery after restart or transient failure
- explicit resync/rebuild signaling
- typed control-plane replay for recent blockhash, cluster topology, and leader schedule inputs
- canonical control-plane quality snapshots through
ControlPlaneStateUpdated - invalidation and tx-feedback events through
StateInvalidatedandTxOutcomeObserved
This is the right substrate for local service layers that want to build a bank, query index, or gRPC stream on top of SOF without depending on validator-native Geyser.
Example implementation:
examples/derived_state_slot_mirror.rs
Replay retention modes:
DerivedStateReplayConfig::checkpoint_only()disables the runtime-owned replay tail and keeps recovery checkpoint-driven.DerivedStateReplayBackend::Diskretains envelopes on disk without keeping a full in-process mirror of the retained tail.
Design references:
../../docs/architecture/derived-state-extension-contract.md../../docs/architecture/derived-state-feed-contract.md
on_slot_status events include local canonical transitions:
processedconfirmedfinalizedorphaned
Operational Notes
- Hooks are dispatched off the ingest hot path through a bounded queue.
- Queue pressure drops hook events instead of stalling ingest.
- Typed host tuning is available through
sof-gossip-tuningandRuntimeSetup::with_gossip_tuning_profile(...). RuntimeExtensionWebSocket connectors support fullws:///wss://handshake + frame decoding.- WebSocket close frames emit
RuntimePacketEventClass::ConnectionClosedinon_packet_received. - WebSocket packet events expose
websocket_frame_type(Text/Binary/Ping/Pong) for startup-time filtering and runtime routing. - In gossip mode, SOF runs as an active bounded relay client by default (UDP relay + repair serve), not as an observer-only passive consumer.
SOF_LIVE_SHREDS_ENABLED=falseenables control-plane-only mode.
Examples
observer_runtimeobserver_with_non_vote_pluginobserver_with_multiple_pluginsnon_vote_tx_loggerraydium_contracttpu_leader_loggerruntime_extension_observer_ingressruntime_extension_udp_listenerruntime_extension_shared_streamruntime_extension_with_pluginsruntime_extension_websocket_connectorderived_state_slot_mirrorkernel_bypass_ingress_metrics(--features kernel-bypass)
Run kernel-bypass ingress E2E test:
Run any example:
Docs
- Workspace docs index:
../../docs/README.md - Architecture docs:
../../docs/architecture/README.md - Operations docs:
../../docs/operations/README.md - Derived-state feed contract:
../../docs/architecture/derived-state-feed-contract.md - Reverse-engineering notes:
REVERSE_ENGINEERING.md - Contribution guide:
../../CONTRIBUTING.md