Zum Inhalt

UMNode — Unus Mundus Node

Status — pre-alpha. UMNode joins an Ethereum network, follows the chain head, and persists a peer inventory; two workers fill a compact on-disk block store (realtime from the head, backfill through history), a block-hash / transaction-hash index is built alongside, and a JSON-RPC server serves block and transaction reads plus debug/ops methods. An execution subsystem (on by default) builds state from genesis and serves eth_call, the state getters, the callTracer trace methods, and — deriving receipts instead of downloading them — eth_getTransactionReceipt, eth_getBlockReceipts and eth_getLogs. This documentation is kept up to date as the project progresses.

UMNode is an ultra-lightweight imitation of a blockchain client, built for one job: serving RPC. It speaks a chain's peer-to-peer wire protocol directly to pull blocks, headers and receipts, stores them locally in a compact segmented store, and serves them over JSON-RPC — without running consensus. State is built by a trie-free embedded EVM that re-executes the stored chain — nothing is trusted that the node didn't derive itself.

It is currently EVM-only: Ethereum (eth/68, eth/69 and eth/70) and BNB Smart Chain (bsc's eth/68 and eth/70 flavours, with the Parlia execution rules). More network families will follow as the core stabilises.

Why UMNode exists

A full node carries the entire weight of consensus to answer an RPC query. UMNode takes the opposite bet: most RPC traffic is reads of historical blocks, transactions and receipts — data that can be fetched directly over the wire protocol and stored compactly. For the state-dependent rest (eth_call, balances, traces), UMNode re-executes the chain through an embedded EVM into a compact flat state store — no Merkle trie, no consensus — so it aims to stay small, cheap to run, and fast to stand up.

The trade-off: state-dependent calls answer only once the backfill has reached genesis and execution has caught up — until then they return an explicit state not ready error (never an approximation). Operators who only need block/transaction serving can skip state entirely with --execute=false.

What it does today

  • Joins the network — discovery (v4/v5), dials out only, never accepts inbound connections.
  • Handshakes at the eth layer — validates network id and EIP-2124 fork id so it only keeps genuinely compatible peers.
  • Tracks the chain head — polls a peer on an interval and follows the head.
  • Persists a peer inventory — remembers known-good peers across restarts so it can re-dial them.
  • Opens a segmented block store — a compact, immutable, compressed on-disk format, created and validated at startup.
  • Fills it from the network — a realtime worker follows the head; a backfill worker fills the rest of history (forward from genesis by default, so an indexer can consume blocks in order).
  • Fetches from existing nodes too — --rpc-peers points it at the JSON-RPC of synced (or partially synced) nodes, used ahead of the p2p peers and validated like them; a node can run from them alone.
  • Indexes by hash — an optional block-hash / transaction-hash index backs by-hash lookups, built as blocks confirm.
  • Keeps as much history as you ask — an archive by default; --block-history N prunes the block store to the most recent N blocks, dropping whole sealed segments and capping state and receipts history with it; --extra-archive-blocks A:B,… keeps block ranges outside that window, with their state history and receipts when the archive has them.
  • Backs its segments up, and starts from them — --backup copies every sealed segment (blocks, state history, receipts) and the state snapshots to S3 / R2 / a directory as it seals, and pruning waits for it: no segment goes before it is backed up. The segment archive is also where a node starts: backfill attaches verified block segments from it (the public archive by default) instead of fetching block by block, and --syncmode snap (the default) restores the newest state snapshot and executes on from its head, downloading only the blocks the node keeps.
  • Serves JSON-RPC — block and transaction reads (eth_getBlockByNumber, eth_getBlockByHash, eth_getTransactionByHash), receipts and logs (eth_getTransactionReceipt, eth_getBlockReceipts, eth_getLogs), the state methods, plus debug / ops methods (debug_status, debug_getBlockArtifact, debug_indexStatus, …).

Where to start

  • Quickstart — run UMNode in minutes with Go or Docker.
  • Configuration — the per-network YAML file and how settings are resolved.
  • CLI flags — every flag, its default and meaning.
  • Architecture — the theory: how UMNode fills and serves its store.
  • Block store — the segmented, immutable, compressed store in depth.
  • JSON-RPC API — every method, its parameters and result shape.
  • Hash indexing — by-hash lookups, and the index's size and upkeep.
  • Networking & peers — discovery, handshake and the peer inventory.
  • Segment archive — backing sealed segments up to S3, and attaching them from an archive.

License & source

Source lives at github.com/ofzhur/umnode.