diff --git a/Cargo.lock b/Cargo.lock index ba777c30..d09d1d71 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1855,6 +1855,7 @@ dependencies = [ "serde_json", "serde_path_to_error", "tokio", + "toml", "tracing", "tracing-subscriber", ] @@ -2513,7 +2514,7 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7e8366a6159044a37876a2b9817124296703c586a5c92e2c53751fa06d8d43e8" dependencies = [ - "toml_edit", + "toml_edit 0.20.2", ] [[package]] @@ -3008,6 +3009,15 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_spanned" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1" +dependencies = [ + "serde", +] + [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -3432,11 +3442,26 @@ dependencies = [ "tracing", ] +[[package]] +name = "toml" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9dd1545e8208b4a5af1aa9bbd0b4cf7e9ea08fabc5d0a5c67fcaafa17433aa3" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit 0.22.9", +] + [[package]] name = "toml_datetime" version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" +dependencies = [ + "serde", +] [[package]] name = "toml_edit" @@ -3446,7 +3471,20 @@ checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" dependencies = [ "indexmap 2.2.5", "toml_datetime", - "winnow", + "winnow 0.5.40", +] + +[[package]] +name = "toml_edit" +version = "0.22.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e40bb779c5187258fd7aad0eb68cb8706a0a81fa712fbea808ab43c4b8374c4" +dependencies = [ + "indexmap 2.2.5", + "serde", + "serde_spanned", + "toml_datetime", + "winnow 0.6.6", ] [[package]] @@ -3980,6 +4018,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "winnow" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0c976aaaa0e1f90dbb21e9587cdaf1d9679a1cde8875c0d6bd83ab96a208352" +dependencies = [ + "memchr", +] + [[package]] name = "winreg" version = "0.50.0" diff --git a/common/src/prover_state/mod.rs b/common/src/prover_state/mod.rs index b2c18e39..44463b53 100644 --- a/common/src/prover_state/mod.rs +++ b/common/src/prover_state/mod.rs @@ -15,30 +15,24 @@ use std::{fmt::Display, sync::OnceLock}; use clap::ValueEnum; use evm_arithmetization::{ - cpu::kernel::aggregator::KERNEL, proof::AllProof, prover::prove, AllStark, GenerationInputs, - StarkConfig, + proof::AllProof, prover::prove, AllStark, GenerationInputs, StarkConfig, }; use plonky2::{ - field::goldilocks_field::GoldilocksField, - plonk::config::{GenericHashOut, PoseidonGoldilocksConfig}, + field::goldilocks_field::GoldilocksField, plonk::config::PoseidonGoldilocksConfig, util::timing::TimingTree, }; use proof_gen::{proof_types::GeneratedTxnProof, prover_state::ProverState, VerifierState}; use tracing::info; use self::circuit::{CircuitConfig, NUM_TABLES}; -use crate::prover_state::{ - persistence::{ - BaseProverResource, DiskResource, MonolithicProverResource, RecursiveCircuitResource, - VerifierResource, - }, - utils::pkg_consistency_check, +use crate::prover_state::persistence::{ + BaseProverResource, DiskResource, MonolithicProverResource, RecursiveCircuitResource, + VerifierResource, }; pub mod circuit; pub mod cli; pub mod persistence; -mod utils; pub(crate) type Config = PoseidonGoldilocksConfig; pub(crate) type Field = GoldilocksField; @@ -259,18 +253,6 @@ impl ProverStateManager { CircuitPersistence::Disk(strategy) => { info!("attempting to load preprocessed circuits from disk..."); - // Check the package consistency before loading the circuits. - pkg_consistency_check([ - self.circuit_config - .as_all_recursive_circuits() - .block - .circuit - .verifier_only - .circuit_digest - .to_bytes(), - KERNEL.hash().to_fixed_bytes().to_vec(), - ]); - let disk_state = match strategy { TableLoadStrategy::OnDemand => BaseProverResource::get(&self.circuit_config), TableLoadStrategy::Monolithic => { diff --git a/common/src/prover_state/persistence.rs b/common/src/prover_state/persistence.rs index dae26e64..cd33b04e 100644 --- a/common/src/prover_state/persistence.rs +++ b/common/src/prover_state/persistence.rs @@ -1,3 +1,4 @@ +use std::env; use std::{ fmt::{Debug, Display}, fs::{self, OpenOptions}, @@ -16,7 +17,7 @@ use super::{ Config, RecursiveCircuitsForTableSize, SIZE, }; -pub(crate) const CIRCUITS_FOLDER: &str = "./circuits"; +const CIRCUITS_FOLDER: &str = "./circuits"; const PROVER_STATE_FILE_PREFIX: &str = "prover_state"; const VERIFIER_STATE_FILE_PREFIX: &str = "verifier_state"; @@ -102,9 +103,10 @@ impl DiskResource for BaseProverResource { fn path(p: &Self::PathConstrutor) -> impl AsRef { format!( - "{}/{}_base_{}", + "{}/{}_base_{}_{}", CIRCUITS_FOLDER, PROVER_STATE_FILE_PREFIX, + env::var("EVM_ARITHMETIZATION_PKG_VER").unwrap_or("NA".to_string()), p.get_configuration_digest() ) } @@ -137,9 +139,10 @@ impl DiskResource for MonolithicProverResource { fn path(p: &Self::PathConstrutor) -> impl AsRef { format!( - "{}/{}_monolithic_{}", + "{}/{}_monolithic_{}_{}", CIRCUITS_FOLDER, PROVER_STATE_FILE_PREFIX, + env::var("EVM_ARITHMETIZATION_PKG_VER").unwrap_or("NA".to_string()), p.get_configuration_digest() ) } @@ -171,9 +174,10 @@ impl DiskResource for RecursiveCircuitResource { fn path((circuit_type, size): &Self::PathConstrutor) -> impl AsRef { format!( - "{}/{}_{}_{}", + "{}/{}_{}_{}_{}", CIRCUITS_FOLDER, PROVER_STATE_FILE_PREFIX, + env::var("EVM_ARITHMETIZATION_PKG_VER").unwrap_or("NA".to_string()), circuit_type.as_short_str(), size ) @@ -214,9 +218,10 @@ impl DiskResource for VerifierResource { fn path(p: &Self::PathConstrutor) -> impl AsRef { format!( - "{}/{}_{}", + "{}/{}_{}_{}", CIRCUITS_FOLDER, VERIFIER_STATE_FILE_PREFIX, + env::var("EVM_ARITHMETIZATION_PKG_VER").unwrap_or("NA".to_string()), p.get_configuration_digest() ) } diff --git a/common/src/prover_state/utils.rs b/common/src/prover_state/utils.rs deleted file mode 100644 index 21d042aa..00000000 --- a/common/src/prover_state/utils.rs +++ /dev/null @@ -1,90 +0,0 @@ -use std::fs::{self, File}; -use std::hash::Hasher; -use std::io::{Read, Write}; -use std::path::Path; - -use seahash::SeaHasher; -use tracing::{info, warn}; - -use super::persistence::CIRCUITS_FOLDER; - -/// Checks the consistency of circuits code by comparing a computed hash -/// derived from the provided array of circuit code hashes against a reference -/// hash stored in a designated file within the circuits folder. This function -/// performs several actions based on this comparison: -/// -/// - If the computed aggregate hash differs from the stored hash, or if the -/// hash file does not exist, the function will delete the existing circuits -/// folder (if it exists), recreate it, and then write the new computed hash -/// into the hash file. -/// -/// - If the computed hash matches the stored hash, indicating no changes in the -/// circuits code, the function takes no action. -/// -/// This process ensures that the stored hash always reflects the current state -/// of the circuits code, providing a mechanism for detecting changes and -/// maintaining consistency. -/// -/// # Parameters -/// -/// * `circuits_hashes` - A dynamic number of `Vec` arguments representing -/// circuit code hashes. -/// -/// # Side Effects -/// -/// - May delete and recreate the circuits folder. -/// - May modify or create a file within the circuits folder to store the latest -/// hash. -pub(crate) fn pkg_consistency_check(circuits_hashes: I) -where - I: IntoIterator, - T: AsRef<[u8]>, -{ - let mut hasher = SeaHasher::new(); - for hash in circuits_hashes { - hasher.write(hash.as_ref()); - } - let hash = hasher.finish(); - - let hash_file_path = Path::new(CIRCUITS_FOLDER).join("circuits_consistency_hash"); - - // Check if the circuits folder exists - match fs::metadata(CIRCUITS_FOLDER) { - Ok(_) => { - // Circuits folder exists, check the hash file - let mut existing_hash = String::new(); - if let Ok(mut hash_file) = File::open(&hash_file_path) { - // If the hash file exists and can be read, compare the hash - if hash_file.read_to_string(&mut existing_hash).is_ok() - && existing_hash == hash.to_string() - { - // Hashes are the same, do nothing - return; - } - } else { - warn!("Unable to read circuits consistency hash file"); - } - - // Hashes differ or hash file cannot be read, delete the folder - if fs::remove_dir_all(CIRCUITS_FOLDER).is_err() { - panic!("Failed to delete circuits storage folder"); - } - } - Err(_) => { - info!( - "Initializing circuits storage folder with new consistency hash: {}", - hash - ); - } - } - - // Recreate the circuits folder and write the new hash - if fs::create_dir(CIRCUITS_FOLDER).is_ok() { - if let Ok(mut hash_file) = File::create(&hash_file_path) { - // Ignore errors in writing the hash - let _ = hash_file.write_all(hash.to_string().as_bytes()); - } - } else { - panic!("Failed to create circuits storage folder"); - } -} diff --git a/leader/Cargo.toml b/leader/Cargo.toml index 5c7bcc92..de39328a 100644 --- a/leader/Cargo.toml +++ b/leader/Cargo.toml @@ -22,6 +22,7 @@ serde_json = { workspace = true } serde_path_to_error = { workspace = true } ethereum-types = { workspace = true } axum = "0.7.4" +toml = "0.8.12" # Local dependencies ops = { path = "../ops" } diff --git a/leader/src/main.rs b/leader/src/main.rs index 8c054ea4..5fc4d767 100644 --- a/leader/src/main.rs +++ b/leader/src/main.rs @@ -1,3 +1,4 @@ +use std::env; use std::{fs::File, path::PathBuf}; use anyhow::Result; @@ -9,11 +10,14 @@ use ops::register; use paladin::runtime::Runtime; use proof_gen::types::PlonkyProofIntern; +use crate::utils::get_package_version; + mod cli; mod http; mod init; mod jerigon; mod stdio; +mod utils; fn get_previous_proof(path: Option) -> Result> { if path.is_none() { @@ -32,6 +36,19 @@ async fn main() -> Result<()> { dotenv().ok(); init::tracing(); + if env::var("EVM_ARITHMETIZATION_PKG_VER").is_err() { + let pkg_ver = get_package_version("evm_arithmetization")?; + // Extract the major and minor version parts and append 'x' as the patch version + if let Some((major_minor, _)) = pkg_ver.as_ref().and_then(|s| s.rsplit_once('.')) { + let circuits_version = format!("{}.x", major_minor); + // Set the environment variable for the evm_arithmetization package version + env::set_var("EVM_ARITHMETIZATION_PKG_VER", circuits_version); + } else { + // Set to "NA" if version extraction fails + env::set_var("EVM_ARITHMETIZATION_PKG_VER", "NA"); + } + } + let args = cli::Cli::parse(); if let paladin::config::Runtime::InMemory = args.paladin.runtime { // If running in emulation mode, we'll need to initialize the prover diff --git a/leader/src/utils.rs b/leader/src/utils.rs new file mode 100644 index 00000000..e2c7d5f1 --- /dev/null +++ b/leader/src/utils.rs @@ -0,0 +1,72 @@ +use std::fs::File; +use std::io::{BufReader, Read}; +use std::path::Path; + +use anyhow::Result; + +/// Retrieves the version of a specified package from the `Cargo.lock` file. +/// +/// This function attempts to find the version of a package specified by +/// `package_name` by reading and parsing the `Cargo.lock` file. The +/// `Cargo.lock` file is expected to be located one directory level up from the +/// directory specified by the `CARGO_MANIFEST_DIR` environment variable. The +/// path may need adjustment depending on the structure of the project. +/// +/// # Parameters +/// - `package_name`: The name of the package for which the version is being +/// retrieved. +/// +/// # Returns +/// - `Ok(Some(String))`: If the package is found in the `Cargo.lock` file, +/// returns the version of the package. +/// - `Ok(None)`: If the package is not found in the `Cargo.lock` file, or if +/// the `Cargo.lock` file does not exist. +/// - `Err(_)`: If any error occurs during the execution, such as issues with +/// file paths, file access, reading, or parsing the `Cargo.lock` file. +/// +/// # Examples +/// ```no_run +/// let version = get_package_version("my_package"); +/// match version { +/// Ok(Some(ver)) => println!("Found version: {}", ver), +/// Ok(None) => println!("Package not found."), +/// Err(e) => println!("Error occurred: {}", e), +/// } +/// ``` +/// +/// # Errors +/// This function can return an `Err` result if: +/// - There is a problem finding, opening, or reading the `Cargo.lock` file. +/// - There is a failure in parsing the `Cargo.lock` file as TOML. +/// +/// The function uses `?` to propagate errors upwards, so the exact nature of +/// the error will be indicated by the error value returned in the `Err` variant +/// of the `Result`. +pub(crate) fn get_package_version(package_name: &str) -> Result> { + let manifest_dir = env!("CARGO_MANIFEST_DIR"); + let zero_bin_path = Path::new(manifest_dir) + .join("../") // Adjust the path according to your workspace structure + .canonicalize()?; + + let cargo_lock_path = zero_bin_path.join("Cargo.lock"); + let cargo_lock_file = File::open(cargo_lock_path); + if cargo_lock_file.is_err() { + return Ok(None); + } + + let mut cargo_lock_contents = String::new(); + BufReader::new(cargo_lock_file?).read_to_string(&mut cargo_lock_contents)?; + + let lockfile: toml::Value = toml::from_str(&cargo_lock_contents)?; + if let Some(package) = lockfile["package"] + .as_array() + .unwrap() + .iter() + .find(|&p| p["name"].as_str() == Some(package_name)) + { + let version = package["version"].as_str().unwrap(); + return Ok(Some(version.to_string())); + } + + Ok(None) +}