From d17715d8c714b6a3417d35755f83382ee91092b5 Mon Sep 17 00:00:00 2001 From: Danil Date: Thu, 11 Apr 2024 11:27:48 +0200 Subject: [PATCH 01/13] chore(env): USE CARGO_MANIFEST_DIR instead of zksync home from server Signed-off-by: Danil --- core/bin/contract-verifier/src/main.rs | 2 +- core/bin/contract-verifier/src/verifier.rs | 4 ++-- .../system-constants-generator/src/main.rs | 2 +- core/lib/contracts/src/lib.rs | 20 +++++++++---------- core/lib/types/src/system_contracts.rs | 2 +- core/tests/loadnext/src/config.rs | 2 +- core/tests/loadnext/src/fs_utils.rs | 4 ++-- .../src/keystore.rs | 2 +- .../src/vk_commitment_helper.rs | 2 +- 9 files changed, 20 insertions(+), 20 deletions(-) diff --git a/core/bin/contract-verifier/src/main.rs b/core/bin/contract-verifier/src/main.rs index 01c0dc568af8..7c5a6404dd1b 100644 --- a/core/bin/contract-verifier/src/main.rs +++ b/core/bin/contract-verifier/src/main.rs @@ -24,7 +24,7 @@ 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 = std::env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| ".".into()); let zksolc_path = format!("{}/etc/zksolc-bin/", zksync_home); let zksolc_versions: Vec = std::fs::read_dir(zksolc_path) diff --git a/core/bin/contract-verifier/src/verifier.rs b/core/bin/contract-verifier/src/verifier.rs index 66e7b6deebbb..3c47bc26d7b2 100644 --- a/core/bin/contract-verifier/src/verifier.rs +++ b/core/bin/contract-verifier/src/verifier.rs @@ -119,7 +119,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 zksync_home = env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| ".".into()); let zksolc_path = Path::new(&zksync_home) .join("etc") .join("zksolc-bin") @@ -218,7 +218,7 @@ impl ContractVerifier { }; let input = Self::build_zkvyper_input(request.clone())?; - let zksync_home = env::var("ZKSYNC_HOME").unwrap_or_else(|_| ".".into()); + let zksync_home = env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| ".".into()); let zkvyper_path = Path::new(&zksync_home) .join("etc") .join("zkvyper-bin") diff --git a/core/bin/system-constants-generator/src/main.rs b/core/bin/system-constants-generator/src/main.rs index 548d4c9a0ce1..63ad19a5ea6f 100644 --- a/core/bin/system-constants-generator/src/main.rs +++ b/core/bin/system-constants-generator/src/main.rs @@ -209,7 +209,7 @@ 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 zksync_home = "."; let fee_constants_path = format!("{zksync_home}/{path_in_repo}"); fs::write(fee_constants_path, content) diff --git a/core/lib/contracts/src/lib.rs b/core/lib/contracts/src/lib.rs index 20ec434c0bf4..2c817ca0f245 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 CARGO_MANIFEST_DIR environment variable. #![allow(clippy::derive_partial_eq_without_eq)] @@ -41,7 +41,7 @@ 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()); + let zksync_home = std::env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| ".".into()); 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)), @@ -50,7 +50,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 = std::env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| ".".into()); let path = Path::new(&zksync_home).join(path); path.exists().then(|| { serde_json::from_value(read_file_to_json_value(&path)["abi"].take()) @@ -126,9 +126,9 @@ pub fn l1_messenger_contract() -> Contract { load_sys_contract("L1Messenger") } -/// Reads bytecode from the path RELATIVE to the ZKSYNC_HOME environment variable. +/// Reads bytecode from the path RELATIVE to the CARGO_MANIFEST_DIR environment variable. pub fn read_bytecode(relative_path: impl AsRef) -> Vec { - let zksync_home = std::env::var("ZKSYNC_HOME").unwrap_or_else(|_| ".".into()); + let zksync_home = std::env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| ".".into()); let artifact_path = Path::new(&zksync_home).join(relative_path); read_bytecode_from_path(artifact_path) } @@ -156,16 +156,16 @@ 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 CARGO_MANIFEST_DIR environment variable. 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_MANIFEST_DIR environment variable. pub fn from_env() -> Self { - let zksync_home = std::env::var("ZKSYNC_HOME").unwrap_or_else(|_| ".".into()); + let zksync_home = std::env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| ".".into()); let zksync_home = PathBuf::from(zksync_home); SystemContractsRepo { root: zksync_home.join("contracts/system-contracts"), @@ -206,9 +206,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 CARGO_MANIFEST_DIR. pub fn read_zbin_bytecode(relative_zbin_path: impl AsRef) -> Vec { - let zksync_home = std::env::var("ZKSYNC_HOME").unwrap_or_else(|_| ".".into()); + let zksync_home = std::env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| ".".into()); let bytecode_path = Path::new(&zksync_home).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 936a4a192798..e1952ce16186 100644 --- a/core/lib/types/src/system_contracts.rs +++ b/core/lib/types/src/system_contracts.rs @@ -174,7 +174,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_MANIFEST_DIR environment variable. pub fn get_system_smart_contracts() -> Vec { SYSTEM_CONTRACTS.clone() } diff --git a/core/tests/loadnext/src/config.rs b/core/tests/loadnext/src/config.rs index c8487e4d595e..74d41660e6ad 100644 --- a/core/tests/loadnext/src/config.rs +++ b/core/tests/loadnext/src/config.rs @@ -190,7 +190,7 @@ fn default_main_token() -> H160 { fn default_test_contracts_path() -> PathBuf { let test_contracts_path = { - let home = std::env::var("ZKSYNC_HOME").unwrap(); + let home = std::env::var("CARGO_MANIFEST_DIR").unwrap(); let path = PathBuf::from(&home); path.join("etc/contracts-test-data") }; diff --git a/core/tests/loadnext/src/fs_utils.rs b/core/tests/loadnext/src/fs_utils.rs index 9fee9916f916..76aebf4b3256 100644 --- a/core/tests/loadnext/src/fs_utils.rs +++ b/core/tests/loadnext/src/fs_utils.rs @@ -26,7 +26,7 @@ pub struct TestContract { } pub fn read_tokens(network: Network) -> anyhow::Result> { - let home = std::env::var("ZKSYNC_HOME")?; + let home = std::env::var("CARGO_MANIFEST_DIR")?; let path = Path::new(&home); let path = path.join(format!("etc/tokens/{network}.json")); @@ -96,7 +96,7 @@ mod tests { #[test] fn check_read_test_contract() { let test_contracts_path = { - let home = std::env::var("ZKSYNC_HOME").unwrap(); + let home = std::env::var("CARGO_MANIFEST_DIR").unwrap(); let path = PathBuf::from(&home); path.join("etc/contracts-test-data") }; 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 aace09a8757e..7998b8239ca5 100644 --- a/prover/vk_setup_data_generator_server_fri/src/keystore.rs +++ b/prover/vk_setup_data_generator_server_fri/src/keystore.rs @@ -44,7 +44,7 @@ pub struct Keystore { } fn get_base_path_from_env() -> String { - let zksync_home = std::env::var("ZKSYNC_HOME").unwrap_or_else(|_| "/".into()); + let zksync_home = std::env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| "/".into()); format!( "{}/prover/vk_setup_data_generator_server_fri/data", zksync_home 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..c821053637dd 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 @@ -22,6 +22,6 @@ pub fn read_contract_toml() -> anyhow::Result { } pub fn get_contract_toml_path() -> String { - let zksync_home = std::env::var("ZKSYNC_HOME").unwrap_or_else(|_| "/".into()); + let zksync_home = std::env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| "/".into()); format!("{}/etc/env/base/contracts.toml", zksync_home) } From 24e043abe19b6bbe8b69d8ce3f73ba9432afeb6c Mon Sep 17 00:00:00 2001 From: Danil Date: Thu, 11 Apr 2024 12:34:26 +0200 Subject: [PATCH 02/13] Adapt code for cargo manifest usage Signed-off-by: Danil --- core/bin/contract-verifier/src/main.rs | 4 +++- core/bin/contract-verifier/src/verifier.rs | 8 ++++++-- core/lib/contracts/src/lib.rs | 20 +++++++++++++++----- core/tests/loadnext/src/config.rs | 2 +- core/tests/loadnext/src/fs_utils.rs | 5 +++-- 5 files changed, 28 insertions(+), 11 deletions(-) diff --git a/core/bin/contract-verifier/src/main.rs b/core/bin/contract-verifier/src/main.rs index 7c5a6404dd1b..461e142702e4 100644 --- a/core/bin/contract-verifier/src/main.rs +++ b/core/bin/contract-verifier/src/main.rs @@ -24,7 +24,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("CARGO_MANIFEST_DIR").unwrap_or_else(|_| ".".into()); + let zksync_home = std::env::var("CARGO_MANIFEST_DIR") + .map(|a| format!("{}/../../", a)) + .unwrap_or_else(|_| ".".into()); let zksolc_path = format!("{}/etc/zksolc-bin/", zksync_home); let zksolc_versions: Vec = std::fs::read_dir(zksolc_path) diff --git a/core/bin/contract-verifier/src/verifier.rs b/core/bin/contract-verifier/src/verifier.rs index 3c47bc26d7b2..9898a7d1a253 100644 --- a/core/bin/contract-verifier/src/verifier.rs +++ b/core/bin/contract-verifier/src/verifier.rs @@ -119,7 +119,9 @@ impl ContractVerifier { }; let input = Self::build_zksolc_input(request.clone(), file_name.clone())?; - let zksync_home = env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| ".".into()); + let zksync_home = std::env::var("CARGO_MANIFEST_DIR") + .map(|a| format!("{}/../../", a)) + .unwrap_or_else(|_| ".".into()); let zksolc_path = Path::new(&zksync_home) .join("etc") .join("zksolc-bin") @@ -218,7 +220,9 @@ impl ContractVerifier { }; let input = Self::build_zkvyper_input(request.clone())?; - let zksync_home = env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| ".".into()); + let zksync_home = std::env::var("CARGO_MANIFEST_DIR") + .map(|a| format!("{}/../../", a)) + .unwrap_or_else(|_| ".".into()); let zkvyper_path = Path::new(&zksync_home) .join("etc") .join("zkvyper-bin") diff --git a/core/lib/contracts/src/lib.rs b/core/lib/contracts/src/lib.rs index 2c817ca0f245..5993d7962be2 100644 --- a/core/lib/contracts/src/lib.rs +++ b/core/lib/contracts/src/lib.rs @@ -41,7 +41,9 @@ 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("CARGO_MANIFEST_DIR").unwrap_or_else(|_| ".".into()); + let zksync_home = std::env::var("CARGO_MANIFEST_DIR") + .map(|a| format!("{a}/../../../")) + .unwrap_or_else(|_| ".".into()); 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)), @@ -50,7 +52,9 @@ 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("CARGO_MANIFEST_DIR").unwrap_or_else(|_| ".".into()); + let zksync_home = std::env::var("CARGO_MANIFEST_DIR") + .map(|a| format!("{a}/../../../")) + .unwrap_or_else(|_| ".".into()); let path = Path::new(&zksync_home).join(path); path.exists().then(|| { serde_json::from_value(read_file_to_json_value(&path)["abi"].take()) @@ -128,7 +132,9 @@ pub fn l1_messenger_contract() -> Contract { /// Reads bytecode from the path RELATIVE to the CARGO_MANIFEST_DIR environment variable. pub fn read_bytecode(relative_path: impl AsRef) -> Vec { - let zksync_home = std::env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| ".".into()); + let zksync_home = std::env::var("CARGO_MANIFEST_DIR") + .map(|a| format!("{a}/../../../")) + .unwrap_or_else(|_| ".".into()); let artifact_path = Path::new(&zksync_home).join(relative_path); read_bytecode_from_path(artifact_path) } @@ -165,7 +171,9 @@ pub struct SystemContractsRepo { impl SystemContractsRepo { /// Returns the default system contracts repository with directory based on the CARGO_MANIFEST_DIR environment variable. pub fn from_env() -> Self { - let zksync_home = std::env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| ".".into()); + let zksync_home = std::env::var("CARGO_MANIFEST_DIR") + .map(|a| format!("{a}/../../../")) + .unwrap_or_else(|_| ".".into()); let zksync_home = PathBuf::from(zksync_home); SystemContractsRepo { root: zksync_home.join("contracts/system-contracts"), @@ -208,7 +216,9 @@ fn read_playground_batch_bootloader_bytecode() -> Vec { /// Reads zbin bytecode from a given path, relative to CARGO_MANIFEST_DIR. pub fn read_zbin_bytecode(relative_zbin_path: impl AsRef) -> Vec { - let zksync_home = std::env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| ".".into()); + let zksync_home = std::env::var("CARGO_MANIFEST_DIR") + .map(|a| format!("{a}/../../../")) + .unwrap_or_else(|_| ".".into()); let bytecode_path = Path::new(&zksync_home).join(relative_zbin_path); read_zbin_bytecode_from_path(bytecode_path) } diff --git a/core/tests/loadnext/src/config.rs b/core/tests/loadnext/src/config.rs index 74d41660e6ad..feed83a52609 100644 --- a/core/tests/loadnext/src/config.rs +++ b/core/tests/loadnext/src/config.rs @@ -192,7 +192,7 @@ fn default_test_contracts_path() -> PathBuf { let test_contracts_path = { let home = std::env::var("CARGO_MANIFEST_DIR").unwrap(); let path = PathBuf::from(&home); - path.join("etc/contracts-test-data") + path.join("../../../etc/contracts-test-data") }; tracing::info!("Test contracts path: {}", test_contracts_path.display()); diff --git a/core/tests/loadnext/src/fs_utils.rs b/core/tests/loadnext/src/fs_utils.rs index 76aebf4b3256..ce993d39e61d 100644 --- a/core/tests/loadnext/src/fs_utils.rs +++ b/core/tests/loadnext/src/fs_utils.rs @@ -28,7 +28,7 @@ pub struct TestContract { pub fn read_tokens(network: Network) -> anyhow::Result> { let home = std::env::var("CARGO_MANIFEST_DIR")?; let path = Path::new(&home); - let path = path.join(format!("etc/tokens/{network}.json")); + let path = path.join(format!("../../../etc/tokens/{network}.json")); let file = File::open(path)?; let reader = BufReader::new(file); @@ -98,7 +98,8 @@ mod tests { let test_contracts_path = { let home = std::env::var("CARGO_MANIFEST_DIR").unwrap(); let path = PathBuf::from(&home); - path.join("etc/contracts-test-data") + let a = path.join("../../../etc/contracts-test-data"); + dbg!(a) }; loadnext_contract(&test_contracts_path).unwrap(); From f8dab9db9f7367db50abb2078d22e02ba799e579 Mon Sep 17 00:00:00 2001 From: Danil Date: Thu, 11 Apr 2024 21:12:45 +0200 Subject: [PATCH 03/13] use workspace load Signed-off-by: Danil --- core/bin/contract-verifier/src/main.rs | 13 +++-- core/bin/contract-verifier/src/verifier.rs | 22 ++++----- .../system-constants-generator/src/main.rs | 5 +- core/lib/contracts/src/lib.rs | 49 +++++++------------ core/lib/types/src/system_contracts.rs | 2 +- core/lib/utils/Cargo.toml | 2 +- core/lib/utils/src/env.rs | 31 ++++++++++++ core/lib/utils/src/lib.rs | 2 + core/tests/loadnext/src/config.rs | 7 +-- core/tests/loadnext/src/fs_utils.rs | 11 ++--- prover/Cargo.lock | 1 + .../src/keystore.rs | 13 +++-- .../src/utils.rs | 3 +- .../src/vk_commitment_helper.rs | 6 ++- 14 files changed, 95 insertions(+), 72 deletions(-) create mode 100644 core/lib/utils/src/env.rs diff --git a/core/bin/contract-verifier/src/main.rs b/core/bin/contract-verifier/src/main.rs index 461e142702e4..8449b38610d0 100644 --- a/core/bin/contract-verifier/src/main.rs +++ b/core/bin/contract-verifier/src/main.rs @@ -24,11 +24,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("CARGO_MANIFEST_DIR") - .map(|a| format!("{}/../../", a)) - .unwrap_or_else(|_| ".".into()); + let zksync_home = locate_workspace().unwrap_or_else(|| ".".into()); - 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| { @@ -49,7 +47,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| { @@ -70,7 +68,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| { @@ -91,7 +89,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| { @@ -117,6 +115,7 @@ async fn update_compiler_versions(connection_pool: &ConnectionPool) { } use structopt::StructOpt; +use zksync_utils::locate_workspace; #[derive(StructOpt)] #[structopt(name = "zkSync contract code verifier", author = "Matter Labs")] diff --git a/core/bin/contract-verifier/src/verifier.rs b/core/bin/contract-verifier/src/verifier.rs index 9898a7d1a253..4ba4ae215012 100644 --- a/core/bin/contract-verifier/src/verifier.rs +++ b/core/bin/contract-verifier/src/verifier.rs @@ -1,7 +1,6 @@ use std::{ collections::HashMap, - env, - path::Path, + path::{Path, PathBuf}, time::{Duration, Instant}, }; @@ -22,6 +21,7 @@ use zksync_types::{ }, Address, }; +use zksync_utils::locate_workspace; use crate::{ error::ContractVerifierError, @@ -33,6 +33,10 @@ lazy_static! { static ref DEPLOYER_CONTRACT: Contract = zksync_contracts::deployer_contract(); } +fn home_path() -> PathBuf { + locate_workspace().unwrap_or_else(|| ".".into()) +} + #[derive(Debug)] enum ConstructorArgs { Check(Vec), @@ -119,10 +123,7 @@ impl ContractVerifier { }; let input = Self::build_zksolc_input(request.clone(), file_name.clone())?; - let zksync_home = std::env::var("CARGO_MANIFEST_DIR") - .map(|a| format!("{}/../../", a)) - .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()) @@ -134,7 +135,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()) @@ -220,10 +221,7 @@ impl ContractVerifier { }; let input = Self::build_zkvyper_input(request.clone())?; - let zksync_home = std::env::var("CARGO_MANIFEST_DIR") - .map(|a| format!("{}/../../", a)) - .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()) @@ -235,7 +233,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 63ad19a5ea6f..2d929d03c627 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::locate_workspace; // 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 = "."; - let fee_constants_path = format!("{zksync_home}/{path_in_repo}"); + let zksync_home = locate_workspace().unwrap_or_else(|| ".".into()); + 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 5993d7962be2..f9e83c901384 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 CARGO_MANIFEST_DIR 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, locate_workspace}; pub mod test_contracts; @@ -40,10 +40,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("CARGO_MANIFEST_DIR") - .map(|a| format!("{a}/../../../")) - .unwrap_or_else(|_| ".".into()); +fn home_path() -> PathBuf { + locate_workspace().unwrap_or_else(|| ".".into()) +} + +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)), @@ -52,9 +54,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("CARGO_MANIFEST_DIR") - .map(|a| format!("{a}/../../../")) - .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()) @@ -130,18 +130,14 @@ pub fn l1_messenger_contract() -> Contract { load_sys_contract("L1Messenger") } -/// Reads bytecode from the path RELATIVE to the CARGO_MANIFEST_DIR environment variable. -pub fn read_bytecode(relative_path: impl AsRef) -> Vec { - let zksync_home = std::env::var("CARGO_MANIFEST_DIR") - .map(|a| format!("{a}/../../../")) - .unwrap_or_else(|_| ".".into()); - let artifact_path = Path::new(&zksync_home).join(relative_path); - read_bytecode_from_path(artifact_path) +/// Reads bytecode from the path RELATIVE to the workspace location environment variable. +pub fn read_bytecode(relative_path: impl AsRef + std::fmt::Debug) -> Vec { + read_bytecode_from_path(relative_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() @@ -162,21 +158,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 CARGO_MANIFEST_DIR environment variable. +/// As most of the static methods in this file, is loading data based on workspace location environment variable. 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 CARGO_MANIFEST_DIR environment variable. + /// Returns the default system contracts repository with directory based on the workspace location environment variable. pub fn from_env() -> Self { - let zksync_home = std::env::var("CARGO_MANIFEST_DIR") - .map(|a| format!("{a}/../../../")) - .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"), } } @@ -214,12 +206,9 @@ fn read_playground_batch_bootloader_bytecode() -> Vec { read_bootloader_code("playground_batch") } -/// Reads zbin bytecode from a given path, relative to CARGO_MANIFEST_DIR. +/// 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("CARGO_MANIFEST_DIR") - .map(|a| format!("{a}/../../../")) - .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 e1952ce16186..f879ab82d35d 100644 --- a/core/lib/types/src/system_contracts.rs +++ b/core/lib/types/src/system_contracts.rs @@ -174,7 +174,7 @@ static SYSTEM_CONTRACTS: Lazy> = Lazy::new(|| { .collect::>() }); -/// Gets default set of system contracts, based on CARGO_MANIFEST_DIR environment variable. +/// Gets default set of system contracts, based on workspace location environment variable. 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 564da8cd9ebb..f41b22d1b38a 100644 --- a/core/lib/utils/Cargo.toml +++ b/core/lib/utils/Cargo.toml @@ -25,8 +25,8 @@ futures.workspace = true hex.workspace = true reqwest = { workspace = true, features = ["blocking"] } itertools.workspace = true +serde_json.workspace = true [dev-dependencies] -serde_json.workspace = true rand.workspace = true tokio = { workspace = true, features = ["macros", "rt"] } diff --git a/core/lib/utils/src/env.rs b/core/lib/utils/src/env.rs new file mode 100644 index 000000000000..4a70ccd5cde9 --- /dev/null +++ b/core/lib/utils/src/env.rs @@ -0,0 +1,31 @@ +use std::{path::PathBuf, sync::Mutex}; + +static WORKSPACE: Mutex> = Mutex::new(None); + +pub fn locate_workspace() -> Option { + let mut workspace = WORKSPACE.lock().unwrap_or_else(|x| x.into_inner()); + if let Some(workspace) = workspace.clone() { + return Some(workspace); + }; + + let output = std::process::Command::new( + std::env::var("CARGO") + .ok() + .unwrap_or_else(|| "cargo".to_string()), + ) + .arg("locate-project") + .arg("--workspace") + .output() + .ok()?; + let root = serde_json::from_slice::(&output.stdout) + .ok()? + .get("root") + .cloned()?; + + let serde_json::Value::String(root) = root else { + return None; + }; + let val = Some(PathBuf::from(root).parent()?.to_path_buf()); + *workspace = val; + workspace.clone() +} diff --git a/core/lib/utils/src/lib.rs b/core/lib/utils/src/lib.rs index df26dbf6ab88..46c0765d73f6 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; @@ -10,5 +11,6 @@ pub mod time; pub mod wait_for_tasks; pub use convert::*; +pub use env::*; pub use misc::*; pub use serde_wrappers::*; diff --git a/core/tests/loadnext/src/config.rs b/core/tests/loadnext/src/config.rs index feed83a52609..021da427143e 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::locate_workspace; use crate::fs_utils::read_tokens; @@ -190,9 +191,9 @@ fn default_main_token() -> H160 { fn default_test_contracts_path() -> PathBuf { let test_contracts_path = { - let home = std::env::var("CARGO_MANIFEST_DIR").unwrap(); - let path = PathBuf::from(&home); - path.join("../../../etc/contracts-test-data") + locate_workspace() + .unwrap_or_else(|| ".".into()) + .join("etc/contracts-test-data") }; tracing::info!("Test contracts path: {}", test_contracts_path.display()); diff --git a/core/tests/loadnext/src/fs_utils.rs b/core/tests/loadnext/src/fs_utils.rs index ce993d39e61d..2605693125de 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::locate_workspace; /// A token stored in `etc/tokens/{network}.json` files. #[derive(Debug, Deserialize)] @@ -26,9 +27,9 @@ pub struct TestContract { } pub fn read_tokens(network: Network) -> anyhow::Result> { - let home = std::env::var("CARGO_MANIFEST_DIR")?; + let home = locate_workspace().unwrap_or(".".into()); let path = Path::new(&home); - let path = path.join(format!("../../../etc/tokens/{network}.json")); + let path = path.join(format!("etc/tokens/{network}.json")); let file = File::open(path)?; let reader = BufReader::new(file); @@ -89,16 +90,14 @@ pub fn loadnext_contract(path: &Path) -> anyhow::Result { #[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("CARGO_MANIFEST_DIR").unwrap(); - let path = PathBuf::from(&home); - let a = path.join("../../../etc/contracts-test-data"); + let path = locate_workspace().unwrap_or(".".into()); + let a = path.join("etc/contracts-test-data"); dbg!(a) }; diff --git a/prover/Cargo.lock b/prover/Cargo.lock index a0d1b1dcb840..2eb1a7998c9f 100644 --- a/prover/Cargo.lock +++ b/prover/Cargo.lock @@ -7970,6 +7970,7 @@ dependencies = [ "num", "reqwest", "serde", + "serde_json", "thiserror", "tokio", "tracing", 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 7998b8239ca5..07da4d62f83c 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::locate_workspace; #[cfg(feature = "gpu")] use crate::GoldilocksGpuProverSetupData; @@ -43,12 +44,10 @@ pub struct Keystore { setup_data_path: Option, } -fn get_base_path_from_env() -> String { - let zksync_home = std::env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| "/".into()); - format!( - "{}/prover/vk_setup_data_generator_server_fri/data", - zksync_home - ) +fn get_base_path_from_env() -> PathBuf { + locate_workspace() + .unwrap_or_else(|_| ".".into()) + .join("/prover/vk_setup_data_generator_server_fri/data") } impl Default for Keystore { 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 40eca014714b..90d7ed6727c2 100644 --- a/prover/vk_setup_data_generator_server_fri/src/utils.rs +++ b/prover/vk_setup_data_generator_server_fri/src/utils.rs @@ -122,7 +122,8 @@ mod tests { #[test] fn test_keyhash_generation() { - let mut path_to_input = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()); + let mut path_to_input = locate_workspace().unwrap_or_else(|_| ".".into()); + path_to_input.push("historical_data"); for version in 18..=22 { 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 c821053637dd..3b9998dd6a63 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 @@ -2,6 +2,7 @@ use std::fs; use anyhow::Context as _; use toml_edit::{Document, Item, Value}; +use zksync_utils::locate_workspace; pub fn get_toml_formatted_value(string_value: String) -> Item { let mut value = Value::from(string_value); @@ -22,6 +23,7 @@ pub fn read_contract_toml() -> anyhow::Result { } pub fn get_contract_toml_path() -> String { - let zksync_home = std::env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| "/".into()); - format!("{}/etc/env/base/contracts.toml", zksync_home) + locate_workspace() + .unwrap_or_else(|| ".".into()) + .join("etc/env/base/contracts.toml") } From 3ccb43f501d589347a88db9e0197fbcf930ffe15 Mon Sep 17 00:00:00 2001 From: Danil Date: Thu, 11 Apr 2024 23:57:21 +0200 Subject: [PATCH 04/13] fix prover Signed-off-by: Danil --- prover/Cargo.lock | 1 + .../Cargo.toml | 3 +- .../src/keystore.rs | 94 ++++++++++--------- .../src/main.rs | 2 +- .../src/utils.rs | 4 +- .../src/vk_commitment_helper.rs | 6 +- 6 files changed, 58 insertions(+), 52 deletions(-) diff --git a/prover/Cargo.lock b/prover/Cargo.lock index 2eb1a7998c9f..15f31f2bb428 100644 --- a/prover/Cargo.lock +++ b/prover/Cargo.lock @@ -6668,6 +6668,7 @@ dependencies = [ "zksync_env_config", "zksync_prover_fri_types", "zksync_types", + "zksync_utils", ] [[package]] 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 07da4d62f83c..06f09feaeca6 100644 --- a/prover/vk_setup_data_generator_server_fri/src/keystore.rs +++ b/prover/vk_setup_data_generator_server_fri/src/keystore.rs @@ -39,14 +39,14 @@ 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() -> PathBuf { locate_workspace() - .unwrap_or_else(|_| ".".into()) + .unwrap_or_else(|| ".".into()) .join("/prover/vk_setup_data_generator_server_fri/data") } @@ -66,20 +66,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 } @@ -87,43 +87,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(|| { @@ -172,7 +178,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) } @@ -184,7 +190,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 +199,7 @@ impl Keystore { ProverServiceDataKey::eip4844(), ProverServiceDataType::VerificationKey, ); - tracing::info!("saving 4844 verification key to: {}", filepath); + tracing::info!("saving 4844 verification key to: {:?}", filepath); Self::save_json_pretty(filepath, &vk) } @@ -208,7 +214,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") @@ -242,8 +248,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<()> { @@ -251,7 +258,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()) } @@ -271,7 +278,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:?}") }) @@ -290,7 +297,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:?}") }) @@ -306,7 +313,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:?}")) } @@ -455,12 +462,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 bbac12484451..654e8fee4f69 100644 --- a/prover/vk_setup_data_generator_server_fri/src/main.rs +++ b/prover/vk_setup_data_generator_server_fri/src/main.rs @@ -168,7 +168,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/utils.rs b/prover/vk_setup_data_generator_server_fri/src/utils.rs index 90d7ed6727c2..fd67fb6c41ad 100644 --- a/prover/vk_setup_data_generator_server_fri/src/utils.rs +++ b/prover/vk_setup_data_generator_server_fri/src/utils.rs @@ -116,13 +116,13 @@ pub fn calculate_snark_vk_hash(keystore: &Keystore) -> anyhow::Result { #[cfg(test)] mod tests { - use std::{env, path::PathBuf, str::FromStr}; + use std::str::FromStr; use super::*; #[test] fn test_keyhash_generation() { - let mut path_to_input = locate_workspace().unwrap_or_else(|_| ".".into()); + let mut path_to_input = locate_workspace().unwrap_or_else(|| ".".into()); path_to_input.push("historical_data"); 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 3b9998dd6a63..2a6fe1b043ed 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,4 +1,4 @@ -use std::fs; +use std::{fs, path::PathBuf}; use anyhow::Context as _; use toml_edit::{Document, Item, Value}; @@ -18,11 +18,11 @@ 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 { +pub fn get_contract_toml_path() -> PathBuf { locate_workspace() .unwrap_or_else(|| ".".into()) .join("etc/env/base/contracts.toml") From 8e616479b0a50ebdf0c05c05d101b9e55c2bd1dd Mon Sep 17 00:00:00 2001 From: Danil Date: Fri, 12 Apr 2024 10:41:54 +0200 Subject: [PATCH 05/13] Add comments Signed-off-by: Danil --- core/lib/utils/src/env.rs | 5 +++++ prover/vk_setup_data_generator_server_fri/src/utils.rs | 2 ++ 2 files changed, 7 insertions(+) diff --git a/core/lib/utils/src/env.rs b/core/lib/utils/src/env.rs index 4a70ccd5cde9..2039fde08f68 100644 --- a/core/lib/utils/src/env.rs +++ b/core/lib/utils/src/env.rs @@ -2,6 +2,11 @@ use std::{path::PathBuf, sync::Mutex}; static WORKSPACE: Mutex> = Mutex::new(None); +/// Find the location of the current workspace, if this code works in workspace +/// then it will return the correct folder if, it's prebuild 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/74f3806b53bea6a4a6c16034e16f317a6dd4eea7/insta/src/env.rs#L369 pub fn locate_workspace() -> Option { let mut workspace = WORKSPACE.lock().unwrap_or_else(|x| x.into_inner()); if let Some(workspace) = workspace.clone() { 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 fd67fb6c41ad..681d8aa856ac 100644 --- a/prover/vk_setup_data_generator_server_fri/src/utils.rs +++ b/prover/vk_setup_data_generator_server_fri/src/utils.rs @@ -118,6 +118,8 @@ pub fn calculate_snark_vk_hash(keystore: &Keystore) -> anyhow::Result { mod tests { use std::str::FromStr; + use zksync_utils::locate_workspace; + use super::*; #[test] From 28405fa236cc80521a8926809a5e726e0e8e2db8 Mon Sep 17 00:00:00 2001 From: Danil Date: Fri, 12 Apr 2024 11:05:24 +0200 Subject: [PATCH 06/13] Use oncecell Signed-off-by: Danil --- Cargo.lock | 1 + core/lib/utils/Cargo.toml | 1 + core/lib/utils/src/env.rs | 23 +++++++++++++---------- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4708e6e7d617..3c2549cc03ac 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8927,6 +8927,7 @@ dependencies = [ "hex", "itertools 0.10.5", "num", + "once_cell", "rand 0.8.5", "reqwest", "serde", diff --git a/core/lib/utils/Cargo.toml b/core/lib/utils/Cargo.toml index f41b22d1b38a..c58339b3a5e6 100644 --- a/core/lib/utils/Cargo.toml +++ b/core/lib/utils/Cargo.toml @@ -26,6 +26,7 @@ hex.workspace = true reqwest = { workspace = true, features = ["blocking"] } itertools.workspace = true serde_json.workspace = true +once_cell.workspace = true [dev-dependencies] rand.workspace = true diff --git a/core/lib/utils/src/env.rs b/core/lib/utils/src/env.rs index 2039fde08f68..6b3ad4cb6d0b 100644 --- a/core/lib/utils/src/env.rs +++ b/core/lib/utils/src/env.rs @@ -1,15 +1,17 @@ -use std::{path::PathBuf, sync::Mutex}; +use std::path::PathBuf; -static WORKSPACE: Mutex> = Mutex::new(None); +use once_cell::sync::OnceCell; + +static WORKSPACE: OnceCell = OnceCell::new(); /// Find the location of the current workspace, if this code works in workspace -/// then it will return the correct folder if, it's prebuild binary e.g. in docker container +/// 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/74f3806b53bea6a4a6c16034e16f317a6dd4eea7/insta/src/env.rs#L369 +/// The code has been inspired by `insta` +/// https://github.com/mitsuhiko/insta/blob/74f3806b53bea6a4a6c16034e16f317a6dd4eea7/insta/src/env.rs pub fn locate_workspace() -> Option { - let mut workspace = WORKSPACE.lock().unwrap_or_else(|x| x.into_inner()); - if let Some(workspace) = workspace.clone() { + let workspace = WORKSPACE.get().cloned(); + if let Some(workspace) = workspace { return Some(workspace); }; @@ -30,7 +32,8 @@ pub fn locate_workspace() -> Option { let serde_json::Value::String(root) = root else { return None; }; - let val = Some(PathBuf::from(root).parent()?.to_path_buf()); - *workspace = val; - workspace.clone() + + let val = PathBuf::from(root).parent()?.to_path_buf(); + WORKSPACE.set(val.clone()).unwrap(); + Some(val) } From bee761c6eab96914944ee5940b3ec0eeb1397a67 Mon Sep 17 00:00:00 2001 From: Danil Date: Fri, 12 Apr 2024 11:59:32 +0200 Subject: [PATCH 07/13] Fix comment Signed-off-by: Danil --- core/lib/utils/src/env.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/lib/utils/src/env.rs b/core/lib/utils/src/env.rs index 6b3ad4cb6d0b..00f751a1123d 100644 --- a/core/lib/utils/src/env.rs +++ b/core/lib/utils/src/env.rs @@ -8,7 +8,7 @@ static WORKSPACE: OnceCell = OnceCell::new(); /// 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/74f3806b53bea6a4a6c16034e16f317a6dd4eea7/insta/src/env.rs +/// https://github.com/mitsuhiko/insta/blob/master/insta/src/env.rs pub fn locate_workspace() -> Option { let workspace = WORKSPACE.get().cloned(); if let Some(workspace) = workspace { From 432a1019181123217320c22a7b9043584e1356b5 Mon Sep 17 00:00:00 2001 From: Danil Date: Fri, 12 Apr 2024 16:38:06 +0200 Subject: [PATCH 08/13] Log error Signed-off-by: Danil --- core/lib/utils/src/env.rs | 7 ++++++- prover/Cargo.lock | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/core/lib/utils/src/env.rs b/core/lib/utils/src/env.rs index 00f751a1123d..a5ca0ea05e09 100644 --- a/core/lib/utils/src/env.rs +++ b/core/lib/utils/src/env.rs @@ -8,7 +8,7 @@ static WORKSPACE: OnceCell = OnceCell::new(); /// 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 +/// `https://github.com/mitsuhiko/insta/blob/master/insta/src/env.rs` pub fn locate_workspace() -> Option { let workspace = WORKSPACE.get().cloned(); if let Some(workspace) = workspace { @@ -23,7 +23,12 @@ pub fn locate_workspace() -> Option { .arg("locate-project") .arg("--workspace") .output() + .map_err(|err| { + tracing::trace!("Can't find workspace location: {}", err); + err + }) .ok()?; + let root = serde_json::from_slice::(&output.stdout) .ok()? .get("root") diff --git a/prover/Cargo.lock b/prover/Cargo.lock index 63315db641b7..bd653d22bf23 100644 --- a/prover/Cargo.lock +++ b/prover/Cargo.lock @@ -7995,6 +7995,7 @@ dependencies = [ "hex", "itertools 0.10.5", "num", + "once_cell", "reqwest", "serde", "serde_json", From 6f90d763069c666f90de3647ed3c6c35358f6c3a Mon Sep 17 00:00:00 2001 From: Danil Date: Fri, 12 Apr 2024 17:44:13 +0200 Subject: [PATCH 09/13] Refactor error handling Signed-off-by: Danil --- core/lib/utils/src/env.rs | 16 ++++++++++++---- .../src/utils.rs | 5 +---- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/core/lib/utils/src/env.rs b/core/lib/utils/src/env.rs index a5ca0ea05e09..33bfed666cad 100644 --- a/core/lib/utils/src/env.rs +++ b/core/lib/utils/src/env.rs @@ -29,16 +29,24 @@ pub fn locate_workspace() -> Option { }) .ok()?; - let root = serde_json::from_slice::(&output.stdout) + let Some(root) = serde_json::from_slice::(&output.stdout) + .map_err(|err| { + tracing::warn!("Parsing `cargo locate-project` error: {}", err); + err + }) .ok()? .get("root") - .cloned()?; + .cloned() + else { + tracing::warn!("root doesn't exist in output from `cargo locate-project`"); + return None; + }; let serde_json::Value::String(root) = root else { + tracing::warn!("root is not a string"); return None; }; let val = PathBuf::from(root).parent()?.to_path_buf(); - WORKSPACE.set(val.clone()).unwrap(); - Some(val) + Some(WORKSPACE.get_or_init(|| val).clone()) } 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 681d8aa856ac..7d1d29219c9b 100644 --- a/prover/vk_setup_data_generator_server_fri/src/utils.rs +++ b/prover/vk_setup_data_generator_server_fri/src/utils.rs @@ -130,10 +130,7 @@ mod tests { 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(); From c036ca520fe2c0b13a06c595754a7c9e9745092f Mon Sep 17 00:00:00 2001 From: Danil Date: Fri, 12 Apr 2024 18:30:48 +0200 Subject: [PATCH 10/13] Remove unnecessary test Signed-off-by: Danil --- prover/vk_setup_data_generator_server_fri/src/tests.rs | 9 --------- prover/vk_setup_data_generator_server_fri/src/utils.rs | 7 ++----- 2 files changed, 2 insertions(+), 14 deletions(-) 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 7d1d29219c9b..61e8b9d7cb3b 100644 --- a/prover/vk_setup_data_generator_server_fri/src/utils.rs +++ b/prover/vk_setup_data_generator_server_fri/src/utils.rs @@ -116,16 +116,13 @@ pub fn calculate_snark_vk_hash(keystore: &Keystore) -> anyhow::Result { #[cfg(test)] mod tests { - use std::str::FromStr; - - use zksync_utils::locate_workspace; + use std::{path::PathBuf, str::FromStr}; use super::*; #[test] fn test_keyhash_generation() { - let mut path_to_input = locate_workspace().unwrap_or_else(|| ".".into()); - + 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 { From 364089ea1ed7ec5e06cb481a7c9800b314f3a9b4 Mon Sep 17 00:00:00 2001 From: Alex Ostrovski Date: Mon, 15 Apr 2024 10:13:11 +0300 Subject: [PATCH 11/13] Brush up `locate_workspace()` --- core/bin/contract-verifier/src/main.rs | 8 +- core/bin/contract-verifier/src/verifier.rs | 8 +- .../system-constants-generator/src/main.rs | 4 +- core/lib/contracts/src/lib.rs | 6 +- core/lib/utils/src/env.rs | 84 +++++++++++-------- core/lib/utils/src/lib.rs | 5 +- core/tests/loadnext/src/config.rs | 23 +++-- core/tests/loadnext/src/fs_utils.rs | 25 +----- .../src/keystore.rs | 6 +- .../src/vk_commitment_helper.rs | 6 +- 10 files changed, 85 insertions(+), 90 deletions(-) diff --git a/core/bin/contract-verifier/src/main.rs b/core/bin/contract-verifier/src/main.rs index 8449b38610d0..e6ce4fcac84d 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; @@ -24,7 +25,7 @@ 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 = locate_workspace().unwrap_or_else(|| ".".into()); + let zksync_home = workspace_dir_or_current_dir(); let zksolc_path = zksync_home.join("etc/zksolc-bin/"); let zksolc_versions: Vec = std::fs::read_dir(zksolc_path) @@ -114,9 +115,6 @@ async fn update_compiler_versions(connection_pool: &ConnectionPool) { transaction.commit().await.unwrap(); } -use structopt::StructOpt; -use zksync_utils::locate_workspace; - #[derive(StructOpt)] #[structopt(name = "zkSync contract code verifier", author = "Matter Labs")] struct Opt { diff --git a/core/bin/contract-verifier/src/verifier.rs b/core/bin/contract-verifier/src/verifier.rs index 4ba4ae215012..5106f1fd38bf 100644 --- a/core/bin/contract-verifier/src/verifier.rs +++ b/core/bin/contract-verifier/src/verifier.rs @@ -1,6 +1,6 @@ use std::{ collections::HashMap, - path::{Path, PathBuf}, + path::Path, time::{Duration, Instant}, }; @@ -21,7 +21,7 @@ use zksync_types::{ }, Address, }; -use zksync_utils::locate_workspace; +use zksync_utils::workspace_dir_or_current_dir; use crate::{ error::ContractVerifierError, @@ -33,8 +33,8 @@ lazy_static! { static ref DEPLOYER_CONTRACT: Contract = zksync_contracts::deployer_contract(); } -fn home_path() -> PathBuf { - locate_workspace().unwrap_or_else(|| ".".into()) +fn home_path() -> &'static Path { + workspace_dir_or_current_dir() } #[derive(Debug)] diff --git a/core/bin/system-constants-generator/src/main.rs b/core/bin/system-constants-generator/src/main.rs index 2d929d03c627..b0276aeb7fa1 100644 --- a/core/bin/system-constants-generator/src/main.rs +++ b/core/bin/system-constants-generator/src/main.rs @@ -17,7 +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::locate_workspace; +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. @@ -210,7 +210,7 @@ fn generate_rust_fee_constants(intrinsic_gas_constants: &IntrinsicSystemGasConst } fn save_file(path_in_repo: &str, content: String) { - let zksync_home = locate_workspace().unwrap_or_else(|| ".".into()); + let zksync_home = workspace_dir_or_current_dir(); let fee_constants_path = zksync_home.join(path_in_repo); fs::write(fee_constants_path, content) diff --git a/core/lib/contracts/src/lib.rs b/core/lib/contracts/src/lib.rs index f9e83c901384..3cfa33f6e5fc 100644 --- a/core/lib/contracts/src/lib.rs +++ b/core/lib/contracts/src/lib.rs @@ -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, locate_workspace}; +use zksync_utils::{bytecode::hash_bytecode, bytes_to_be_words, workspace_dir_or_current_dir}; pub mod test_contracts; @@ -40,8 +40,8 @@ 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 home_path() -> PathBuf { - locate_workspace().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 { diff --git a/core/lib/utils/src/env.rs b/core/lib/utils/src/env.rs index 33bfed666cad..fec413927929 100644 --- a/core/lib/utils/src/env.rs +++ b/core/lib/utils/src/env.rs @@ -1,20 +1,14 @@ -use std::path::PathBuf; +use std::{ + path::{Path, PathBuf}, + str, +}; +use anyhow::Context as _; use once_cell::sync::OnceCell; -static WORKSPACE: OnceCell = OnceCell::new(); - -/// 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 { - let workspace = WORKSPACE.get().cloned(); - if let Some(workspace) = workspace { - return Some(workspace); - }; +static WORKSPACE: OnceCell> = OnceCell::new(); +fn locate_workspace_inner() -> anyhow::Result { let output = std::process::Command::new( std::env::var("CARGO") .ok() @@ -23,30 +17,52 @@ pub fn locate_workspace() -> Option { .arg("locate-project") .arg("--workspace") .output() - .map_err(|err| { - tracing::trace!("Can't find workspace location: {}", err); - err - }) - .ok()?; + .context("Can't find Cargo workspace location")?; - let Some(root) = serde_json::from_slice::(&output.stdout) - .map_err(|err| { - tracing::warn!("Parsing `cargo locate-project` error: {}", err); - err - }) - .ok()? - .get("root") - .cloned() - else { - tracing::warn!("root doesn't exist in output from `cargo locate-project`"); - return None; - }; + 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 { - tracing::warn!("root is not a string"); - return None; + 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() +} - let val = PathBuf::from(root).parent()?.to_path_buf(); - Some(WORKSPACE.get_or_init(|| val).clone()) +/// 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 46c0765d73f6..1c17d4efe264 100644 --- a/core/lib/utils/src/lib.rs +++ b/core/lib/utils/src/lib.rs @@ -10,7 +10,4 @@ mod serde_wrappers; pub mod time; pub mod wait_for_tasks; -pub use convert::*; -pub use env::*; -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 021da427143e..7f3e1e258305 100644 --- a/core/tests/loadnext/src/config.rs +++ b/core/tests/loadnext/src/config.rs @@ -4,7 +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::locate_workspace; +use zksync_utils::workspace_dir_or_current_dir; use crate::fs_utils::read_tokens; @@ -190,14 +190,8 @@ fn default_main_token() -> H160 { } fn default_test_contracts_path() -> PathBuf { - let test_contracts_path = { - locate_workspace() - .unwrap_or_else(|| ".".into()) - .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 } @@ -347,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 2605693125de..8af9df8afee7 100644 --- a/core/tests/loadnext/src/fs_utils.rs +++ b/core/tests/loadnext/src/fs_utils.rs @@ -5,7 +5,7 @@ use std::{fs::File, io::BufReader, path::Path}; use serde::Deserialize; use zksync_types::{ethabi::Contract, network::Network, Address}; -use zksync_utils::locate_workspace; +use zksync_utils::workspace_dir_or_current_dir; /// A token stored in `etc/tokens/{network}.json` files. #[derive(Debug, Deserialize)] @@ -27,10 +27,8 @@ pub struct TestContract { } pub fn read_tokens(network: Network) -> anyhow::Result> { - let home = locate_workspace().unwrap_or(".".into()); - 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); @@ -87,20 +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 super::*; - - #[test] - fn check_read_test_contract() { - let test_contracts_path = { - let path = locate_workspace().unwrap_or(".".into()); - let a = path.join("etc/contracts-test-data"); - dbg!(a) - }; - - loadnext_contract(&test_contracts_path).unwrap(); - } -} 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 06f09feaeca6..60d808bd873d 100644 --- a/prover/vk_setup_data_generator_server_fri/src/keystore.rs +++ b/prover/vk_setup_data_generator_server_fri/src/keystore.rs @@ -20,7 +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::locate_workspace; +use zksync_utils::workspace_dir_or_current_dir; #[cfg(feature = "gpu")] use crate::GoldilocksGpuProverSetupData; @@ -45,9 +45,7 @@ pub struct Keystore { } fn get_base_path_from_env() -> PathBuf { - locate_workspace() - .unwrap_or_else(|| ".".into()) - .join("/prover/vk_setup_data_generator_server_fri/data") + workspace_dir_or_current_dir().join("/prover/vk_setup_data_generator_server_fri/data") } impl Default for Keystore { 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 2a6fe1b043ed..3f1f839648e3 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 @@ -2,7 +2,7 @@ use std::{fs, path::PathBuf}; use anyhow::Context as _; use toml_edit::{Document, Item, Value}; -use zksync_utils::locate_workspace; +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); @@ -23,7 +23,5 @@ pub fn read_contract_toml() -> anyhow::Result { } pub fn get_contract_toml_path() -> PathBuf { - locate_workspace() - .unwrap_or_else(|| ".".into()) - .join("etc/env/base/contracts.toml") + workspace_dir_or_current_dir().join("etc/env/base/contracts.toml") } From d5a39d68593d446892d69264e533c72b12cfba6e Mon Sep 17 00:00:00 2001 From: Alex Ostrovski Date: Mon, 15 Apr 2024 11:10:09 +0300 Subject: [PATCH 12/13] Fix paths in prover workspace --- prover/vk_setup_data_generator_server_fri/src/keystore.rs | 2 +- .../src/vk_commitment_helper.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) 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 60d808bd873d..cc4a0d4bb95e 100644 --- a/prover/vk_setup_data_generator_server_fri/src/keystore.rs +++ b/prover/vk_setup_data_generator_server_fri/src/keystore.rs @@ -45,7 +45,7 @@ pub struct Keystore { } fn get_base_path_from_env() -> PathBuf { - workspace_dir_or_current_dir().join("/prover/vk_setup_data_generator_server_fri/data") + workspace_dir_or_current_dir().join("vk_setup_data_generator_server_fri/data") } impl Default for Keystore { 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 3f1f839648e3..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 @@ -23,5 +23,5 @@ pub fn read_contract_toml() -> anyhow::Result { } pub fn get_contract_toml_path() -> PathBuf { - workspace_dir_or_current_dir().join("etc/env/base/contracts.toml") + workspace_dir_or_current_dir().join("../etc/env/base/contracts.toml") } From 8210a678e158b69d61b50a3809875802f6815427 Mon Sep 17 00:00:00 2001 From: Alex Ostrovski Date: Wed, 17 Apr 2024 12:13:03 +0300 Subject: [PATCH 13/13] Fix "workspace location" mentions --- core/lib/contracts/src/lib.rs | 6 +++--- core/lib/types/src/system_contracts.rs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/core/lib/contracts/src/lib.rs b/core/lib/contracts/src/lib.rs index 3cfa33f6e5fc..5cde122ab24d 100644 --- a/core/lib/contracts/src/lib.rs +++ b/core/lib/contracts/src/lib.rs @@ -130,7 +130,7 @@ pub fn l1_messenger_contract() -> Contract { load_sys_contract("L1Messenger") } -/// Reads bytecode from the path RELATIVE to the workspace location environment variable. +/// 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) } @@ -158,14 +158,14 @@ 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 workspace location 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 workspace location environment variable. + /// Returns the default system contracts repository with directory based on the Cargo workspace location. pub fn from_env() -> Self { SystemContractsRepo { root: home_path().join("contracts/system-contracts"), diff --git a/core/lib/types/src/system_contracts.rs b/core/lib/types/src/system_contracts.rs index 88bfefd738fe..f841fb0b3c12 100644 --- a/core/lib/types/src/system_contracts.rs +++ b/core/lib/types/src/system_contracts.rs @@ -168,7 +168,7 @@ static SYSTEM_CONTRACTS: Lazy> = Lazy::new(|| { .collect::>() }); -/// Gets default set of system contracts, based on workspace location environment variable. +/// Gets default set of system contracts, based on Cargo workspace location. pub fn get_system_smart_contracts() -> Vec { SYSTEM_CONTRACTS.clone() }