This document describes the internal architecture of the Ferrous Network node, including modules, data flow, key abstractions, and the concurrency model.
The crate root is defined in lib.rs and exposes these top-level modules:
- consensus
- dashboard
- mining
- network
- primitives
- rpc
- script
- storage
- wallet
Core blockchain logic:
- block.rs:
BlockHeader,U256, target decoding and PoW checks. - transaction.rs:
Transaction,TxInput,TxOutput,Witness, serialization and basic structure checks. - utxo.rs: In-memory UTXO set (
UtxoSet) and spend/apply logic. - chain.rs:
ChainState, block storage, reorganization, and MedianTimePast. - difficulty.rs: Difficulty target calculation and validation.
- validation.rs: Block-level consensus rules (weight, coinbase, timestamps, witness commitments).
- merkle.rs: Merkle and witness merkle tree construction.
- params.rs:
ChainParamsandNetwork(Mainnet/Testnet/Regtest).
P2P Networking stack:
- manager.rs:
PeerManager, the central hub for P2P connections and message dispatch. - peer.rs:
Peerstate machine, connection handling, and message queues. - protocol.rs: Wire protocol definitions, message types (
Version,Inv,Block, etc.), and serialization. - sync.rs:
SyncManager, handling headers-first synchronization and block downloads. - relay.rs:
BlockRelay, managing inventory announcements and transaction propagation. - discovery.rs: Peer discovery, address exchange (
GetAddr/Addr), and bootstrapping. - keepalive.rs: Connection health monitoring (Ping/Pong) and dead peer detection.
- addrman.rs:
AddressManagerfor storing and selecting peer addresses.
Block template construction and PoW search:
- mining/mod.rs: Module glue.
- miner.rs:
Minertype, coinbase construction, timestamp selection, and nonce search.
Stack-based script engine:
- opcodes.rs: Opcode enumeration and decoding.
- engine.rs: Interpreter, P2PKH/P2WPKH validation, signature checks.
- sighash.rs: Transaction digest computation for signatures.
JSON-RPC interface:
- server.rs: HTTP server, request handling, and method dispatch.
- methods.rs: Request/response structs for RPC methods.
Persistent storage and indexes:
- db.rs: RocksDB wrapper and column family wiring.
- blocks.rs: Block/header storage and indexes.
- chain_state.rs: Persistent chain tip and best-header tracking.
- utxo.rs: UTXO storage.
Wallet management and transaction building:
- manager.rs: Wallet state and address management.
- builder.rs: Transaction construction.
Low-level utilities:
- hash.rs:
sha256dandHash256type alias. - serialize.rs: Custom binary encoding/decoding traits.
- varint.rs: Bitcoin-style VarInt encoding.
Defined in chain.rs, ChainState holds the in-memory view of the active chain:
- Map of block hash to
BlockData(header, transactions, height, cumulative work). - Height index (height → block hash).
- Tip hash and height.
UtxoSetfor validating new transactions.ChainParamsfor the selected network.
Key responsibilities:
new(genesis, genesis_tx, params)initializes the chain with a single genesis block and UTXO state.add_block(header, transactions)validates difficulty, structure, and UTXO rules, then updates chain state and triggers reorgs.reorganize(new_tip)rebuilds the UTXO set along the new best chain using cumulative work.median_time_past()computes MTP over up to 11 previous blocks for timestamp rules and mining.
Defined in utxo.rs, UtxoSet is an in-memory HashMap keyed by outpoints. It:
- Tracks spendable outputs for all blocks on the active chain.
- Enforces coinbase maturity (via
COINBASE_MATURITYin validation.rs). - Prevents double spends when applying new transactions.
Defined in miner.rs, Miner encapsulates:
- Network parameters (
ChainParams) to compute the current target. - Mining address (scriptPubKey bytes) to receive coinbase rewards.
Responsibilities:
create_coinbase(height, subsidy, fees)builds a coinbase transaction that commits to the block height inscript_sig.mine_block(chain, transactions)constructs a block template, computes the target viacalculate_next_target, and searches nonces untilcheck_proof_of_workpasses.mine_and_attach(chain, transactions)mines a block and attaches it toChainStatein one operation.
To ensure robustness, the node includes a dedicated recovery system:
- RecoveryManager: Monitors network health and detects partitions.
- Tracks active peer count and last block reception time.
- Automatically attempts reconnection if isolated (0 peers for >5m or stale tip >30m).
- Strategies: Query known good peers (AddressManager), fallback to seed nodes, or force full reconnect.
- NetworkStats: Aggregates metrics (bytes sent/recv, message counts, ban scores) for diagnostics.
- Diagnostics: Provides detailed peer health reports via RPC.
Defined in server.rs, RpcServer owns:
Arc<Mutex<ChainState>>for synchronized access to the chain.Arc<Miner>for mining operations.Arc<PeerManager>for P2P network control.Arc<RecoveryManager>for network health monitoring.Arc<NetworkStats>for metrics.- A
tiny_http::Serverinstance bound to the configured address.
Responsibilities:
run()accepts HTTP requests and dispatches JSON-RPC calls.- Implements control, wallet, mining, and network methods including
getblockchaininfo,getblockhash,getblock,getbestblockhash,getmininginfo,getnetworkinfo,getpeerinfo,getconnectioncount,getnewaddress,getbalance,listunspent,listaddresses,sendtoaddress,generatetoaddress,resetnetwork, andstop.
PeerManageris initialized and starts listening on the configured port.NetworkListeneraccepts incoming TCP connections and spawns a thread for each.PeerDiscoveryruns in the background, finding new peers viagetaddrandaddrmessages.KeepaliveManagersends periodicpingmessages to ensure connection health.- Incoming messages are dispatched by
PeerManagerto specialized handlers:SyncManager: Handlesheadersandblockdownloads during Initial Block Download (IBD).BlockRelay: Propagates new blocks and transactions viainv/getdata.PeerDiscovery: Updates the address book with new peer information.
SyncManager tracks progress using a SyncState enum:
IdleDownloadingHeadersDownloadingBlocksSynced
- The node is started from examples/node.rs with a chosen network.
create_genesis()builds and mines a genesis block in-memory.ChainState::newinitializes the chain with genesis and a freshUtxoSet.Miner::mine_and_attachis invoked either via CLI mining (--mine) or via RPC (mineblocks/generatetoaddress):next_block_timestampuses MedianTimePast and network-adjusted time to pick a valid timestamp.calculate_next_targetin difficulty.rs computes the next difficulty target from the previous header and timestamp.Mineriterates nonce values untilBlockHeader::check_proof_of_worksucceeds.
ChainState::add_blockvalidates the new block and connects it:- Validates difficulty via
validate_difficulty. - Validates structure and PoW via
validate_block. - Updates
UtxoSetif the chain is extended or reorganized.
- Validates difficulty via
- If valid, the new block is relayed to peers via
BlockRelay::broadcast_block.
- Incoming HTTP requests are handled by
RpcServer::run. - The body is parsed as JSON and forwarded to
handle_json_rpc. - Depending on
method, the server:- Reads from
ChainState(e.g.getblockchaininfo,getbestblockhash,getblock). - Mutates
ChainStatevia mining (mineblocks). - Queries
PeerManager(e.g.getpeerinfo,addnode).
- Reads from
- Responses are serialized using the structs in methods.rs and returned as JSON.
The node uses a simplified concurrency model relying on std::sync:
ChainStateis protected by a globalRwLock, shared between RPC, Mining, and Networking threads. Read-heavy operations (RPC queries, block template construction) hold a read lock; write operations (block application, reorgs) hold a write lock.PeerManageruses internalMutexlocks for its peer map and component references (Relay,Sync,Discovery).- Background threads:
- RPC Server: One thread per request —
run()spawns a new thread per incoming request so that long-running calls (e.g.mineblocksPoW, ~150s) do not block concurrent requests. - P2P Listener: One thread accepting connections.
- Peer Threads: Short-lived handshake threads (one per new connection, exits after handshake completes). All post-handshake message reading is done by a single central message-handler loop in
PeerManagerthat polls all connected peers. - Maintenance Threads: Separate threads for
PeerDiscovery(30s loop) andKeepaliveManager(60s loop).
- RPC Server: One thread per request —
Mineris stateless/immutable configuration wrapped inArc.
Implications:
- Global Lock Contention:
ChainStatelock is the primary bottleneck. Long validation or reorganization holds the lock, blocking RPC and P2P processing. - Deadlock Risk: Care is taken to avoid holding the
PeerManagerlock while calling intoChainState, or vice-versa. - Scaling:
RwLockforChainStateand per-request RPC concurrency are already implemented. Remaining planned improvements: async I/O for peer threads (currently one thread per peer), and further parallel IBD tuning (multi-peer download with ordered apply, Phase 2/3 complete).
Key external dependencies (see Cargo.toml):
sha2,ripemd: Implementhash160andsha256dwithout custom crypto.secp256k1: Provides ECDSA verification for transaction signatures.num-bigint: Used in difficulty and work calculations.serde,serde_json: JSON encoding/decoding for RPC.tiny_http: Minimal HTTP server for the RPC interface.clap: Command-line parsing for the example node binary.
Design choices:
- No unsafe code: Enforced at the crate level in lib.rs.
- In-memory hot path:
ChainStatemaintains an in-memory view of the active chain for validation and mining, while persistence is provided via RocksDB. - Explicit serialization: Custom
Encode/Decodetraits in serialize.rs avoid relying onserdefor consensus-critical binary formats.
ChainStateis guarded by a globalRwLockand is a known bottleneck under load (RPC timeouts can occur during heavy sync/mining).- Parallel IBD is in progress: Phase 1 headers-first state machine is deployed; multi-peer download + ordered apply are planned next.
- Address format and wallet/RPC ergonomics are evolving and will change as Dilithium and later privacy features are integrated.