The
{version} segment below is optional. With version mode enabled, Kafka topics, S3 keys, and etcd keys all carry a version namespace, which lets multiple data versions run in parallel on the same infrastructure.Kafka
Internal topic
Published by the write node, consumed by leafage-evm and consistency-checker.External topic
Published by consistency-checker, subscribed to by external consumers. leafage-evm does not consume this topic.is_fork.
In version mode, the checker writes to both the version topic and the singleton topic; only the Leader holding the etcd lock writes to the latter.
S3
The two buckets are split by consumer. All keys start withchainID, so multiple chains can share the same bucket.
Internal bucket (NodeX bucket)
StateDiff is keyed by state root rather than block hash: adjacent blocks with the same state root share one object, so empty blocks produce no new objects. When the parent and current block have the same state root, leafage-evm skips the fetch and treats it as an empty diff.
External bucket (ChainTable bucket)
BlockFile contains the block, transactions, call traces, and event logs, and is the main data source for external consumers. BlockValidation is a validation digest of the same data and also serves as the index by height:
{chainID}[/{version}]/{height}/ are all the candidate blocks at that height. Two components rely on this index:
- consistency-checker rewrites non-canonical objects as
is_fork: true - leafage-evm uses it during S3 catch-up to resolve a height to the canonical block hash
docs/protocol.md in the pipeline repository for the full field definitions.
etcd key space
All keys start withchainID (with an optional version segment), so different chains are naturally isolated.
Structure of the node info:
Version switching
{chainID}/version is the control point for version mode; two components read it:
- consistency-checker compares its own
versionconfig with the value in etcd; when they match, it contends for the{chainID}/outer_block_noticelock to become the Leader that publishes to the singleton topic. - nodex-proxy rewrites the base
chainIdin the request to{chainId}-{version}and routes to the versioned node pool.
RPC contracts
trace_debankBlock
Provided by the write node, used to obtain the complete execution output of a single block in setups without Kafka. leafage-evm’s HTTP fallback mode depends on it.
DebankOutPut, which contains BlockFile, Header, StateDiff, and ValidationHash — corresponding one-to-one with the contents of the four object types on S3.
Health checks
nodex-proxy’s health check retries every 5 seconds, up to
node_health_check_max_wait (default 300 seconds). Only nodes that pass the check enter the load balancing pool.
Routing-related error codes
When leafage-evm returns these error codes, nodex-proxy automatically switches node pools and retries once.Compatibility rules
When changing cross-component interfaces, keep in mind:- Kafka message structures only add fields and never change semantics. Consumers decode JSON; extra fields are ignored, but missing fields lead to zero values being misinterpreted.
- S3 key formats are hard-coded conventions shared by leafage-evm, consistency-checker, and external consumers; changing them requires updating all three and accounting for existing objects.
- etcd key formats are likewise hard-coded in three components; the way the
{chainID}and{version}segments are joined must be consistent. - Error codes are part of routing behavior; adding one requires matching handling logic on the nodex-proxy side.