diff --git a/Cargo.lock b/Cargo.lock index b050480440e4..219255d29ddf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9402,6 +9402,7 @@ dependencies = [ "hex", "itertools 0.10.5", "num", + "once_cell", "rand 0.8.5", "reqwest", "serde", diff --git a/core/bin/contract-verifier/src/main.rs b/core/bin/contract-verifier/src/main.rs index 73b2f919c31a..98b4a859d14d 100644 --- a/core/bin/contract-verifier/src/main.rs +++ b/core/bin/contract-verifier/src/main.rs @@ -3,6 +3,7 @@ use std::{cell::RefCell, time::Duration}; use anyhow::Context as _; use futures::{channel::mpsc, executor::block_on, SinkExt, StreamExt}; use prometheus_exporter::PrometheusExporterConfig; +use structopt::StructOpt; use tokio::sync::watch; use zksync_config::{ configs::{ObservabilityConfig, PrometheusConfig}, @@ -11,7 +12,7 @@ use zksync_config::{ use zksync_dal::{ConnectionPool, Core, CoreDal}; use zksync_env_config::FromEnv; use zksync_queued_job_processor::JobProcessor; -use zksync_utils::wait_for_tasks::ManagedTasks; +use zksync_utils::{wait_for_tasks::ManagedTasks, workspace_dir_or_current_dir}; use crate::verifier::ContractVerifier; @@ -25,9 +26,9 @@ async fn update_compiler_versions(connection_pool: &ConnectionPool) { let mut storage = connection_pool.connection().await.unwrap(); let mut transaction = storage.start_transaction().await.unwrap(); - let zksync_home = std::env::var("ZKSYNC_HOME").unwrap_or_else(|_| ".".into()); + let zksync_home = workspace_dir_or_current_dir(); - let zksolc_path = format!("{}/etc/zksolc-bin/", zksync_home); + let zksolc_path = zksync_home.join("etc/zksolc-bin/"); let zksolc_versions: Vec = std::fs::read_dir(zksolc_path) .unwrap() .filter_map(|file| { @@ -48,7 +49,7 @@ async fn update_compiler_versions(connection_pool: &ConnectionPool) { .await .unwrap(); - let solc_path = format!("{}/etc/solc-bin/", zksync_home); + let solc_path = zksync_home.join("etc/solc-bin/"); let solc_versions: Vec = std::fs::read_dir(solc_path) .unwrap() .filter_map(|file| { @@ -69,7 +70,7 @@ async fn update_compiler_versions(connection_pool: &ConnectionPool) { .await .unwrap(); - let zkvyper_path = format!("{}/etc/zkvyper-bin/", zksync_home); + let zkvyper_path = zksync_home.join("etc/zkvyper-bin/"); let zkvyper_versions: Vec = std::fs::read_dir(zkvyper_path) .unwrap() .filter_map(|file| { @@ -90,7 +91,7 @@ async fn update_compiler_versions(connection_pool: &ConnectionPool) { .await .unwrap(); - let vyper_path = format!("{}/etc/vyper-bin/", zksync_home); + let vyper_path = zksync_home.join("etc/vyper-bin/"); let vyper_versions: Vec = std::fs::read_dir(vyper_path) .unwrap() .filter_map(|file| { @@ -115,7 +116,6 @@ async fn update_compiler_versions(connection_pool: &ConnectionPool) { transaction.commit().await.unwrap(); } -use structopt::StructOpt; use zksync_config::configs::DatabaseSecrets; #[derive(StructOpt)] diff --git a/core/bin/contract-verifier/src/verifier.rs b/core/bin/contract-verifier/src/verifier.rs index 938ea2fd1ba6..8d5ba9fccfe2 100644 --- a/core/bin/contract-verifier/src/verifier.rs +++ b/core/bin/contract-verifier/src/verifier.rs @@ -1,6 +1,5 @@ use std::{ collections::HashMap, - env, path::Path, time::{Duration, Instant}, }; @@ -22,6 +21,7 @@ use zksync_types::{ }, Address, }; +use zksync_utils::workspace_dir_or_current_dir; use crate::{ error::ContractVerifierError, @@ -34,6 +34,10 @@ lazy_static! { static ref DEPLOYER_CONTRACT: Contract = zksync_contracts::deployer_contract(); } +fn home_path() -> &'static Path { + workspace_dir_or_current_dir() +} + #[derive(Debug)] enum ConstructorArgs { Check(Vec), @@ -120,8 +124,7 @@ impl ContractVerifier { }; let input = Self::build_zksolc_input(request.clone(), file_name.clone())?; - let zksync_home = env::var("ZKSYNC_HOME").unwrap_or_else(|_| ".".into()); - let zksolc_path = Path::new(&zksync_home) + let zksolc_path = Path::new(&home_path()) .join("etc") .join("zksolc-bin") .join(request.req.compiler_versions.zk_compiler_version()) @@ -133,7 +136,7 @@ impl ContractVerifier { )); } - let solc_path = Path::new(&zksync_home) + let solc_path = Path::new(&home_path()) .join("etc") .join("solc-bin") .join(request.req.compiler_versions.compiler_version()) @@ -219,8 +222,7 @@ impl ContractVerifier { }; let input = Self::build_zkvyper_input(request.clone())?; - let zksync_home = env::var("ZKSYNC_HOME").unwrap_or_else(|_| ".".into()); - let zkvyper_path = Path::new(&zksync_home) + let zkvyper_path = Path::new(&home_path()) .join("etc") .join("zkvyper-bin") .join(request.req.compiler_versions.zk_compiler_version()) @@ -232,7 +234,7 @@ impl ContractVerifier { )); } - let vyper_path = Path::new(&zksync_home) + let vyper_path = Path::new(&home_path()) .join("etc") .join("vyper-bin") .join(request.req.compiler_versions.compiler_version()) diff --git a/core/bin/system-constants-generator/src/main.rs b/core/bin/system-constants-generator/src/main.rs index 548d4c9a0ce1..b0276aeb7fa1 100644 --- a/core/bin/system-constants-generator/src/main.rs +++ b/core/bin/system-constants-generator/src/main.rs @@ -17,6 +17,7 @@ use zksync_types::{ IntrinsicSystemGasConstants, ProtocolVersionId, GUARANTEED_PUBDATA_IN_TX, L1_GAS_PER_PUBDATA_BYTE, MAX_NEW_FACTORY_DEPS, REQUIRED_L1_TO_L2_GAS_PER_PUBDATA_BYTE, }; +use zksync_utils::workspace_dir_or_current_dir; // For configs we will use the default value of `800_000` to represent the rough amount of L1 gas // needed to cover the batch expenses. @@ -209,8 +210,8 @@ fn generate_rust_fee_constants(intrinsic_gas_constants: &IntrinsicSystemGasConst } fn save_file(path_in_repo: &str, content: String) { - let zksync_home = std::env::var("ZKSYNC_HOME").expect("No ZKSYNC_HOME env var"); - let fee_constants_path = format!("{zksync_home}/{path_in_repo}"); + let zksync_home = workspace_dir_or_current_dir(); + let fee_constants_path = zksync_home.join(path_in_repo); fs::write(fee_constants_path, content) .unwrap_or_else(|_| panic!("Failed to write to {}", path_in_repo)); diff --git a/core/lib/contracts/src/lib.rs b/core/lib/contracts/src/lib.rs index 285f9f0430e7..5166d17dd066 100644 --- a/core/lib/contracts/src/lib.rs +++ b/core/lib/contracts/src/lib.rs @@ -1,6 +1,6 @@ //! Set of utility functions to read contracts both in Yul and Sol format. //! -//! Careful: some of the methods are reading the contracts based on the ZKSYNC_HOME environment variable. +//! Careful: some of the methods are reading the contracts based on the workspace environment variable. #![allow(clippy::derive_partial_eq_without_eq)] @@ -15,7 +15,7 @@ use ethabi::{ }; use once_cell::sync::Lazy; use serde::{Deserialize, Serialize}; -use zksync_utils::{bytecode::hash_bytecode, bytes_to_be_words}; +use zksync_utils::{bytecode::hash_bytecode, bytes_to_be_words, workspace_dir_or_current_dir}; pub mod test_contracts; @@ -48,8 +48,12 @@ const LOADNEXT_CONTRACT_FILE: &str = const LOADNEXT_SIMPLE_CONTRACT_FILE: &str = "etc/contracts-test-data/artifacts-zk/contracts/loadnext/loadnext_contract.sol/Foo.json"; -fn read_file_to_json_value(path: impl AsRef) -> serde_json::Value { - let zksync_home = std::env::var("ZKSYNC_HOME").unwrap_or_else(|_| ".".into()); +fn home_path() -> &'static Path { + workspace_dir_or_current_dir() +} + +fn read_file_to_json_value(path: impl AsRef + std::fmt::Debug) -> serde_json::Value { + let zksync_home = home_path(); let path = Path::new(&zksync_home).join(path); serde_json::from_reader( File::open(&path).unwrap_or_else(|e| panic!("Failed to open file {:?}: {}", path, e)), @@ -58,7 +62,7 @@ fn read_file_to_json_value(path: impl AsRef) -> serde_json::Value { } fn load_contract_if_present + std::fmt::Debug>(path: P) -> Option { - let zksync_home = std::env::var("ZKSYNC_HOME").unwrap_or_else(|_| ".".into()); + let zksync_home = home_path(); let path = Path::new(&zksync_home).join(path); path.exists().then(|| { serde_json::from_value(read_file_to_json_value(&path)["abi"].take()) @@ -79,7 +83,7 @@ pub fn load_sys_contract(contract_name: &str) -> Contract { )) } -pub fn read_contract_abi(path: impl AsRef) -> String { +pub fn read_contract_abi(path: impl AsRef + std::fmt::Debug) -> String { read_file_to_json_value(path)["abi"] .as_str() .expect("Failed to parse abi") @@ -149,6 +153,11 @@ pub fn l1_messenger_contract() -> Contract { load_sys_contract("L1Messenger") } +/// Reads bytecode from the path RELATIVE to the Cargo workspace location. +pub fn read_bytecode(relative_path: impl AsRef + std::fmt::Debug) -> Vec { + read_bytecode_from_path(relative_path) +} + pub fn eth_contract() -> Contract { load_sys_contract("L2BaseToken") } @@ -157,16 +166,9 @@ pub fn known_codes_contract() -> Contract { load_sys_contract("KnownCodesStorage") } -/// Reads bytecode from the path RELATIVE to the ZKSYNC_HOME environment variable. -pub fn read_bytecode(relative_path: impl AsRef) -> Vec { - let zksync_home = std::env::var("ZKSYNC_HOME").unwrap_or_else(|_| ".".into()); - let artifact_path = Path::new(&zksync_home).join(relative_path); - read_bytecode_from_path(artifact_path) -} - /// Reads bytecode from a given path. -fn read_bytecode_from_path(artifact_path: PathBuf) -> Vec { - let artifact = read_file_to_json_value(artifact_path.clone()); +fn read_bytecode_from_path(artifact_path: impl AsRef + std::fmt::Debug) -> Vec { + let artifact = read_file_to_json_value(&artifact_path); let bytecode = artifact["bytecode"] .as_str() @@ -187,19 +189,17 @@ static DEFAULT_SYSTEM_CONTRACTS_REPO: Lazy = /// Structure representing a system contract repository - that allows /// fetching contracts that are located there. -/// As most of the static methods in this file, is loading data based on ZKSYNC_HOME environment variable. +/// As most of the static methods in this file, is loading data based on the Cargo workspace location. pub struct SystemContractsRepo { // Path to the root of the system contracts repository. pub root: PathBuf, } impl SystemContractsRepo { - /// Returns the default system contracts repository with directory based on the ZKSYNC_HOME environment variable. + /// Returns the default system contracts repository with directory based on the Cargo workspace location. pub fn from_env() -> Self { - let zksync_home = std::env::var("ZKSYNC_HOME").unwrap_or_else(|_| ".".into()); - let zksync_home = PathBuf::from(zksync_home); SystemContractsRepo { - root: zksync_home.join("contracts/system-contracts"), + root: home_path().join("contracts/system-contracts"), } } @@ -237,10 +237,9 @@ fn read_playground_batch_bootloader_bytecode() -> Vec { read_bootloader_code("playground_batch") } -/// Reads zbin bytecode from a given path, relative to ZKSYNC_HOME. +/// Reads zbin bytecode from a given path, relative to workspace location. pub fn read_zbin_bytecode(relative_zbin_path: impl AsRef) -> Vec { - let zksync_home = std::env::var("ZKSYNC_HOME").unwrap_or_else(|_| ".".into()); - let bytecode_path = Path::new(&zksync_home).join(relative_zbin_path); + let bytecode_path = Path::new(&home_path()).join(relative_zbin_path); read_zbin_bytecode_from_path(bytecode_path) } diff --git a/core/lib/types/src/system_contracts.rs b/core/lib/types/src/system_contracts.rs index c802246da1d2..a28c45b8feae 100644 --- a/core/lib/types/src/system_contracts.rs +++ b/core/lib/types/src/system_contracts.rs @@ -180,7 +180,7 @@ static SYSTEM_CONTRACTS: Lazy> = Lazy::new(|| { .collect::>() }); -/// Gets default set of system contracts, based on ZKSYNC_HOME environment variable. +/// Gets default set of system contracts, based on Cargo workspace location. pub fn get_system_smart_contracts() -> Vec { SYSTEM_CONTRACTS.clone() } diff --git a/core/lib/utils/Cargo.toml b/core/lib/utils/Cargo.toml index 1fe736094e9d..4eea7d1398d1 100644 --- a/core/lib/utils/Cargo.toml +++ b/core/lib/utils/Cargo.toml @@ -25,9 +25,10 @@ futures.workspace = true hex.workspace = true reqwest = { workspace = true, features = ["blocking"] } itertools.workspace = true +serde_json.workspace = true +once_cell.workspace = true [dev-dependencies] -serde_json.workspace = true rand.workspace = true tokio = { workspace = true, features = ["macros", "rt"] } bincode.workspace = true diff --git a/core/lib/utils/src/env.rs b/core/lib/utils/src/env.rs new file mode 100644 index 000000000000..fec413927929 --- /dev/null +++ b/core/lib/utils/src/env.rs @@ -0,0 +1,68 @@ +use std::{ + path::{Path, PathBuf}, + str, +}; + +use anyhow::Context as _; +use once_cell::sync::OnceCell; + +static WORKSPACE: OnceCell> = OnceCell::new(); + +fn locate_workspace_inner() -> anyhow::Result { + let output = std::process::Command::new( + std::env::var("CARGO") + .ok() + .unwrap_or_else(|| "cargo".to_string()), + ) + .arg("locate-project") + .arg("--workspace") + .output() + .context("Can't find Cargo workspace location")?; + + let output = + serde_json::from_slice::(&output.stdout).with_context(|| { + format!( + "Error parsing `cargo locate-project` output {}", + str::from_utf8(&output.stdout).unwrap_or("(non-utf8 output)") + ) + })?; + let root = output.get("root").with_context(|| { + format!("root doesn't exist in output from `cargo locate-project` {output:?}") + })?; + + let serde_json::Value::String(root) = root else { + return Err(anyhow::anyhow!("`root` is not a string: {root:?}")); + }; + let root_path = PathBuf::from(root); + Ok(root_path + .parent() + .with_context(|| format!("`root` path doesn't have a parent: {}", root_path.display()))? + .to_path_buf()) +} + +/// Find the location of the current workspace, if this code works in workspace +/// then it will return the correct folder if, it's binary e.g. in docker container +/// you have to use fallback to another directory +/// The code has been inspired by `insta` +/// `https://github.com/mitsuhiko/insta/blob/master/insta/src/env.rs` +pub fn locate_workspace() -> Option<&'static Path> { + // Since `locate_workspace_inner()` should be deterministic, it makes little sense to call + // `OnceCell::get_or_try_init()` here; the repeated calls are just as unlikely to succeed as the initial call. + // Instead, we store `None` in the `OnceCell` if initialization failed. + WORKSPACE + .get_or_init(|| { + let result = locate_workspace_inner(); + if let Err(err) = &result { + // `get_or_init()` is guaranteed to call the provided closure once per `OnceCell`; + // i.e., we won't spam logs here. + tracing::warn!("locate_workspace() failed: {err:?}"); + } + result.ok() + }) + .as_deref() +} + +/// Returns [`locate_workspace()`] output with the "." fallback. +pub fn workspace_dir_or_current_dir() -> &'static Path { + locate_workspace().unwrap_or_else(|| Path::new(".")) +} diff --git a/core/lib/utils/src/lib.rs b/core/lib/utils/src/lib.rs index df26dbf6ab88..1c17d4efe264 100644 --- a/core/lib/utils/src/lib.rs +++ b/core/lib/utils/src/lib.rs @@ -2,6 +2,7 @@ pub mod bytecode; mod convert; +mod env; pub mod http_with_retries; pub mod misc; pub mod panic_extractor; @@ -9,6 +10,4 @@ mod serde_wrappers; pub mod time; pub mod wait_for_tasks; -pub use convert::*; -pub use misc::*; -pub use serde_wrappers::*; +pub use self::{convert::*, env::*, misc::*, serde_wrappers::*}; diff --git a/core/tests/loadnext/src/config.rs b/core/tests/loadnext/src/config.rs index c8487e4d595e..7f3e1e258305 100644 --- a/core/tests/loadnext/src/config.rs +++ b/core/tests/loadnext/src/config.rs @@ -4,6 +4,7 @@ use serde::Deserialize; use tokio::sync::Semaphore; use zksync_contracts::test_contracts::LoadnextContractExecutionParams; use zksync_types::{network::Network, Address, L2ChainId, H160}; +use zksync_utils::workspace_dir_or_current_dir; use crate::fs_utils::read_tokens; @@ -189,14 +190,8 @@ fn default_main_token() -> H160 { } fn default_test_contracts_path() -> PathBuf { - let test_contracts_path = { - let home = std::env::var("ZKSYNC_HOME").unwrap(); - let path = PathBuf::from(&home); - path.join("etc/contracts-test-data") - }; - + let test_contracts_path = workspace_dir_or_current_dir().join("etc/contracts-test-data"); tracing::info!("Test contracts path: {}", test_contracts_path.display()); - test_contracts_path } @@ -346,3 +341,16 @@ impl RequestLimiters { } } } + +#[cfg(test)] +mod tests { + + use super::*; + use crate::fs_utils::loadnext_contract; + + #[test] + fn check_read_test_contract() { + let test_contracts_path = default_test_contracts_path(); + loadnext_contract(&test_contracts_path).unwrap(); + } +} diff --git a/core/tests/loadnext/src/fs_utils.rs b/core/tests/loadnext/src/fs_utils.rs index 9fee9916f916..8af9df8afee7 100644 --- a/core/tests/loadnext/src/fs_utils.rs +++ b/core/tests/loadnext/src/fs_utils.rs @@ -5,6 +5,7 @@ use std::{fs::File, io::BufReader, path::Path}; use serde::Deserialize; use zksync_types::{ethabi::Contract, network::Network, Address}; +use zksync_utils::workspace_dir_or_current_dir; /// A token stored in `etc/tokens/{network}.json` files. #[derive(Debug, Deserialize)] @@ -26,10 +27,8 @@ pub struct TestContract { } pub fn read_tokens(network: Network) -> anyhow::Result> { - let home = std::env::var("ZKSYNC_HOME")?; - let path = Path::new(&home); - let path = path.join(format!("etc/tokens/{network}.json")); - + let home = workspace_dir_or_current_dir(); + let path = home.join(format!("etc/tokens/{network}.json")); let file = File::open(path)?; let reader = BufReader::new(file); @@ -86,21 +85,3 @@ pub fn loadnext_contract(path: &Path) -> anyhow::Result { let path = path.join("artifacts-zk/contracts/loadnext/loadnext_contract.sol"); read_contract_dir(&path) } - -#[cfg(test)] -mod tests { - use std::path::PathBuf; - - use super::*; - - #[test] - fn check_read_test_contract() { - let test_contracts_path = { - let home = std::env::var("ZKSYNC_HOME").unwrap(); - let path = PathBuf::from(&home); - path.join("etc/contracts-test-data") - }; - - loadnext_contract(&test_contracts_path).unwrap(); - } -} diff --git a/prover/Cargo.lock b/prover/Cargo.lock index 1746f8c2323e..89cb099cfa3c 100644 --- a/prover/Cargo.lock +++ b/prover/Cargo.lock @@ -7090,6 +7090,7 @@ dependencies = [ "zksync_env_config", "zksync_prover_fri_types", "zksync_types", + "zksync_utils", ] [[package]] @@ -8450,8 +8451,10 @@ dependencies = [ "hex", "itertools 0.10.5", "num", + "once_cell", "reqwest", "serde", + "serde_json", "thiserror", "tokio", "tracing", diff --git a/prover/vk_setup_data_generator_server_fri/Cargo.toml b/prover/vk_setup_data_generator_server_fri/Cargo.toml index c7309ee98f37..bda9dafe3de6 100644 --- a/prover/vk_setup_data_generator_server_fri/Cargo.toml +++ b/prover/vk_setup_data_generator_server_fri/Cargo.toml @@ -22,9 +22,10 @@ path = "src/lib.rs" [dependencies] vlog.workspace = true zksync_types.workspace = true +zksync_utils.workspace = true zksync_prover_fri_types.workspace = true zkevm_test_harness.workspace = true -circuit_definitions = { workspace = true, features = [ "log_tracing" ] } +circuit_definitions = { workspace = true, features = ["log_tracing"] } shivini = { workspace = true, optional = true } zksync_config.workspace = true zksync_env_config.workspace = true diff --git a/prover/vk_setup_data_generator_server_fri/src/keystore.rs b/prover/vk_setup_data_generator_server_fri/src/keystore.rs index 21ca42ba3a38..d68957353aac 100644 --- a/prover/vk_setup_data_generator_server_fri/src/keystore.rs +++ b/prover/vk_setup_data_generator_server_fri/src/keystore.rs @@ -1,7 +1,7 @@ use std::{ fs::{self, File}, io::Read, - path::Path, + path::{Path, PathBuf}, }; use anyhow::Context as _; @@ -20,6 +20,7 @@ use zksync_config::configs::FriProverConfig; use zksync_env_config::FromEnv; use zksync_prover_fri_types::ProverServiceDataKey; use zksync_types::basic_fri_types::AggregationRound; +use zksync_utils::workspace_dir_or_current_dir; #[cfg(feature = "gpu")] use crate::GoldilocksGpuProverSetupData; @@ -38,17 +39,13 @@ pub enum ProverServiceDataType { /// - large setup keys, used during proving. pub struct Keystore { /// Directory to store all the small keys. - basedir: String, + basedir: PathBuf, /// Directory to store large setup keys. setup_data_path: Option, } -fn get_base_path_from_env() -> String { - let zksync_home = std::env::var("ZKSYNC_HOME").unwrap_or_else(|_| "/".into()); - format!( - "{}/prover/vk_setup_data_generator_server_fri/data", - zksync_home - ) +fn get_base_path_from_env() -> PathBuf { + workspace_dir_or_current_dir().join("vk_setup_data_generator_server_fri/data") } impl Default for Keystore { @@ -67,20 +64,20 @@ impl Default for Keystore { impl Keystore { /// Base-dir is the location of smaller keys (like verification keys and finalization hints). /// Setup data path is used for the large setup keys. - pub fn new(basedir: String, setup_data_path: String) -> Self { + pub fn new(basedir: PathBuf, setup_data_path: String) -> Self { Keystore { basedir, setup_data_path: Some(setup_data_path), } } - pub fn new_with_optional_setup_path(basedir: String, setup_data_path: Option) -> Self { + pub fn new_with_optional_setup_path(basedir: PathBuf, setup_data_path: Option) -> Self { Keystore { basedir, setup_data_path, } } - pub fn get_base_path(&self) -> &str { + pub fn get_base_path(&self) -> &PathBuf { &self.basedir } @@ -88,43 +85,49 @@ impl Keystore { &self, key: ProverServiceDataKey, service_data_type: ProverServiceDataType, - ) -> String { + ) -> PathBuf { let name = key.name(); match service_data_type { ProverServiceDataType::VerificationKey => { - format!("{}/verification_{}_key.json", self.basedir, name) - } - ProverServiceDataType::SetupData => { - format!( - "{}/setup_{}_data.bin", - self.setup_data_path - .as_ref() - .expect("Setup data path not set"), - name - ) - } - ProverServiceDataType::FinalizationHints => { - format!("{}/finalization_hints_{}.bin", self.basedir, name) - } - ProverServiceDataType::SnarkVerificationKey => { - format!("{}/snark_verification_{}_key.json", self.basedir, name) + self.basedir.join(format!("verification_{}_key.json", name)) } + ProverServiceDataType::SetupData => PathBuf::from(format!( + "{}/setup_{}_data.bin", + self.setup_data_path + .as_ref() + .expect("Setup data path not set"), + name + )), + ProverServiceDataType::FinalizationHints => self + .basedir + .join(format!("finalization_hints_{}.bin", name)), + ProverServiceDataType::SnarkVerificationKey => self + .basedir + .join(format!("snark_verification_{}_key.json", name)), } } - fn load_json_from_file Deserialize<'a>>(filepath: String) -> anyhow::Result { + fn load_json_from_file Deserialize<'a>>( + filepath: impl AsRef + std::fmt::Debug, + ) -> anyhow::Result { let text = std::fs::read_to_string(&filepath) - .with_context(|| format!("Failed reading verification key from path: {filepath}"))?; - serde_json::from_str::(&text) - .with_context(|| format!("Failed deserializing verification key from path: {filepath}")) + .with_context(|| format!("Failed reading verification key from path: {filepath:?}"))?; + serde_json::from_str::(&text).with_context(|| { + format!("Failed deserializing verification key from path: {filepath:?}") + }) } - fn save_json_pretty(filepath: String, data: &T) -> anyhow::Result<()> { + fn save_json_pretty( + filepath: impl AsRef + std::fmt::Debug, + data: &T, + ) -> anyhow::Result<()> { std::fs::write(&filepath, serde_json::to_string_pretty(data).unwrap()) - .with_context(|| format!("writing to '{filepath}' failed")) + .with_context(|| format!("writing to '{filepath:?}' failed")) } - fn load_bincode_from_file Deserialize<'a>>(filepath: String) -> anyhow::Result { - let mut file = File::open(filepath.clone()) + fn load_bincode_from_file Deserialize<'a>>( + filepath: impl AsRef + std::fmt::Debug, + ) -> anyhow::Result { + let mut file = File::open(&filepath) .with_context(|| format!("Failed reading setup-data from path: {filepath:?}"))?; let mut buffer = Vec::new(); file.read_to_end(&mut buffer).with_context(|| { @@ -166,7 +169,7 @@ impl Keystore { ProverServiceDataKey::new(vk.numeric_circuit_type(), AggregationRound::BasicCircuits), ProverServiceDataType::VerificationKey, ); - tracing::info!("saving basic verification key to: {}", filepath); + tracing::info!("saving basic verification key to: {:?}", filepath); Self::save_json_pretty(filepath, &vk) } @@ -178,7 +181,7 @@ impl Keystore { ProverServiceDataKey::new_recursive(vk.numeric_circuit_type()), ProverServiceDataType::VerificationKey, ); - tracing::info!("saving recursive layer verification key to: {}", filepath); + tracing::info!("saving recursive layer verification key to: {:?}", filepath); Self::save_json_pretty(filepath, &vk) } @@ -193,7 +196,7 @@ impl Keystore { ) -> anyhow::Result<()> { let filepath = self.get_file_path(key.clone(), ProverServiceDataType::FinalizationHints); - tracing::info!("saving finalization hints for {:?} to: {}", key, filepath); + tracing::info!("saving finalization hints for {:?} to: {:?}", key, filepath); let serialized = bincode::serialize(&hint).context("Failed to serialize finalization hints")?; fs::write(filepath, serialized).context("Failed to write finalization hints to file") @@ -227,8 +230,9 @@ impl Keystore { ProverServiceDataKey::snark(), ProverServiceDataType::SnarkVerificationKey, ); - std::fs::read_to_string(&filepath) - .with_context(|| format!("Failed reading Snark verification key from path: {filepath}")) + std::fs::read_to_string(&filepath).with_context(|| { + format!("Failed reading Snark verification key from path: {filepath:?}") + }) } pub fn save_snark_verification_key(&self, vk: ZkSyncSnarkWrapperVK) -> anyhow::Result<()> { @@ -236,7 +240,7 @@ impl Keystore { ProverServiceDataKey::snark(), ProverServiceDataType::SnarkVerificationKey, ); - tracing::info!("saving snark verification key to: {}", filepath); + tracing::info!("saving snark verification key to: {:?}", filepath); Self::save_json_pretty(filepath, &vk.into_inner()) } @@ -256,7 +260,7 @@ impl Keystore { file.read_to_end(&mut buffer).with_context(|| { format!("Failed reading setup-data to buffer from path: {filepath:?}") })?; - tracing::info!("loading {:?} setup data from path: {}", key, filepath); + tracing::info!("loading {:?} setup data from path: {:?}", key, filepath); bincode::deserialize::(&buffer).with_context(|| { format!("Failed deserializing setup-data at path: {filepath:?} for circuit: {key:?}") }) @@ -275,7 +279,7 @@ impl Keystore { file.read_to_end(&mut buffer).with_context(|| { format!("Failed reading setup-data to buffer from path: {filepath:?}") })?; - tracing::info!("loading {:?} setup data from path: {}", key, filepath); + tracing::info!("loading {:?} setup data from path: {:?}", key, filepath); bincode::deserialize::(&buffer).with_context(|| { format!("Failed deserializing setup-data at path: {filepath:?} for circuit: {key:?}") }) @@ -291,7 +295,7 @@ impl Keystore { serialized_setup_data: &Vec, ) -> anyhow::Result<()> { let filepath = self.get_file_path(key.clone(), ProverServiceDataType::SetupData); - tracing::info!("saving {:?} setup data to: {}", key, filepath); + tracing::info!("saving {:?} setup data to: {:?}", key, filepath); std::fs::write(filepath.clone(), serialized_setup_data) .with_context(|| format!("Failed saving setup-data at path: {filepath:?}")) } @@ -440,12 +444,9 @@ impl Keystore { } pub fn load_commitments(&self) -> anyhow::Result { - Self::load_json_from_file(format!("{}/commitments.json", self.get_base_path())) + Self::load_json_from_file(self.get_base_path().join("commitments.json")) } pub fn save_commitments(&self, commitments: &VkCommitments) -> anyhow::Result<()> { - Self::save_json_pretty( - format!("{}/commitments.json", self.get_base_path()), - &commitments, - ) + Self::save_json_pretty(self.get_base_path().join("commitments.json"), &commitments) } } diff --git a/prover/vk_setup_data_generator_server_fri/src/main.rs b/prover/vk_setup_data_generator_server_fri/src/main.rs index ce3a0799baa0..4cf7aa1abb30 100644 --- a/prover/vk_setup_data_generator_server_fri/src/main.rs +++ b/prover/vk_setup_data_generator_server_fri/src/main.rs @@ -158,7 +158,7 @@ fn print_stats(digests: HashMap) -> anyhow::Result<()> { fn keystore_from_optional_path(path: Option, setup_path: Option) -> Keystore { if let Some(path) = path { - return Keystore::new_with_optional_setup_path(path, setup_path); + return Keystore::new_with_optional_setup_path(path.into(), setup_path); } if setup_path.is_some() { panic!("--setup_path must not be set when --path is not set"); diff --git a/prover/vk_setup_data_generator_server_fri/src/tests.rs b/prover/vk_setup_data_generator_server_fri/src/tests.rs index 41aba88f784c..39b5f7a44fb8 100644 --- a/prover/vk_setup_data_generator_server_fri/src/tests.rs +++ b/prover/vk_setup_data_generator_server_fri/src/tests.rs @@ -63,15 +63,6 @@ proptest! { } -// Test `get_base_path` method -#[test] -fn test_get_base_path() { - let keystore = Keystore::default(); - - let base_path = keystore.get_base_path(); - assert!(!base_path.is_empty(), "Base path should not be empty"); -} - // Test `ProverServiceDataKey::new` method #[test] fn test_proverservicedatakey_new() { diff --git a/prover/vk_setup_data_generator_server_fri/src/utils.rs b/prover/vk_setup_data_generator_server_fri/src/utils.rs index 555204eb9e2b..a1fa832df8a5 100644 --- a/prover/vk_setup_data_generator_server_fri/src/utils.rs +++ b/prover/vk_setup_data_generator_server_fri/src/utils.rs @@ -114,21 +114,18 @@ pub fn calculate_snark_vk_hash(keystore: &Keystore) -> anyhow::Result { #[cfg(test)] mod tests { - use std::{env, path::PathBuf, str::FromStr}; + use std::{path::PathBuf, str::FromStr}; use super::*; #[test] fn test_keyhash_generation() { - let mut path_to_input = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()); + let mut path_to_input = PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap()); path_to_input.push("historical_data"); for version in 18..=22 { let basepath = path_to_input.join(format!("{}", version)); - let keystore = Keystore::new_with_optional_setup_path( - basepath.as_os_str().to_str().unwrap().to_string(), - None, - ); + let keystore = Keystore::new_with_optional_setup_path(basepath, None); let expected = H256::from_str(&keystore.load_commitments().unwrap().snark_wrapper).unwrap(); diff --git a/prover/vk_setup_data_generator_server_fri/src/vk_commitment_helper.rs b/prover/vk_setup_data_generator_server_fri/src/vk_commitment_helper.rs index 9a6c074b1d23..5a2c274d4674 100644 --- a/prover/vk_setup_data_generator_server_fri/src/vk_commitment_helper.rs +++ b/prover/vk_setup_data_generator_server_fri/src/vk_commitment_helper.rs @@ -1,7 +1,8 @@ -use std::fs; +use std::{fs, path::PathBuf}; use anyhow::Context as _; use toml_edit::{Document, Item, Value}; +use zksync_utils::workspace_dir_or_current_dir; pub fn get_toml_formatted_value(string_value: String) -> Item { let mut value = Value::from(string_value); @@ -17,11 +18,10 @@ pub fn write_contract_toml(contract_doc: Document) -> anyhow::Result<()> { pub fn read_contract_toml() -> anyhow::Result { let path = get_contract_toml_path(); let toml_data = std::fs::read_to_string(path.clone()) - .with_context(|| format!("contract.toml file does not exist on path {path}"))?; + .with_context(|| format!("contract.toml file does not exist on path {path:?}"))?; toml_data.parse::().context("invalid config file") } -pub fn get_contract_toml_path() -> String { - let zksync_home = std::env::var("ZKSYNC_HOME").unwrap_or_else(|_| "/".into()); - format!("{}/etc/env/base/contracts.toml", zksync_home) +pub fn get_contract_toml_path() -> PathBuf { + workspace_dir_or_current_dir().join("../etc/env/base/contracts.toml") }