Skip to content

Commit 5af9d16

Browse files
caiquejjxmattsse
andauthored
feat: add mixed mining mode (#8280)
* feat: add mixed mining mode * feat: add mixed mining usage * fix: ensure unique txs * chore: undo comment deletion * touchups --------- Co-authored-by: Matthias Seitz <[email protected]>
1 parent 62cdea8 commit 5af9d16

File tree

4 files changed

+58
-1
lines changed

4 files changed

+58
-1
lines changed

crates/anvil/src/cmd.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,9 @@ pub struct NodeArgs {
9898
#[arg(long, visible_alias = "no-mine", conflicts_with = "block_time")]
9999
pub no_mining: bool,
100100

101+
#[arg(long, visible_alias = "mixed-mining", requires = "block_time")]
102+
pub mixed_mining: bool,
103+
101104
/// The hosts the server will listen on.
102105
#[arg(
103106
long,
@@ -200,6 +203,7 @@ impl NodeArgs {
200203
.with_hardfork(self.hardfork)
201204
.with_blocktime(self.block_time)
202205
.with_no_mining(self.no_mining)
206+
.with_mixed_mining(self.mixed_mining, self.block_time)
203207
.with_account_generator(self.account_generator())
204208
.with_genesis_balance(genesis_balance)
205209
.with_genesis_timestamp(self.timestamp)

crates/anvil/src/config.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,8 @@ pub struct NodeConfig {
113113
pub block_time: Option<Duration>,
114114
/// Disable auto, interval mining mode uns use `MiningMode::None` instead
115115
pub no_mining: bool,
116+
/// Enables auto and interval mining mode
117+
pub mixed_mining: bool,
116118
/// port to use for the server
117119
pub port: u16,
118120
/// maximum number of transactions in a block
@@ -395,6 +397,7 @@ impl Default for NodeConfig {
395397
genesis_balance: Unit::ETHER.wei().saturating_mul(U256::from(100u64)),
396398
block_time: None,
397399
no_mining: false,
400+
mixed_mining: false,
398401
port: NODE_PORT,
399402
// TODO make this something dependent on block capacity
400403
max_transactions: 1_000,
@@ -633,6 +636,17 @@ impl NodeConfig {
633636
self
634637
}
635638

639+
#[must_use]
640+
pub fn with_mixed_mining<D: Into<Duration>>(
641+
mut self,
642+
mixed_mining: bool,
643+
block_time: Option<D>,
644+
) -> Self {
645+
self.block_time = block_time.map(Into::into);
646+
self.mixed_mining = mixed_mining;
647+
self
648+
}
649+
636650
/// If set to `true` auto mining will be disabled
637651
#[must_use]
638652
pub fn with_no_mining(mut self, no_mining: bool) -> Self {

crates/anvil/src/eth/miner.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,9 @@ pub enum MiningMode {
132132
Auto(ReadyTransactionMiner),
133133
/// A miner that constructs a new block every `interval` tick
134134
FixedBlockTime(FixedBlockTimeMiner),
135+
136+
/// A minner that uses both Auto and FixedBlockTime
137+
Mixed(ReadyTransactionMiner, FixedBlockTimeMiner),
135138
}
136139

137140
impl MiningMode {
@@ -147,6 +150,13 @@ impl MiningMode {
147150
Self::FixedBlockTime(FixedBlockTimeMiner::new(duration))
148151
}
149152

153+
pub fn mixed(max_transactions: usize, listener: Receiver<TxHash>, duration: Duration) -> Self {
154+
Self::Mixed(
155+
ReadyTransactionMiner { max_transactions, has_pending_txs: None, rx: listener.fuse() },
156+
FixedBlockTimeMiner::new(duration),
157+
)
158+
}
159+
150160
/// polls the [Pool] and returns those transactions that should be put in a block, if any.
151161
pub fn poll(
152162
&mut self,
@@ -157,6 +167,29 @@ impl MiningMode {
157167
Self::None => Poll::Pending,
158168
Self::Auto(miner) => miner.poll(pool, cx),
159169
Self::FixedBlockTime(miner) => miner.poll(pool, cx),
170+
Self::Mixed(auto, fixed) => {
171+
let auto_txs = auto.poll(pool, cx);
172+
let fixed_txs = fixed.poll(pool, cx);
173+
174+
match (auto_txs, fixed_txs) {
175+
// Both auto and fixed transactions are ready, combine them
176+
(Poll::Ready(mut auto_txs), Poll::Ready(fixed_txs)) => {
177+
for tx in fixed_txs {
178+
// filter unique transactions
179+
if auto_txs.iter().any(|auto_tx| auto_tx.hash() == tx.hash()) {
180+
continue;
181+
}
182+
auto_txs.push(tx);
183+
}
184+
Poll::Ready(auto_txs)
185+
}
186+
// Only auto transactions are ready, return them
187+
(Poll::Ready(auto_txs), Poll::Pending) => Poll::Ready(auto_txs),
188+
// Only fixed transactions are ready or both are pending,
189+
// return fixed transactions or pending status
190+
(Poll::Pending, fixed_txs) => fixed_txs,
191+
}
192+
}
160193
}
161194
}
162195
}

crates/anvil/src/lib.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,13 +142,19 @@ pub async fn try_spawn(mut config: NodeConfig) -> io::Result<(EthApi, NodeHandle
142142
no_mining,
143143
transaction_order,
144144
genesis,
145+
mixed_mining,
145146
..
146147
} = config.clone();
147148

148149
let pool = Arc::new(Pool::default());
149150

150151
let mode = if let Some(block_time) = block_time {
151-
MiningMode::interval(block_time)
152+
if mixed_mining {
153+
let listener = pool.add_ready_listener();
154+
MiningMode::mixed(max_transactions, listener, block_time)
155+
} else {
156+
MiningMode::interval(block_time)
157+
}
152158
} else if no_mining {
153159
MiningMode::None
154160
} else {

0 commit comments

Comments
 (0)