diff --git a/Cargo.lock b/Cargo.lock index 0ac2383f3..f4321e206 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1767,6 +1767,27 @@ dependencies = [ "subtle", ] +[[package]] +name = "directories" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a49173b84e034382284f27f1af4dcbbd231ffa358c0fe316541a7337f376a35" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys 0.48.0", +] + [[package]] name = "displaydoc" version = "0.2.5" @@ -2877,6 +2898,16 @@ version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" +[[package]] +name = "libredox" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +dependencies = [ + "bitflags 2.6.0", + "libc", +] + [[package]] name = "linkme" version = "0.3.27" @@ -3275,6 +3306,12 @@ dependencies = [ "zero_bin_common", ] +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + [[package]] name = "overload" version = "0.1.1" @@ -3962,6 +3999,17 @@ dependencies = [ "bitflags 2.6.0", ] +[[package]] +name = "redox_users" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" +dependencies = [ + "getrandom", + "libredox", + "thiserror", +] + [[package]] name = "regex" version = "1.10.5" @@ -5780,8 +5828,10 @@ dependencies = [ "async-stream", "cargo_metadata", "clap", + "directories", "evm_arithmetization", "futures", + "once_cell", "plonky2", "proof_gen", "serde", diff --git a/zero_bin/common/Cargo.toml b/zero_bin/common/Cargo.toml index 0d0e35191..d5a317bf1 100644 --- a/zero_bin/common/Cargo.toml +++ b/zero_bin/common/Cargo.toml @@ -9,6 +9,8 @@ keywords.workspace = true categories.workspace = true [dependencies] +directories = "5.0.1" + thiserror = { workspace = true } tracing = { workspace = true } proof_gen = { workspace = true } @@ -24,6 +26,7 @@ alloy = { workspace = true } async-stream = { workspace = true } cargo_metadata = { workspace = true } vergen = { workspace = true } +once_cell = { workspace = true } [build-dependencies] cargo_metadata = { workspace = true } diff --git a/zero_bin/common/src/prover_state/mod.rs b/zero_bin/common/src/prover_state/mod.rs index aacd7c12e..355a4451e 100644 --- a/zero_bin/common/src/prover_state/mod.rs +++ b/zero_bin/common/src/prover_state/mod.rs @@ -17,6 +17,7 @@ use clap::ValueEnum; use evm_arithmetization::{ proof::AllProof, prover::prove, AllStark, GenerationInputs, StarkConfig, }; +use persistence::set_circuit_cache_dir_env_if_not_set; use plonky2::{ field::goldilocks_field::GoldilocksField, plonk::config::PoseidonGoldilocksConfig, util::timing::TimingTree, @@ -242,6 +243,7 @@ impl ProverStateManager { /// Initialize global prover state from the configuration. pub fn initialize(&self) -> anyhow::Result<()> { info!("initializing prover state..."); + set_circuit_cache_dir_env_if_not_set()?; let state = match self.persistence { CircuitPersistence::None => { diff --git a/zero_bin/common/src/prover_state/persistence.rs b/zero_bin/common/src/prover_state/persistence.rs index 750726696..7d8720626 100644 --- a/zero_bin/common/src/prover_state/persistence.rs +++ b/zero_bin/common/src/prover_state/persistence.rs @@ -6,6 +6,8 @@ use std::{ path::Path, }; +use directories::ProjectDirs; +use once_cell::sync::Lazy; use plonky2::util::serialization::{ Buffer, DefaultGateSerializer, DefaultGeneratorSerializer, IoError, }; @@ -17,10 +19,20 @@ use super::{ Config, RecursiveCircuitsForTableSize, SIZE, }; -const CIRCUITS_DIR: &str = "circuits/"; const PROVER_STATE_FILE_PREFIX: &str = "prover_state"; const VERIFIER_STATE_FILE_PREFIX: &str = "verifier_state"; -const CARGO_WORKSPACE_DIR_ENV: &str = "CARGO_WORKSPACE_DIR"; +const ZK_EVM_CACHE_DIR_NAME: &str = "zk_evm_circuit_cache"; +const ZK_EVM_CACHE_DIR_ENV: &str = "ZK_EVM_CACHE_DIR"; + +static CIRCUIT_CACHE_DIR: Lazy = Lazy::new(|| { + // Guaranteed to be set by the binary if not set by the user. + std::env::var(ZK_EVM_CACHE_DIR_ENV).unwrap_or_else(|_| { + format!( + "expected the env var \"{}\" to be set", + ZK_EVM_CACHE_DIR_ENV + ) + }) +}); fn get_serializers() -> ( DefaultGateSerializer, @@ -73,11 +85,11 @@ pub(crate) trait DiskResource { p: &Self::PathConstrutor, r: &Self::Resource, ) -> Result<(), DiskResourceError> { - let circuits_dir = relative_circuit_dir_path(); + let circuits_dir = &*CIRCUIT_CACHE_DIR; // Create the base folder if non-existent. - if std::fs::metadata(&circuits_dir).is_err() { - std::fs::create_dir(&circuits_dir).map_err(|_| { + if std::fs::metadata(circuits_dir).is_err() { + std::fs::create_dir(circuits_dir).map_err(|_| { DiskResourceError::IoError::(std::io::Error::other( "Could not create circuits folder", )) @@ -107,7 +119,7 @@ impl DiskResource for BaseProverResource { fn path(p: &Self::PathConstrutor) -> impl AsRef { format!( "{}/{}_base_{}_{}", - &relative_circuit_dir_path(), + *CIRCUIT_CACHE_DIR, PROVER_STATE_FILE_PREFIX, env!("EVM_ARITHMETIZATION_PKG_VER"), p.get_configuration_digest() @@ -143,7 +155,7 @@ impl DiskResource for MonolithicProverResource { fn path(p: &Self::PathConstrutor) -> impl AsRef { format!( "{}/{}_monolithic_{}_{}", - &relative_circuit_dir_path(), + *CIRCUIT_CACHE_DIR, PROVER_STATE_FILE_PREFIX, env!("EVM_ARITHMETIZATION_PKG_VER"), p.get_configuration_digest() @@ -178,7 +190,7 @@ impl DiskResource for RecursiveCircuitResource { fn path((circuit_type, size): &Self::PathConstrutor) -> impl AsRef { format!( "{}/{}_{}_{}_{}", - &relative_circuit_dir_path(), + *CIRCUIT_CACHE_DIR, PROVER_STATE_FILE_PREFIX, env!("EVM_ARITHMETIZATION_PKG_VER"), circuit_type.as_short_str(), @@ -222,7 +234,7 @@ impl DiskResource for VerifierResource { fn path(p: &Self::PathConstrutor) -> impl AsRef { format!( "{}/{}_{}_{}", - &relative_circuit_dir_path(), + *CIRCUIT_CACHE_DIR, VERIFIER_STATE_FILE_PREFIX, env!("EVM_ARITHMETIZATION_PKG_VER"), p.get_configuration_digest() @@ -277,11 +289,18 @@ fn prover_to_disk( Ok(()) } -/// If we're running in the cargo workspace, then always use the `circuits` -/// directory that lives in `tools/`. Otherwise, just use `circuits` in the -/// current directory. -fn relative_circuit_dir_path() -> String { - env::var(CARGO_WORKSPACE_DIR_ENV) - .map(|p| format!("{}/{}", p, CIRCUITS_DIR)) - .unwrap_or_else(|_| CIRCUITS_DIR.to_string()) +/// We store serialized circuits inside the cache directory specified by an env +/// variable. If the user does not set this, then we set it base to the OS's +/// standard location for the cache directory. +pub(crate) fn set_circuit_cache_dir_env_if_not_set() -> anyhow::Result<()> { + if std::env::var_os(ZK_EVM_CACHE_DIR_ENV).is_none() { + let circuit_cache_dir = match ProjectDirs::from("", "", ZK_EVM_CACHE_DIR_NAME) { + Some(proj_dir) => proj_dir.cache_dir().to_path_buf(), + None => std::env::current_dir()?, + }; + + std::env::set_var(ZK_EVM_CACHE_DIR_ENV, circuit_cache_dir); + } + + Ok(()) }