diff --git a/prover/Cargo.lock b/prover/Cargo.lock index 46981afb799..5154d57abfe 100644 --- a/prover/Cargo.lock +++ b/prover/Cargo.lock @@ -579,13 +579,13 @@ dependencies = [ [[package]] name = "boojum" version = "0.2.0" -source = "git+https://github.com/matter-labs/era-boojum?branch=main#03888f0fbf810a18e98d010dd11891fe32097352" +source = "git+https://github.com/matter-labs/era-boojum?branch=main#30300f043c9afaeeb35d0f7bd3cc0acaf69ccde4" dependencies = [ "arrayvec 0.7.4", "bincode", "blake2 0.10.6 (registry+https://github.com/rust-lang/crates.io-index)", "const_format", - "convert_case 0.6.0", + "convert_case", "crossbeam 0.8.4", "crypto-bigint 0.5.5", "cs_derive 0.1.0 (git+https://github.com/matter-labs/era-boojum?branch=main)", @@ -808,7 +808,7 @@ dependencies = [ [[package]] name = "circuit_definitions" version = "0.1.0" -source = "git+https://github.com/matter-labs/era-zkevm_test_harness.git?branch=v1.4.1#f16b40eb4662768b5e29030b240420abc60d115b" +source = "git+https://github.com/matter-labs/era-zkevm_test_harness.git?branch=v1.4.1#ce188bd36b9ea0d99a8cdb4da9beb91cd3f721c4" dependencies = [ "crossbeam 0.8.4", "derivative", @@ -976,15 +976,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" -[[package]] -name = "convert_case" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" -dependencies = [ - "unicode-segmentation", -] - [[package]] name = "core-foundation" version = "0.9.4" @@ -1215,7 +1206,7 @@ dependencies = [ [[package]] name = "cs_derive" version = "0.1.0" -source = "git+https://github.com/matter-labs/era-boojum?branch=main#03888f0fbf810a18e98d010dd11891fe32097352" +source = "git+https://github.com/matter-labs/era-boojum?branch=main#30300f043c9afaeeb35d0f7bd3cc0acaf69ccde4" dependencies = [ "proc-macro-error", "proc-macro2 1.0.78", @@ -1428,7 +1419,7 @@ version = "0.99.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" dependencies = [ - "convert_case 0.4.0", + "convert_case", "proc-macro2 1.0.78", "quote 1.0.35", "rustc_version", @@ -6840,7 +6831,7 @@ dependencies = [ [[package]] name = "zkevm_test_harness" version = "1.4.1" -source = "git+https://github.com/matter-labs/era-zkevm_test_harness.git?branch=v1.4.1#f16b40eb4662768b5e29030b240420abc60d115b" +source = "git+https://github.com/matter-labs/era-zkevm_test_harness.git?branch=v1.4.1#ce188bd36b9ea0d99a8cdb4da9beb91cd3f721c4" dependencies = [ "bincode", "circuit_definitions 0.1.0 (git+https://github.com/matter-labs/era-zkevm_test_harness.git?branch=v1.4.1)", diff --git a/prover/prover_fri/tests/basic_test.rs b/prover/prover_fri/tests/basic_test.rs index d9c407b32ef..aad7651fb6d 100644 --- a/prover/prover_fri/tests/basic_test.rs +++ b/prover/prover_fri/tests/basic_test.rs @@ -11,7 +11,7 @@ use zksync_prover_fri_types::{ }; use zksync_types::{basic_fri_types::AggregationRound, L1BatchNumber}; use zksync_vk_setup_data_server_fri::{ - keystore::Keystore, setup_data_generator::generate_cpu_base_layer_setup_data, + keystore::Keystore, setup_data_generator::generate_setup_data_common, }; fn compare_serialized(expected: &T, actual: &T) { @@ -57,10 +57,10 @@ async fn prover_and_assert_base_layer( CircuitWrapper::Recursive(_) => anyhow::bail!("Expected base layer circuit"), }; let keystore = Keystore::default(); - let setup_data = Arc::new( - generate_cpu_base_layer_setup_data(&keystore, circuit) - .context("generate_cpu_base_layers_setup_data()")?, - ); + let circuit_setup_data = + generate_setup_data_common(&keystore, true, circuit.numeric_circuit_type()) + .context("generate_cpu_base_layers_setup_data()")?; + let setup_data = Arc::new(circuit_setup_data.into()); let setup_key = ProverServiceDataKey::new(circuit_id, aggregation_round); let prover_job = ProverJob::new(block_number, expected_proof_id, circuit_wrapper, setup_key); let artifacts = Prover::prove( diff --git a/prover/vk_setup_data_generator_server_fri/src/lib.rs b/prover/vk_setup_data_generator_server_fri/src/lib.rs index dd88d114561..54b3538ad91 100644 --- a/prover/vk_setup_data_generator_server_fri/src/lib.rs +++ b/prover/vk_setup_data_generator_server_fri/src/lib.rs @@ -1,7 +1,7 @@ -#![feature(generic_const_exprs)] #![feature(allocator_api)] use serde::{Deserialize, Serialize}; +use zkevm_test_harness::compute_setups::CircuitSetupData; use zksync_prover_fri_types::circuit_definitions::boojum::{ algebraic_props::{round_function::AbsorptionModeOverwrite, sponge::GenericAlgebraicSponge}, cs::{ @@ -68,6 +68,20 @@ pub type GoldilocksProverSetupData = ProverSetupData< >, >; +impl From for GoldilocksProverSetupData { + fn from(circuit_setup_data: CircuitSetupData) -> Self { + Self { + setup_base: circuit_setup_data.setup_base, + setup: circuit_setup_data.setup, + vk: circuit_setup_data.vk, + setup_tree: circuit_setup_data.setup_tree, + vars_hint: circuit_setup_data.vars_hint, + wits_hint: circuit_setup_data.wits_hint, + finalization_hint: circuit_setup_data.finalization_hint, + } + } +} + #[cfg(feature = "gpu")] #[derive(Debug, Serialize, Deserialize)] #[serde(bound = "F: serde::Serialize + serde::de::DeserializeOwned")] 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 a14807a7347..ba3dce8a617 100644 --- a/prover/vk_setup_data_generator_server_fri/src/main.rs +++ b/prover/vk_setup_data_generator_server_fri/src/main.rs @@ -1,3 +1,6 @@ +//! Tool to generate different types of keys used by the proving system. +//! +//! It can generate verification keys, setup keys, and also commitments. use std::collections::HashMap; use anyhow::Context as _; @@ -15,10 +18,7 @@ use zkevm_test_harness::{ use zksync_prover_fri_types::circuit_definitions::circuit_definitions::recursion_layer::ZkSyncRecursionLayerStorageType; use zksync_vk_setup_data_server_fri::{ keystore::Keystore, - setup_data_generator::{ - generate_all_cpu_setup_data, generate_all_gpu_setup_data, generate_cpu_setup_data, - generate_gpu_setup_data, - }, + setup_data_generator::{CPUSetupDataGenerator, GPUSetupDataGenerator, SetupDataGenerator}, }; mod commitment_generator; @@ -80,43 +80,53 @@ enum CircuitSelector { Basic, } +#[derive(Debug, Parser)] +struct GeneratorOptions { + circuits_type: CircuitSelector, + + /// Specify for which circuit to generate the keys. + #[arg(long)] + numeric_circuit: Option, + + /// If true, then setup keys are not written and only md5 sum is printed. + #[arg(long, default_value = "false")] + dry_run: bool, + + #[arg(long)] + path: Option, + + #[arg(long)] + setup_path: Option, +} + #[derive(Debug, Subcommand)] enum Command { /// Generates verification keys (and finalization hints) for all the basic & leaf circuits. /// Used for verification. #[command(name = "generate-vk")] - GenerateVerificationKeys {}, + GenerateVerificationKeys { + #[arg(long)] + path: Option, + }, /// Generates setup keys (used by the CPU prover). #[command(name = "generate-sk")] GenerateSetupKeys { - circuits_type: CircuitSelector, - - /// Specify for which circuit to generate the keys. - #[arg(long)] - numeric_circuit: Option, - - /// If true, then setup keys are not written and only md5 sum is printed. - #[arg(long, default_value = "false")] - dry_run: bool, + #[command(flatten)] + options: GeneratorOptions, }, /// Generates setup keys (used by the GPU prover). #[command(name = "generate-sk-gpu")] GenerateGPUSetupKeys { - circuits_type: CircuitSelector, - - /// Specify for which circuit to generate the keys. - #[arg(long)] - numeric_circuit: Option, - - /// If true, then setup keys are not written and only md5 sum is printed. - #[arg(long, default_value = "false")] - dry_run: bool, + #[command(flatten)] + options: GeneratorOptions, }, /// Generates and updates the commitments - used by the verification contracts. #[command(name = "update-commitments")] UpdateCommitments { #[arg(long, default_value = "true")] dryrun: bool, + #[arg(long)] + path: Option, }, } @@ -132,6 +142,55 @@ fn print_stats(digests: HashMap) -> anyhow::Result<()> { Ok(()) } +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); + } + if setup_path.is_some() { + panic!("--setup_path must not be set when --path is not set"); + } + Keystore::default() +} + +fn generate_setup_keys( + generator: &dyn SetupDataGenerator, + options: &GeneratorOptions, +) -> anyhow::Result<()> { + match options.circuits_type { + CircuitSelector::All => { + let digests = generator.generate_all(options.dry_run)?; + tracing::info!("Setup keys md5(s):"); + print_stats(digests) + } + CircuitSelector::Recursive => { + let digest = generator + .generate_and_write_setup_data( + false, + options + .numeric_circuit + .expect("--numeric-circuit must be provided"), + options.dry_run, + ) + .context("generate_setup_data()")?; + tracing::info!("digest: {:?}", digest); + Ok(()) + } + CircuitSelector::Basic => { + let digest = generator + .generate_and_write_setup_data( + true, + options + .numeric_circuit + .expect("--numeric-circuit must be provided"), + options.dry_run, + ) + .context("generate_setup_data()")?; + tracing::info!("digest: {:?}", digest); + Ok(()) + } + } +} + fn main() -> anyhow::Result<()> { tracing_subscriber::fmt() .with_env_filter( @@ -142,84 +201,39 @@ fn main() -> anyhow::Result<()> { .init(); let opt = Cli::parse(); - // Setting key store from argument flags will come in next PR. - let keystore = Keystore::default(); match opt.command { - Command::GenerateVerificationKeys {} => { + Command::GenerateVerificationKeys { path } => { + let keystore = keystore_from_optional_path(path, None); tracing::info!( "Generating verification keys and storing them inside {:?}", keystore.get_base_path() ); generate_vks(&keystore).context("generate_vks()") } - Command::UpdateCommitments { dryrun } => read_and_update_contract_toml(&keystore, dryrun), - - Command::GenerateSetupKeys { - circuits_type, - numeric_circuit, - dry_run, - } => match circuits_type { - CircuitSelector::All => { - let digests = generate_all_cpu_setup_data(&keystore, dry_run)?; - tracing::info!("CPU Setup keys md5(s):"); - print_stats(digests) - } - CircuitSelector::Recursive => { - let digest = generate_cpu_setup_data( - &keystore, - false, - numeric_circuit.expect("--numeric-circuit must be provided"), - dry_run, - ) - .context("generate_cpu_setup_data()")?; - tracing::info!("digest: {:?}", digest); - Ok(()) - } - CircuitSelector::Basic => { - let digest = generate_cpu_setup_data( - &keystore, - true, - numeric_circuit.expect("--numeric-circuit must be provided"), - dry_run, - ) - .context("generate_cpu_setup_data()")?; - tracing::info!("digest: {:?}", digest); - Ok(()) - } - }, - Command::GenerateGPUSetupKeys { - circuits_type, - numeric_circuit, - dry_run, - } => match circuits_type { - CircuitSelector::All => { - let digests = generate_all_gpu_setup_data(&keystore, dry_run)?; - tracing::info!("GPU Setup keys md5(s):"); - print_stats(digests) - } - CircuitSelector::Recursive => { - let digest = generate_gpu_setup_data( - &keystore, - false, - numeric_circuit.expect("--numeric-circuit must be provided"), - dry_run, - ) - .context("generate_gpu_setup_data()")?; - tracing::info!("digest: {:?}", digest); - Ok(()) - } - CircuitSelector::Basic => { - let digest = generate_gpu_setup_data( - &keystore, - true, - numeric_circuit.expect("--numeric-circuit must be provided"), - dry_run, - ) - .context("generate_gpu_setup_data()")?; - tracing::info!("digest: {:?}", digest); - Ok(()) - } - }, + Command::UpdateCommitments { dryrun, path } => { + let keystore = keystore_from_optional_path(path, None); + + read_and_update_contract_toml(&keystore, dryrun) + } + + Command::GenerateSetupKeys { options } => { + let generator = CPUSetupDataGenerator { + keystore: keystore_from_optional_path( + options.path.clone(), + options.setup_path.clone(), + ), + }; + generate_setup_keys(&generator, &options) + } + Command::GenerateGPUSetupKeys { options } => { + let generator = GPUSetupDataGenerator { + keystore: keystore_from_optional_path( + options.path.clone(), + options.setup_path.clone(), + ), + }; + generate_setup_keys(&generator, &options) + } } } diff --git a/prover/vk_setup_data_generator_server_fri/src/setup_data_generator.rs b/prover/vk_setup_data_generator_server_fri/src/setup_data_generator.rs index 830ec5bb580..2e73ec8cf65 100644 --- a/prover/vk_setup_data_generator_server_fri/src/setup_data_generator.rs +++ b/prover/vk_setup_data_generator_server_fri/src/setup_data_generator.rs @@ -1,3 +1,6 @@ +//! Set of functions to handle the generation of setup keys. +//! We generate separate set of keys for CPU and for GPU proving. + use std::collections::HashMap; use anyhow::Context as _; @@ -6,304 +9,189 @@ use circuit_definitions::{ zkevm_circuits::scheduler::aux::BaseLayerCircuitType, }; use zkevm_test_harness::{ - geometry_config::get_geometry_config, - prover_utils::{create_base_layer_setup_data, create_recursive_layer_setup_data}, -}; -use zksync_prover_fri_types::{ - circuit_definitions::{ - aux_definitions::witness_oracle::VmWitnessOracle, - boojum::{field::goldilocks::GoldilocksField, worker::Worker}, - circuit_definitions::{ - base_layer::ZkSyncBaseLayerCircuit, recursion_layer::ZkSyncRecursiveLayerCircuit, - }, - ZkSyncDefaultRoundFunction, BASE_LAYER_CAP_SIZE, BASE_LAYER_FRI_LDE_FACTOR, - }, - ProverServiceDataKey, + compute_setups::{generate_circuit_setup_data, CircuitSetupData}, + data_source::SetupDataSource, }; +use zksync_prover_fri_types::ProverServiceDataKey; use zksync_types::basic_fri_types::AggregationRound; #[cfg(feature = "gpu")] -use {crate::GpuProverSetupData, shivini::cs::setup::GpuSetup, shivini::ProverContext}; - -use crate::{ - keystore::Keystore, - utils::{ - get_basic_circuits, get_leaf_circuits, get_node_circuit, get_scheduler_circuit, CYCLE_LIMIT, - }, - GoldilocksProverSetupData, ProverSetupData, +use { + crate::GpuProverSetupData, shivini::cs::setup::GpuSetup, shivini::ProverContext, + zksync_prover_fri_types::circuit_definitions::boojum::worker::Worker, }; -fn generate_all( +use crate::{keystore::Keystore, GoldilocksProverSetupData}; + +/// Internal helper function, that calls the test harness to generate the setup data. +/// It also does a final sanity check to make sure that verification keys didn't change. +pub fn generate_setup_data_common( keystore: &Keystore, - dry_run: bool, - f: fn(&Keystore, bool, u8, bool) -> anyhow::Result, -) -> anyhow::Result> { - let mut result = HashMap::new(); + is_base_layer: bool, + circuit_type: u8, +) -> anyhow::Result { + let mut data_source = keystore.load_keys_to_data_source()?; + let circuit_setup_data = + generate_circuit_setup_data(is_base_layer, circuit_type, &mut data_source).unwrap(); + + let (finalization, vk) = if is_base_layer { + ( + keystore.load_finalization_hints(ProverServiceDataKey::new( + circuit_type, + AggregationRound::BasicCircuits, + ))?, + data_source + .get_base_layer_vk(circuit_type) + .unwrap() + .into_inner(), + ) + } else { + ( + keystore.load_finalization_hints(ProverServiceDataKey::new_recursive(circuit_type))?, + data_source + .get_recursion_layer_vk(circuit_type) + .unwrap() + .into_inner(), + ) + }; - for numeric_circuit in - BaseLayerCircuitType::VM as u8..=BaseLayerCircuitType::L1MessagesHasher as u8 - { - let digest = f(keystore, true, numeric_circuit, dry_run) - .context(format!("base layer, circuit {:?}", numeric_circuit))?; - result.insert(format!("base_{}", numeric_circuit), digest); + // Sanity check to make sure that generated setup data is matching. + if finalization != circuit_setup_data.finalization_hint { + anyhow::bail!("finalization hint mismatch for circuit: {circuit_type}"); } - - // +2 - as '1' and '2' are scheduler and node respectively. - for numeric_circuit in ZkSyncRecursionLayerStorageType::SchedulerCircuit as u8 - ..=ZkSyncRecursionLayerStorageType::LeafLayerCircuitForL1MessagesHasher as u8 - { - let digest = f(keystore, false, numeric_circuit, dry_run) - .context(format!("recursive layer, circuit {:?}", numeric_circuit))?; - result.insert(format!("recursive_{}", numeric_circuit), digest); + if vk != circuit_setup_data.vk { + anyhow::bail!("vk mismatch for circuit: {circuit_type}"); } - Ok(result) -} - -pub fn generate_all_cpu_setup_data( - keystore: &Keystore, - dry_run: bool, -) -> anyhow::Result> { - generate_all(keystore, dry_run, generate_cpu_setup_data) + Ok(circuit_setup_data) } -pub fn generate_all_gpu_setup_data( - keystore: &Keystore, - dry_run: bool, -) -> anyhow::Result> { - generate_all(keystore, dry_run, generate_gpu_setup_data) -} +/// Trait to cover GPU and CPU setup data generation. +pub trait SetupDataGenerator { + /// Generates the setup keys. + fn generate_setup_data( + &self, + is_base_layer: bool, + numeric_circuit: u8, + ) -> anyhow::Result>; + + fn keystore(&self) -> &Keystore; + + /// Generates and stores the setup keys. + /// Returns the md5 check sum of the stored file. + fn generate_and_write_setup_data( + &self, + is_base_layer: bool, + numeric_circuit: u8, + dry_run: bool, + ) -> anyhow::Result { + let serialized = self.generate_setup_data(is_base_layer, numeric_circuit)?; + let digest = md5::compute(&serialized); + + if !dry_run { + self.keystore() + .save_setup_data_for_circuit_type( + if is_base_layer { + ProverServiceDataKey::new(numeric_circuit, AggregationRound::BasicCircuits) + } else { + ProverServiceDataKey::new_recursive(numeric_circuit) + }, + &serialized, + ) + .context("save_setup_data()")?; + } else { + tracing::warn!("Dry run - not writing the key"); + } + Ok(format!("{:?}", digest)) + } -pub fn generate_cpu_setup_data( - keystore: &Keystore, - is_base_layer: bool, - numeric_circuit: u8, - dry_run: bool, -) -> anyhow::Result { - match is_base_layer { - true => { - let circuit = get_base_layer_circuit(keystore, numeric_circuit) - .context("get_base_layer_circuit")?; - let prover_setup_data = generate_cpu_base_layer_setup_data(keystore, circuit) - .context("generate_cpu_base_layer_setup_data()")?; - // Serialization should always succeed. - let serialized = - bincode::serialize(&prover_setup_data).expect("Failed serializing setup data"); - let digest = md5::compute(&serialized); + fn generate_all(&self, dry_run: bool) -> anyhow::Result> { + let mut result = HashMap::new(); - if !dry_run { - keystore - .save_setup_data_for_circuit_type( - ProverServiceDataKey::new(numeric_circuit, AggregationRound::BasicCircuits), - &serialized, - ) - .context("save_setup_data_for_circuit_type()")?; - } else { - tracing::warn!("Dry run - not writing the key"); - } - Ok(format!("{:?}", digest)) + for numeric_circuit in + BaseLayerCircuitType::VM as u8..=BaseLayerCircuitType::L1MessagesHasher as u8 + { + let digest = self + .generate_and_write_setup_data(true, numeric_circuit, dry_run) + .context(format!("base layer, circuit {:?}", numeric_circuit))?; + result.insert(format!("base_{}", numeric_circuit), digest); } - false => { - let circuit = get_recursive_circuit(keystore, numeric_circuit) - .context("get_recursive_circuit()")?; - let prover_setup_data = generate_cpu_recursive_layer_setup_data(keystore, circuit) - .context("generate_cpu_recursive_layer_setup_data()")?; - // Serialization should always succeed. - let serialized = - bincode::serialize(&prover_setup_data).expect("Failed serializing setup data"); - let digest = md5::compute(&serialized); - if !dry_run { - keystore - .save_setup_data_for_circuit_type( - ProverServiceDataKey::new_recursive(numeric_circuit), - &serialized, - ) - .context("save_setup_data_for_circuit_type()")?; - } else { - tracing::warn!("Dry run - not writing the key"); - } - Ok(format!("{:?}", digest)) + for numeric_circuit in ZkSyncRecursionLayerStorageType::SchedulerCircuit as u8 + ..=ZkSyncRecursionLayerStorageType::LeafLayerCircuitForL1MessagesHasher as u8 + { + let digest = self + .generate_and_write_setup_data(false, numeric_circuit, dry_run) + .context(format!("recursive layer, circuit {:?}", numeric_circuit))?; + result.insert(format!("recursive_{}", numeric_circuit), digest); } + Ok(result) } } -fn get_base_layer_circuit( - keystore: &Keystore, - id: u8, -) -> anyhow::Result< - ZkSyncBaseLayerCircuit< - GoldilocksField, - VmWitnessOracle, - ZkSyncDefaultRoundFunction, - >, -> { - get_basic_circuits(keystore, CYCLE_LIMIT, get_geometry_config()) - .context("get_basic_circuits()")? - .into_iter() - .find(|circuit| id == circuit.numeric_circuit_type()) - .with_context(|| format!("No basic circuit found for id: {id}")) +pub struct CPUSetupDataGenerator { + pub keystore: Keystore, } -fn get_recursive_circuit( - keystore: &Keystore, - id: u8, -) -> anyhow::Result { - let mut recursive_circuits = get_leaf_circuits(keystore).context("get_leaf_circuits()")?; - recursive_circuits.push(get_node_circuit(keystore).context("get_node_circuit()")?); - recursive_circuits.push(get_scheduler_circuit(keystore).context("get_scheduler_circuit()")?); - recursive_circuits - .into_iter() - .find(|circuit| id == circuit.numeric_circuit_type()) - .with_context(|| format!("No recursive circuit found for id: {id}")) -} +impl SetupDataGenerator for CPUSetupDataGenerator { + fn generate_setup_data( + &self, + is_base_layer: bool, + numeric_circuit: u8, + ) -> anyhow::Result> { + let circuit_setup_data = + generate_setup_data_common(&self.keystore, is_base_layer, numeric_circuit)?; -pub fn generate_cpu_base_layer_setup_data( - keystore: &Keystore, - circuit: ZkSyncBaseLayerCircuit< - GoldilocksField, - VmWitnessOracle, - ZkSyncDefaultRoundFunction, - >, -) -> anyhow::Result { - let circuit_type = circuit.numeric_circuit_type(); - tracing::info!( - "starting setup data generator for base layer circuit: {}.", - circuit_type - ); - let worker = Worker::new(); - let (setup_base, setup, vk, setup_tree, vars_hint, wits_hint, finalization_hint) = - create_base_layer_setup_data( - circuit.clone(), - &worker, - BASE_LAYER_FRI_LDE_FACTOR, - BASE_LAYER_CAP_SIZE, - ); - let key = ProverServiceDataKey::new(circuit_type, AggregationRound::BasicCircuits); - let existing_finalization_hint = keystore - .load_finalization_hints(key) - .context("load_finalization_hints()")?; - if existing_finalization_hint != finalization_hint { - anyhow::bail!("finalization hint mismatch for circuit: {circuit_type}"); - } - let existing_vk = keystore - .load_base_layer_verification_key(circuit_type) - .with_context(|| format!("load_base_layer_verification_key({circuit_type})"))?; - if existing_vk.into_inner() != vk { - anyhow::bail!("vk mismatch for circuit: {circuit_type}"); - } - Ok(ProverSetupData { - setup_base, - setup, - vk, - setup_tree, - vars_hint, - wits_hint, - finalization_hint, - }) -} + let prover_setup_data: GoldilocksProverSetupData = circuit_setup_data.into(); -fn generate_cpu_recursive_layer_setup_data( - keystore: &Keystore, - circuit: ZkSyncRecursiveLayerCircuit, -) -> anyhow::Result { - let circuit_type = circuit.numeric_circuit_type(); - tracing::info!( - "starting setup data generator for recursive layer circuit: {}.", - circuit_type - ); - let worker = Worker::new(); - let (setup_base, setup, vk, setup_tree, vars_hint, wits_hint, finalization_hint) = - create_recursive_layer_setup_data( - circuit.clone(), - &worker, - BASE_LAYER_FRI_LDE_FACTOR, - BASE_LAYER_CAP_SIZE, - ); - let key = ProverServiceDataKey::new_recursive(circuit_type); - let existing_finalization_hint = keystore - .load_finalization_hints(key) - .context("load_finalization_hints()")?; - if existing_finalization_hint != finalization_hint { - anyhow::bail!("finalization hint mismatch for circuit: {circuit_type}"); + Ok(bincode::serialize(&prover_setup_data).expect("Failed serializing setup data")) } - let existing_vk = keystore - .load_recursive_layer_verification_key(circuit_type) - .context("load_recursive_layer_verification_key()")?; - if existing_vk.into_inner() != vk { - anyhow::bail!("vk mismatch for circuit: {circuit_type}"); + + fn keystore(&self) -> &Keystore { + &self.keystore } - Ok(ProverSetupData { - setup_base, - setup, - vk: vk.clone(), - setup_tree, - vars_hint, - wits_hint, - finalization_hint, - }) } -#[cfg(not(feature = "gpu"))] -pub fn generate_gpu_setup_data( - _keystore: &Keystore, - _is_base_layer: bool, - _numeric_circuit: u8, - _dry_run: bool, -) -> anyhow::Result { - anyhow::bail!("Must compile with --gpu feature to use this option.") +pub struct GPUSetupDataGenerator { + pub keystore: Keystore, } -#[cfg(feature = "gpu")] -pub fn generate_gpu_setup_data( - keystore: &Keystore, - is_base_layer: bool, - numeric_circuit: u8, - dry_run: bool, -) -> anyhow::Result { - let _context = ProverContext::create().context("failed initializing gpu prover context")?; - let (cpu_setup_data, key) = match is_base_layer { - true => { - let circuit = get_base_layer_circuit(keystore, numeric_circuit) - .context("get_base_layer_circuit()")?; - ( - generate_cpu_base_layer_setup_data(keystore, circuit.clone()) - .context("generate_cpu_base_layer_setup_data()")?, - ProverServiceDataKey::new(numeric_circuit, AggregationRound::BasicCircuits), - ) +impl SetupDataGenerator for GPUSetupDataGenerator { + fn generate_setup_data( + &self, + is_base_layer: bool, + numeric_circuit: u8, + ) -> anyhow::Result> { + #[cfg(not(feature = "gpu"))] + { + let _ = (is_base_layer, numeric_circuit); + anyhow::bail!("Must compile with --gpu feature to use this option."); } - false => { - let circuit = get_recursive_circuit(keystore, numeric_circuit) - .context("get_recursive_circuit()")?; - ( - generate_cpu_recursive_layer_setup_data(keystore, circuit.clone()) - .context("generate_cpu_recursive_layer_setup_data()")?, - ProverServiceDataKey::new_recursive(numeric_circuit), + #[cfg(feature = "gpu")] + { + let _context = + ProverContext::create().context("failed initializing gpu prover context")?; + let circuit_setup_data = + generate_setup_data_common(&self.keystore, is_base_layer, numeric_circuit)?; + + let worker = Worker::new(); + let gpu_setup_data = GpuSetup::from_setup_and_hints( + circuit_setup_data.setup_base, + circuit_setup_data.setup_tree, + circuit_setup_data.vars_hint.clone(), + circuit_setup_data.wits_hint, + &worker, ) + .context("failed creating GPU base layer setup data")?; + let gpu_prover_setup_data = GpuProverSetupData { + setup: gpu_setup_data, + vk: circuit_setup_data.vk, + finalization_hint: circuit_setup_data.finalization_hint, + }; + // Serialization should always succeed. + Ok(bincode::serialize(&gpu_prover_setup_data).expect("Failed serializing setup data")) } - }; - let worker = Worker::new(); - let gpu_setup_data = GpuSetup::from_setup_and_hints( - cpu_setup_data.setup_base, - cpu_setup_data.setup_tree, - cpu_setup_data.vars_hint.clone(), - cpu_setup_data.wits_hint, - &worker, - ) - .context("failed creating GPU base layer setup data")?; - let gpu_prover_setup_data = GpuProverSetupData { - setup: gpu_setup_data, - vk: cpu_setup_data.vk, - finalization_hint: cpu_setup_data.finalization_hint, - }; - // Serialization should always succeed. - let serialized = - bincode::serialize(&gpu_prover_setup_data).expect("Failed serializing setup data"); - let digest = md5::compute(&serialized); - if !dry_run { - keystore - .save_setup_data_for_circuit_type(key, &serialized) - .context("save_setup_data_for_circuit_type")?; - } else { - tracing::warn!("Dry run - not writing the key"); } - Ok(format!("{:?}", digest)) + + fn keystore(&self) -> &Keystore { + &self.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 48311c07e88..ab63620afaa 100644 --- a/prover/vk_setup_data_generator_server_fri/src/utils.rs +++ b/prover/vk_setup_data_generator_server_fri/src/utils.rs @@ -1,305 +1,16 @@ -use std::{ - collections::{HashMap, VecDeque}, - fs, -}; - use anyhow::Context as _; -use circuit_definitions::circuit_definitions::recursion_layer::scheduler::SchedulerCircuit; -use itertools::Itertools; -use zkevm_test_harness::{ - compute_setups::{generate_base_layer_vks_and_proofs, generate_recursive_layer_vks_and_proofs}, - data_source::{in_memory_data_source::InMemoryDataSource, BlockDataSource}, - ethereum_types::{Address, U256}, - external_calls::run, - helper::artifact_utils::{save_predeployed_contracts, TestArtifact}, - sha3::{Digest, Keccak256}, - toolset::GeometryConfig, - witness::{ - recursive_aggregation::compute_leaf_params, - tree::{BinarySparseStorageTree, ZKSyncTestingTree}, - }, -}; +use zkevm_test_harness::witness::recursive_aggregation::compute_leaf_params; use zksync_prover_fri_types::circuit_definitions::{ - aux_definitions::witness_oracle::VmWitnessOracle, - base_layer_proof_config, - boojum::{ - field::goldilocks::GoldilocksField, - gadgets::{ - queue::full_state_queue::FullStateCircuitQueueRawWitness, - traits::allocatable::CSAllocatable, - }, - }, - circuit_definitions::{ - base_layer::ZkSyncBaseLayerCircuit, - recursion_layer::{ - base_circuit_type_into_recursive_leaf_circuit_type, - leaf_layer::ZkSyncLeafLayerRecursiveCircuit, - node_layer::ZkSyncNodeLayerRecursiveCircuit, ZkSyncRecursionLayerStorageType, - ZkSyncRecursionProof, ZkSyncRecursiveLayerCircuit, RECURSION_ARITY, SCHEDULER_CAPACITY, - }, - }, - recursion_layer_proof_config, zk_evm, - zk_evm::{bytecode_to_code_hash, testing::storage::InMemoryStorage}, + boojum::field::goldilocks::GoldilocksField, + circuit_definitions::recursion_layer::base_circuit_type_into_recursive_leaf_circuit_type, zkevm_circuits::{ - recursion::{ - leaf_layer::{ - input::{ - RecursionLeafInput, RecursionLeafInstanceWitness, - RecursionLeafParametersWitness, - }, - LeafLayerRecursionConfig, - }, - node_layer::{ - input::{RecursionNodeInput, RecursionNodeInstanceWitness}, - NodeLayerRecursionConfig, - }, - }, - scheduler::{ - aux::BaseLayerCircuitType, input::SchedulerCircuitInstanceWitness, SchedulerConfig, - }, + recursion::leaf_layer::input::RecursionLeafParametersWitness, + scheduler::aux::BaseLayerCircuitType, }, - ZkSyncDefaultRoundFunction, }; use crate::keystore::Keystore; -pub const CYCLE_LIMIT: usize = 20000; - -fn read_witness_artifact(filepath: &str) -> anyhow::Result { - let text = fs::read_to_string(filepath) - .with_context(|| format!("Failed to read witness artifact from path: {filepath}"))?; - serde_json::from_str(text.as_str()).context("serde_json::from_str()") -} - -pub fn get_basic_circuits( - keystore: &Keystore, - cycle_limit: usize, - geometry: GeometryConfig, -) -> anyhow::Result< - Vec< - ZkSyncBaseLayerCircuit< - GoldilocksField, - VmWitnessOracle, - ZkSyncDefaultRoundFunction, - >, - >, -> { - let path = format!("{}/witness_artifacts.json", keystore.get_base_path()); - let mut test_artifact = read_witness_artifact(&path).context("read_withess_artifact()")?; - - let mut storage_impl = InMemoryStorage::new(); - let mut tree = ZKSyncTestingTree::empty(); - - test_artifact.entry_point_address = - *zk_evm::zkevm_opcode_defs::system_params::BOOTLOADER_FORMAL_ADDRESS; - - let predeployed_contracts = test_artifact - .predeployed_contracts - .clone() - .into_iter() - .chain(Some(( - test_artifact.entry_point_address, - test_artifact.entry_point_code.clone(), - ))) - .collect::>(); - save_predeployed_contracts(&mut storage_impl, &mut tree, &predeployed_contracts); - - let used_bytecodes = HashMap::from_iter( - test_artifact - .predeployed_contracts - .values() - .map(|bytecode| { - ( - bytecode_to_code_hash(bytecode).unwrap().into(), - bytecode.clone(), - ) - }) - .chain( - Some(test_artifact.default_account_code.clone()).map(|bytecode| { - ( - bytecode_to_code_hash(&bytecode).unwrap().into(), - bytecode.clone(), - ) - }), - ), - ); - - let previous_enumeration_index = tree.next_enumeration_index(); - let previous_root = tree.root(); - // simulate content hash - - let mut hasher = Keccak256::new(); - hasher.update(previous_enumeration_index.to_be_bytes()); - hasher.update(previous_root); - hasher.update(0u64.to_be_bytes()); // porter shard - hasher.update([0u8; 32]); // porter shard - - let mut previous_data_hash = [0u8; 32]; - previous_data_hash[..].copy_from_slice(hasher.finalize().as_slice()); - - let previous_aux_hash = [0u8; 32]; - let previous_meta_hash = [0u8; 32]; - - let mut hasher = Keccak256::new(); - hasher.update(previous_data_hash); - hasher.update(previous_meta_hash); - hasher.update(previous_aux_hash); - - let mut previous_content_hash = [0u8; 32]; - previous_content_hash[..].copy_from_slice(hasher.finalize().as_slice()); - - let default_account_codehash = - bytecode_to_code_hash(&test_artifact.default_account_code).unwrap(); - let default_account_codehash = U256::from_big_endian(&default_account_codehash); - - let mut base_layer_circuits = vec![]; - let _ = run( - Address::zero(), - test_artifact.entry_point_address, - test_artifact.entry_point_code, - vec![], - false, - default_account_codehash, - used_bytecodes, - vec![], - cycle_limit, - geometry, - storage_impl, - &mut tree, - |circuit| base_layer_circuits.push(circuit), - |_, _, _| {}, - ); - - Ok(base_layer_circuits - .into_iter() - .dedup_by(|a, b| a.numeric_circuit_type() == b.numeric_circuit_type()) - .collect()) -} - -pub fn get_leaf_circuits(keystore: &Keystore) -> anyhow::Result> { - let mut circuits = vec![]; - for base_circuit_type in - (BaseLayerCircuitType::VM as u8)..=(BaseLayerCircuitType::L1MessagesHasher as u8) - { - let input = RecursionLeafInput::placeholder_witness(); - let vk = keystore - .load_base_layer_verification_key(base_circuit_type) - .with_context(|| format!("load_base_layer_verification_key({base_circuit_type})"))?; - - let witness = RecursionLeafInstanceWitness { - input, - vk_witness: vk.clone().into_inner(), - queue_witness: FullStateCircuitQueueRawWitness { - elements: VecDeque::new(), - }, - proof_witnesses: VecDeque::new(), - }; - - let config = LeafLayerRecursionConfig { - proof_config: base_layer_proof_config(), - vk_fixed_parameters: vk.into_inner().fixed_parameters, - capacity: RECURSION_ARITY, - _marker: std::marker::PhantomData, - }; - - let circuit = ZkSyncLeafLayerRecursiveCircuit { - base_layer_circuit_type: BaseLayerCircuitType::from_numeric_value(base_circuit_type), - witness, - config, - transcript_params: (), - _marker: std::marker::PhantomData, - }; - - let circuit = ZkSyncRecursiveLayerCircuit::leaf_circuit_from_base_type( - BaseLayerCircuitType::from_numeric_value(base_circuit_type), - circuit, - ); - circuits.push(circuit) - } - Ok(circuits) -} - -pub fn get_node_circuit(keystore: &Keystore) -> anyhow::Result { - let input = RecursionNodeInput::placeholder_witness(); - - let input_vk = keystore - .load_recursive_layer_verification_key( - ZkSyncRecursionLayerStorageType::LeafLayerCircuitForMainVM as u8, - ) - .context("load_recursive_layer_verification_key(LeafLAyerCircyutFromMainVM")?; - let witness = RecursionNodeInstanceWitness { - input, - vk_witness: input_vk.clone().into_inner(), - split_points: VecDeque::new(), - proof_witnesses: VecDeque::new(), - }; - - let config = NodeLayerRecursionConfig { - proof_config: recursion_layer_proof_config(), - vk_fixed_parameters: input_vk.clone().into_inner().fixed_parameters, - leaf_layer_capacity: RECURSION_ARITY, - node_layer_capacity: RECURSION_ARITY, - _marker: std::marker::PhantomData, - }; - let circuit = ZkSyncNodeLayerRecursiveCircuit { - witness, - config, - transcript_params: (), - _marker: std::marker::PhantomData, - }; - Ok(ZkSyncRecursiveLayerCircuit::NodeLayerCircuit(circuit)) -} - -pub fn get_scheduler_circuit(keystore: &Keystore) -> anyhow::Result { - let mut scheduler_witness = SchedulerCircuitInstanceWitness::placeholder(); - - // node VK - let node_vk = keystore - .load_recursive_layer_verification_key( - ZkSyncRecursionLayerStorageType::NodeLayerCircuit as u8, - ) - .context("load_recursive_layer_verification_key(NodeLayerCircuit)")? - .into_inner(); - scheduler_witness.node_layer_vk_witness = node_vk.clone(); - - let config = SchedulerConfig { - proof_config: recursion_layer_proof_config(), - vk_fixed_parameters: node_vk.fixed_parameters, - capacity: SCHEDULER_CAPACITY, - _marker: std::marker::PhantomData, - }; - let scheduler_circuit = SchedulerCircuit { - witness: scheduler_witness, - config, - transcript_params: (), - eip4844_proof_config: None, - eip4844_vk: None, - eip4844_vk_fixed_parameters: None, - _marker: std::marker::PhantomData, - }; - Ok(ZkSyncRecursiveLayerCircuit::SchedulerCircuit( - scheduler_circuit, - )) -} - -#[allow(dead_code)] -fn get_recursive_layer_proofs() -> Vec { - let mut in_memory_source = InMemoryDataSource::new(); - generate_base_layer_vks_and_proofs(&mut in_memory_source).expect("Failed generating base vk's"); - generate_recursive_layer_vks_and_proofs(&mut in_memory_source) - .expect("Failed generating recursive vk's"); - let mut scheduler_proofs: Vec = vec![]; - for recursive_circuit_type in (ZkSyncRecursionLayerStorageType::LeafLayerCircuitForMainVM as u8) - ..=(ZkSyncRecursionLayerStorageType::LeafLayerCircuitForL1MessagesHasher as u8) - { - let proof = in_memory_source - .get_node_layer_proof(recursive_circuit_type, 0, 0) - .unwrap(); - scheduler_proofs.push(proof.into_inner()); - } - scheduler_proofs -} - pub fn get_leaf_vk_params( keystore: &Keystore, ) -> anyhow::Result)>> {