Skip to main content
Different query nodes keep different ranges of state, so every request has to answer one question: which block’s state do you want? The answer is called the block context. leafage-evm uses it to pick the state layer to execute on; nodex-proxy uses it to pick the node pool to send the request to.

Two semantics: Equals and Contains

Methods in the DeBank namespace (contractMultiCall, estimateGas, getAddressBalance, and so on) accept an optional blockCtx parameter:
Contains fits cases where “the data just must not be older than some height”, such as reading a configuration slot that rarely changes. Equals fits cases that need reproducible results, such as reconciliation and historical lookups. Omitting blockCtx is the same as { "block_id": "latest", "type": "Equals" }.

Forms of block_id

Block parameters of standard eth_* methods

Methods such as eth_call and eth_getBalance keep Ethereum’s block parameter ("latest", a hex height, or {"blockHash": …}). leafage-evm treats them with Equals semantics: the request executes on the state of exactly the height it names. nodex-proxy parses only blockCtx-shaped objects as block context; the block parameter of eth_* methods does not take part in pool selection. Such requests go to a State node first, and when the State node returns -39006 the proxy re-sends them to an Archive node. To skip that hop, say so explicitly in a request header:

Routing rules

nodex-proxy first picks a node pool by block context, then picks a node inside the pool by weight or round robin. The chain head height comes from etcd’s {chainID}[/{version}]/lastBlockNumber, the confirmed height written by consistency-checker. The two pools back each other up: an empty State pool falls back to the Archive pool and vice versa. Chains with only one pool skip context parsing entirely.
The proxy’s “64” is hard-coded, while the query node’s window is set by --diff-depth-limit, whose default happens to be 64 as well. Shrinking the query node window without touching the proxy makes some requests that belong on Archive fail once on a State node first.

Error-code-driven fallback

Three error codes translate “this node does not have that state” into routing actions: A request already on an Archive node is not retried again. Clients that talk to leafage-evm directly have to handle these three codes themselves.

Summary

  • The block context answers “which block’s state”, with two semantics, Equals (exact) and Contains (no older than); omitting it means latest.
  • Contains always runs on latest state on the leafage-evm side and always goes to a State node on the proxy side.
  • The block parameter of eth_* methods does not take part in pool selection; -39006 triggers the fallback to Archive, and x-nodex-node-type: archive forces it.
  • The routing threshold is measured from the confirmed height in etcd, with the boundary 64 blocks behind it.
Continue reading: