Skip to content

Repository files navigation

Gravity Connector

Validator sidecar accepting connections from an external relay.

Requirements

  • Rust toolchain is pinned via rust-toolchain.toml (nightly-2026-03-10); rustup will pick it up automatically.
  • Agave 4.1, or Jito-Solana 4.1.2 or newer, running with --enable-scheduler-bindings so the connector can attach to the scheduler bindings IPC socket.

Build

cargo build --profile release-prod

Run

./target/release-prod/connector path/to/config.toml

See config.example.toml for a documented sample config.

Operator setup

Agave

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

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.

Restart policy

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=2

Or add the restart policy to a Docker run command:

docker run --restart always ...

Runtime notes

  • 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_addrs and reconnects automatically while any of them is down. Relay entries should use tcp://host:port URLs; 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_core and connector_network_core are 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_addr to 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.

Monitoring

  • The connector serves /metrics (Prometheus text, all metrics prefixed gravity_connector_) and /health (JSON summary, 200 when healthy and 503 otherwise) on metrics_addr, default 0.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 synthesises up per scrape.
  • Metrics cover connection status only: the Agave link, the relay connection, and the Jito block engine streams. gravity_connector_healthy carries the same verdict as /health.
  • /health is 200 only 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.

Shutdown behavior

  • 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_PROGRESS and 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_path keypair, the connector sets stop code AGAVE_IDENTITY_MISMATCH and 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.json recording 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.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages