Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add mixed mining mode #8280

Merged
merged 7 commits into from
Jul 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading