Skip to content

Commit

Permalink
feat(anvil): --cache-path (#9343)
Browse files Browse the repository at this point in the history
* feat(`anvil`): --cache-path

* nits

* test

* nit

* run with tempdir

* nit
  • Loading branch information
yash-atreya authored Nov 21, 2024
1 parent 25cc1ac commit 057c8ac
Show file tree
Hide file tree
Showing 9 changed files with 88 additions and 5 deletions.
18 changes: 18 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ alloy-transport = { version = "0.6.4", default-features = false }
alloy-transport-http = { version = "0.6.4", default-features = false }
alloy-transport-ipc = { version = "0.6.4", default-features = false }
alloy-transport-ws = { version = "0.6.4", default-features = false }
alloy-node-bindings = { version = "0.6.4", default-features = false }

## alloy-core
alloy-dyn-abi = "0.8.11"
Expand Down
1 change: 1 addition & 0 deletions crates/anvil/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ alloy-rpc-client = { workspace = true, features = ["pubsub"] }
alloy-transport-ipc = { workspace = true, features = ["mock"] }
alloy-provider = { workspace = true, features = ["txpool-api"] }
alloy-transport-ws.workspace = true
alloy-node-bindings.workspace = true
alloy-json-rpc.workspace = true
alloy-pubsub.workspace = true
foundry-test-utils.workspace = true
Expand Down
7 changes: 6 additions & 1 deletion crates/anvil/src/cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,10 @@ pub struct NodeArgs {

#[command(flatten)]
pub server_config: ServerConfig,

/// Path to the cache directory where states are stored.
#[arg(long, value_name = "PATH")]
pub cache_path: Option<PathBuf>,
}

#[cfg(windows)]
Expand Down Expand Up @@ -274,7 +278,8 @@ impl NodeArgs {
.with_alphanet(self.evm_opts.alphanet)
.with_disable_default_create2_deployer(self.evm_opts.disable_default_create2_deployer)
.with_slots_in_an_epoch(self.slots_in_an_epoch)
.with_memory_limit(self.evm_opts.memory_limit))
.with_memory_limit(self.evm_opts.memory_limit)
.with_cache_path(self.cache_path))
}

fn account_generator(&self) -> AccountGenerator {
Expand Down
11 changes: 11 additions & 0 deletions crates/anvil/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,8 @@ pub struct NodeConfig {
pub alphanet: bool,
/// Do not print log messages.
pub silent: bool,
/// The path where states are cached.
pub cache_path: Option<PathBuf>,
}

impl NodeConfig {
Expand Down Expand Up @@ -465,6 +467,7 @@ impl Default for NodeConfig {
precompile_factory: None,
alphanet: false,
silent: false,
cache_path: None,
}
}
}
Expand Down Expand Up @@ -969,6 +972,13 @@ impl NodeConfig {
self
}

/// Sets the path where states are cached
#[must_use]
pub fn with_cache_path(mut self, cache_path: Option<PathBuf>) -> Self {
self.cache_path = cache_path;
self
}

/// Configures everything related to env, backend and database and returns the
/// [Backend](mem::Backend)
///
Expand Down Expand Up @@ -1051,6 +1061,7 @@ impl NodeConfig {
self.max_persisted_states,
self.transaction_block_keeper,
self.block_time,
self.cache_path.clone(),
Arc::new(tokio::sync::RwLock::new(self.clone())),
)
.await;
Expand Down
4 changes: 4 additions & 0 deletions crates/anvil/src/eth/backend/mem/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ pub struct DiskStateCache {
}

