Skip to content

feat: optimistic block notifications#798

Open
pauldelucia wants to merge 1 commit into
a16z:masterfrom
pauldelucia:feat/optimistic-update-notifications
Open

feat: optimistic block notifications#798
pauldelucia wants to merge 1 commit into
a16z:masterfrom
pauldelucia:feat/optimistic-update-notifications

Conversation

@pauldelucia

@pauldelucia pauldelucia commented May 23, 2026

Copy link
Copy Markdown

Summary

Adds a watch-channel notification path for the latest optimistic-header-derived block, mirroring the shape of #738's checkpoint notifications. Builds on the consensus client's already-tracked optimistic_header state — no new sync logic, just exposes data that the light client already maintains.

// new on the Consensus trait
fn optimistic_block_recv(&self) -> Option<watch::Receiver<Option<B>>>;

// new on HeliosApi
async fn current_optimistic_block(&self) -> Result<Option<N::BlockResponse>>;
fn new_optimistic_blocks_recv(&self) -> Result<watch::Receiver<Option<N::BlockResponse>>>;

Motivation

#302 originally asked for "tracking and getting notified when a new update is applied" with a concrete use case of "setting a hook on new optimistic update, to do some action (e.g. re-check a list of balances)". #738 addressed the checkpoint half of that — the finalized side. This addresses the optimistic side.

block_recv already streams the same blocks via mpsc, but the watch variant lets multiple subscribers each see the latest value without coordinating a single consumer. Concrete external use cases:

  • A data indexer that needs to react to chain-tip advances under sync-committee attestation without waiting for full finality (~12.8min).
  • A dashboard / SSE service that fans out updates to many connected clients — each subscriber holds its own watch::Receiver clone of the same channel.
  • A monitoring tool tracking "what does Helios think is the head right now?" for health checks.

For comparison: block_recv (mpsc) is a stream meant for a single consumer; the new watch channel is meant for many lightweight observers that only care about the latest value.

Changes

  • core/src/consensus.rs — add optimistic_block_recv to the Consensus trait
  • core/src/client/api.rs — add current_optimistic_block + new_optimistic_blocks_recv to HeliosApi
  • core/src/client/node.rs — implement the new HeliosApi methods (delegate to Consensus::optimistic_block_recv)
  • ethereum/src/consensus.rs — wire optimistic_block_send into ConsensusClient + Inner, publish in both branches of send_blocks (matching how block_send was already invoked)
  • opstack/src/consensus.rs, linea/src/consensus.rs — implement the trait method returning None, matching how they already handle checkpoint_recv

44 lines added across 6 files. cargo test --workspace --lib clean (23 tests passing), cargo clippy --workspace --lib clean, cargo fmt --check clean.

What's deliberately NOT in this PR

  • JSON-RPC method + subscription. Would mirror helios_getCurrentCheckpoint / helios_subscribeNewCheckpoints from feat: checkpoint notifications #738, but doing so cleanly requires making the HeliosRpc trait generic over N::BlockResponse (the current shape returns concrete Option<B256> for checkpoints, which works because B256 is concrete; blocks are network-specific). That's a bigger trait-surface change that the maintainers may prefer to design themselves. Happy to follow up in a separate PR if you want this — the Rust-API additions in this PR work standalone for crate consumers.
  • helios-ts bindings. Depend on the JSON-RPC layer, so deferred along with that.

Note on tests

There's no test directly observing the new channel — there's no analogous test for finalized_block_send either, since exercising send_blocks end-to-end needs richer mock-RPC fixture work than the existing tests do. The channel wiring is mechanical (mirrors finalized_block_send exactly). Happy to add a test if reviewers prefer — pointer to the right test pattern would help.

Follow-up to a16z#738 (checkpoint notifications). Exposes the latest
optimistic-header-derived block via a `tokio::sync::watch::Receiver`
on the same shape as `finalized_block_recv`:

- `Consensus::optimistic_block_recv() -> Option<watch::Receiver<Option<B>>>`
- `HeliosApi::current_optimistic_block() -> Result<Option<N::BlockResponse>>`
- `HeliosApi::new_optimistic_blocks_recv() -> Result<watch::Receiver<Option<N::BlockResponse>>>`

Use case: external consumers (e.g. data indexers, dashboards) that need
to react to chain-tip advances under sync-committee attestation without
waiting for full finality. `block_recv` already streams the same blocks
via mpsc, but the watch variant lets multiple subscribers each see the
latest value without coordinating a single consumer.

`ConsensusClient` for Ethereum publishes on `optimistic_block_send` in
both branches of `send_blocks` so the receiver always reflects the most
recent optimistic execution block. opstack and linea return `None` from
the trait method, matching their existing handling of light-client
features they don't implement.

Closes the gap noted in a16z#302 between checkpoint notifications and
arbitrary-update notifications for light-client consumers.
@pauldelucia

Copy link
Copy Markdown
Author

Hi @ncitron could you have a look at this one please?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant