From 2bd85e85f78a422d84bd4b24437e80b6c4e3faee Mon Sep 17 00:00:00 2001 From: KaffinPX Date: Wed, 29 Jul 2026 02:33:48 +0300 Subject: [PATCH 1/8] feat(miner): Log hashrate every `10 seconds` --- miner/src/guesser.rs | 45 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 5 deletions(-) diff --git a/miner/src/guesser.rs b/miner/src/guesser.rs index 34e3380..8cd0a69 100644 --- a/miner/src/guesser.rs +++ b/miner/src/guesser.rs @@ -1,6 +1,9 @@ use std::sync::Arc; use std::sync::atomic::AtomicBool; +use std::sync::atomic::AtomicU64; use std::sync::atomic::Ordering; +use std::time::Duration; +use std::time::Instant; use nyks_protocol::BFieldElement; use nyks_protocol::consensus::block::block_header::BlockPow; @@ -127,10 +130,20 @@ impl Guesser { guesser_buffer: Arc>, cancel: Arc, ) { + let hashes_done = Arc::new(AtomicU64::new(0)); + let logger_handle = + Self::spawn_hashrate_logger(hashes_done.clone(), cancel.clone()); + let mining_template = template.clone(); - let mine_result = - tokio::task::spawn_blocking(move || mine(&mining_template, &guesser_buffer, &cancel)) - .await; + let mine_result = tokio::task::spawn_blocking(move || { + mine(&mining_template, &guesser_buffer, &cancel, &hashes_done) + }) + .await; + + // Mining stopped for any reason (found/cancelled/exhausted/panicked) — + // stop the logger now rather than leaking a task that ticks forever. + logger_handle.abort(); + let pow = match mine_result { Ok(Some(pow)) => pow, @@ -161,6 +174,24 @@ impl Guesser { } } } + + fn spawn_hashrate_logger( + hashes_done: Arc, + cancel: Arc, + ) -> JoinHandle<()> { + tokio::spawn(async move { + let mut interval = tokio::time::interval(Duration::from_secs(10)); + let start = Instant::now(); + interval.tick().await; + + while !cancel.load(Ordering::Relaxed) { + interval.tick().await; + let total = hashes_done.load(Ordering::Relaxed); + let rate = total as f64 / start.elapsed().as_secs_f64().max(0.001); + info!("Hashrate: {:.2} MH/s ({total} total)", rate / 1e6); + } + }) + } } // Parallel nonce search. Returns None if cancelled or exhausted. @@ -168,6 +199,7 @@ fn mine( template: &RpcBlockTemplate, guesser_buffer: &GuesserBuffer, cancel: &AtomicBool, + hashes_done: &AtomicU64, ) -> Option { // Check for cancellation every ~500k nonces rather than every iteration. const CHECKPOINT_DISTANCE: u64 = 1 << 19; @@ -190,8 +222,11 @@ fn mine( (0u64..u64::MAX) .into_par_iter() .find_map_any(|i| { - if i % CHECKPOINT_DISTANCE == 0 && cancel.load(Ordering::Relaxed) { - return Some(None); + if i % CHECKPOINT_DISTANCE == 0 { + hashes_done.fetch_add(CHECKPOINT_DISTANCE, Ordering::Relaxed); + if cancel.load(Ordering::Relaxed) { + return Some(None); + } } let nonce = Digest(bfe_array![n0, n1, n2, n3, i]); From be99c4ce0b5f14f0617fb8cf4185a46231623e48 Mon Sep 17 00:00:00 2001 From: KaffinPX Date: Wed, 29 Jul 2026 02:35:49 +0300 Subject: [PATCH 2/8] feat(miner): Continue mining even if it fails one time --- miner/src/guesser.rs | 75 +++++++++++++++++++++++++------------------- 1 file changed, 42 insertions(+), 33 deletions(-) diff --git a/miner/src/guesser.rs b/miner/src/guesser.rs index 8cd0a69..ebe1189 100644 --- a/miner/src/guesser.rs +++ b/miner/src/guesser.rs @@ -19,6 +19,7 @@ use rayon::iter::IntoParallelIterator; use rayon::iter::ParallelIterator; use tokio::sync::RwLock; use tokio::task::JoinHandle; +use tracing::error; use tracing::info; use tracing::warn; @@ -131,48 +132,56 @@ impl Guesser { cancel: Arc, ) { let hashes_done = Arc::new(AtomicU64::new(0)); - let logger_handle = - Self::spawn_hashrate_logger(hashes_done.clone(), cancel.clone()); + let logger_handle = Self::spawn_hashrate_logger(hashes_done.clone(), cancel.clone()); - let mining_template = template.clone(); - let mine_result = tokio::task::spawn_blocking(move || { - mine(&mining_template, &guesser_buffer, &cancel, &hashes_done) - }) - .await; - - // Mining stopped for any reason (found/cancelled/exhausted/panicked) — - // stop the logger now rather than leaking a task that ticks forever. - logger_handle.abort(); - - let pow = match mine_result { - Ok(Some(pow)) => pow, - - Ok(None) => { - info!("Mining stopped (cancelled or nonce space exhausted)."); - return; + loop { + if cancel.load(Ordering::Relaxed) { + break; } - Err(e) => { - info!("Mining task panicked: {e}"); - return; - } - }; + let mining_template = template.clone(); + let guesser_buffer = guesser_buffer.clone(); + let cancel_for_mine = cancel.clone(); + let hashes_done_for_mine = hashes_done.clone(); + + let mine_result = tokio::task::spawn_blocking(move || { + mine( + &mining_template, + &guesser_buffer, + &cancel_for_mine, + &hashes_done_for_mine, + ) + }) + .await; + + let pow = match mine_result { + Ok(Some(pow)) => pow, + Ok(None) => { + info!("Mining stopped (cancelled or nonce space exhausted)."); + break; + } + Err(e) => { + error!("Mining task panicked: {e}"); + break; + } + }; - info!("Found the solution! Submitting to node..."); + info!("Found the solution! Submitting to node..."); - match client.submit_block(template.block, pow.into()).await { - Ok(response) => { - if response.success { + match client + .submit_block(template.block.clone(), pow.into()) + .await + { + Ok(response) if response.success => { info!("Block is accepted by node."); - } else { - warn!("Block is rejected by node, channel error."); + break; } - } - Err(e) => { - // TODO: RETRY - warn!("Block is rejected by node, reason: {}", e); + Ok(_) => warn!("Block is rejected by node, channel error. Retrying..."), + Err(e) => warn!("Block is rejected by node, reason: {}. Retrying...", e), } } + + logger_handle.abort(); } fn spawn_hashrate_logger( From cbdf74a41a3e3fa242312d2e730e83f484cc4cba Mon Sep 17 00:00:00 2001 From: KaffinPX Date: Wed, 29 Jul 2026 02:40:00 +0300 Subject: [PATCH 3/8] feat(miner): Avoid unnecessary template clone --- miner/src/guesser.rs | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/miner/src/guesser.rs b/miner/src/guesser.rs index ebe1189..645d6d4 100644 --- a/miner/src/guesser.rs +++ b/miner/src/guesser.rs @@ -19,7 +19,6 @@ use rayon::iter::IntoParallelIterator; use rayon::iter::ParallelIterator; use tokio::sync::RwLock; use tokio::task::JoinHandle; -use tracing::error; use tracing::info; use tracing::warn; @@ -33,7 +32,7 @@ struct MinerBuffer { // Holds the cancel flag so stop() can signal the blocking thread directly. #[derive(Debug)] struct MinerTask { - template: RpcBlockTemplate, + template: Arc, cancel: Arc, handle: JoinHandle<()>, } @@ -62,15 +61,18 @@ impl Guesser { self.stop().await; let guesser_buffer = self.get_or_recompute_buffer(prev_block_digest).await; + let template = Arc::new(template); + info!( "Switching to mining template {}...", template.block.kernel.mast_hash().to_hex() ); + let cancel = Arc::new(AtomicBool::new(false)); + let client = self.client.clone(); let task_template = template.clone(); - let cancel = Arc::new(AtomicBool::new(false)); - let task_cancel = Arc::clone(&cancel); + let task_cancel = cancel.clone(); let handle = tokio::spawn(async move { Self::run_mining_task(client, task_template, guesser_buffer, task_cancel).await; @@ -104,11 +106,11 @@ impl Guesser { *guard = Some(MinerBuffer { digest: prev_block_digest, - buffer: Arc::clone(&new_buffer), + buffer: new_buffer.clone(), }); new_buffer } else { - Arc::clone(&guard.as_ref().unwrap().buffer) + guard.as_ref().unwrap().buffer.clone() } } @@ -127,7 +129,7 @@ impl Guesser { async fn run_mining_task( client: HttpClient, - template: RpcBlockTemplate, + template: Arc, guesser_buffer: Arc>, cancel: Arc, ) { @@ -140,14 +142,14 @@ impl Guesser { } let mining_template = template.clone(); - let guesser_buffer = guesser_buffer.clone(); + let guesser_buffer_for_mine = guesser_buffer.clone(); let cancel_for_mine = cancel.clone(); let hashes_done_for_mine = hashes_done.clone(); let mine_result = tokio::task::spawn_blocking(move || { mine( &mining_template, - &guesser_buffer, + &guesser_buffer_for_mine, &cancel_for_mine, &hashes_done_for_mine, ) @@ -161,7 +163,7 @@ impl Guesser { break; } Err(e) => { - error!("Mining task panicked: {e}"); + info!("Mining task panicked: {e}"); break; } }; From f5e66450b964d3a139d7899d49f9692ad1c28a50 Mon Sep 17 00:00:00 2001 From: KaffinPX Date: Wed, 29 Jul 2026 02:49:41 +0300 Subject: [PATCH 4/8] style(miner): Move args into its own file --- miner/src/core/args.rs | 19 +++++++++++++++++++ miner/src/core/mod.rs | 1 + miner/src/main.rs | 14 ++------------ 3 files changed, 22 insertions(+), 12 deletions(-) create mode 100644 miner/src/core/args.rs create mode 100644 miner/src/core/mod.rs diff --git a/miner/src/core/args.rs b/miner/src/core/args.rs new file mode 100644 index 0000000..4d3a5d0 --- /dev/null +++ b/miner/src/core/args.rs @@ -0,0 +1,19 @@ +use clap::Parser; +use nyks_protocol::consensus::network::Network; + +#[derive(Parser)] +#[command(name = "nyks-miner")] +#[command(about = "A nyks CPU miner")] +pub struct Args { + /// RPC URL to use (JSON/HTTP) + #[arg(long, default_value = "http://localhost:9797")] + pub rpc_url: String, + + /// Address to mine for (coinbase reward receiver) + #[arg(long)] + pub address: String, + + /// Network we are going to mine on. + #[arg(long, default_value_t = Network::Main)] + pub network: Network, +} diff --git a/miner/src/core/mod.rs b/miner/src/core/mod.rs new file mode 100644 index 0000000..8c43337 --- /dev/null +++ b/miner/src/core/mod.rs @@ -0,0 +1 @@ +pub mod args; \ No newline at end of file diff --git a/miner/src/main.rs b/miner/src/main.rs index 0b5084a..265e0b2 100644 --- a/miner/src/main.rs +++ b/miner/src/main.rs @@ -6,22 +6,12 @@ use nyks_rpc_client::http::HttpClient; use tracing::info; use tracing_subscriber::EnvFilter; +use crate::core::args::Args; use crate::flow::Miner; pub mod flow; pub mod guesser; - -#[derive(Parser)] -#[command(name = "nyks-miner")] -#[command(about = "A nyks CPU miner")] -struct Args { - /// Address to mine for (coinbase reward receiver) - #[arg(long)] - address: String, - /// RPC URL to use (JSON/HTTP) - #[arg(long)] - rpc_url: String, -} +pub mod core; #[tokio::main] async fn main() -> Result<()> { From fc8e2dad3700da5aa83fa7dafd48277f8db97442 Mon Sep 17 00:00:00 2001 From: KaffinPX Date: Wed, 29 Jul 2026 02:50:58 +0300 Subject: [PATCH 5/8] style(miner): Move miner files into its scope --- miner/src/main.rs | 5 ++--- miner/src/{ => miner}/flow.rs | 2 +- miner/src/{ => miner}/guesser.rs | 0 miner/src/miner/mod.rs | 2 ++ 4 files changed, 5 insertions(+), 4 deletions(-) rename miner/src/{ => miner}/flow.rs (98%) rename miner/src/{ => miner}/guesser.rs (100%) create mode 100644 miner/src/miner/mod.rs diff --git a/miner/src/main.rs b/miner/src/main.rs index 265e0b2..6ad68e6 100644 --- a/miner/src/main.rs +++ b/miner/src/main.rs @@ -7,10 +7,9 @@ use tracing::info; use tracing_subscriber::EnvFilter; use crate::core::args::Args; -use crate::flow::Miner; +use crate::miner::flow::Miner; -pub mod flow; -pub mod guesser; +pub mod miner; pub mod core; #[tokio::main] diff --git a/miner/src/flow.rs b/miner/src/miner/flow.rs similarity index 98% rename from miner/src/flow.rs rename to miner/src/miner/flow.rs index f1c66aa..ac74b10 100644 --- a/miner/src/flow.rs +++ b/miner/src/miner/flow.rs @@ -8,7 +8,7 @@ use nyks_rpc_client::http::HttpClient; use tokio::sync::RwLock; use tracing::info; -use crate::guesser::Guesser; +use crate::miner::guesser::Guesser; #[derive(Clone, Debug)] pub struct Miner { diff --git a/miner/src/guesser.rs b/miner/src/miner/guesser.rs similarity index 100% rename from miner/src/guesser.rs rename to miner/src/miner/guesser.rs diff --git a/miner/src/miner/mod.rs b/miner/src/miner/mod.rs new file mode 100644 index 0000000..b8647ed --- /dev/null +++ b/miner/src/miner/mod.rs @@ -0,0 +1,2 @@ +pub mod flow; +pub mod guesser; \ No newline at end of file From d20e66587a90cafe8775016ee52216f52a7c7844 Mon Sep 17 00:00:00 2001 From: KaffinPX Date: Wed, 29 Jul 2026 03:16:03 +0300 Subject: [PATCH 6/8] feat(miner): Validate address and add minimum guessing percentage --- miner/src/core/args.rs | 25 +++++++++++++++++++++++++ miner/src/core/mod.rs | 2 +- miner/src/main.rs | 8 +++++--- miner/src/miner/flow.rs | 19 +++++++++++++++++-- miner/src/miner/mod.rs | 2 +- 5 files changed, 49 insertions(+), 7 deletions(-) diff --git a/miner/src/core/args.rs b/miner/src/core/args.rs index 4d3a5d0..1a66e19 100644 --- a/miner/src/core/args.rs +++ b/miner/src/core/args.rs @@ -1,5 +1,7 @@ use clap::Parser; use nyks_protocol::consensus::network::Network; +use nyks_standards::wallet::keys::address::Address; +use nyks_standards::wallet::keys::address::Recipient; #[derive(Parser)] #[command(name = "nyks-miner")] @@ -16,4 +18,27 @@ pub struct Args { /// Network we are going to mine on. #[arg(long, default_value_t = Network::Main)] pub network: Network, + + /// Minimum guesser reward as a percentage of total block reward (0-100), default 10. + #[arg(long, default_value_t = 10.0)] + pub min_percentage_reward: f64, +} + +impl Args { + /// Validates the percentage is in range and converts it to a fraction + /// (e.g. 10.0 -> 0.10) for internal use. + pub fn min_reward_fraction(&self) -> f64 { + assert!( + (0.0..=100.0).contains(&self.min_percentage_reward), + "min-percentage-reward must be between 0 and 100, got {}", + self.min_percentage_reward + ); + + self.min_percentage_reward / 100.0 + } + + /// Validates that `address` is a well-formed address for the selected network. + pub fn validate_address(&self) { + Address::from_bech32m(&self.address, self.network).expect("Invalid address"); + } } diff --git a/miner/src/core/mod.rs b/miner/src/core/mod.rs index 8c43337..6e10f4a 100644 --- a/miner/src/core/mod.rs +++ b/miner/src/core/mod.rs @@ -1 +1 @@ -pub mod args; \ No newline at end of file +pub mod args; diff --git a/miner/src/main.rs b/miner/src/main.rs index 6ad68e6..ad09e88 100644 --- a/miner/src/main.rs +++ b/miner/src/main.rs @@ -9,8 +9,8 @@ use tracing_subscriber::EnvFilter; use crate::core::args::Args; use crate::miner::flow::Miner; -pub mod miner; pub mod core; +pub mod miner; #[tokio::main] async fn main() -> Result<()> { @@ -26,8 +26,10 @@ async fn main() -> Result<()> { info!("Initializing nyks-miner, the operator of nyks blocks..."); - let client = HttpClient::new(args.rpc_url); - let miner = Miner::new(client, args.address); + args.validate_address(); + + let client = HttpClient::new(args.rpc_url.clone()); + let miner = Miner::new(client, args.address.clone(), args.min_reward_fraction()); miner.main_loop().await; diff --git a/miner/src/miner/flow.rs b/miner/src/miner/flow.rs index ac74b10..8d15a7c 100644 --- a/miner/src/miner/flow.rs +++ b/miner/src/miner/flow.rs @@ -2,11 +2,12 @@ use std::sync::Arc; use std::time::Duration; use num_traits::Zero; +use nyks_protocol::consensus::block::Block; use nyks_protocol::consensus::type_scripts::native_currency_amount::NativeCurrencyAmount; use nyks_rpc_client::RpcApi; use nyks_rpc_client::http::HttpClient; use tokio::sync::RwLock; -use tracing::info; +use tracing::{debug, info}; use crate::miner::guesser::Guesser; @@ -14,15 +15,17 @@ use crate::miner::guesser::Guesser; pub struct Miner { client: HttpClient, address: String, + min_reward_fraction: f64, guesser_reward: Arc>, guesser: Guesser, } impl Miner { - pub fn new(client: HttpClient, address: String) -> Self { + pub fn new(client: HttpClient, address: String, min_reward_fraction: f64) -> Self { Miner { client: client.clone(), address, + min_reward_fraction, guesser_reward: Arc::new(RwLock::new(NativeCurrencyAmount::zero())), guesser: Guesser::new(client), } @@ -47,6 +50,18 @@ impl Miner { if let Some(template) = template { let new_guesser_reward = template.metadata.total_guesser_reward.0; + let total_reward = Block::block_subsidy(template.block.kernel.header.height); + + let guesser_share = new_guesser_reward.to_nau() as f64 / total_reward.to_nau() as f64; + if guesser_share < self.min_reward_fraction { + debug!( + "Skipping template: guesser share {:.2}% below minimum {:.2}%.", + guesser_share * 100.0, + self.min_reward_fraction * 100.0 + ); + return; + } + let mut current_guesser_reward = self.guesser_reward.write().await; if new_guesser_reward > *current_guesser_reward { diff --git a/miner/src/miner/mod.rs b/miner/src/miner/mod.rs index b8647ed..0bea828 100644 --- a/miner/src/miner/mod.rs +++ b/miner/src/miner/mod.rs @@ -1,2 +1,2 @@ pub mod flow; -pub mod guesser; \ No newline at end of file +pub mod guesser; From ee3cea73f2bbf9083bdc5208ef54b26a2b062a38 Mon Sep 17 00:00:00 2001 From: KaffinPX Date: Wed, 29 Jul 2026 03:26:19 +0300 Subject: [PATCH 7/8] feat(miner): Cache and log composing time per template --- miner/src/miner/flow.rs | 46 +++++++++++++++++++++++++++++++---------- 1 file changed, 35 insertions(+), 11 deletions(-) diff --git a/miner/src/miner/flow.rs b/miner/src/miner/flow.rs index 8d15a7c..451815b 100644 --- a/miner/src/miner/flow.rs +++ b/miner/src/miner/flow.rs @@ -1,5 +1,5 @@ use std::sync::Arc; -use std::time::Duration; +use std::time::{Duration, Instant}; use num_traits::Zero; use nyks_protocol::consensus::block::Block; @@ -18,6 +18,7 @@ pub struct Miner { min_reward_fraction: f64, guesser_reward: Arc>, guesser: Guesser, + composing_since: Arc>>, } impl Miner { @@ -28,12 +29,12 @@ impl Miner { min_reward_fraction, guesser_reward: Arc::new(RwLock::new(NativeCurrencyAmount::zero())), guesser: Guesser::new(client), + composing_since: Arc::new(RwLock::new(None)), } } pub async fn main_loop(&self) { let mut interval = tokio::time::interval(Duration::from_secs(5)); - loop { interval.tick().await; self.scan_templates().await; @@ -49,10 +50,18 @@ impl Miner { .template; if let Some(template) = template { + // If we were waiting on a template, capture how long composing took + let composing_time = { + let mut composing_since = self.composing_since.write().await; + composing_since + .take() + .map(|start| start.elapsed().as_secs_f64()) + }; + let new_guesser_reward = template.metadata.total_guesser_reward.0; let total_reward = Block::block_subsidy(template.block.kernel.header.height); - let guesser_share = new_guesser_reward.to_nau() as f64 / total_reward.to_nau() as f64; + if guesser_share < self.min_reward_fraction { debug!( "Skipping template: guesser share {:.2}% below minimum {:.2}%.", @@ -65,21 +74,36 @@ impl Miner { let mut current_guesser_reward = self.guesser_reward.write().await; if new_guesser_reward > *current_guesser_reward { - info!( - "Switching to mining of new template with {} NYKS reward.", - new_guesser_reward - ); + match composing_time { + Some(secs) => info!( + "Switching to mining of new template with {} NYKS reward (composed in {:.2}s).", + new_guesser_reward, secs + ), + None => info!( + "Switching to mining of new template with {} NYKS reward.", + new_guesser_reward + ), + } *current_guesser_reward = new_guesser_reward; self.guesser .override_task(template.metadata.prev_block, template) .await; } - } else if self.guesser.is_running().await { - info!("New tip is found, waiting for a composed template..."); + } else { + { + let mut composing_since = self.composing_since.write().await; + if composing_since.is_none() { + info!("Waiting for a template..."); + *composing_since = Some(Instant::now()); + } + } - *self.guesser_reward.write().await = NativeCurrencyAmount::zero(); - self.guesser.stop().await; + if self.guesser.is_running().await { + info!("New tip is found, waiting for a composed template..."); + *self.guesser_reward.write().await = NativeCurrencyAmount::zero(); + self.guesser.stop().await; + } } } } From 9fdee85ad9194bb0cf28fcb6cc9a13380c0575d5 Mon Sep 17 00:00:00 2001 From: KaffinPX Date: Wed, 29 Jul 2026 17:00:40 +0300 Subject: [PATCH 8/8] feat(miner): Verify remote node is on the expected network --- miner/src/core/args.rs | 24 ++++++++++++++++++++++++ miner/src/main.rs | 3 +-- miner/src/miner/flow.rs | 3 ++- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/miner/src/core/args.rs b/miner/src/core/args.rs index 1a66e19..33303d3 100644 --- a/miner/src/core/args.rs +++ b/miner/src/core/args.rs @@ -1,5 +1,7 @@ use clap::Parser; use nyks_protocol::consensus::network::Network; +use nyks_rpc_client::RpcApi; +use nyks_rpc_client::http::HttpClient; use nyks_standards::wallet::keys::address::Address; use nyks_standards::wallet::keys::address::Recipient; @@ -37,6 +39,28 @@ impl Args { self.min_percentage_reward / 100.0 } + /// Creates an RPC client and verifies that the connected node is on the + /// expected network. + pub async fn rpc_client(&self) -> HttpClient { + let client = HttpClient::new(self.rpc_url.clone()); + + let remote_network = client + .network() + .await + .expect("Failed to connect to RPC node") + .network + .parse::() + .unwrap(); + + assert_eq!( + self.network, remote_network, + "Network mismatch: expected {:?}, connected node is on {:?}", + self.network, remote_network, + ); + + client + } + /// Validates that `address` is a well-formed address for the selected network. pub fn validate_address(&self) { Address::from_bech32m(&self.address, self.network).expect("Invalid address"); diff --git a/miner/src/main.rs b/miner/src/main.rs index ad09e88..3dc1e8f 100644 --- a/miner/src/main.rs +++ b/miner/src/main.rs @@ -2,7 +2,6 @@ use std::panic; use anyhow::Result; use clap::Parser; -use nyks_rpc_client::http::HttpClient; use tracing::info; use tracing_subscriber::EnvFilter; @@ -28,7 +27,7 @@ async fn main() -> Result<()> { args.validate_address(); - let client = HttpClient::new(args.rpc_url.clone()); + let client = args.rpc_client().await; let miner = Miner::new(client, args.address.clone(), args.min_reward_fraction()); miner.main_loop().await; diff --git a/miner/src/miner/flow.rs b/miner/src/miner/flow.rs index 451815b..619e858 100644 --- a/miner/src/miner/flow.rs +++ b/miner/src/miner/flow.rs @@ -7,7 +7,8 @@ use nyks_protocol::consensus::type_scripts::native_currency_amount::NativeCurren use nyks_rpc_client::RpcApi; use nyks_rpc_client::http::HttpClient; use tokio::sync::RwLock; -use tracing::{debug, info}; +use tracing::debug; +use tracing::info; use crate::miner::guesser::Guesser;