diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 67628e35..2e96764c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -76,6 +76,30 @@ jobs: - name: Build release run: cargo build --release + no-logs-in-release: + name: No Logging in Release Binary + runs-on: ubuntu-latest + needs: build + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + - uses: Swatinem/rust-cache@v2 + - name: Ensure release binary contains no tracing callsite metadata + run: | + cargo build --release --bin saorsa-node + BINARY=target/release/saorsa-node + # When cfg(debug_assertions)-gated logging is working correctly, no tracing + # callsite metadata (module paths with "event :" patterns) should + # survive in the release binary. We check for the "event :" pattern + # that tracing embeds at each callsite. + MATCHES=$(strings "$BINARY" | grep -cE '^event (src/|/home/).*\.rs:[0-9]+' || true) + if [ "$MATCHES" -gt 0 ]; then + echo "FAIL: release binary contains $MATCHES tracing callsite(s):" + strings "$BINARY" | grep -E '^event (src/|/home/).*\.rs:[0-9]+' + exit 1 + fi + echo "PASS: release binary contains no tracing callsite metadata" + security: name: Security Audit runs-on: ubuntu-latest diff --git a/src/bin/saorsa-cli/cli.rs b/src/bin/saorsa-cli/cli.rs index 00372153..d33ee104 100644 --- a/src/bin/saorsa-cli/cli.rs +++ b/src/bin/saorsa-cli/cli.rs @@ -25,6 +25,7 @@ pub struct Cli { #[arg(long)] pub allow_loopback: bool, + #[cfg(debug_assertions)] /// Log level. #[arg(long, default_value = "info")] pub log_level: String, diff --git a/src/bin/saorsa-cli/main.rs b/src/bin/saorsa-cli/main.rs index 62d2cefe..3bff4f0b 100644 --- a/src/bin/saorsa-cli/main.rs +++ b/src/bin/saorsa-cli/main.rs @@ -16,10 +16,11 @@ use saorsa_node::client::self_encrypt::{ use saorsa_node::client::{QuantumClient, QuantumConfig, XorName}; use saorsa_node::devnet::DevnetManifest; use saorsa_node::error::Error; +use saorsa_node::info; use std::io::{Read as _, Write as _}; use std::path::{Path, PathBuf}; use std::sync::Arc; -use tracing::info; +#[cfg(debug_assertions)] use tracing_subscriber::{fmt, prelude::*, EnvFilter}; /// Length of an `XorName` address in bytes. @@ -31,13 +32,16 @@ async fn main() -> color_eyre::Result<()> { let cli = Cli::parse(); - let filter = - EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new(&cli.log_level)); + #[cfg(debug_assertions)] + { + let filter = + EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new(&cli.log_level)); - tracing_subscriber::registry() - .with(fmt::layer().with_writer(std::io::stderr)) - .with(filter) - .init(); + tracing_subscriber::registry() + .with(fmt::layer().with_writer(std::io::stderr)) + .with(filter) + .init(); + } info!("saorsa-cli v{}", env!("CARGO_PKG_VERSION")); @@ -185,8 +189,8 @@ async fn handle_download( )); }; - let chunk_count = data_map.chunk_identifiers.len(); - info!("DataMap loaded: {chunk_count} chunk(s)"); + let _chunk_count = data_map.chunk_identifiers.len(); + info!("DataMap loaded: {_chunk_count} chunk(s)"); // Determine output path let output_path = output.map_or_else( diff --git a/src/bin/saorsa-devnet/cli.rs b/src/bin/saorsa-devnet/cli.rs index 4bb5ae3a..fbe833e4 100644 --- a/src/bin/saorsa-devnet/cli.rs +++ b/src/bin/saorsa-devnet/cli.rs @@ -44,6 +44,7 @@ pub struct Cli { #[arg(long)] pub manifest: Option, + #[cfg(debug_assertions)] /// Log level for devnet process. #[arg(long, default_value = "info")] pub log_level: String, diff --git a/src/bin/saorsa-devnet/main.rs b/src/bin/saorsa-devnet/main.rs index 8b94f04e..e39da884 100644 --- a/src/bin/saorsa-devnet/main.rs +++ b/src/bin/saorsa-devnet/main.rs @@ -5,7 +5,8 @@ mod cli; use clap::Parser; use cli::Cli; use saorsa_node::devnet::{Devnet, DevnetConfig, DevnetEvmInfo, DevnetManifest}; -use tracing::info; +use saorsa_node::info; +#[cfg(debug_assertions)] use tracing_subscriber::{fmt, prelude::*, EnvFilter}; #[tokio::main] @@ -14,13 +15,16 @@ async fn main() -> color_eyre::Result<()> { let cli = Cli::parse(); - let filter = - EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new(&cli.log_level)); + #[cfg(debug_assertions)] + { + let filter = + EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new(&cli.log_level)); - tracing_subscriber::registry() - .with(fmt::layer()) - .with(filter) - .init(); + tracing_subscriber::registry() + .with(fmt::layer()) + .with(filter) + .init(); + } info!("saorsa-devnet v{}", env!("CARGO_PKG_VERSION")); diff --git a/src/bin/saorsa-node/cli.rs b/src/bin/saorsa-node/cli.rs index e04f2b5a..b8a76d26 100644 --- a/src/bin/saorsa-node/cli.rs +++ b/src/bin/saorsa-node/cli.rs @@ -67,20 +67,24 @@ pub struct Cli { #[arg(long, default_value = "9100", env = "SAORSA_METRICS_PORT")] pub metrics_port: u16, + #[cfg(debug_assertions)] /// Log level. #[arg(long, value_enum, default_value = "info", env = "RUST_LOG")] pub log_level: CliLogLevel, + #[cfg(debug_assertions)] /// Log output format. #[arg(long, value_enum, default_value = "text", env = "SAORSA_LOG_FORMAT")] pub log_format: CliLogFormat, + #[cfg(debug_assertions)] /// Directory for log file output. /// When set, logs are written to files in this directory instead of stdout. /// Files rotate daily and are named saorsa-node.YYYY-MM-DD.log. #[arg(long, env = "SAORSA_LOG_DIR")] pub log_dir: Option, + #[cfg(debug_assertions)] /// Maximum number of rotated log files to retain (only used with --log-dir). /// Oldest files are deleted when this limit is reached. Rotation is daily. #[arg(long, default_value = "7", env = "SAORSA_LOG_MAX_FILES")] @@ -208,7 +212,10 @@ impl Cli { config.port = self.port; config.ip_version = self.ip_version.into(); config.bootstrap = self.bootstrap; - config.log_level = self.log_level.into(); + #[cfg(debug_assertions)] + { + config.log_level = self.log_level.into(); + } config.network_mode = self.network_mode.into(); // Upgrade config diff --git a/src/bin/saorsa-node/main.rs b/src/bin/saorsa-node/main.rs index a13acc3a..1efcc0cd 100644 --- a/src/bin/saorsa-node/main.rs +++ b/src/bin/saorsa-node/main.rs @@ -3,10 +3,14 @@ mod cli; use clap::Parser; -use cli::{Cli, CliLogFormat}; +use cli::Cli; +#[cfg(debug_assertions)] +use cli::CliLogFormat; +use saorsa_node::info; use saorsa_node::NodeBuilder; -use tracing::info; +#[cfg(debug_assertions)] use tracing_subscriber::prelude::*; +#[cfg(debug_assertions)] use tracing_subscriber::{fmt, EnvFilter, Layer}; #[tokio::main] @@ -17,63 +21,67 @@ async fn main() -> color_eyre::Result<()> { // Parse CLI arguments let cli = Cli::parse(); - // Extract logging options before consuming the CLI struct - let log_format = cli.log_format; - let log_dir = cli.log_dir.clone(); - let log_max_files = cli.log_max_files; + #[cfg(debug_assertions)] + { + // Extract logging options before consuming the CLI struct + let log_format = cli.log_format; + let log_dir = cli.log_dir.clone(); + let log_max_files = cli.log_max_files; - // Initialize tracing - let log_level: String = cli.log_level.into(); - let filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new(&log_level)); + // Initialize tracing + let log_level: String = cli.log_level.into(); + let filter = + EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new(&log_level)); - // _guard must live for the duration of main() to ensure log flushing. - // The guard's Drop impl flushes buffered logs — it is intentionally held, not read. - #[allow(clippy::collection_is_never_read)] - let _guard: Option; + // _guard must live for the duration of main() to ensure log flushing. + // The guard's Drop impl flushes buffered logs — it is intentionally held, not read. + #[allow(clippy::collection_is_never_read)] + let _guard: Option; - let layer: Box + Send + Sync> = match (log_format, log_dir) { - (CliLogFormat::Text, None) => { - _guard = None; - Box::new(fmt::layer()) - } - (CliLogFormat::Json, None) => { - _guard = None; - Box::new(fmt::layer().json().flatten_event(true)) - } - (CliLogFormat::Text, Some(dir)) => { - let file_appender = tracing_appender::rolling::Builder::new() - .rotation(tracing_appender::rolling::Rotation::DAILY) - .max_log_files(log_max_files) - .filename_prefix("saorsa-node") - .filename_suffix("log") - .build(dir)?; - let (non_blocking, guard) = tracing_appender::non_blocking(file_appender); - _guard = Some(guard); - Box::new(fmt::layer().with_writer(non_blocking).with_ansi(false)) - } - (CliLogFormat::Json, Some(dir)) => { - let file_appender = tracing_appender::rolling::Builder::new() - .rotation(tracing_appender::rolling::Rotation::DAILY) - .max_log_files(log_max_files) - .filename_prefix("saorsa-node") - .filename_suffix("log") - .build(dir)?; - let (non_blocking, guard) = tracing_appender::non_blocking(file_appender); - _guard = Some(guard); - Box::new( - fmt::layer() - .json() - .flatten_event(true) - .with_writer(non_blocking) - .with_ansi(false), - ) - } - }; + let layer: Box + Send + Sync> = match (log_format, log_dir) { + (CliLogFormat::Text, None) => { + _guard = None; + Box::new(fmt::layer()) + } + (CliLogFormat::Json, None) => { + _guard = None; + Box::new(fmt::layer().json().flatten_event(true)) + } + (CliLogFormat::Text, Some(dir)) => { + let file_appender = tracing_appender::rolling::Builder::new() + .rotation(tracing_appender::rolling::Rotation::DAILY) + .max_log_files(log_max_files) + .filename_prefix("saorsa-node") + .filename_suffix("log") + .build(dir)?; + let (non_blocking, guard) = tracing_appender::non_blocking(file_appender); + _guard = Some(guard); + Box::new(fmt::layer().with_writer(non_blocking).with_ansi(false)) + } + (CliLogFormat::Json, Some(dir)) => { + let file_appender = tracing_appender::rolling::Builder::new() + .rotation(tracing_appender::rolling::Rotation::DAILY) + .max_log_files(log_max_files) + .filename_prefix("saorsa-node") + .filename_suffix("log") + .build(dir)?; + let (non_blocking, guard) = tracing_appender::non_blocking(file_appender); + _guard = Some(guard); + Box::new( + fmt::layer() + .json() + .flatten_event(true) + .with_writer(non_blocking) + .with_ansi(false), + ) + } + }; - tracing_subscriber::registry() - .with(layer) - .with(filter) - .init(); + tracing_subscriber::registry() + .with(layer) + .with(filter) + .init(); + } info!( version = env!("CARGO_PKG_VERSION"), diff --git a/src/client/chunk_protocol.rs b/src/client/chunk_protocol.rs index 4b141112..2906ebf6 100644 --- a/src/client/chunk_protocol.rs +++ b/src/client/chunk_protocol.rs @@ -4,12 +4,12 @@ //! generic function used by both [`super::QuantumClient`] and E2E test helpers. use crate::ant_protocol::{ChunkMessage, ChunkMessageBody, CHUNK_PROTOCOL_ID}; +use crate::{debug, warn}; use saorsa_core::identity::PeerId; use saorsa_core::{P2PEvent, P2PNode}; use std::time::Duration; use tokio::sync::broadcast::error::RecvError; use tokio::time::Instant; -use tracing::{debug, warn}; /// Send a chunk-protocol message to `target_peer` and await a matching response. /// @@ -57,8 +57,8 @@ pub async fn send_and_await_chunk_response( })) if topic == CHUNK_PROTOCOL_ID && source == *target_peer => { let response = match ChunkMessage::decode(&data) { Ok(r) => r, - Err(e) => { - warn!("Failed to decode chunk message, skipping: {e}"); + Err(_e) => { + warn!("Failed to decode chunk message, skipping: {_e}"); continue; } }; @@ -70,8 +70,8 @@ pub async fn send_and_await_chunk_response( } } Ok(Ok(_)) => {} - Ok(Err(RecvError::Lagged(skipped))) => { - debug!("Chunk protocol events lagged by {skipped} messages, continuing"); + Ok(Err(RecvError::Lagged(_skipped))) => { + debug!("Chunk protocol events lagged by {_skipped} messages, continuing"); } Ok(Err(RecvError::Closed)) | Err(_) => break, } diff --git a/src/client/quantum.rs b/src/client/quantum.rs index e779416a..8f6689a7 100644 --- a/src/client/quantum.rs +++ b/src/client/quantum.rs @@ -26,6 +26,7 @@ use crate::ant_protocol::{ use crate::error::{Error, Result}; use crate::payment::single_node::REQUIRED_QUOTES; use crate::payment::{calculate_price, PaymentProof, SingleNodePayment}; +use crate::{debug, info, warn}; use ant_evm::{Amount, EncodedPeerId, PaymentQuote, ProofOfPayment}; use bytes::Bytes; use evmlib::wallet::Wallet; @@ -36,7 +37,6 @@ use std::collections::{BTreeMap, HashSet}; use std::sync::atomic::{AtomicU64, Ordering}; use std::sync::Arc; use std::time::Duration; -use tracing::{debug, info, warn}; /// Default timeout for network operations in seconds. const DEFAULT_TIMEOUT_SECS: u64 = 30; @@ -173,8 +173,8 @@ impl QuantumClient { /// Returns an error if the network operation fails. pub async fn get_chunk(&self, address: &XorName) -> Result> { if tracing::enabled!(tracing::Level::DEBUG) { - let addr_hex = hex::encode(address); - debug!("Querying saorsa network for chunk: {addr_hex}"); + let _addr_hex = hex::encode(address); + debug!("Querying saorsa network for chunk: {_addr_hex}"); } let Some(ref node) = self.p2p_node else { @@ -294,8 +294,8 @@ impl QuantumClient { &self, content: Bytes, ) -> Result<(XorName, Vec)> { - let content_len = content.len(); - info!("Storing chunk with payment ({content_len} bytes)"); + let _content_len = content.len(); + info!("Storing chunk with payment ({_content_len} bytes)"); let Some(ref node) = self.p2p_node else { return Err(Error::Network("P2P node not configured".into())); @@ -454,8 +454,8 @@ impl QuantumClient { /// /// Returns an error if DHT lookup or quote collection fails. pub async fn prepare_chunk_payment(&self, content: Bytes) -> Result { - let content_len = content.len(); - debug!("Preparing payment for chunk ({content_len} bytes)"); + let _content_len = content.len(); + debug!("Preparing payment for chunk ({_content_len} bytes)"); self.p2p_node .as_ref() @@ -524,9 +524,9 @@ impl QuantumClient { return Ok(Vec::new()); } - let total_amount: Amount = prepared.iter().map(|p| p.payment.total_amount()).sum(); - let chunk_count = prepared.len(); - info!("Batch payment for {chunk_count} chunks: {total_amount} atto total"); + let _total_amount: Amount = prepared.iter().map(|p| p.payment.total_amount()).sum(); + let _chunk_count = prepared.len(); + info!("Batch payment for {_chunk_count} chunks: {_total_amount} atto total"); let all_quote_payments: Vec<(ant_evm::QuoteHash, ant_evm::RewardsAddress, Amount)> = prepared @@ -541,13 +541,13 @@ impl QuantumClient { }, )?; - let unique_tx_count = { + let _unique_tx_count = { let mut txs: Vec<_> = tx_hash_map.values().collect(); txs.sort(); txs.dedup(); txs.len() }; - info!("Batch payment successful: {unique_tx_count} on-chain transaction(s) for {chunk_count} chunks"); + info!("Batch payment successful: {_unique_tx_count} on-chain transaction(s) for {_chunk_count} chunks"); prepared .into_iter() @@ -676,7 +676,7 @@ impl QuantumClient { request_id: u64, timeout_secs: u64, addr_hex: String, - content_size: usize, + _content_size: usize, ) -> Result { let timeout = Duration::from_secs(timeout_secs); send_and_await_chunk_response( @@ -688,7 +688,7 @@ impl QuantumClient { |body| match body { ChunkMessageBody::PutResponse(ChunkPutResponse::Success { address: addr }) => { info!( - "Chunk stored at address: {} ({content_size} bytes)", + "Chunk stored at address: {} ({_content_size} bytes)", hex::encode(addr), ); Some(Ok(addr)) @@ -835,9 +835,9 @@ impl QuantumClient { }; if tracing::enabled!(tracing::Level::DEBUG) { - let addr_hex = hex::encode(address); + let _addr_hex = hex::encode(address); debug!( - "Requesting {REQUIRED_QUOTES} quotes from DHT for chunk {addr_hex} (size: {data_size})" + "Requesting {REQUIRED_QUOTES} quotes from DHT for chunk {_addr_hex} (size: {data_size})" ); } @@ -921,8 +921,8 @@ impl QuantumClient { let message_bytes = match message.encode() { Ok(bytes) => bytes, - Err(e) => { - warn!("Failed to encode quote request for {peer_id}: {e}"); + Err(_e) => { + warn!("Failed to encode quote request for {peer_id}: {_e}"); continue; } }; @@ -990,8 +990,8 @@ impl QuantumClient { break; } } - Err(e) => { - warn!("Failed to get quote from {peer_id}: {e}"); + Err(_e) => { + warn!("Failed to get quote from {peer_id}: {_e}"); // Continue trying other peers } } @@ -1006,9 +1006,9 @@ impl QuantumClient { } if tracing::enabled!(tracing::Level::INFO) { - let quote_count = quotes_with_peers.len(); - let addr_hex = hex::encode(address); - info!("Collected {quote_count} quotes for chunk {addr_hex}"); + let _quote_count = quotes_with_peers.len(); + let _addr_hex = hex::encode(address); + info!("Collected {_quote_count} quotes for chunk {_addr_hex}"); } Ok((closest_peer, quotes_with_peers)) diff --git a/src/client/self_encrypt.rs b/src/client/self_encrypt.rs index 50c5487c..2a38c67e 100644 --- a/src/client/self_encrypt.rs +++ b/src/client/self_encrypt.rs @@ -15,6 +15,7 @@ use crate::client::data_types::XorName as ChunkAddress; use crate::client::quantum::{PaidChunk, PreparedChunk, QuantumClient}; use crate::error::{Error, Result}; +use crate::{info, warn}; use bytes::Bytes; use futures::stream::{FuturesUnordered, StreamExt}; use self_encryption::DataMap; @@ -26,7 +27,6 @@ use std::path::Path; use std::pin::Pin; use std::sync::{Arc, Mutex}; use tokio::runtime::Handle; -use tracing::{info, warn}; use xor_name::XorName; /// Size of the read buffer used when streaming file data into the encryptor. @@ -115,9 +115,9 @@ fn write_stream_to_file( })(); if let Err(e) = result { - if let Err(cleanup_err) = std::fs::remove_file(&tmp_path) { + if let Err(_cleanup_err) = std::fs::remove_file(&tmp_path) { warn!( - "Failed to remove temp file {}: {cleanup_err}", + "Failed to remove temp file {}: {_cleanup_err}", tmp_path.display() ); } @@ -357,8 +357,8 @@ pub async fn download_and_decrypt_file( output_path: &Path, client: &QuantumClient, ) -> Result<()> { - let chunk_count = data_map.chunk_identifiers.len(); - info!("Decrypting file: {chunk_count} chunk(s) to decrypt (fetching on-demand)"); + let _chunk_count = data_map.chunk_identifiers.len(); + info!("Decrypting file: {_chunk_count} chunk(s) to decrypt (fetching on-demand)"); let handle = Handle::current(); @@ -448,8 +448,8 @@ pub async fn store_data_map_public( let content = Bytes::from(data_map_bytes); let (address, tx_hashes) = client.put_chunk_with_payment(content).await?; let tx_strs: Vec = tx_hashes.iter().map(|tx| format!("{tx:?}")).collect(); - let address_hex = hex::encode(address); - info!("DataMap stored publicly at {address_hex}"); + let _address_hex = hex::encode(address); + info!("DataMap stored publicly at {_address_hex}"); Ok((address, tx_strs)) } diff --git a/src/config.rs b/src/config.rs index 008d54ba..8fa2912d 100644 --- a/src/config.rs +++ b/src/config.rs @@ -145,6 +145,7 @@ pub struct NodeConfig { #[serde(default = "default_max_message_size")] pub max_message_size: usize, + #[cfg(debug_assertions)] /// Log level. #[serde(default = "default_log_level")] pub log_level: String, @@ -265,6 +266,7 @@ impl Default for NodeConfig { bootstrap_cache: BootstrapCacheConfig::default(), storage: StorageConfig::default(), max_message_size: default_max_message_size(), + #[cfg(debug_assertions)] log_level: default_log_level(), } } @@ -370,6 +372,7 @@ fn default_max_message_size() -> usize { crate::ant_protocol::MAX_WIRE_MESSAGE_SIZE } +#[cfg(debug_assertions)] fn default_log_level() -> String { "info".to_string() } diff --git a/src/devnet.rs b/src/devnet.rs index e8a6f0da..d2c52ee9 100644 --- a/src/devnet.rs +++ b/src/devnet.rs @@ -10,6 +10,7 @@ use crate::payment::{ QuotingMetricsTracker, }; use crate::storage::{AntProtocol, LmdbStorage, LmdbStorageConfig}; +use crate::{debug, info, warn}; use ant_evm::RewardsAddress; use evmlib::Network as EvmNetwork; use rand::Rng; @@ -26,7 +27,6 @@ use tokio::sync::RwLock; use tokio::task::JoinHandle; use tokio::time::Instant; use tokio_util::sync::CancellationToken; -use tracing::{debug, info, warn}; // ============================================================================= // Devnet Constants @@ -432,14 +432,14 @@ impl Devnet { handle.abort(); } - let node_index = node.index; + let _node_index = node.index; let node_state = Arc::clone(&node.state); let p2p_node = node.p2p_node.take(); shutdown_futures.push(async move { if let Some(p2p) = p2p_node { - if let Err(e) = p2p.shutdown().await { - warn!("Error shutting down node {node_index}: {e}"); + if let Err(_e) = p2p.shutdown().await { + warn!("Error shutting down node {_node_index}: {_e}"); } } *node_state.write().await = NodeState::Stopped; @@ -448,8 +448,8 @@ impl Devnet { futures::future::join_all(shutdown_futures).await; if self.config.cleanup_data_dir { - if let Err(e) = tokio::fs::remove_dir_all(&self.config.data_dir).await { - warn!("Failed to cleanup devnet data directory: {e}"); + if let Err(_e) = tokio::fs::remove_dir_all(&self.config.data_dir).await { + warn!("Failed to cleanup devnet data directory: {_e}"); } } @@ -491,8 +491,8 @@ impl Devnet { } async fn start_regular_nodes(&mut self) -> Result<()> { - let regular_count = self.config.node_count - self.config.bootstrap_count; - info!("Starting {} regular nodes", regular_count); + let _regular_count = self.config.node_count - self.config.bootstrap_count; + info!("Starting {} regular nodes", _regular_count); let bootstrap_addrs: Vec = self .nodes @@ -655,7 +655,7 @@ impl Devnet { let mut events = p2p.subscribe_events(); let p2p_clone = Arc::clone(p2p); let protocol_clone = Arc::clone(protocol); - let node_index = node.index; + let _node_index = node.index; node.protocol_task = Some(tokio::spawn(async move { while let Ok(event) = events.recv().await { if let P2PEvent::Message { @@ -666,14 +666,14 @@ impl Devnet { { if topic == CHUNK_PROTOCOL_ID { debug!( - "Node {node_index} received chunk protocol message from {source}" + "Node {_node_index} received chunk protocol message from {source}" ); let protocol = Arc::clone(&protocol_clone); let p2p = Arc::clone(&p2p_clone); tokio::spawn(async move { match protocol.handle_message(&data).await { Ok(response) => { - if let Err(e) = p2p + if let Err(_e) = p2p .send_message( &source, CHUNK_PROTOCOL_ID, @@ -682,12 +682,12 @@ impl Devnet { .await { warn!( - "Node {node_index} failed to send response to {source}: {e}" + "Node {_node_index} failed to send response to {source}: {_e}" ); } } - Err(e) => { - warn!("Node {node_index} protocol handler error: {e}"); + Err(_e) => { + warn!("Node {_node_index} protocol handler error: {_e}"); } } }); @@ -786,9 +786,9 @@ impl Devnet { tokio::select! { () = shutdown.cancelled() => break, () = tokio::time::sleep(check_interval) => { - for (i, node) in nodes.iter().enumerate() { + for (_i, node) in nodes.iter().enumerate() { if !node.is_running() { - warn!("Node {} appears unhealthy", i); + warn!("Node {} appears unhealthy", _i); } } } diff --git a/src/lib.rs b/src/lib.rs index 42560d40..3d787903 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -38,13 +38,13 @@ #![warn(missing_docs)] #![warn(clippy::all)] #![warn(clippy::pedantic)] - pub mod ant_protocol; pub mod client; pub mod config; pub mod devnet; pub mod error; pub mod event; +pub(crate) mod logging; pub mod node; pub mod payment; pub mod storage; diff --git a/src/logging.rs b/src/logging.rs new file mode 100644 index 00000000..0040cbdf --- /dev/null +++ b/src/logging.rs @@ -0,0 +1,50 @@ +//! Conditional logging macros that compile to nothing in release builds. +//! +//! These macros wrap `tracing` and are gated behind `cfg(debug_assertions)`, +//! ensuring that no tracing callsite metadata (module paths, file paths, +//! field names) is present in release binaries. + +/// Emit a TRACE-level event (debug builds only). +#[macro_export] +macro_rules! trace { + ($($arg:tt)*) => {{ + #[cfg(debug_assertions)] + { tracing::trace!($($arg)*) } + }}; +} + +/// Emit a DEBUG-level event (debug builds only). +#[macro_export] +macro_rules! debug { + ($($arg:tt)*) => {{ + #[cfg(debug_assertions)] + { tracing::debug!($($arg)*) } + }}; +} + +/// Emit an INFO-level event (debug builds only). +#[macro_export] +macro_rules! info { + ($($arg:tt)*) => {{ + #[cfg(debug_assertions)] + { tracing::info!($($arg)*) } + }}; +} + +/// Emit a WARN-level event (debug builds only). +#[macro_export] +macro_rules! warn { + ($($arg:tt)*) => {{ + #[cfg(debug_assertions)] + { tracing::warn!($($arg)*) } + }}; +} + +/// Emit an ERROR-level event (debug builds only). +#[macro_export] +macro_rules! error { + ($($arg:tt)*) => {{ + #[cfg(debug_assertions)] + { tracing::error!($($arg)*) } + }}; +} diff --git a/src/node.rs b/src/node.rs index 552e03c9..b6edb943 100644 --- a/src/node.rs +++ b/src/node.rs @@ -12,6 +12,7 @@ use crate::payment::wallet::parse_rewards_address; use crate::payment::{EvmVerifierConfig, PaymentVerifier, PaymentVerifierConfig, QuoteGenerator}; use crate::storage::{AntProtocol, LmdbStorage, LmdbStorageConfig}; use crate::upgrade::{AutoApplyUpgrader, UpgradeMonitor, UpgradeResult}; +use crate::{debug, error, info, warn}; use ant_evm::RewardsAddress; use evmlib::Network as EvmNetwork; use saorsa_core::identity::NodeIdentity; @@ -25,7 +26,6 @@ use std::sync::Arc; use tokio::sync::Semaphore; use tokio::task::JoinHandle; use tokio_util::sync::CancellationToken; -use tracing::{debug, error, info, warn}; /// Node storage capacity limit (5 GB). /// @@ -93,9 +93,9 @@ impl NodeBuilder { // Warn if payment disabled in any mode if !self.config.payment.enabled { - let mode = self.config.network_mode; + let _mode = self.config.network_mode; warn!("⚠️ ⚠️ ⚠️"); - warn!("⚠️ PAYMENT VERIFICATION DISABLED (mode: {mode:?})"); + warn!("⚠️ PAYMENT VERIFICATION DISABLED (mode: {_mode:?})"); warn!("⚠️ This should ONLY be used for testing!"); warn!("⚠️ All storage requests will be accepted for FREE"); warn!("⚠️ ⚠️ ⚠️"); @@ -103,9 +103,9 @@ impl NodeBuilder { // Resolve identity and root_dir (may update self.config.root_dir) let identity = Arc::new(Self::resolve_identity(&mut self.config).await?); - let peer_id = identity.peer_id().to_hex(); + let _peer_id = identity.peer_id().to_hex(); - info!(peer_id = %peer_id, root_dir = %self.config.root_dir.display(), "Node identity resolved"); + info!(peer_id = %_peer_id, root_dir = %self.config.root_dir.display(), "Node identity resolved"); // Ensure root directory exists std::fs::create_dir_all(&self.config.root_dir)?; @@ -404,8 +404,8 @@ impl NodeBuilder { .unwrap_or_else(|| config.root_dir.join("bootstrap_cache")); // Create cache directory - if let Err(e) = std::fs::create_dir_all(&cache_dir) { - warn!("Failed to create bootstrap cache directory: {e}"); + if let Err(_e) = std::fs::create_dir_all(&cache_dir) { + warn!("Failed to create bootstrap cache directory: {_e}"); return None; } @@ -423,8 +423,8 @@ impl NodeBuilder { ); Some(manager) } - Err(e) => { - warn!("Failed to initialize bootstrap cache: {e}"); + Err(_e) => { + warn!("Failed to initialize bootstrap cache: {_e}"); None } } @@ -481,12 +481,12 @@ impl RunningNode { .await .map_err(|e| Error::Startup(format!("Failed to start P2P node: {e}")))?; - let addrs = self.p2p_node.listen_addrs().await; - info!(listen_addrs = ?addrs, "P2P node started"); + let _addrs = self.p2p_node.listen_addrs().await; + info!(listen_addrs = ?_addrs, "P2P node started"); // Emit started event - if let Err(e) = self.events_tx.send(NodeEvent::Started) { - warn!("Failed to send Started event: {e}"); + if let Err(_e) = self.events_tx.send(NodeEvent::Started) { + warn!("Failed to send Started event: {_e}"); } // Start protocol message routing (P2P → AntProtocol → P2P response) @@ -515,27 +515,27 @@ impl RunningNode { ); // Send notification event - if let Err(e) = events_tx.send(NodeEvent::UpgradeAvailable { + if let Err(_e) = events_tx.send(NodeEvent::UpgradeAvailable { version: upgrade_info.version.to_string(), }) { - warn!("Failed to send UpgradeAvailable event: {e}"); + warn!("Failed to send UpgradeAvailable event: {_e}"); } // Auto-apply the upgrade info!("Starting auto-apply upgrade..."); match upgrader.apply_upgrade(&upgrade_info).await { - Ok(UpgradeResult::Success { version }) => { - info!(version = %version, "Upgrade successful, process will restart"); + Ok(UpgradeResult::Success { version: _version }) => { + info!(version = %_version, "Upgrade successful, process will restart"); // If we reach here, exec() failed or not supported } - Ok(UpgradeResult::RolledBack { reason }) => { - warn!("Upgrade rolled back: {reason}"); + Ok(UpgradeResult::RolledBack { reason: _reason }) => { + warn!("Upgrade rolled back: {_reason}"); } Ok(UpgradeResult::NoUpgrade) => { debug!("No upgrade needed"); } - Err(e) => { - error!("Critical upgrade error: {e}"); + Err(_e) => { + error!("Critical upgrade error: {_e}"); } } } @@ -554,10 +554,10 @@ impl RunningNode { // Log bootstrap cache stats before shutdown if let Some(ref manager) = self.bootstrap_manager { - let stats = manager.stats().await; + let _stats = manager.stats().await; info!( "Bootstrap cache shutdown: {} peers, avg quality {:.2}", - stats.total_peers, stats.average_quality + _stats.total_peers, _stats.average_quality ); } @@ -568,12 +568,12 @@ impl RunningNode { // Shutdown P2P node info!("Shutting down P2P node..."); - if let Err(e) = self.p2p_node.shutdown().await { - warn!("Error during P2P node shutdown: {e}"); + if let Err(_e) = self.p2p_node.shutdown().await { + warn!("Error during P2P node shutdown: {_e}"); } - if let Err(e) = self.events_tx.send(NodeEvent::ShuttingDown) { - warn!("Failed to send ShuttingDown event: {e}"); + if let Err(_e) = self.events_tx.send(NodeEvent::ShuttingDown) { + warn!("Failed to send ShuttingDown event: {_e}"); } info!("Node shutdown complete"); Ok(()) @@ -661,15 +661,15 @@ impl RunningNode { }; match protocol.handle_message(&data).await { Ok(response) => { - if let Err(e) = p2p + if let Err(_e) = p2p .send_message(&source, CHUNK_PROTOCOL_ID, response.to_vec()) .await { - warn!("Failed to send protocol response to {source}: {e}"); + warn!("Failed to send protocol response to {source}: {_e}"); } } - Err(e) => { - warn!("Protocol handler error: {e}"); + Err(_e) => { + warn!("Protocol handler error: {_e}"); } } }); diff --git a/src/payment/metrics.rs b/src/payment/metrics.rs index 9342350e..3d160ca3 100644 --- a/src/payment/metrics.rs +++ b/src/payment/metrics.rs @@ -5,12 +5,12 @@ //! - Storage capacity and usage //! - Network liveness information +use crate::{debug, info, warn}; use ant_evm::QuotingMetrics; use parking_lot::RwLock; use std::path::PathBuf; use std::sync::atomic::{AtomicU64, AtomicUsize, Ordering}; use std::time::Instant; -use tracing::{debug, info, warn}; /// Number of operations between disk persists (debounce). const PERSIST_INTERVAL: usize = 10; @@ -91,8 +91,8 @@ impl QuotingMetricsTracker { /// Record a payment received. pub fn record_payment(&self) { - let count = self.received_payment_count.fetch_add(1, Ordering::SeqCst) + 1; - debug!("Payment received, total count: {count}"); + let _count = self.received_payment_count.fetch_add(1, Ordering::SeqCst) + 1; + debug!("Payment received, total count: {_count}"); self.maybe_persist(); } @@ -179,8 +179,8 @@ impl QuotingMetricsTracker { }; if let Ok(bytes) = rmp_serde::to_vec(&data) { - if let Err(e) = std::fs::write(path, bytes) { - warn!("Failed to persist metrics: {e}"); + if let Err(_e) = std::fs::write(path, bytes) { + warn!("Failed to persist metrics: {_e}"); } } } diff --git a/src/payment/quote.rs b/src/payment/quote.rs index fe9c61d1..d2cd529a 100644 --- a/src/payment/quote.rs +++ b/src/payment/quote.rs @@ -7,6 +7,7 @@ //! capabilities from saorsa-core. This module provides the interface //! and will be fully integrated when the node is initialized. +use crate::debug; use crate::error::{Error, Result}; use crate::payment::metrics::QuotingMetricsTracker; use ant_evm::{PaymentQuote, QuotingMetrics, RewardsAddress}; @@ -14,7 +15,6 @@ use saorsa_core::MlDsa65; use saorsa_pqc::pqc::types::{MlDsaPublicKey, MlDsaSecretKey, MlDsaSignature}; use saorsa_pqc::pqc::MlDsaOperations; use std::time::SystemTime; -use tracing::debug; /// Content address type (32-byte `XorName`). pub type XorName = [u8; 32]; @@ -157,8 +157,8 @@ impl QuoteGenerator { }; if tracing::enabled!(tracing::Level::DEBUG) { - let content_hex = hex::encode(content); - debug!("Generated quote for {content_hex} (size: {data_size}, type: {data_type})"); + let _content_hex = hex::encode(content); + debug!("Generated quote for {_content_hex} (size: {data_size}, type: {data_type})"); } Ok(quote) @@ -231,8 +231,8 @@ pub fn verify_quote_signature(quote: &PaymentQuote) -> bool { // Parse public key from quote let pub_key = match MlDsaPublicKey::from_bytes("e.pub_key) { Ok(pk) => pk, - Err(e) => { - debug!("Failed to parse ML-DSA-65 public key from quote: {e}"); + Err(_e) => { + debug!("Failed to parse ML-DSA-65 public key from quote: {_e}"); return false; } }; @@ -240,8 +240,8 @@ pub fn verify_quote_signature(quote: &PaymentQuote) -> bool { // Parse signature from quote let signature = match MlDsaSignature::from_bytes("e.signature) { Ok(sig) => sig, - Err(e) => { - debug!("Failed to parse ML-DSA-65 signature from quote: {e}"); + Err(_e) => { + debug!("Failed to parse ML-DSA-65 signature from quote: {_e}"); return false; } }; @@ -258,8 +258,8 @@ pub fn verify_quote_signature(quote: &PaymentQuote) -> bool { } valid } - Err(e) => { - debug!("ML-DSA-65 verification error: {e}"); + Err(_e) => { + debug!("ML-DSA-65 verification error: {_e}"); false } } @@ -290,8 +290,8 @@ pub fn wire_ml_dsa_signer( let ml_dsa = MlDsa65::new(); generator.set_signer(pub_key_bytes, move |msg| match ml_dsa.sign(&sk, msg) { Ok(sig) => sig.as_bytes().to_vec(), - Err(e) => { - tracing::error!("ML-DSA-65 signing failed: {e}"); + Err(_e) => { + crate::error!("ML-DSA-65 signing failed: {_e}"); vec![] } }); diff --git a/src/payment/single_node.rs b/src/payment/single_node.rs index d336bc07..103d3788 100644 --- a/src/payment/single_node.rs +++ b/src/payment/single_node.rs @@ -11,11 +11,11 @@ //! This saves gas fees while maintaining the same total payment amount. use crate::error::{Error, Result}; +use crate::info; use ant_evm::{Amount, PaymentQuote, QuoteHash, QuotingMetrics, RewardsAddress}; use evmlib::contract::payment_vault; use evmlib::wallet::Wallet; use evmlib::Network as EvmNetwork; -use tracing::info; /// Required number of quotes for `SingleNode` payment (matches `CLOSE_GROUP_SIZE`) pub const REQUIRED_QUOTES: usize = 5; diff --git a/src/payment/verifier.rs b/src/payment/verifier.rs index 910599f5..f7449e6a 100644 --- a/src/payment/verifier.rs +++ b/src/payment/verifier.rs @@ -8,13 +8,13 @@ use crate::payment::cache::{CacheStats, VerifiedCache, XorName}; use crate::payment::proof::deserialize_proof; use crate::payment::quote::{verify_quote_content, verify_quote_signature}; use crate::payment::single_node::REQUIRED_QUOTES; +use crate::{debug, info}; use ant_evm::{ProofOfPayment, RewardsAddress}; use evmlib::contract::payment_vault::error::Error as PaymentVaultError; use evmlib::contract::payment_vault::verify_data_payment; use evmlib::Network as EvmNetwork; use saorsa_core::identity::node_identity::peer_id_from_public_key_bytes; use std::time::SystemTime; -use tracing::{debug, info}; /// Minimum allowed size for a payment proof in bytes. /// @@ -123,9 +123,9 @@ impl PaymentVerifier { pub fn new(config: PaymentVerifierConfig) -> Self { let cache = VerifiedCache::with_capacity(config.cache_capacity); - let cache_capacity = config.cache_capacity; - let evm_enabled = config.evm.enabled; - info!("Payment verifier initialized (cache_capacity={cache_capacity}, evm_enabled={evm_enabled})"); + let _cache_capacity = config.cache_capacity; + let _evm_enabled = config.evm.enabled; + info!("Payment verifier initialized (cache_capacity={_cache_capacity}, evm_enabled={_evm_enabled})"); Self { cache, config } } @@ -284,9 +284,9 @@ impl PaymentVerifier { /// not bypass verification here. async fn verify_evm_payment(&self, xorname: &XorName, payment: &ProofOfPayment) -> Result<()> { if tracing::enabled!(tracing::Level::DEBUG) { - let xorname_hex = hex::encode(xorname); - let quote_count = payment.peer_quotes.len(); - debug!("Verifying EVM payment for {xorname_hex} with {quote_count} quotes"); + let _xorname_hex = hex::encode(xorname); + let _quote_count = payment.peer_quotes.len(); + debug!("Verifying EVM payment for {_xorname_hex} with {_quote_count} quotes"); } debug_assert!(self.config.evm.enabled); diff --git a/src/storage/handler.rs b/src/storage/handler.rs index 936f2064..fccd9b4e 100644 --- a/src/storage/handler.rs +++ b/src/storage/handler.rs @@ -35,9 +35,9 @@ use crate::client::compute_address; use crate::error::{Error, Result}; use crate::payment::{PaymentVerifier, QuoteGenerator}; use crate::storage::lmdb::LmdbStorage; +use crate::{debug, info, warn}; use bytes::Bytes; use std::sync::Arc; -use tracing::{debug, info, warn}; /// ANT protocol handler. /// @@ -131,8 +131,8 @@ impl AntProtocol { /// Handle a PUT request. async fn handle_put(&self, request: ChunkPutRequest) -> ChunkPutResponse { let address = request.address; - let addr_hex = hex::encode(address); - debug!("Handling PUT request for {addr_hex}"); + let _addr_hex = hex::encode(address); + debug!("Handling PUT request for {_addr_hex}"); // 1. Validate chunk size if request.content.len() > MAX_CHUNK_SIZE { @@ -154,7 +154,7 @@ impl AntProtocol { // 3. Check if already exists (idempotent success) match self.storage.exists(&address) { Ok(true) => { - debug!("Chunk {addr_hex} already exists"); + debug!("Chunk {_addr_hex} already exists"); return ChunkPutResponse::AlreadyExists { address }; } Err(e) => { @@ -188,16 +188,16 @@ impl AntProtocol { // 5. Store chunk match self.storage.put(&address, &request.content).await { Ok(_) => { - let content_len = request.content.len(); - info!("Stored chunk {addr_hex} ({content_len} bytes)"); + let _content_len = request.content.len(); + info!("Stored chunk {_addr_hex} ({_content_len} bytes)"); // Record the store and payment in metrics self.quote_generator.record_store(DATA_TYPE_CHUNK); self.quote_generator.record_payment(); ChunkPutResponse::Success { address } } - Err(e) => { - warn!("Failed to store chunk {addr_hex}: {e}"); - ChunkPutResponse::Error(ProtocolError::StorageFailed(e.to_string())) + Err(_e) => { + warn!("Failed to store chunk {_addr_hex}: {_e}"); + ChunkPutResponse::Error(ProtocolError::StorageFailed(_e.to_string())) } } } @@ -205,31 +205,31 @@ impl AntProtocol { /// Handle a GET request. async fn handle_get(&self, request: ChunkGetRequest) -> ChunkGetResponse { let address = request.address; - let addr_hex = hex::encode(address); - debug!("Handling GET request for {addr_hex}"); + let _addr_hex = hex::encode(address); + debug!("Handling GET request for {_addr_hex}"); match self.storage.get(&address).await { Ok(Some(content)) => { - let content_len = content.len(); - debug!("Retrieved chunk {addr_hex} ({content_len} bytes)"); + let _content_len = content.len(); + debug!("Retrieved chunk {_addr_hex} ({_content_len} bytes)"); ChunkGetResponse::Success { address, content } } Ok(None) => { - debug!("Chunk {addr_hex} not found"); + debug!("Chunk {_addr_hex} not found"); ChunkGetResponse::NotFound { address } } - Err(e) => { - warn!("Failed to retrieve chunk {addr_hex}: {e}"); - ChunkGetResponse::Error(ProtocolError::StorageFailed(e.to_string())) + Err(_e) => { + warn!("Failed to retrieve chunk {_addr_hex}: {_e}"); + ChunkGetResponse::Error(ProtocolError::StorageFailed(_e.to_string())) } } } /// Handle a quote request. fn handle_quote(&self, request: &ChunkQuoteRequest) -> ChunkQuoteResponse { - let addr_hex = hex::encode(request.address); - let data_size = request.data_size; - debug!("Handling quote request for {addr_hex} (size: {data_size})"); + let _addr_hex = hex::encode(request.address); + let _data_size = request.data_size; + debug!("Handling quote request for {_addr_hex} (size: {_data_size})"); // Validate data size - data_size is u64, cast carefully and reject overflow let Ok(data_size_usize) = usize::try_from(request.data_size) else { diff --git a/src/storage/lmdb.rs b/src/storage/lmdb.rs index c7b93e6c..73573561 100644 --- a/src/storage/lmdb.rs +++ b/src/storage/lmdb.rs @@ -9,11 +9,11 @@ use crate::ant_protocol::XorName; use crate::error::{Error, Result}; +use crate::{debug, trace, warn}; use heed::types::Bytes; use heed::{Database, Env, EnvOpenOptions}; use std::path::{Path, PathBuf}; use tokio::task::spawn_blocking; -use tracing::{debug, trace, warn}; /// Default LMDB map size: 32 GiB. /// @@ -369,8 +369,8 @@ impl LmdbStorage { let mut stats = self.stats.read().clone(); match self.current_chunks() { Ok(count) => stats.current_chunks = count, - Err(e) => { - warn!("Failed to read current_chunks for stats: {e}"); + Err(_e) => { + warn!("Failed to read current_chunks for stats: {_e}"); stats.current_chunks = 0; } } diff --git a/src/upgrade/apply.rs b/src/upgrade/apply.rs index 40703609..3eb4bb50 100644 --- a/src/upgrade/apply.rs +++ b/src/upgrade/apply.rs @@ -9,6 +9,7 @@ use crate::error::{Error, Result}; use crate::upgrade::{signature, UpgradeInfo, UpgradeResult}; +use crate::{debug, error, info, warn}; use flate2::read::GzDecoder; use semver::Version; use std::env; @@ -16,7 +17,6 @@ use std::fs::{self, File}; use std::io::Read; use std::path::{Path, PathBuf}; use tar::Archive; -use tracing::{debug, error, info, warn}; /// Maximum allowed upgrade archive size (200 MiB). const MAX_ARCHIVE_SIZE_BYTES: usize = 200 * 1024 * 1024; diff --git a/src/upgrade/mod.rs b/src/upgrade/mod.rs index a686a0f0..3ee8c24c 100644 --- a/src/upgrade/mod.rs +++ b/src/upgrade/mod.rs @@ -21,10 +21,10 @@ pub use signature::{ }; use crate::error::{Error, Result}; +use crate::{debug, info, warn}; use semver::Version; use std::fs; use std::path::Path; -use tracing::{debug, info, warn}; /// Maximum allowed upgrade binary size (200 MiB). /// diff --git a/src/upgrade/monitor.rs b/src/upgrade/monitor.rs index d85f05fb..e1c822a7 100644 --- a/src/upgrade/monitor.rs +++ b/src/upgrade/monitor.rs @@ -11,10 +11,10 @@ use crate::config::UpgradeChannel; use crate::error::{Error, Result}; use crate::upgrade::rollout::StagedRollout; use crate::upgrade::UpgradeInfo; +use crate::{debug, info, warn}; use semver::Version; use serde::Deserialize; use std::time::{Duration, Instant}; -use tracing::{debug, info, warn}; /// GitHub release API response. #[derive(Debug, Deserialize)] @@ -77,8 +77,8 @@ impl UpgradeMonitor { .user_agent(concat!("saorsa-node/", env!("CARGO_PKG_VERSION"))) .timeout(Duration::from_secs(30)) .build() - .unwrap_or_else(|e| { - warn!("Failed to build reqwest client for upgrades: {e}"); + .unwrap_or_else(|_e| { + warn!("Failed to build reqwest client for upgrades: {_e}"); reqwest::Client::new() }); @@ -248,11 +248,11 @@ impl UpgradeMonitor { self.pending_upgrade_detected = Some(Instant::now()); self.pending_upgrade_version = Some(info.version.clone()); - let delay = rollout.calculate_delay_for_version(&info.version); + let _delay = rollout.calculate_delay_for_version(&info.version); info!( new_version = %info.version, - delay_hours = delay.as_secs() / 3600, - delay_minutes = (delay.as_secs() % 3600) / 60, + delay_hours = _delay.as_secs() / 3600, + delay_minutes = (_delay.as_secs() % 3600) / 60, "New version detected, staged rollout delay calculated" ); } @@ -274,11 +274,11 @@ impl UpgradeMonitor { ); Ok(Some(info)) } else { - let remaining = delay.saturating_sub(elapsed); + let _remaining = delay.saturating_sub(elapsed); debug!( "Staged rollout: {}h {}m remaining before upgrade to {}", - remaining.as_secs() / 3600, - (remaining.as_secs() % 3600) / 60, + _remaining.as_secs() / 3600, + (_remaining.as_secs() % 3600) / 60, info.version ); Ok(None) diff --git a/src/upgrade/rollout.rs b/src/upgrade/rollout.rs index ef680fd0..9f036939 100644 --- a/src/upgrade/rollout.rs +++ b/src/upgrade/rollout.rs @@ -23,8 +23,8 @@ //! - Nodes are evenly distributed across the rollout window //! - The same node always upgrades at the same point in the window +use crate::debug; use std::time::Duration; -use tracing::debug; /// Staged rollout configuration and delay calculation. #[derive(Debug, Clone)] diff --git a/src/upgrade/signature.rs b/src/upgrade/signature.rs index 5f052aaf..02e95c2d 100644 --- a/src/upgrade/signature.rs +++ b/src/upgrade/signature.rs @@ -17,11 +17,11 @@ //! This is an inherent property of FIPS 204 ML-DSA lattice-based signatures and //! is accepted as a reasonable trade-off for post-quantum security. +use crate::debug; use crate::error::{Error, Result}; use saorsa_pqc::api::sig::{ml_dsa_65, MlDsaPublicKey, MlDsaSignature, MlDsaVariant}; use std::fs; use std::path::Path; -use tracing::debug; /// Signing context for domain separation (prevents cross-protocol attacks). pub const SIGNING_CONTEXT: &[u8] = b"saorsa-node-release-v1";