Validator sidecar accepting connections from an external relay.
- Rust toolchain is pinned via
rust-toolchain.toml(nightly-2026-03-10);rustupwill pick it up automatically. - Agave 4.1, or Jito-Solana 4.1.2 or newer, running with
--enable-scheduler-bindingsso the connector can attach to the scheduler bindings IPC socket.
cargo build --profile release-prod./target/release-prod/connector path/to/config.tomlSee config.example.toml for a documented sample config.
Run Agave with scheduler bindings enabled so the connector can attach to the validator's external scheduler IPC socket:
agave-validator \
--enable-scheduler-bindings \
...In the connector config, use the Agave client variant and point ledger_path at
the validator ledger. The connector derives admin.rpc and
scheduler_bindings.ipc from this directory:
client_variant = "agave"
ledger_path = "/path/to/ledger"If the validator should not receive Jito bundles, omit the [jito] section. If
the validator runs regular Agave but should still receive Jito bundles through
the external scheduler, keep the [jito] section populated; in that mode the
connector subscribes to Jito block engines and handles tip-management lifecycle
transactions itself. jito.block_engine_proxy_addr is only used for
client_variant = "jito".
Jito-Solana is the recommended validator client. The minimum supported Jito-Solana version is 4.1.2.
Run Jito-Solana with scheduler bindings enabled and configure its block-engine URL to the connector's local proxy:
jito-solana-validator \
--enable-scheduler-bindings \
--block-engine-url http://127.0.0.1:11226 \
--disable-block-engine-autoconfig \
...The connector config must use the Jito client variant and expose the local proxy on the same host and port:
client_variant = "jito"
[jito]
block_engine_proxy_addr = "127.0.0.1:11226"To configure static shred retransmit destinations, set
shred_retransmit_receivers in the connector config. The connector keeps these
configured addresses and appends any addresses received from the active relay.
See config.example.toml for examples.
Do not configure Jito-Solana with a real public Jito block-engine URL in this mode. Jito-Solana still needs a block-engine connection to receive block-builder fee and tip-management data, but direct connections to public block engines can also feed bundles and packets into Jito-Solana's own pipeline. That competes with the external scheduler, which should own sequencing while the relay is connected.
The connector runs a local block-engine proxy that solves both requirements. The validator
gets the block-builder and tip-management data it expects, while the connector
subscribes to the real Jito block engines internally and routes bundles and
packets through the external scheduler. If the relay is disconnected, the
proxy can forward block-engine traffic to Jito-Solana as a fallback. Use
--disable-block-engine-autoconfig so Jito-Solana does not auto-discover and
connect to public Jito endpoints outside the connector.
Operators should run the connector with an always-restart policy. The connector may occasionally exit or panic on recoverable conditions, such as stale Agave progress or a prolonged relay disconnect, so the operator's restart policy should start a fresh connector process automatically.
For example, add the restart fields to a systemd service:
[Service]
Restart=always
RestartSec=2Or add the restart policy to a Docker run command:
docker run --restart always ...- If Agave has not created the scheduler bindings IPC socket yet, the connector logs the error and retries the connection every 10 seconds.
- Before the initial IPC handshake, the connector retries until Agave is ready. After a successful handshake, if Agave stops sending progress updates for more than 2 seconds, the connector exits with stop code
AGAVE_NO_PROGRESS; the restarted process then performs a fresh IPC handshake. - The connector dials the relays listed in
relay_addrsand reconnects automatically while any of them is down. Relay entries should usetcp://host:portURLs; legacy IP-and-port entries remain accepted. Hostnames are resolved off the latency-sensitive network thread and resolved again after disconnects. If DNS returns multiple addresses, the connector rotates through them after connection failures. - Relay URLs use the existing plaintext TCP transport; DNS names do not enable TLS or authenticate the relay host. DNS changes do not move a healthy connection and take effect when that connection disconnects.
- The CPU cores configured by
connector_agave_coreandconnector_network_coreare dedicated to the connector and are expected to run at or near 100% utilization for optimal performance. Operators should not co-locate other workloads on those cores. - For validators running Jito-Solana, bind
jito.block_engine_proxy_addrto localhost unless the network is otherwise trusted. The local proxy only implements the auth surface needed by Jito-Solana and does not validate bearer tokens on block-engine RPCs. - If the connector enters a sequencing leader slot and receives no valid schedule, it writes a failsafe file and exits; see shutdown behavior below.
- The connector serves
/metrics(Prometheus text, all metrics prefixedgravity_connector_) and/health(JSON summary,200when healthy and503otherwise) onmetrics_addr, default0.0.0.0:9093. Set it to a specific interface to limit exposure, or firewall the port to your scrapers. The listener is bound early, before the identity and relay waits, so it is scrapeable during startup. Liveness needs no dedicated endpoint: Prometheus already synthesisesupper scrape. - Metrics cover connection status only: the Agave link, the relay connection, and the Jito block engine streams.
gravity_connector_healthycarries the same verdict as/health. /healthis200only once the connector is past startup with both Agave and a relay connected, using the same 2 second progress threshold the connector exits on. The JSON body names the failing check. Block engine connectivity is reported but not part of the verdict, since the connector still works for non-Jito flow with every upstream down.
- On startup, the connector waits for a relay connection before connecting to Agave. If no relay accepts, it keeps retrying and logs that it is still waiting; this is not a stop condition.
- While running, if the active relay disconnects, the connector keeps Agave connected and retries that relay in the background. If another relay connection is already available, the connector switches to it. If no relay is connected for 10 minutes, the connector panics; the operator's restart policy should start it again.
- If Agave stops sending progress updates for more than 2 seconds, the connector sets stop code
AGAVE_NO_PROGRESSand exits. This usually means the validator restarted or the scheduler bindings connection is stale; the connector does not reconnect in-process after a completed handshake, so operators should rely on the restart policy to start a fresh connector process. - If Agave's admin RPC reports an identity different from the configured
identity_pathkeypair, the connector sets stop codeAGAVE_IDENTITY_MISMATCHand exits. On restart it remains in the startup identity wait until Agave reports the configured identity again. - If a sequencing leader slot completes without any valid schedule from the relay, the connector writes the failsafe file and panics. The failsafe file is a local JSON marker at
~/.local/share/gravity-connector/failsafe.jsonrecording the safety stop reason and timestamp. On restart, the connector stays blocked by that marker and logs it periodically, so Agave continues on its vanilla scheduling path until the failsafe expires or the relay sends a delete-failsafe request.