Block change notification
Each time the write node sets a new canonical head, it publishes oneBlockChangeNotification to the Kafka internal topic:
Canonical chain and fork blocks
The canonical chain is the chain that contains the write node’s current canonical head. Before publishing, the write node compares the last published block with the new head by finding their common ancestor:changeType is 1 and newBlocks is ascending by height; when a branch is dropped, changeType is 2 and both dropBlocks and newBlocks are present.
The dropped blocks are fork blocks. They do not vanish from the system:
The same height may have several objects under the external bucket prefix
{chainID}[/{version}]/{height}/; is_fork is the only way to tell them apart. A query node catching up from a cold start relies on it to resolve a height to its canonical hash.
Published versus confirmed
At the moment the write node publishes a notification, query nodes have not applied the block yet. A consumer subscribed directly to the internal topic would receive the notification while the block is “not yet queryable”. consistency-checker adds a confirmation step in between:is_fork. On a reorg, the checker publishes the drop notifications first, then the new-block notifications.
External consumers therefore get one guarantee: when the notification arrives, the query cluster can already serve that block. If replicas are still not ready after check_timeout_ms (default 2000 milliseconds), the checker does not publish the block and retries the whole step.
One block, three records
Once a block is confirmed, three places along the pipeline each keep a record of it, serving different readers:
Both leafage-evm and consistency-checker expose
getLatestBlock / getBlockByHeight / getBlockById / blockIsValid. The method names match but the semantics differ: the former returns the node’s own current view, the latter returns confirmed blocks.
Summary
- A block change notification carries hashes and heights only, on a single totally ordered partition, published by the Leader alone; payloads live in S3.
- A reorg is expressed as
changeType: 2plusdropBlocks; dropped fork blocks stay in both S3 and query node memory, and consistency-checker writes backis_fork. - Published (internal topic) and confirmed (external topic) are two different streams; external consumers should subscribe only to the latter.
- The confirmed height is written to etcd’s
lastBlockNumber, which is what nodex-proxy uses to choose between State and Archive.
- Block context and routing: how a request says “which block”, and how the confirmed height feeds into routing.
- Data flow: reorg handling details in the write node, leafage-evm, and the checker.
- Interface contracts: naming, encoding, and producer settings of the two topics.