Skip to content

Commit

Permalink
feat: add mixed mining mode (foundry-rs#8280)
Browse files Browse the repository at this point in the history
* 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]>
  • Loading branch information
caiquejjx and mattsse authored Jul 23, 2024
1 parent 62cdea8 commit 5af9d16
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 1 deletion.
4 changes: 4 additions & 0 deletions crates/anvil/src/cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,9 @@ pub struct NodeArgs {
#[arg(long, visible_alias = "no-mine", conflicts_with = "block_time")]
pub no_mining: bool,

#[arg(long, visible_alias = "mixed-mining", requires = "block_time")]
pub mixed_mining: bool,

/// The hosts the server will listen on.
#[arg(
long,
Expand Down Expand Up @@ -200,6 +203,7 @@ impl NodeArgs {
.with_hardfork(self.hardfork)
.with_blocktime(self.block_time)
.with_no_mining(self.no_mining)
.with_mixed_mining(self.mixed_mining, self.block_time)
.with_account_generator(self.account_generator())
.with_genesis_balance(genesis_balance)
.with_genesis_timestamp(self.timestamp)
Expand Down
14 changes: 14 additions & 0 deletions crates/anvil/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,8 @@ pub struct NodeConfig {
pub block_time: Option<Duration>,
/// Disable auto, interval mining mode uns use `MiningMode::None` instead
pub no_mining: bool,
/// Enables auto and interval mining mode
pub mixed_mining: bool,
/// port to use for the server
pub port: u16,
/// maximum number of transactions in a block
Expand Down Expand Up @@ -395,6 +397,7 @@ impl Default for NodeConfig {
genesis_balance: Unit::ETHER.wei().saturating_mul(U256::from(100u64)),
block_time: None,
no_mining: false,
mixed_mining: false,
port: NODE_PORT,
// TODO make this something dependent on block capacity
max_transactions: 1_000,
Expand Down Expand Up @@ -633,6 +636,17 @@ impl NodeConfig {
self
}

#[must_use]
pub fn with_mixed_mining<D: Into<Duration>>(
mut self,
mixed_mining: bool,
block_time: Option<D>,
) -> Self {
self.block_time = block_time.map(Into::into);
self.mixed_mining = mixed_mining;
self
}

/// If set to `true` auto mining will be disabled
#[must_use]
pub fn with_no_mining(mut self, no_mining: bool) -> Self {
Expand Down
33 changes: 33 additions & 0 deletions crates/anvil/src/eth/miner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,9 @@ pub enum MiningMode {
Auto(ReadyTransactionMiner),
/// A miner that constructs a new block every `interval` tick
FixedBlockTime(FixedBlockTimeMiner),

/// A minner that uses both Auto and FixedBlockTime
Mixed(ReadyTransactionMiner, FixedBlockTimeMiner),
}

impl MiningMode {
Expand All @@ -147,6 +150,13 @@ impl MiningMode {
Self::FixedBlockTime(FixedBlockTimeMiner::new(duration))
}

pub fn mixed(max_transactions: usize, listener: Receiver<TxHash>, duration: Duration) -> Self {
Self::Mixed(
ReadyTransactionMiner { max_transactions, has_pending_txs: None, rx: listener.fuse() },
FixedBlockTimeMiner::new(duration),
)
}

/// polls the [Pool] and returns those transactions that should be put in a block, if any.
pub fn poll(
&mut self,
Expand All @@ -157,6 +167,29 @@ impl MiningMode {
Self::None => Poll::Pending,
Self::Auto(miner) => miner.poll(pool, cx),
Self::FixedBlockTime(miner) => miner.poll(pool, cx),
Self::Mixed(auto, fixed) => {
let auto_txs = auto.poll(pool, cx);
let fixed_txs = fixed.poll(pool, cx);

match (auto_txs, fixed_txs) {
// Both auto and fixed transactions are ready, combine them
(Poll::Ready(mut auto_txs), Poll::Ready(fixed_txs)) => {
for tx in fixed_txs {
// filter unique transactions
if auto_txs.iter().any(|auto_tx| auto_tx.hash() == tx.hash()) {
continue;
}
auto_txs.push(tx);
}
Poll::Ready(auto_txs)
}
// Only auto transactions are ready, return them
(Poll::Ready(auto_txs), Poll::Pending) => Poll::Ready(auto_txs),
// Only fixed transactions are ready or both are pending,
// return fixed transactions or pending status
(Poll::Pending, fixed_txs) => fixed_txs,
}
}
}
}
}
Expand Down
8 changes: 7 additions & 1 deletion crates/anvil/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,13 +142,19 @@ pub async fn try_spawn(mut config: NodeConfig) -> io::Result<(EthApi, NodeHandle
no_mining,
transaction_order,
genesis,
mixed_mining,
..
} = config.clone();

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

let mode = if let Some(block_time) = block_time {
MiningMode::interval(block_time)
if mixed_mining {
let listener = pool.add_ready_listener();
MiningMode::mixed(max_transactions, listener, block_time)
} else {
MiningMode::interval(block_time)
}
} else if no_mining {
MiningMode::None
} else {
Expand Down

0 comments on commit 5af9d16

Please sign in to comment.