Skip to content

Commit 29dee41

Browse files
committed
feat: use AnvilApi
1 parent c50f330 commit 29dee41

File tree

4 files changed

+73
-46
lines changed

4 files changed

+73
-46
lines changed

Cargo.lock

Lines changed: 37 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ alloy-provider = { version = "1.0.37", default-features = false }
135135
alloy-rpc-client = { version = "1.0.37", default-features = false }
136136
alloy-rpc-types-engine = { version = "1.0.37", default-features = false }
137137
alloy-rpc-types-eth = { version = "1.0.37", default-features = false }
138+
alloy-rpc-types-anvil = { version = "1.0.37", default-features = false }
138139
alloy-sol-types = { version = "1.4.1", default-features = false }
139140
alloy-signer = { version = "1.0.37", default-features = false }
140141
alloy-signer-local = { version = "1.0.37", default-features = false }

crates/node/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ alloy-eips = { workspace = true, optional = true }
8080
anvil = { git = "https://github.com/foundry-rs/foundry.git", rev = "2c84e1c970d11ef5023a77d8002a1cb70b143888", default-features = false, optional = true }
8181
alloy-rpc-types-eth = { workspace = true, optional = true }
8282
alloy-rpc-types-engine = { workspace = true, optional = true }
83+
alloy-rpc-types-anvil = { workspace = true, optional = true }
8384
reth-e2e-test-utils = { workspace = true, optional = true }
8485
reth-engine-local = { workspace = true, optional = true }
8586
reth-provider = { workspace = true, optional = true }
@@ -160,4 +161,7 @@ test-utils = [
160161
"anvil",
161162
"reth-storage-api",
162163
"alloy-rpc-types-eth",
164+
"alloy-rpc-types-anvil",
165+
"alloy-provider/anvil-api",
166+
"alloy-provider/anvil-node",
163167
]

crates/node/src/test_utils/fixture.rs

Lines changed: 31 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,20 @@ use super::{
44
block_builder::BlockBuilder, l1_helpers::L1Helper, setup_engine, tx_helpers::TxHelper,
55
};
66
use crate::{
7-
BlobProviderArgs, ChainOrchestratorArgs, ConsensusAlgorithm, ConsensusArgs, EngineDriverArgs,
8-
L1ProviderArgs, RollupNodeDatabaseArgs, RollupNodeGasPriceOracleArgs, RollupNodeNetworkArgs,
9-
RpcArgs, ScrollRollupNode, ScrollRollupNodeConfig, SequencerArgs, SignerArgs, TestArgs,
7+
constants, BlobProviderArgs, ChainOrchestratorArgs, ConsensusAlgorithm, ConsensusArgs,
8+
EngineDriverArgs, L1ProviderArgs, RollupNodeDatabaseArgs, RollupNodeGasPriceOracleArgs,
9+
RollupNodeNetworkArgs, RpcArgs, ScrollRollupNode, ScrollRollupNodeConfig, SequencerArgs,
10+
SignerArgs, TestArgs,
1011
};
1112

1213
use alloy_eips::BlockNumberOrTag;
1314
use alloy_primitives::Address;
14-
use alloy_provider::{Provider, ProviderBuilder};
15+
use alloy_provider::{ext::AnvilApi, layers::CacheLayer, Provider, ProviderBuilder};
16+
use alloy_rpc_client::RpcClient;
17+
use alloy_rpc_types_anvil::ReorgOptions;
1518
use alloy_rpc_types_eth::Block;
1619
use alloy_signer_local::PrivateKeySigner;
20+
use alloy_transport::layers::RetryBackoffLayer;
1721
use reth_chainspec::EthChainSpec;
1822
use reth_e2e_test_utils::{wallet::Wallet, NodeHelperType, TmpDB};
1923
use reth_eth_wire_types::BasicNetworkPrimitives;
@@ -216,66 +220,46 @@ impl TestFixture {
216220
self.get_status(0).await
217221
}
218222