impl DiskStateCache {
/// Specify the path where to create the tempdir in
pub fn with_path(self, temp_path: PathBuf) -> Self {
Self { temp_path: Some(temp_path), temp_dir: None }
}
/// Returns the cache file for the given hash
fn with_cache_file<F, R>(&mut self, hash: B256, f: F) -> Option<R>
where
Expand Down
9 changes: 7 additions & 2 deletions crates/anvil/src/eth/backend/mem/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,12 +103,12 @@ use revm::{
use std::{
collections::BTreeMap,
io::{Read, Write},
path::PathBuf,
sync::Arc,
time::Duration,
};
use storage::{Blockchain, MinedTransaction, DEFAULT_HISTORY_LIMIT};
use tokio::sync::RwLock as AsyncRwLock;

pub mod cache;
pub mod fork_db;
pub mod in_memory_db;
Expand Down Expand Up @@ -227,6 +227,7 @@ impl Backend {
max_persisted_states: Option<usize>,
transaction_block_keeper: Option<usize>,
automine_block_time: Option<Duration>,
cache_path: Option<PathBuf>,
node_config: Arc<AsyncRwLock<NodeConfig>>,
) -> Self {
// if this is a fork then adjust the blockchain storage
Expand All @@ -249,7 +250,7 @@ impl Backend {
genesis.timestamp
};

let states = if prune_state_history_config.is_config_enabled() {
let mut states = if prune_state_history_config.is_config_enabled() {
// if prune state history is enabled, configure the state cache only for memory
prune_state_history_config
.max_memory_history
Expand All @@ -264,6 +265,10 @@ impl Backend {
Default::default()
};

if let Some(cache_path) = cache_path {
states = states.disk_path(cache_path);
}

let (slots_in_an_epoch, precompile_factory) = {
let cfg = node_config.read().await;
(cfg.slots_in_an_epoch, cfg.precompile_factory.clone())
Expand Down
8 changes: 7 additions & 1 deletion crates/anvil/src/eth/backend/mem/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ use foundry_evm::{
};
use parking_lot::RwLock;
use revm::primitives::SpecId;
use std::{collections::VecDeque, fmt, sync::Arc, time::Duration};
use std::{collections::VecDeque, fmt, path::PathBuf, sync::Arc, time::Duration};
// use yansi::Paint;

// === various limits in number of blocks ===
Expand Down Expand Up @@ -94,6 +94,12 @@ impl InMemoryBlockStates {
self
}

/// Configures the path on disk where the states will cached.
pub fn disk_path(mut self, path: PathBuf) -> Self {
self.disk_cache = self.disk_cache.with_path(path);
self
}

/// This modifies the `limit` what to keep stored in memory.
///
/// This will ensure the new limit adjusts based on the block time.
Expand Down
34 changes: 33 additions & 1 deletion crates/anvil/tests/it/anvil.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@

use alloy_consensus::EMPTY_ROOT_HASH;
use alloy_eips::BlockNumberOrTag;
use alloy_primitives::Address;
use alloy_node_bindings::utils::run_with_tempdir;
use alloy_primitives::{Address, U256};
use alloy_provider::Provider;
use anvil::{spawn, EthereumHardfork, NodeConfig};
use std::time::Duration;

#[tokio::test(flavor = "multi_thread")]
async fn test_can_change_mining_mode() {
Expand Down Expand Up @@ -118,3 +120,33 @@ async fn test_cancun_fields() {
assert!(block.header.blob_gas_used.is_some());
assert!(block.header.excess_blob_gas.is_some());
}

#[tokio::test(flavor = "multi_thread")]
#[cfg(not(windows))]
async fn test_cache_path() {
run_with_tempdir("custom-anvil-cache", |tmp_dir| async move {
let cache_path = tmp_dir.join("cache");
let (api, _handle) = spawn(
NodeConfig::test()
.with_cache_path(Some(cache_path.clone()))
.with_max_persisted_states(Some(5_usize))
.with_blocktime(Some(Duration::from_millis(1))),
)
.await;

api.anvil_mine(Some(U256::from(1000)), None).await.unwrap();

// sleep to ensure the cache is written
tokio::time::sleep(Duration::from_secs(2)).await;

assert!(cache_path.exists());
assert!(cache_path.read_dir().unwrap().count() > 0);

// Clean the directory, this is to prevent an error when temp_dir is dropped.
let _ = std::fs::remove_dir_all(cache_path);

//sleep to ensure OS file handles are released
tokio::time::sleep(Duration::from_secs(1)).await;
})
.await;
}

0 comments on commit 057c8ac

Please sign in to comment.