diff --git a/core/bin/system-constants-generator/src/utils.rs b/core/bin/system-constants-generator/src/utils.rs index e3558de3e6a1..0010377696bb 100644 --- a/core/bin/system-constants-generator/src/utils.rs +++ b/core/bin/system-constants-generator/src/utils.rs @@ -2,8 +2,8 @@ use std::{cell::RefCell, rc::Rc}; use once_cell::sync::Lazy; use zksync_contracts::{ - load_sys_contract, read_bootloader_code, read_bytecode_from_path, read_sys_contract_bytecode, - read_yul_bytecode, BaseSystemContracts, ContractLanguage, SystemContractCode, + load_sys_contract, read_bootloader_code, read_sys_contract_bytecode, BaseSystemContracts, + ContractLanguage, SystemContractCode, }; use zksync_multivm::{ interface::{ @@ -171,16 +171,7 @@ pub(super) fn get_l1_txs(number_of_txs: usize) -> (Vec, Vec Vec { - if let Some(contract) = read_bytecode_from_path(format!( - "contracts/system-contracts/zkout/{test}.yul/contracts-preprocessed/bootloader/{test}.yul.json", - )){ - contract - } else { - read_yul_bytecode( - "contracts/system-contracts/bootloader/tests/artifacts", - test - ) - } + read_sys_contract_bytecode("", test, ContractLanguage::Yul) } fn default_l1_batch() -> L1BatchEnv { diff --git a/core/lib/contract_verifier/src/contract_identifier.rs b/core/lib/contract_verifier/src/contract_identifier.rs new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/core/lib/contracts/src/lib.rs b/core/lib/contracts/src/lib.rs index e7cf1508f733..081ae41aae48 100644 --- a/core/lib/contracts/src/lib.rs +++ b/core/lib/contracts/src/lib.rs @@ -293,32 +293,66 @@ impl SystemContractsRepo { ) -> Vec { match lang { ContractLanguage::Sol => { - if let Some(contracts) = read_bytecode_from_path( + let possible_paths = vec![ self.root .join(format!("zkout/{0}{1}.sol/{1}.json", directory, name)), - ) { - contracts - } else { - read_bytecode_from_path(self.root.join(format!( + self.root.join(format!( "artifacts-zk/contracts-preprocessed/{0}{1}.sol/{1}.json", directory, name - ))) - .unwrap_or_else(|| { - panic!("One of the outputs should exists for {directory}{name}"); - }) + )), + ]; + for path in &possible_paths { + if let Some(contracts) = read_bytecode_from_path(path) { + return contracts; + } } + panic!("One of the outputs should exists for {directory}{name}. Checked paths: {possible_paths:?}"); } ContractLanguage::Yul => { - if let Some(contract) = read_bytecode_from_path(self.root.join(format!( - "zkout/{name}.yul/contracts-preprocessed/{directory}/{name}.yul.json", - ))) { - contract + // TODO: Newer versions of foundry-zksync no longer use directory for yul contracts, but we cannot + // easily get rid of the old lookup, because old foundry-zksync is compiled into `zk_environment` + // image. Once `foundry-zksync` is updated to at least 0.0.4, we can remove folder names from the + // `SYSTEM_CONTRACT_LIST` for yul contracts and merge two lookups below. + let possible_paths = vec![ + self.root.join(format!("zkout/{0}.yul/{0}.json", name)), + self.root + .join(format!("zkout/{0}{1}.yul/{1}.json", directory, name)), + self.root.join(format!( + "zkout/{name}.yul/contracts-preprocessed/{directory}/{name}.yul.json", + )), + ]; + + for path in &possible_paths { + if let Some(contracts) = read_bytecode_from_path(path) { + return contracts; + } + } + + // Fallback for very old versions. + let artifacts_path = self + .root + .join(format!("contracts-preprocessed/{directory}artifacts")); + + let bytecode_path = artifacts_path.join(format!("{name}.yul/{name}.yul.zbin")); + // Legacy versions of zksolc use the following path for output data if a yul file is being compiled: .yul.zbin + // New zksolc versions use .yul/.yul.zbin, for consistency with solidity files compilation. + // In addition, the output of the legacy zksolc in this case is a binary file, while in new versions it is hex encoded. + if fs::exists(&bytecode_path) + .unwrap_or_else(|err| panic!("Invalid path: {bytecode_path:?}, {err}")) + { + read_zbin_bytecode_from_hex_file(bytecode_path) } else { - read_yul_bytecode_by_path( - self.root - .join(format!("contracts-preprocessed/{directory}artifacts")), - name, - ) + let bytecode_path_legacy = artifacts_path.join(format!("{name}.yul.zbin")); + + if fs::exists(&bytecode_path_legacy).unwrap_or_else(|err| { + panic!("Invalid path: {bytecode_path_legacy:?}, {err}") + }) { + read_zbin_bytecode_from_path(bytecode_path_legacy) + } else { + panic!( + "Can't find bytecode for '{name}' yul contract at {artifacts_path:?} or {possible_paths:?}" + ) + } } } } @@ -326,25 +360,7 @@ impl SystemContractsRepo { } pub fn read_bootloader_code(bootloader_type: &str) -> Vec { - if let Some(contract) = - read_bytecode_from_path(home_path().join("contracts/system-contracts").join(format!( - "zkout/{bootloader_type}.yul/contracts-preprocessed/bootloader/{bootloader_type}.yul.json", - ))) - { - return contract; - }; - read_yul_bytecode( - "contracts/system-contracts/bootloader/build/artifacts", - bootloader_type, - ) -} - -fn read_proved_batch_bootloader_bytecode() -> Vec { - read_bootloader_code("proved_batch") -} - -fn read_playground_batch_bootloader_bytecode() -> Vec { - read_bootloader_code("playground_batch") + read_sys_contract_bytecode("bootloader", bootloader_type, ContractLanguage::Yul) } /// Reads zbin bytecode from a given path, relative to workspace location. @@ -353,34 +369,6 @@ pub fn read_zbin_bytecode(relative_zbin_path: impl AsRef) -> Vec { read_zbin_bytecode_from_path(bytecode_path) } -pub fn read_yul_bytecode(relative_artifacts_path: &str, name: &str) -> Vec { - let artifacts_path = Path::new(&home_path()).join(relative_artifacts_path); - read_yul_bytecode_by_path(artifacts_path, name) -} - -pub fn read_yul_bytecode_by_path(artifacts_path: PathBuf, name: &str) -> Vec { - let bytecode_path = artifacts_path.join(format!("{name}.yul/{name}.yul.zbin")); - - // Legacy versions of zksolc use the following path for output data if a yul file is being compiled: .yul.zbin - // New zksolc versions use .yul/.yul.zbin, for consistency with solidity files compilation. - // In addition, the output of the legacy zksolc in this case is a binary file, while in new versions it is hex encoded. - if fs::exists(&bytecode_path) - .unwrap_or_else(|err| panic!("Invalid path: {bytecode_path:?}, {err}")) - { - read_zbin_bytecode_from_hex_file(bytecode_path) - } else { - let bytecode_path_legacy = artifacts_path.join(format!("{name}.yul.zbin")); - - if fs::exists(&bytecode_path_legacy) - .unwrap_or_else(|err| panic!("Invalid path: {bytecode_path_legacy:?}, {err}")) - { - read_zbin_bytecode_from_path(bytecode_path_legacy) - } else { - panic!("Can't find bytecode for '{name}' yul contract at {artifacts_path:?}") - } - } -} - /// Reads zbin bytecode from a given path. fn read_zbin_bytecode_from_path(bytecode_path: PathBuf) -> Vec { fs::read(&bytecode_path) @@ -451,7 +439,7 @@ impl BaseSystemContracts { /// BaseSystemContracts with proved bootloader - for handling transactions. pub fn load_from_disk() -> Self { - let bootloader_bytecode = read_proved_batch_bootloader_bytecode(); + let bootloader_bytecode = read_bootloader_code("proved_batch"); BaseSystemContracts::load_with_bootloader(bootloader_bytecode) } @@ -468,7 +456,7 @@ impl BaseSystemContracts { /// BaseSystemContracts with playground bootloader - used for handling eth_calls. pub fn playground() -> Self { - let bootloader_bytecode = read_playground_batch_bootloader_bytecode(); + let bootloader_bytecode = read_bootloader_code("playground_batch"); BaseSystemContracts::load_with_bootloader(bootloader_bytecode) }