nu-node/src/main.rs
Mukan Erkin 265097375a feat(nu-node): single-validator block production loop
- nu-vm/engine.rs: execute_block runs all txs in a block against StateDb;
  TokenTransfer fully applied, other variants return "not implemented" receipt
- StateAccessor trait: set_balance/inc_nonce now take &self (RocksDB interior mutability)
- src/block_loop.rs: tokio task that produces a block each slot (6s) in dev mode;
  drains mempool, executes txs, removes successful ones, persists block to RocksDB
- StateDb wrapped in Arc<Mutex> — block loop holds write lock per block, RPC holds
  read lock for nu_getAccount
- main.rs: spawns block_loop when --dev --validator flags are set

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-24 10:54:48 +03:00

81 lines
2 KiB
Rust

mod block_loop;
use std::sync::Arc;
use anyhow::Result;
use clap::Parser;
use tokio::sync::Mutex;
use tracing_subscriber::EnvFilter;
use nu_mempool::Mempool;
use nu_rpc::server::RpcServer;
use nu_state::StateDb;
#[derive(Parser)]
#[command(name = "nu-node", version)]
struct Cli {
/// Single-validator dev mode — no consensus, produces blocks every slot
#[arg(long)]
dev: bool,
/// Act as block-producing validator
#[arg(long)]
validator: bool,
/// Validator address (required when --validator is set)
#[arg(long, default_value = "0xDEV0000000000000000000000000000000000000")]
validator_addr: String,
/// JSON-RPC HTTP bind address
#[arg(long, default_value = "0.0.0.0:9545")]
rpc_addr: String,
/// RocksDB data directory
#[arg(long, default_value = "./data/state")]
db_path: String,
/// Chain identifier
#[arg(long, default_value = "nu-devnet-1")]
chain_id: String,
}
#[tokio::main]
async fn main() -> Result<()> {
tracing_subscriber::fmt()
.with_env_filter(EnvFilter::from_default_env())
.init();
let cli = Cli::parse();
let db = Arc::new(Mutex::new(StateDb::open(&cli.db_path)?));
tracing::info!("State DB opened at {}", cli.db_path);
let mempool = Arc::new(Mutex::new(Mempool::new()));
// Spawn block production loop in dev mode
if cli.dev && cli.validator {
let cfg = block_loop::BlockLoopConfig {
validator_addr: cli.validator_addr.clone(),
chain_id: cli.chain_id.clone(),
};
tokio::spawn(block_loop::run(cfg, Arc::clone(&db), Arc::clone(&mempool)));
}
let rpc = RpcServer::new(
cli.rpc_addr.clone(),
Arc::clone(&db),
Arc::clone(&mempool),
cli.chain_id.clone(),
);
tracing::info!(
chain_id = %cli.chain_id,
rpc_addr = %cli.rpc_addr,
dev = cli.dev,
validator = cli.validator,
"nu-node ready"
);
rpc.run().await?;
Ok(())
}