219-
/// Get the Anvil HTTP endpoint if Anvil was started.
220-
pub fn anvil_endpoint(&self) -> Option<String> {
221-
self.anvil.as_ref().map(|a| a.http_endpoint())
223+
/// Get the Anvil HTTP provider with retry and cache layers.
224+
pub fn anvil_provider(&self) -> Option<impl Provider + Clone> {
225+
self.anvil.as_ref().map(|anvil| {
226+
let retry_layer = RetryBackoffLayer::new(
227+
constants::L1_PROVIDER_MAX_RETRIES,
228+
constants::L1_PROVIDER_INITIAL_BACKOFF,
229+
constants::PROVIDER_COMPUTE_UNITS_PER_SECOND,
230+
);
231+
let client = RpcClient::builder()
232+
.layer(retry_layer)
233+
.http(anvil.http_endpoint().parse().expect("failed to parse anvil http endpoint"));
234+
let cache_layer = CacheLayer::new(constants::L1_PROVIDER_CACHE_MAX_ITEMS);
235+
ProviderBuilder::new().layer(cache_layer).connect_client(client)
236+
})
222237
}
223238

224239
/// Generate Anvil blocks by calling `anvil_mine` RPC method.
225240
pub async fn anvil_mine_blocks(&self, num_blocks: u64) -> eyre::Result<()> {
226-
// Ensure Anvil is running
227-
let anvil_endpoint =
228-
self.anvil_endpoint().ok_or_else(|| eyre::eyre!("Anvil is not running"))?;
229-
230-
// Create RPC client
231-
let client = alloy_rpc_client::RpcClient::new_http(anvil_endpoint.parse()?);
232-
233-
// Mine blocks using anvil_mine RPC method
234-
// Parameters: (num_blocks, interval_in_seconds)
235-
let _: () = client.request("anvil_mine", (num_blocks, 0)).await?;
236-
237-
Ok(())
241+
let provider = self.anvil_provider().ok_or_else(|| eyre::eyre!("Anvil is not running"))?;
242+
Ok(provider.anvil_mine(Some(num_blocks), None).await?)
238243
}
239244

240245
/// Inject a raw transaction to Anvil.
241246
pub async fn anvil_inject_tx(
242247
&self,
243248
raw_tx: impl Into<alloy_primitives::Bytes>,
244249
) -> eyre::Result<alloy_primitives::B256> {
245-
// Ensure Anvil is running
246-
let anvil_endpoint =
247-
self.anvil_endpoint().ok_or_else(|| eyre::eyre!("Anvil is not running"))?;
248-
249-
// Create provider
250-
let provider = ProviderBuilder::new().connect_http(anvil_endpoint.parse()?);
251-
252-
// Send raw transaction
250+
let provider = self.anvil_provider().ok_or_else(|| eyre::eyre!("Anvil is not running"))?;
253251
let raw_tx_bytes = raw_tx.into();
254252
let pending_tx = provider.send_raw_transaction(&raw_tx_bytes).await?;
255-
256253
let tx_hash = *pending_tx.tx_hash();
257254
tracing::info!("Sent raw transaction to Anvil: {:?}", tx_hash);
258-
259255
Ok(tx_hash)
260256
}
261257

262258
/// Reorg Anvil by a specific depth (number of blocks to rewind).
263259
pub async fn anvil_reorg(&self, depth: u64) -> eyre::Result<()> {
264-
// Ensure Anvil is running
265-
let anvil_endpoint =
266-
self.anvil_endpoint().ok_or_else(|| eyre::eyre!("Anvil is not running"))?;
267-
268-
// Create RPC client
269-
let client = alloy_rpc_client::RpcClient::new_http(anvil_endpoint.parse()?);
270-
271-
// Call anvil_reorg
272-
// Parameters: (depth, transactions)
273-
// - depth: number of blocks to rewind from current head
274-
// - transactions: empty array means reorg without adding new transactions
275-
let _: () = client.request("anvil_reorg", (depth, Vec::<String>::new())).await?;
276-
260+
let provider = self.anvil_provider().ok_or_else(|| eyre::eyre!("Anvil is not running"))?;
261+
provider.anvil_reorg(ReorgOptions { depth, tx_block_pairs: Vec::new() }).await?;
277262
tracing::info!("Reorged Anvil by {} blocks", depth);
278-
279263
Ok(())
280264
}
281265
}
@@ -523,7 +507,8 @@ impl TestFixtureBuilder {
523507
/// Enable Anvil with optional configuration.
524508
///
525509
/// # Parameters
526-
/// - `state_path`: Optional path to Anvil state file. Defaults to `./tests/testdata/anvil_state.json` if `None`.
510+
/// - `state_path`: Optional path to Anvil state file. Defaults to
511+
/// `./tests/testdata/anvil_state.json` if `None`.
527512
/// - `chain_id`: Optional chain ID for Anvil. If `None`, Anvil uses its default.
528513
/// - `block_time`: Optional block time in seconds. If `None`, Anvil uses its default.
529514
///
@@ -545,8 +530,8 @@ impl TestFixtureBuilder {
545530
block_time: Option<u64>,
546531
) -> Self {
547532
self.anvil_config.enabled = true;
548-
self.anvil_config.state_path = state_path
549-
.or_else(|| Some(PathBuf::from("./tests/testdata/anvil_state.json")));
533+
self.anvil_config.state_path =
534+
state_path.or_else(|| Some(PathBuf::from("./tests/testdata/anvil_state.json")));
550535
self.anvil_config.chain_id = chain_id;
551536
self.anvil_config.block_time = block_time;
552537
self

0 commit comments

Comments
 (0)