Node Architecture
This page describes the internal architecture of a Mersennet node β the Rust binary that produces blocks, executes transactions, participates in consensus, and serves the JSON-RPC API.
Overviewβ
A running Mersennet node is composed of five cooperating subsystems:
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β PRIME CHAIN NODE β
β β
β βββββββββββββ βββββββββββββ ββββββββββββ ββββββββββββββββββββ β
β β JSON-RPC β β WebSocket β β P2P β β Block Producer β β
β β Server β β Server β β Network β β (Engine Loop) β β
β β :8545 β β :9945 β β :30303 β β β β
β βββββββ¬βββββββ βββββββ¬ββββββ ββββββ¬ββββββ βββββββββ¬βββββββββββ β
β β β β β β
β ββββββββββββββββββ΄ββββββββ¬ββββββββ΄ββββββββββββββββββ β
β β β
β ββββββββββββββ΄βββββββββββββ β
β β ENGINE β β
β β β β
β β βββββββββββββββββββ β β
β β β EVM (revm) β β β
β β β + Precompiles β β β
β β ββββββββββ¬βββββββββ β β
β β β β β
β β ββββββββββ΄βββββββββ β β
β β β State Backend β β β
β β β sled / redb β β β
β β βββββββββββββββββββ β β
β β β β
β β βββββββββββββββββββ β β
β β β Consensus β β β
β β β (DPoS + BFT) β β β
β β βββββββββββββββββββ β β
β β β β
β β βββββββββββββββββββ β β
β β β Mempool β β β
β β βββββββββββββββββββ β β
β β β β
β β βββββββββββββββββββ β β
β β β PrimeOrders β β β
β β β Order Book β β β
β β βββββββββββββββββββ β β
β ββββββββββββββββββββββββββ β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
| Component | Role |
|---|---|
| Engine | Central coordinator: drives block production, EVM execution, consensus, and state management |
| P2P Network | TCP/UDP transport for block propagation, transaction gossip, and consensus votes |
| JSON-RPC Server | HTTP endpoint implementing Ethereum-compatible JSON-RPC methods |
| WebSocket Server | Persistent connection endpoint for subscriptions (eth_subscribe) |
| Block Producer | Timer-driven loop that triggers block creation at the configured block_time_ms |
Module Breakdownβ
The codebase is organized into four Rust crates:
crates/core/ β Core Domain Logicβ
The heart of the node. Contains all types, execution logic, and consensus:
| Module | Purpose |
|---|---|
engine | Engine struct coordinating block production, EVM execution, and state transitions. Defines Block, Transaction, Receipt, LogEntry types |
consensus | DPoS validator management, proposer rotation, BFT finalization, slashing, rewards |
hotstuff2 | Alternative HotStuff-2 consensus pipeline (optional) |
crypto | secp256k1 signing/verification, tx_signing_hash, sign_transaction, recover_signer |
state | PersistentState with sled backend, Merkle tree computation, snapshots |
state_redb | Alternative RedbState backend using the redb embedded database |
flat_state | FlatState β flat key-value representation for fast reads |
state_trait | StateBackend trait abstracting storage (sled, redb, in-memory) |
mempool | Transaction pool with nonce ordering, gas price priority, per-sender limits, replacement logic |
precompiles | PrimeOrders EVM precompile registration at address 0x0100 |
precompile_abi | ABI encoding/decoding for precompile function selectors |
prime_orders | Order book state: markets, orders, positions, matching engine |
config | AppConfig and all sub-config structs (EngineConfig, P2pConfig, etc.) |
events | Domain event types for PrimeOrders and Bridge operations |
errors | Error types for RPC validation and PrimeOrders |
network | Network simulation and consensus message types (Prevote, Precommit, etc.) |
bridge | Cross-domain bridge queue (EVM β PrimeOrders) |
prometheus | Prometheus metrics registry and /metrics endpoint |
identity | Node identity (keypair) generation and persistence |
governance | On-chain governance proposals and voting |
pipeline | Block execution pipeline orchestration |
parallel | Parallel transaction execution engine |
fba | Frequent Batch Auction (FBA) matching engine |
mainnet | Mainnet safety guards and invariant checks |
metrics | Internal metrics collection |
zk_proofs | Zero-knowledge proof generation |
zk_sp1 | SP1 zkVM integration |
crates/node/ β Node Binaryβ
The executable entry point that wires all components together:
| File | Purpose |
|---|---|
bin/prime-chain.rs | Main binary: CLI parsing, config loading, identity management, engine initialization, block production loop, P2P networking, RPC server startup |
bin/genesis.rs | Genesis file generator utility |
bin/faucet.rs | Testnet faucet HTTP server |
bin/stresstest.rs | Transaction stress test tool |
bin/loadtest.rs | Network load testing tool |
crates/rpc/ β JSON-RPC Serverβ
HTTP and WebSocket RPC servers:
| File | Purpose |
|---|---|
rpc.rs | HTTP JSON-RPC server using tiny_http. Handles eth_* and prime_* methods. Includes CORS, metrics, and Prometheus /metrics endpoint |
ws.rs | WebSocket server for eth_subscribe (new blocks, pending transactions, logs) |
rpc_router.rs | Method dispatch router mapping RPC method names to handler functions |
crates/network/ β P2P Networkingβ
Peer-to-peer communication layer:
| File | Purpose |
|---|---|
p2p.rs | P2pNetwork and NetworkNode β peer management, message routing, block/tx/vote handling |
net_transport.rs | TcpSync (reliable block sync) and UdpGossip (low-latency tx/vote propagation) |
noise.rs | Noise Protocol Framework encryption for P2P channels |
Execution Pipelineβ
When the block timer fires, the following sequence executes:
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β BLOCK PRODUCTION PIPELINE β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Timer fires (every block_time_ms)
β
βΌ
βββββββββββββββββββββββββββ
β 1. PROPOSER SELECTION β Consensus selects the validator with the
β β highest accumulated priority (stake-weighted
β β round-robin). If this node is not the
β β proposer, it waits for an incoming block.
ββββββββββββββ¬βββββββββββββ
β
βΌ
βββββββββββββββββββββββββββ
β 2. TX GATHERING β Drain pending transactions from the mempool,
β β ordered by gas_price (highest first). Stop
β β when cumulative gas reaches gas_limit_per_block.
ββββββββββββββ¬βββββββββββββ
β
βΌ
βββββββββββββββββββββββββββ
β 3. EVM EXECUTION β For each transaction:
β β a. Build revm::Env (caller, callee, value,
β β data, gas_limit, gas_price)
β β b. Execute via revm with PrimeOrders
β β precompile at 0x0100
β β c. Collect ExecutionResult β Receipt
β β d. Update account states in StateBackend
ββββββββββββββ¬βββββββββββββ
β
βΌ
βββββββββββββββββββββββββββ
β 4. BRIDGE PROCESSING β Process cross-domain bridge messages:
β β - EVM β PrimeOrders deposits
β β - PrimeOrders β EVM withdrawals
ββββββββββββββ¬βββββββββββββ
β
βΌ
βββββββββββββββββββββββββββ
β 5. STATE ROOT β Compute Merkle root over all account states
β β (sorted address β serialized account data).
β β This becomes the block's state_root.
ββββββββββββββ¬βββββββββββββ
β
βΌ
βββββββββββββββββββββββββββ
β 6. REWARD DISTRIBUTION β Calculate block reward based on token
β β economics (10 PRIM/block, halving every
β β 35M blocks). Distribute proportionally
β β to validators by stake weight.
ββββββββββββββ¬βββββββββββββ
β
βΌ
βββββββββββββββββββββββββββ
β 7. FINALIZATION β Run BFT consensus:
β β - Broadcast block to peers
β β - Collect prevotes (2/3+ stake)
β β - Collect precommits (2/3+ stake)
β β - Process slashing evidence
β β - Mark block as finalized
ββββββββββββββ¬βββββββββββββ
β
βΌ
βββββββββββββββββββββββββββ
β 8. BROADCAST β Send finalized block to all connected
β β peers via TCP. Update Prometheus metrics.
β β Notify WebSocket subscribers.
βββββββββββββββββββββββββββ
Storageβ
State Backend Architectureβ
State persistence is abstracted behind the StateBackend trait, allowing pluggable storage engines:
βββββββββββββββββββββββ
β StateBackend β (trait)
β βββββββββββββββββ β
β get_account() β
β set_account() β
β get_storage() β
β set_storage() β
β get_code() β
β state_root() β
β snapshot() / load() β
ββββββββββββ¬βββββββββββ
β
βββββββββββββΌββββββββββββ
β β β
βΌ βΌ βΌ
ββββββββββββ ββββββββββββ ββββββββββββ
β Sled β β Redb β β InMemory β
β (default)β β β β (testing)β
ββββββββββββ ββββββββββββ ββββββββββββ
Sled Backend (Default)β
The default sled backend persists all state to disk at the configured state_path:
state/
βββ node_key.json # Node identity (secp256k1 keypair)
βββ peers.json # Known peer addresses
βββ sled_db/ # sled embedded database
βββ accounts # Address β AccountInfo (nonce, balance, code_hash)
βββ storage # (Address, Slot) β U256 value
βββ code # CodeHash β Bytecode
βββ metadata # Chain height, state root, etc.
Snapshotsβ
The state backend supports snapshots for:
- Crash recovery β Restore to last consistent state on unexpected shutdown
- State sync β Share state snapshots with new nodes joining the network
- Archive queries β Historical state lookups at specific block heights
EVM Integrationβ
Mersennet uses revm (Rust EVM) for transaction execution with the Shanghai specification.
Execution Flowβ
For each transaction, the engine:
- Constructs a
revm::Envwith block context (number, timestamp, coinbase, base_fee, gas_limit) and transaction context (caller, callee, value, data, gas_limit, gas_price) - Builds an
Evminstance with the in-memory database and registered precompiles - Executes the transaction, which may:
- Transfer PRIM between accounts
- Deploy a new contract (when
toisNone) - Call an existing contract
- Interact with the PrimeOrders precompile at
0x0100
- Captures the
ExecutionResult(success/revert/halt, gas used, output, logs) - Commits state changes to the
StateBackend
Precompilesβ
Beyond the standard Ethereum precompiles (ecRecover, SHA-256, RIPEMD-160, identity, modexp, ecAdd, ecMul, ecPairing, blake2f), Mersennet adds:
| Address | Name | Description |
|---|---|---|
0x0100 | PrimeOrders | Native on-chain order book. Solidity contracts can place/cancel orders, query order books, and manage positions atomically within a transaction |
The PrimeOrders precompile is registered via a custom EvmHandler that injects it into the precompile table before each block's execution. A thread-local context (PRIME_ORDERS_CTX) provides the precompile access to the order book state.
Gas Meteringβ
Gas follows standard EVM rules:
- Base transaction cost: 21,000 gas
- Contract creation: 32,000 gas + code deposit cost
- Storage operations: 20,000 gas (SSTORE cold), 5,000 gas (SSTORE warm)
- PrimeOrders precompile calls: fixed gas costs per operation type
- Block gas limit: 30,000,000 (configurable)
EIP-1559 Fee Marketβ
Mersennet implements EIP-1559 dynamic base fee:
if gas_used > target_gas (gas_limit / elasticity):
base_fee increases (up to 12.5% per block)
if gas_used < target_gas:
base_fee decreases (up to 12.5% per block)
Configuration:
fee_elasticity_multiplier: 2 (target gas = gas_limit / 2 = 15M)fee_max_change_denominator: 8 (max 12.5% change per block)
Custom Transaction Formatβ
Mersennet uses a custom binary format for transaction signing, inspired by EIP-155:
Signing Hash Inputβ
The signing hash is keccak256 of the following concatenated big-endian fields:
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Field β Size β Encoding β Description β
βββββββββββββββββΌββββββββββΌββββββββββββββββββΌβββββββββββββββββββ€
β chain_id β 8 bytes β u64 big-endian β Network ID (7919)β
β nonce β 8 bytes β u64 big-endian β Sender nonce β
β gas_price β 32 bytesβ U256 big-endian β Price per gas β
β gas_limit β 8 bytes β u64 big-endian β Max gas β
β to β 20 bytesβ Address or 0x00 β Recipient (0x00 β
β β β β for deploy) β
β value β 32 bytesβ U256 big-endian β PRIM to transfer β
β data β N bytes β Raw bytes β Calldata β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
signing_hash = keccak256(chain_id || nonce || gas_price || gas_limit || to || value || data)
Signed Transaction Wire Formatβ
After signing, the complete transaction includes the original fields plus the ECDSA signature:
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Signing payload (as above) β
β chain_id(8) || nonce(8) || gas_price(32) || gas_limit(8) β
β || to(20) || value(32) || data(N) β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Signature β
β r(32) || s(32) || v(1) β
β β
β v = recovery_id + 35 + chain_id Γ 2 (EIP-155) β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Signature Verificationβ
To recover the signer:
- Reconstruct the signing hash from the transaction fields
- Compute
recovery_id = v - 35 - chain_id Γ 2 - Recover the secp256k1 public key from
(r, s, recovery_id, hash) - Derive the Ethereum address:
keccak256(public_key)[12..32]
Startup Sequenceβ
When the prime-chain binary starts:
1. Initialize tracing (structured logging from RUST_LOG env)
2. Initialize Prometheus metrics exporter
3. Parse CLI arguments and load config.json
4. Load or create node identity (secp256k1 keypair)
5. Initialize Engine with configured storage backend
6. Configure mempool limits, fee market, slashing parameters
7. Apply genesis state (fund accounts, register validators)
8. Set token economics (max supply, rewards, halving)
9. Start JSON-RPC server (if enabled)
10. Start WebSocket server (if enabled)
11. Start P2P networking (TCP sync + UDP gossip)
12. Enter block production loop:
ββ Every block_time_ms:
ββ Process incoming P2P messages (blocks, txs, votes)
ββ If proposer: produce_block()
ββ Run consensus finalization
ββ Broadcast results to peers
ββ Update metrics
13. On SIGINT/SIGTERM: graceful shutdown