iuna

iuna - experimental devnet protocol
git clone https://iuna.jhx.app/git/iuna.git
Log | Files | Refs | README | LICENSE

commit e8faafc931432f434d85862800286ebfd71330ea
parent a70b7f796ded9a81bfdd6e698582fcfd997f7f21
Author: Joris Hartog <jorishartog@hotmail.com>
Date:   Wed, 29 Jul 2026 16:35:42 +0200

Clean up runtime logging

Diffstat:
Arust-toolchain.toml | 4++++
Msrc/adapters/p2p.rs | 25+++++++++++++++++--------
Msrc/adapters/stratum.rs | 9++++++---
Msrc/app.rs | 14+++++++++++++-
Msrc/main.rs | 83+++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------
5 files changed, 98 insertions(+), 37 deletions(-)

diff --git a/rust-toolchain.toml b/rust-toolchain.toml @@ -0,0 +1,4 @@ +[toolchain] +channel = "1.86.0" +components = ["rustfmt", "clippy"] +profile = "minimal" diff --git a/src/adapters/p2p.rs b/src/adapters/p2p.rs @@ -25,7 +25,7 @@ use crate::{ app::{ BlockInventory, GossipEnvelope, MEMPOOL_STATUS_LIMIT, NETWORK_ID, NodeCore, PROTOCOL_VERSION, PeerDirection, ProtocolHello, SharedNode, SharedPeerBook, - TransactionRejection, now_ms, + TransactionRejection, debug_logging_enabled, now_ms, }, domain::{Block, ChainSnapshot, Ledger, Transaction, TransactionSubmitOutcome, verify_vdf}, }; @@ -609,7 +609,9 @@ impl GossipNetwork { async fn forward_outbox(&self) { let outbox = self.inner.node.lock().await.drain_outbox(); if let Err(error) = self.broadcast(outbox).await { - eprintln!("p2p rebroadcast failed: {error:#}"); + if debug_logging_enabled() { + eprintln!("p2p rebroadcast failed: {error:#}"); + } } } } @@ -642,14 +644,17 @@ async fn accept_loop(network: GossipNetwork, listener: TcpListener) { &network.inner.metrics.last_session_failure, format!("{remote_addr}: {error:#}"), ); - eprintln!( - "p2p inbound connection from {remote_addr} failed: {error:#}" - ); + if debug_logging_enabled() { + eprintln!( + "p2p inbound connection from {remote_addr} failed: {error:#}" + ); + } } } }); } - Err(error) => eprintln!("p2p accept failed: {error:#}"), + Err(error) if debug_logging_enabled() => eprintln!("p2p accept failed: {error:#}"), + Err(_) => {} } } } @@ -745,7 +750,9 @@ async fn outbound_session( .lock() .await .record_error(&peer, message.clone()); - eprintln!("p2p session with {peer} failed: {message}"); + if debug_logging_enabled() { + eprintln!("p2p session with {peer} failed: {message}"); + } } } @@ -2142,7 +2149,9 @@ async fn record_inbound_result( .await .record_misbehavior(&peer, message.clone()); } - eprintln!("p2p envelope from {peer} ignored: {message}"); + if debug_logging_enabled() { + eprintln!("p2p envelope from {peer} ignored: {message}"); + } } } } diff --git a/src/adapters/stratum.rs b/src/adapters/stratum.rs @@ -17,7 +17,7 @@ use tokio::{ use crate::{ adapters::p2p::GossipNetwork, - app::{ExternalMineJob, SharedNode}, + app::{ExternalMineJob, SharedNode, debug_logging_enabled}, domain::{STRATUM_EXTRANONCE1_HEX, STRATUM_EXTRANONCE2_SIZE, StratumMineShare}, }; @@ -66,13 +66,16 @@ async fn run_listener(server: StratumServer, listener: TcpListener) { let server = server.clone(); tokio::spawn(async move { if let Err(error) = handle_connection(server, stream).await { - eprintln!("stratum session with {remote} failed: {error:#}"); + if debug_logging_enabled() { + eprintln!("stratum session with {remote} failed: {error:#}"); + } } }); } - Err(error) => { + Err(error) if debug_logging_enabled() => { eprintln!("stratum accept failed: {error:#}"); } + Err(_) => {} } } } diff --git a/src/app.rs b/src/app.rs @@ -1,6 +1,9 @@ use std::{ collections::{BTreeMap, BTreeSet}, - sync::Arc, + sync::{ + Arc, + atomic::{AtomicBool, Ordering}, + }, time::{SystemTime, UNIX_EPOCH}, }; @@ -31,6 +34,15 @@ pub const PEER_MISBEHAVIOR_BAN_MS: u64 = 10 * 60 * 1_000; pub const PEER_CLOCK_OFFSET_ACCEPTANCE_MS: i64 = 10 * 60 * 1_000; const PEER_CLOCK_OFFSET_STALE_MS: u64 = 20 * 60 * 1_000; const AUTO_POW_NONCE_ATTEMPTS_PER_TICK: u64 = 8; +static DEBUG_LOGGING: AtomicBool = AtomicBool::new(false); + +pub fn set_debug_logging(enabled: bool) { + DEBUG_LOGGING.store(enabled, Ordering::Relaxed); +} + +pub fn debug_logging_enabled() -> bool { + DEBUG_LOGGING.load(Ordering::Relaxed) +} #[derive(Clone, Debug)] pub struct NodeConfig { diff --git a/src/main.rs b/src/main.rs @@ -10,7 +10,10 @@ use std::{ use anyhow::{Context, Result, bail}; use iuna::{ adapters::{chain_store::SqliteChainStore, config_store, http, p2p, stratum, wallet_store}, - app::{NodeCore, PeerBook, SharedNode, SharedPeerBook, StratumStatus, now_ms}, + app::{ + NodeCore, PeerBook, SharedNode, SharedPeerBook, StratumStatus, debug_logging_enabled, + now_ms, set_debug_logging, + }, domain::{ Amount, ChainSnapshot, GenesisBurn, Ledger, MICRO_IUNA, VDF_TARGET_BLOCK_MS, run_vdf, }, @@ -29,6 +32,8 @@ async fn main() -> Result<()> { let Some(opts) = CliOptions::parse()? else { return Ok(()); }; + set_debug_logging(opts.debug); + let debug_logging = opts.debug; let wallet_path = opts.wallet_path(); let config_path = opts.config_path(); let wallet_file_exists = wallet_path.exists(); @@ -124,13 +129,13 @@ async fn main() -> Result<()> { let finalizer_node = Arc::clone(&node); let finalizer_gossip = gossip.clone(); tokio::spawn(async move { - run_automatic_finalizer(finalizer_node, finalizer_gossip).await; + run_automatic_finalizer(finalizer_node, finalizer_gossip, debug_logging).await; }); let sync_node = Arc::clone(&node); let sync_gossip = gossip.clone(); tokio::spawn(async move { - run_peer_sync(sync_node, sync_gossip).await; + run_peer_sync(sync_node, sync_gossip, debug_logging).await; }); if !has_chain { @@ -249,6 +254,7 @@ struct CliOptions { join_peers: Vec<String>, chain_mode: ChainMode, data_dir: PathBuf, + debug: bool, } impl CliOptions { @@ -267,6 +273,7 @@ impl CliOptions { join_peers: Vec::new(), chain_mode: ChainMode::Setup, data_dir: default_data_dir(), + debug: false, }; let raw_args = args.into_iter().collect::<Vec<_>>(); @@ -317,6 +324,7 @@ impl CliOptions { opts.join_peers.push(peer); } "--data-dir" => opts.data_dir = PathBuf::from(next_value(&mut args, "--data-dir")?), + "--debug" => opts.debug = true, "--help" | "-h" => { print_help(); std::process::exit(0); @@ -404,7 +412,8 @@ fn help_text() -> &'static str { --p2p <addr:port> P2P TCP listener address (default 127.0.0.1:9444)\n\ --stratum <addr:port> Stratum V1 listener for SHA-256 ASIC miners\n\ --join <addr:port> Fetch chain snapshot from this peer before finalization\n\ - --data-dir <path> Local wallet directory (default ~/.iuna)\n\n\ + --data-dir <path> Local wallet directory (default ~/.iuna)\n\ + --debug Print verbose runtime logs\n\n\ Environment:\n\ IUNA_DEV_SKIP_SEED_VERIFY=1 Show a setup button to skip seed verification\n" } @@ -522,7 +531,7 @@ async fn join_chain_ledger(join_peers: &[String], advertised_addr: SocketAddr) - ) } -async fn run_automatic_finalizer(node: SharedNode, gossip: p2p::GossipNetwork) { +async fn run_automatic_finalizer(node: SharedNode, gossip: p2p::GossipNetwork, debug: bool) { let mut last_logged_skip: Option<(u64, String)> = None; loop { if !node.lock().await.has_real_chain() { @@ -538,21 +547,25 @@ async fn run_automatic_finalizer(node: SharedNode, gossip: p2p::GossipNetwork) { }; if let Err(error) = gossip.broadcast(outbox).await { - eprintln!("p2p broadcast failed after automatic burn: {error:#}"); + if debug { + eprintln!("p2p broadcast failed after automatic burn: {error:#}"); + } } - if let Some(tx) = &plan.pow_mined { - println!( - "auto-pow queued mine action for height {} ({})", - height, - tx.signature() - ); + if debug { + if let Some(tx) = &plan.pow_mined { + println!( + "auto-pow queued mine action for height {} ({})", + height, + tx.signature() + ); + } } let Some(work) = plan.work else { if let Some(reason) = &plan.skipped_reason { let skip = (height, reason.clone()); - if last_logged_skip.as_ref() != Some(&skip) { + if debug && last_logged_skip.as_ref() != Some(&skip) { println!("auto-finalization skipped at height {height}: {reason}"); last_logged_skip = Some(skip); } @@ -562,18 +575,22 @@ async fn run_automatic_finalizer(node: SharedNode, gossip: p2p::GossipNetwork) { }; last_logged_skip = None; - println!( - "leader selected locally for candidate block {}; running VDF for {} rounds", - work.height(), - work.vdf_rounds() - ); + if debug { + println!( + "leader selected locally for candidate block {}; running VDF for {} rounds", + work.height(), + work.vdf_rounds() + ); + } let seed = work.vdf_seed().to_string(); let rounds = work.vdf_rounds(); let vdf_output = match tokio::task::spawn_blocking(move || run_vdf(&seed, rounds)).await { Ok(output) => output, Err(error) => { - eprintln!("VDF worker failed: {error:#}"); + if debug { + eprintln!("VDF worker failed: {error:#}"); + } continue; } }; @@ -586,21 +603,25 @@ async fn run_automatic_finalizer(node: SharedNode, gossip: p2p::GossipNetwork) { }; match finalized { - Ok(block) => { + Ok(block) if debug => { println!("auto-finalized block {} ({})", block.height, block.hash); } - Err(error) => println!("auto-finalization skipped after VDF: {error:#}"), + Ok(_) => {} + Err(error) if debug => println!("auto-finalization skipped after VDF: {error:#}"), + Err(_) => {} } if let Err(error) = gossip.broadcast(outbox).await { - eprintln!("p2p broadcast failed after automatic block: {error:#}"); + if debug { + eprintln!("p2p broadcast failed after automatic block: {error:#}"); + } } tokio::task::yield_now().await; } } -async fn run_peer_sync(node: SharedNode, gossip: p2p::GossipNetwork) { +async fn run_peer_sync(node: SharedNode, gossip: p2p::GossipNetwork, debug: bool) { loop { tokio::time::sleep(std::time::Duration::from_secs(5)).await; let envelopes = { @@ -613,7 +634,9 @@ async fn run_peer_sync(node: SharedNode, gossip: p2p::GossipNetwork) { let mut envelopes = envelopes; envelopes.push(gossip.peer_exchange().await); if let Err(error) = gossip.broadcast(envelopes).await { - eprintln!("p2p sync gossip failed: {error:#}"); + if debug { + eprintln!("p2p sync gossip failed: {error:#}"); + } } } } @@ -646,7 +669,10 @@ async fn run_chain_persistence_with_interval( match persist_chain_snapshot(&store, snapshot).await { Ok(()) => last_saved_tip = Some(tip_hash), - Err(error) => eprintln!("chain persistence failed: {error:#}"), + Err(error) if debug_logging_enabled() => { + eprintln!("chain persistence failed: {error:#}") + } + Err(_) => {} } } } @@ -688,6 +714,7 @@ mod tests { assert!(help_text().contains("IUNA_DEV_SKIP_SEED_VERIFY=1")); assert!(help_text().contains("skip seed verification")); assert!(help_text().contains("--stratum <addr:port>")); + assert!(help_text().contains("--debug")); } fn ledger_with_one_spendable_iuna(wallet: &Wallet) -> Ledger { @@ -736,6 +763,12 @@ mod tests { } #[test] + fn debug_logging_can_be_enabled() { + assert!(!parse(&[]).unwrap().unwrap().debug); + assert!(parse(&["--debug"]).unwrap().unwrap().debug); + } + + #[test] fn removed_wallet_seed_is_rejected() { let error = parse(&["--wallet-seed", "alice", "--genesis"]).unwrap_err(); assert!(error.to_string().contains("--wallet-seed was removed"));