Skip to main content
Leafage is an architecture for EVM state queries and block data distribution. It separates what a traditional full node couples together: sync and execution, state storage, RPC serving, and data export. One write node joins the P2P network and executes blocks; the state diffs and block data produced by execution are distributed through Kafka + S3 to any number of query nodes and to external consumers. Clients never talk to a node directly: a gateway routes each request to a suitable query node according to its block context.

Execute once, consume everywhere

At its core, Leafage separates “execution” from “consuming execution results”:
  • Write side: the chain’s original execution client plus the pipeline library. It is the only role that executes blocks. While executing, it exports state diffs, block headers, and transactions / traces / events to S3, and publishes block change notifications to Kafka.
  • Read side: leafage-evm query nodes. They do not sync, do not execute blocks, and do not maintain a Merkle Patricia Trie. They apply state diffs to local state in notification order and run read-only calls with revm.
All query nodes consume the same single-partition Kafka notification stream and apply the same diffs in the same order, so there is no P2P non-determinism. Adding query capacity means starting one more query node, not syncing the whole chain again.

The five components and their roles

Components never call each other directly. They cooperate through three pieces of middleware: Kafka carries notifications, S3 carries payloads, and etcd carries runtime state.

Data flowing through the pipeline

For every block it executes, the write node produces four objects and one notification: The internal bucket and internal topic serve Leafage’s own query nodes. The external bucket and external topic serve external consumers such as indexers and analytics platforms. The external topic is published by consistency-checker and contains only confirmed blocks.

Three kinds of query nodes

leafage-evm keeps as much history as its startup flags say, which splits it into State and Archive nodes. A Native node is a full node of the original chain, used as a fallback. nodex-proxy routes between the three node pools according to the block context carried by the request, and automatically retries on an Archive or Native node when a State node returns -39006 or -39008.

Three identities of a block

The same block passes through three stages along the pipeline. Keeping them apart is what makes the component interfaces readable:

Isolation unit: chain and version

One chain is one independent deployment unit. Kafka topics, S3 keys, and etcd keys all start with chainID, so multiple chains can share one Kafka, S3, and etcd. With version mode enabled, the key space gains an extra version segment. Two data versions of the same chain can then run side by side on the same infrastructure, and etcd’s {chainID}/version switches between them without clients noticing.

Glossary

Summary

  • Leafage is an architecture for EVM state queries and block data distribution: only the write node executes blocks; every other role consumes the results.
  • The write side exports four objects, StateDiff, Header, BlockFile, BlockValidation, plus one block change notification; Kafka carries notifications only, payloads go through S3.
  • Query nodes come in three kinds, State / Archive / Native; nodex-proxy routes by block context and falls back automatically on error codes.
  • A block has three identities, published, confirmed, fork block; external consumers should rely only on confirmed notifications.
Continue reading: