Skip to main content

Module events

Module events 

Source
Expand description

Event → state pipeline (Pillar B.2 — the reader half of the event pipeline).

Phase 3 (state_update) built the writer half: the generic StateUpdate vocabulary and the cold-aware apply_updates that consumes it. This module builds the reader half: it turns an on-chain Log into that same vocabulary and drives it through the cache, keeping event-derived state reactively fresh.

§The flow

Log ─▶ EventDecoder::decode(log, &StateView) ─▶ Vec<StateUpdate>
                                                     │
                                      apply_updates ▼
                                                 EvmCache  (+ StateDiff)

A DecoderRegistry dispatches a log to the decoders registered for its emitting address (plus any global decoders) and concatenates their output. An EventPipeline orchestrates a block’s logs: ingest_logs decodes and applies them log-by-log in order (so a later log’s decode observes the effects of earlier ones through the StateView), reorg_to purges the addresses touched after a new head, and reconcile re-reads sampled event-derived slots against chain truth (correct and alarm).

§Decoders are pure data functions

EventDecoder::decode is a pure function of (log, pre-state): it performs no I/O and emits serializable, replayable StateUpdate data. Most updates need no pre-state (SlotDelta and SlotMasked are read-modify-write at apply time), but stateful external adapters may read the narrow read-only StateView to compute a post-state from cached pre-state. The view never touches RPC; a slot absent from the cache reads None (cold), and a decoder that cannot compute against a cold word surfaces a skip rather than inventing a value.

§!Send cache discipline

EvmCache is !Send (it owns the mutable fork and blocks on RPC internally). All of EventPipeline’s core methods (ingest_logs / reorg_to / reconcile) take &mut EvmCache and are synchronous — they never .await, so the cache is never held across a yield point. This is what makes the core deterministically testable offline. The async drive convenience holds the cache only across the log source await (the source future is Send; the cache is untouched during it).

§Freshness wiring

BlockDigest::touched_slots surfaces the (address, slot) set written for a block so a caller can classify event-derived slots in a FreshnessRegistry — typically pin them (Validity::Pinned) or mark them Validity::ValidThrough so the optimistic validator does not waste RPC re-verifying state the pipeline keeps fresh — then call FreshnessController::on_new_block. No controller internals change. Periodically call reconcile to sample-check those slots against the chain (honest freshness).

Modules§

erc20
Generic ERC-20 Transfer decoder (generic core).

Structs§

BlockDigest
Per-block result of EventPipeline::ingest_logs.
DecoderRegistry
Dispatches a log to the decoders registered for its emitting address (and any global decoders) and concatenates their output.
EventPipeline
Orchestrates decoding, applying, reorg handling, and reconciliation of a block’s logs against an EvmCache.
ReconcileReport
Result of EventPipeline::reconcile.
ReorgConfig
How a reorg purges the addresses touched after the new head.

Traits§

EventDecoder
Decode one log into zero or more targeted StateUpdates.
LogSource
An async source of blocks of logs for drive.
StateView
Read-only view of current cached state handed to a decoder.

Functions§

drive
Drive pipeline over source, ingesting each block (reorging first when signalled) and invoking on_block after each ingest.

Type Aliases§

ReorgSignal
A signalled reorg accompanying a block from a LogSource.