Jito Geyser gRPC Plugin

repository·master·Indexed 40 days ago

https://github.com/jito-foundation/geyser-grpc-plugin

A lightweight gRPC service and Geyser plugin for Solana validators designed to stream account, slot, transaction, and block updates to subscribers. Includes the jito-geyser-cli for interacting with the service, a Rust client for consuming streams with monotonicity and ordering guarantees, and jito-geyser-protos for protobuf definitions supporting Solana libraries approximately version ~v1.14.

Tokens
7K
Snippets
27
Records
38
Agent score
49%

What's inside Jito Geyser gRPC Plugin

  1. Build the geyser-grpc-plugin

    master

    You can build the plugin using either cargo or docker.

    Important Compatibility Requirements:

    • The Solana version library must match the imported packages in this repository.
    • The cargo version (defined in rust-toolchain.toml) must match the rust-toolchain.toml used in the Solana repository.

    Build Options:

    • Cargo: Use standard cargo build commands.
    • Docker: Use the provided ./f script to build the binary within a container, which outputs the result to a container-output folder.
    # Using cargo
    $ cargo b --release
    
    # Using docker
    $ ./f
  2. Run the geyser-grpc-plugin with a Solana validator

    master

    To integrate the plugin into your Solana validator, follow these steps:

    1. Configure: Copy and edit the example configuration file (./server/example-config.json) to match your validator's requirements.
    2. Configure Validator: Add the --geyser-plugin-config startup argument to your Solana validator command, pointing to your edited JSON file.
    3. Restart: Restart your validator.
    4. Verify: Check the validator logs for the following strings to confirm the plugin has started successfully:
      • Starting GeyserPluginService from config files
      • geyser_grpc_plugin_server::server
    # Example validator startup argument
    --geyser-plugin-config geyser.json
  3. How to pull in Solana Labs changes

    master

    The protobufs in this repository are largely copied from Solana Labs. If you need to update them to match newer Solana Labs changes, note the following:

    • confirmed_block.proto and transaction_by_addr.proto are currently untouched.
    • The library structure uses tonic::include_proto! to expose the definitions. If you modify the proto files, you may need to update the module declarations in lib.rs to match the new paths.
  4. Manage subscription lifecycle with SubscriptionStream

    master

    The SubscriptionStream struct is used to manage real-time data streams and provides a mechanism to notify other processes when a client's subscription is closed. This is essential for cleaning up state associated with a specific stream when a connection is dropped.

    Key Features

    • Automatic Cleanup Notification: When the SubscriptionStream is dropped (e.g., the client disconnects), it automatically triggers a signal to a provided StreamClosedSender.
    • Stream Interface: It implements the tokio_stream::Stream trait, allowing it to be used with standard async stream utilities.
    • Unique Identification: Each stream is associated with a unique ID and a name for logging and tracking.

    Implementation Details

    To create a new stream, use SubscriptionStream::new. You must provide a receiver for the data, a unique ID, and a sender that implements the StreamClosedSender trait to handle the cleanup event.

    // Conceptual usage pattern for creating a SubscriptionStream
    let stream = SubscriptionStream::new(
        stream_rx,           // Receiver<Result<T, Status>>
        stream_id,           // Unique ID
        (event_sender, event), // (S, E) where S: StreamClosedSender<E>
        "stream_name",      // &'static str
    );
  5. How GeyserConsumer handles account updates

    master

    The GeyserConsumer provides an opinionated approach to consuming account updates, ensuring data integrity through two main guarantees:

    1. Monotonicity: Account updates are streamed monotonically. If the server sends updates for older slots late, they are discarded to prevent processing stale data.
    2. Ordering: Account updates received out of order (based on sequence numbers) will trigger an error.

    To maintain these guarantees, the consumer tracks the highest_rooted_slot and uses a max_rooted_slot_distance to determine if an incoming update is too stale to process.

  6. Configure the Geyser gRPC Plugin

    master

    The plugin is configured via a JSON file. The configuration defines network settings, buffer sizes for different update types, and security settings like TLS and access tokens.

    Key configuration fields include:

    • bind_address: The network address and port the gRPC server will listen on.
    • account_update_buffer_size, slot_update_buffer_size, block_update_buffer_size, transaction_update_buffer_size: Sizes for the internal channels used to pipe updates to the gRPC service.
    • slot_entry_update_buffer_size: Size for slot entry updates (defaults to 1,000,000 if not provided).
    • skip_startup_stream: If set to true, the plugin will ignore updates during the initial startup phase.
    • account_data_notifications_enabled: If set to false, account data notifications are disabled.
    • geyser_service_config: Contains GeyserServiceConfig settings, including access_token for authentication and tls_config for encrypted connections.
    {
        "bind_address": "0.0.0.0:10000",
        "account_update_buffer_size": 100000,
        "slot_update_buffer_size": 100000,
        "slot_entry_update_buffer_size": 1000000,
        "block_update_buffer_size": 100000,
        "transaction_update_buffer_size": 100000,
        "skip_startup_stream": false,
        "account_data_notifications_enabled": true,
        "geyser_service_config": {
            "heartbeat_interval_ms": 1000,
            "subscriber_buffer_size": 1000000,
            "access_token": "YOUR_ACCESS_TOKEN",
            "tls_config": {
                "cert_path": "/path/to/cert.pem",
                "key_path": "/path/to/key.pem"
            }
        }
    }