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:
- bip39.rs: BIP39 entropy/mnemonic/seed derivation. Converts 256-bit entropy to a 24-word mnemonic and derives a 64-byte seed via PBKDF2-HMAC-SHA512 (2048 iterations).
- bip39_wordlist.rs: The 2048-word BIP39 English wordlist.
- shamir.rs: GF(256) Shamir's Secret Sharing. Splits arbitrary byte secrets into M-of-N shares using polynomial evaluation over GF(256) with irreducible polynomial 0x11b.
- keys.rs:
KeyStore— persistent key storage in binary FERR v2 format. Encrypts with ChaCha20-Poly1305 AEAD keyed by PBKDF2-HMAC-SHA512 (210,000 iterations). Derives keys from BIP39 seed via SHA-512. Migrates old CSV wallets on load. Atomic writes via tmp+rename. - address.rs: Base58Check address encoding/decoding. P2PKH script construction and address recovery from script pubkeys.
- manager.rs:
Wallet— high-level wallet interface. WrapsKeyStorewith UTXO queries, balance calculation, and address generation. UTXOs returned sorted descending by value for greedy coin selection. - builder.rs: Transaction construction. Selects coins (largest-first), builds outputs, signs inputs with ECDSA, generates change address via dedicated change derivation path.
Low-level utilities:
- hash.rs:
sha256dandHash256type alias. - serialize.rs: Custom binary encoding/decoding traits.
- varint.rs: Compact-size VarInt encoding.
Defined in chain.rs, ChainState holds the in-memory view of the active chain:
LruCache<Hash256, BlockData>capped at 2048 entries. Blocks not in the cache are served from RocksDB on demand.- 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.build_template(chain)reads chain state under a read lock and returns aBlockTemplate(coinbase, transactions, target). Lock is released immediately.solve_template(template)runs the nonce search in parallel via rayon with no chain lock held.build_template_to(chain, script)variant used bygeneratetoaddressfor a custom coinbase script.
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<RwLock<ChainState>>for synchronized access to the chain.Arc<Miner>for mining operations.Arc<Mutex<Wallet>>for wallet operations.Arc<PeerManager>for P2P network control.Arc<RecoveryManager>for network health monitoring.Arc<NetworkStats>for metrics.Arc<NetworkMempool>for transaction pool access.- 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.- Block production uses a three-phase split to avoid holding the chain lock during PoW:
- Phase 1 (build):
build_template(&ChainState)acquires a read lock, reads the tip, selects mempool transactions, constructs a coinbase, and returns aBlockTemplate. Lock released immediately. - Phase 2 (solve):
solve_template(BlockTemplate)searches nonces in parallel via rayon with no chain lock held.next_block_timestampenforces MedianTimePast;calculate_next_targetcomputes the difficulty target. - Phase 3 (commit):
ChainState::add_blockacquires a write lock briefly to validate and attach the solved block.
- Phase 1 (build):
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.