From 888fe52d5b96f6a934d712a70180085db67fffcd Mon Sep 17 00:00:00 2001 From: 7suyash7 Date: Wed, 27 Aug 2025 20:56:17 +0400 Subject: [PATCH] fix(engine): Prevent instant miner from creating empty blocks Signed-off-by: 7suyash7 --- crates/engine/local/src/miner.rs | 26 +++++++++++++++--------- crates/node/builder/src/launch/common.rs | 5 ++++- crates/node/core/src/node_config.rs | 5 ++++- 3 files changed, 24 insertions(+), 12 deletions(-) diff --git a/crates/engine/local/src/miner.rs b/crates/engine/local/src/miner.rs index 0b430782f1e..604965d3ca3 100644 --- a/crates/engine/local/src/miner.rs +++ b/crates/engine/local/src/miner.rs @@ -24,12 +24,14 @@ use tracing::error; /// A mining mode for the local dev engine. #[derive(Debug)] -pub enum MiningMode { +pub enum MiningMode { /// In this mode a block is built as soon as /// a valid transaction reaches the pool. /// If `max_transactions` is set, a block is built when that many transactions have /// accumulated. Instant { + /// The transaction pool. + pool: Pool, /// Stream of transaction notifications. rx: Fuse>, /// Maximum number of transactions to accumulate before mining a block. @@ -42,11 +44,11 @@ pub enum MiningMode { Interval(Interval), } -impl MiningMode { +impl MiningMode { /// Constructor for a [`MiningMode::Instant`] - pub fn instant(pool: Pool, max_transactions: Option) -> Self { + pub fn instant(pool: Pool, max_transactions: Option) -> Self { let rx = pool.pending_transactions_listener(); - Self::Instant { rx: ReceiverStream::new(rx).fuse(), max_transactions, accumulated: 0 } + Self::Instant { pool, rx: ReceiverStream::new(rx).fuse(), max_transactions, accumulated: 0 } } /// Constructor for a [`MiningMode::Interval`] @@ -56,15 +58,18 @@ impl MiningMode { } } -impl Future for MiningMode { +impl Future for MiningMode { type Output = (); fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let this = self.get_mut(); match this { - Self::Instant { rx, max_transactions, accumulated } => { + Self::Instant { pool, rx, max_transactions, accumulated } => { // Poll for new transaction notifications while let Poll::Ready(Some(_)) = rx.poll_next_unpin(cx) { + if pool.pending_and_queued_txn_count().0 == 0 { + continue; + } if let Some(max_tx) = max_transactions { *accumulated += 1; // If we've reached the max transactions threshold, mine a block @@ -91,13 +96,13 @@ impl Future for MiningMode { /// Local miner advancing the chain #[derive(Debug)] -pub struct LocalMiner { +pub struct LocalMiner { /// The payload attribute builder for the engine payload_attributes_builder: B, /// Sender for events to engine. to_engine: ConsensusEngineHandle, /// The mining mode for the engine - mode: MiningMode, + mode: MiningMode, /// The payload builder for the engine payload_builder: PayloadBuilderHandle, /// Timestamp for the next block. @@ -106,17 +111,18 @@ pub struct LocalMiner { last_block_hashes: Vec, } -impl LocalMiner +impl LocalMiner where T: PayloadTypes, B: PayloadAttributesBuilder<::PayloadAttributes>, + Pool: TransactionPool + Unpin, { /// Spawns a new [`LocalMiner`] with the given parameters. pub fn new( provider: impl BlockReader, payload_attributes_builder: B, to_engine: ConsensusEngineHandle, - mode: MiningMode, + mode: MiningMode, payload_builder: PayloadBuilderHandle, ) -> Self { let latest_header = diff --git a/crates/node/builder/src/launch/common.rs b/crates/node/builder/src/launch/common.rs index 1e3a5ca13fc..11ffca009dd 100644 --- a/crates/node/builder/src/launch/common.rs +++ b/crates/node/builder/src/launch/common.rs @@ -442,7 +442,10 @@ impl LaunchContextWith MiningMode { + pub fn dev_mining_mode(&self, pool: Pool) -> MiningMode + where + Pool: TransactionPool + Unpin, + { if let Some(interval) = self.node_config().dev.block_time { MiningMode::interval(interval) } else { diff --git a/crates/node/core/src/node_config.rs b/crates/node/core/src/node_config.rs index 66a5b2b5153..96fa8cc8dfa 100644 --- a/crates/node/core/src/node_config.rs +++ b/crates/node/core/src/node_config.rs @@ -494,7 +494,10 @@ impl NodeConfig { } /// Returns the [`MiningMode`] intended for --dev mode. - pub fn dev_mining_mode(&self, pool: impl TransactionPool) -> MiningMode { + pub fn dev_mining_mode(&self, pool: Pool) -> MiningMode + where + Pool: TransactionPool + Unpin, + { if let Some(interval) = self.dev.block_time { MiningMode::interval(interval) } else {