Architecture
Five JavaScript layers, one Node.js process, no C++ dependencies — everything from consensus wire format to the RPC interface your wallet already speaks.
TL;DR. ANT + HTTP networking, Tendermint-style BFT consensus, a Sparse Merkle Tree state, a Hardened JavaScript sandbox for contracts, and a JSON-RPC interface on top — all post-quantum, all running as a single Node.js process light enough for a Raspberry Pi 4.
Aevum is five JavaScript layers stacked on top of each other, all running inside a single Node.js process light enough for a Raspberry Pi 4.
The stack
- JSON-RPC (HTTP + WebSocket) at the top
- Hardened JavaScript VM using SES Compartments
- Sparse Merkle Tree state, backed by LevelDB
- Tendermint-style BFT consensus, signed with ML-DSA-65
- Aevum Native Transport (ANT) + HTTP at the bottom
Every layer is independently readable, with no C++ dependencies — pure Node.js, with WASM for the cryptography primitives.
Networking: ANT + HTTP
Two transports do two different jobs. ANT is a persistent-TCP, length-prefixed protocol built specifically for consensus votes between a small, known set of validators. It runs in its own worker thread so a burst of consensus traffic can never starve the keep-alive loop.
HTTP handles everything else: block sync, RPC queries, and client interactions through the same JSON-RPC endpoint. Full nodes pull blocks in batches of 32 from peers via a /block-raw/:n endpoint. Consensus needs a tight, low-latency channel between known validators; block sync needs to work from behind a restrictive corporate firewall. One transport can't do both well, so Aevum doesn't ask it to.
Consensus: BFT
A Tendermint-style BFT committee of roughly 100 validators finalizes each block across four stages — propose, pre-vote, pre-commit, finality — each requiring 2/3 of voting power. Every vote is an ML-DSA-65 (Dilithium3) signature. At ~3.3KB per signature, ~100 signatures per block is close to the practical ceiling for a committee this size — see Consensus & Validators for the full picture.
State: Sparse Merkle Tree
Account balances, nonces, contract code, and contract storage all live in a single Sparse Merkle Tree, indexed by hash. The tree root goes in every block header, so every validator can check they're looking at the same state. LevelDB handles persistence underneath; full nodes prune opportunistically, and archive nodes keep every historical root.
Execution: Hardened JavaScript
Contracts are plain JavaScript source. Each transaction executes inside a fresh SES Compartment, with storage, events, and cross-contract calls injected as globals — and anything that would break determinism (wall-clock time, randomness, network access) simply isn't there to call.
Gas is metered per transaction type rather than per opcode: a base cost, plus charges for storage writes, event bytes, and a cold-load surcharge for large modules on their first call in a block.
Interface: JSON-RPC
Aevum exposes a JSON-RPC 2.0 interface modeled on Ethereum's. Most eth_* methods behave identically, so MetaMask, ethers.js, viem, and existing block explorers mostly just work. The one place compatibility breaks is signing: MetaMask produces ECDSA signatures, and Aevum needs Dilithium3 — so signing goes through the Aevum Wallet extension or SDK instead.
Transaction flow
- A wallet builds an SSZ-encoded transaction and signs it with Dilithium3
- The wallet submits it via
eth_sendRawTransactionto any full node - The node validates signature, nonce, balance, and gas, then broadcasts it over HTTP
- The current proposer assembles mempool transactions into a candidate block
- The committee pre-votes, pre-commits, and finalizes it with Dilithium3 signatures
- The VM executes each transaction, updating the Sparse Merkle Tree
- Receipts, events, and the new state root are persisted and streamed over JSON-RPC