From 0fa2472d8b694d69838f5b0277d16eeb4aada780 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Mon, 12 Aug 2024 12:17:04 +0200 Subject: [PATCH] Do witness processing without CS (#169) --- circuit_encodings/Cargo.toml | 2 +- kzg/Cargo.toml | 2 +- src/witness/individual_circuits/log_demux.rs | 8 +- src/witness/individual_circuits/main_vm.rs | 20 +- .../memory_related/ram_permutation.rs | 9 +- .../storage_application.rs | 3 - src/witness/oracle.rs | 27 +- src/witness/postprocessing/mod.rs | 59 +--- src/witness/recursive_aggregation.rs | 85 +---- src/witness/utils.rs | 317 +++++++++++++----- 10 files changed, 271 insertions(+), 261 deletions(-) diff --git a/circuit_encodings/Cargo.toml b/circuit_encodings/Cargo.toml index e43160f7..e7a0e566 100644 --- a/circuit_encodings/Cargo.toml +++ b/circuit_encodings/Cargo.toml @@ -13,7 +13,7 @@ description = "ZKsync Era circuits encodings" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -zkevm_circuits = "=0.150.2" +zkevm_circuits = "=0.150.3" zk_evm = "=0.150.0" derivative = "2.2" diff --git a/kzg/Cargo.toml b/kzg/Cargo.toml index 2fa5fa26..e9ca7703 100644 --- a/kzg/Cargo.toml +++ b/kzg/Cargo.toml @@ -23,7 +23,7 @@ once_cell = "1" serde_with = {version = "1", features = ["hex"]} boojum = "=0.2.2" -zkevm_circuits = "=0.150.2" +zkevm_circuits = "=0.150.3" [dev-dependencies] rand = "0.4" diff --git a/src/witness/individual_circuits/log_demux.rs b/src/witness/individual_circuits/log_demux.rs index 0c11f550..f0277924 100644 --- a/src/witness/individual_circuits/log_demux.rs +++ b/src/witness/individual_circuits/log_demux.rs @@ -19,7 +19,6 @@ use circuit_definitions::encodings::recursion_request::RecursionQueueSimulator; use circuit_definitions::zkevm_circuits::demux_log_queue::DemuxOutput; use circuit_definitions::zkevm_circuits::scheduler::aux::BaseLayerCircuitType; use circuit_definitions::{encodings::*, Field, RoundFunction}; -use postprocessing::CsForWitnessGeneration; use zk_evm::zkevm_opcode_defs::SECP256R1_VERIFY_PRECOMPILE_ADDRESS; use crate::zk_evm::aux_structures::LogQuery as LogQuery_; @@ -182,7 +181,6 @@ pub(crate) fn process_logs_demux_and_make_circuits< per_circuit_capacity: usize, round_function: &RoundFunction, geometry: &GeometryConfig, - cs_for_witness_generation: &mut CsForWitnessGeneration, mut circuit_callback: CB, mut recursion_queue_callback: QSCB, ) -> ( @@ -198,11 +196,7 @@ pub(crate) fn process_logs_demux_and_make_circuits< let circuit_type = BaseLayerCircuitType::LogDemultiplexer; - let mut maker = CircuitMaker::new( - geometry.cycles_per_log_demuxer, - round_function.clone(), - cs_for_witness_generation, - ); + let mut maker = CircuitMaker::new(geometry.cycles_per_log_demuxer, round_function.clone()); // trivial empty case if log_demux_artifacts diff --git a/src/witness/individual_circuits/main_vm.rs b/src/witness/individual_circuits/main_vm.rs index 4025a65f..9fdce6af 100644 --- a/src/witness/individual_circuits/main_vm.rs +++ b/src/witness/individual_circuits/main_vm.rs @@ -5,10 +5,9 @@ use crate::witness::aux_data_structs::one_per_circuit_accumulator::CircuitsEntry use crate::witness::aux_data_structs::per_circuit_accumulator::PerCircuitAccumulatorSparse; use crate::witness::individual_circuits::SmallField; use crate::witness::oracle::FrameLogQueueDetailedState; -use crate::witness::postprocessing::{ - ClosedFormInputField, CsForWitnessGeneration, FirstAndLastCircuitWitness, -}; +use crate::witness::postprocessing::{ClosedFormInputField, FirstAndLastCircuitWitness}; use crate::witness::tracer::vm_snapshot::VmSnapshot; +use crate::witness::utils::simulate_public_input_value_from_encodable_witness; use crate::zk_evm::aux_structures::MemoryQuery; use crate::zk_evm::vm_state::VmLocalState; use crate::zkevm_circuits::base_structures::vm_state::{ @@ -316,9 +315,7 @@ fn repack_input_for_main_vm( use crate::witness::postprocessing::observable_witness::VmObservableWitness; use crate::zkevm_circuits::fsm_input_output::circuit_inputs::main_vm::VmCircuitWitness; -use super::{ - simulate_public_input_value_from_witness, vm_instance_witness_to_circuit_formal_input, -}; +use super::vm_instance_witness_to_circuit_formal_input; pub(crate) fn process_main_vm< CB: FnMut(ZkSyncBaseLayerCircuit), @@ -344,7 +341,6 @@ pub(crate) fn process_main_vm< flat_new_frames_history: Vec<(Cycle, CallStackEntry)>, mut vm_snapshots: Vec, round_function: Poseidon2Goldilocks, - cs_for_witness_generation: &mut CsForWitnessGeneration, circuit_callback: &mut CB, recursion_queue_callback: &mut QSCB, ) -> ( @@ -372,11 +368,11 @@ pub(crate) fn process_main_vm< observable_input.as_ref().unwrap().clone(); } - let (proof_system_input, compact_form_witness) = simulate_public_input_value_from_witness( - cs_for_witness_generation.take_cs(), - circuit_input.closed_form_input.clone(), - &round_function, - ); + let (proof_system_input, compact_form_witness) = + simulate_public_input_value_from_encodable_witness( + circuit_input.closed_form_input.clone(), + &round_function, + ); let instance = VMMainCircuit { witness: AtomicCell::new(Some(circuit_input)), diff --git a/src/witness/individual_circuits/memory_related/ram_permutation.rs b/src/witness/individual_circuits/memory_related/ram_permutation.rs index fd775395..e2597c4f 100644 --- a/src/witness/individual_circuits/memory_related/ram_permutation.rs +++ b/src/witness/individual_circuits/memory_related/ram_permutation.rs @@ -22,7 +22,7 @@ use circuit_definitions::encodings::recursion_request::RecursionQueueSimulator; use circuit_definitions::zkevm_circuits::scheduler::aux::BaseLayerCircuitType; use circuit_definitions::{encodings::*, Field, RoundFunction}; use memory_query::{CustomMemoryQueueSimulator, QueueWitness}; -use postprocessing::{CsForWitnessGeneration, FirstAndLastCircuitWitness}; +use postprocessing::FirstAndLastCircuitWitness; use rayon::prelude::*; use snark_wrapper::boojum::field::Field as _; @@ -45,7 +45,6 @@ pub(crate) fn compute_ram_circuit_snapshots< num_non_deterministic_heap_queries: usize, per_circuit_capacity: usize, geometry: &GeometryConfig, - cs_for_witness_generation: &mut CsForWitnessGeneration, mut circuit_callback: CB, mut recursion_queue_callback: QSCB, ) -> ( @@ -274,11 +273,7 @@ pub(crate) fn compute_ram_circuit_snapshots< let mut last_queue_state = (placeholder_witness.clone(), placeholder_witness); let circuit_type = BaseLayerCircuitType::RamValidation; - let mut maker = CircuitMaker::new( - geometry.cycles_per_ram_permutation, - round_function.clone(), - cs_for_witness_generation, - ); + let mut maker = CircuitMaker::new(geometry.cycles_per_ram_permutation, round_function.clone()); for ( idx, diff --git a/src/witness/individual_circuits/storage_application.rs b/src/witness/individual_circuits/storage_application.rs index 997a8215..b046250c 100644 --- a/src/witness/individual_circuits/storage_application.rs +++ b/src/witness/individual_circuits/storage_application.rs @@ -21,7 +21,6 @@ use circuit_definitions::encodings::recursion_request::RecursionQueueSimulator; use circuit_definitions::encodings::state_diff_record::StateDiffRecord; use circuit_definitions::encodings::LogQueueSimulator; use circuit_definitions::zkevm_circuits::scheduler::aux::BaseLayerCircuitType; -use postprocessing::CsForWitnessGeneration; use tracing; use zk_evm::aux_structures::LogQuery; @@ -41,7 +40,6 @@ pub(crate) fn decompose_into_storage_application_witnesses< round_function: &Poseidon2Goldilocks, num_rounds_per_circuit: usize, geometry: &GeometryConfig, - cs_for_witness_generation: &mut CsForWitnessGeneration, mut circuit_callback: CB, mut recursion_queue_callback: QSCB, ) -> ( @@ -54,7 +52,6 @@ pub(crate) fn decompose_into_storage_application_witnesses< let mut maker = CircuitMaker::new( geometry.cycles_per_storage_application, round_function.clone(), - cs_for_witness_generation, ); if deduplicated_rollup_storage_queries.is_empty() { diff --git a/src/witness/oracle.rs b/src/witness/oracle.rs index 43fe73c5..2f7cddea 100644 --- a/src/witness/oracle.rs +++ b/src/witness/oracle.rs @@ -5,8 +5,7 @@ use super::artifacts::LogCircuitsArtifacts; use super::individual_circuits::main_vm::CallstackSimulationResult; use super::postprocessing::{ - BlockFirstAndLastBasicCircuitsObservableWitnesses, CsForWitnessGeneration, - FirstAndLastCircuitWitness, + BlockFirstAndLastBasicCircuitsObservableWitnesses, FirstAndLastCircuitWitness, }; use super::tracer::callstack_handler::*; use super::utils::*; @@ -701,7 +700,6 @@ fn process_io_log_circuits< demuxed_log_queues_states: IOLogsQueuesStates, demuxed_log_queries: DemuxedIOLogQueries, round_function: &Poseidon2Goldilocks, - cs_for_witness_generation: &mut CsForWitnessGeneration, mut circuit_callback: &mut CB, mut recursion_queue_callback: &mut QSCB, ) -> ( @@ -799,7 +797,6 @@ fn process_io_log_circuits< round_function, geometry.cycles_per_storage_application as usize, geometry, - cs_for_witness_generation, &mut circuit_callback, &mut recursion_queue_callback, ); @@ -919,7 +916,6 @@ fn process_memory_related_circuits< executed_decommittment_queries: Vec<(Cycle, DecommittmentQuery, Vec)>, precompiles_data: PrecompilesInputData, round_function: &Poseidon2Goldilocks, - cs_for_witness_generation: &mut CsForWitnessGeneration, mut circuit_callback: &mut CB, mut recursion_queue_callback: &mut QSCB, ) -> ( @@ -1112,7 +1108,6 @@ fn process_memory_related_circuits< num_non_deterministic_heap_queries, geometry.cycles_per_ram_permutation as usize, geometry, - cs_for_witness_generation, &mut circuit_callback, &mut recursion_queue_callback, ); @@ -1216,10 +1211,6 @@ pub(crate) fn create_artifacts_from_tracer< *round_function, ); - // Scratch-space constraint system for circuits processing - // Used when creating circuit instances and compact form witnesses - let mut cs_for_witness_generation = CsForWitnessGeneration::new(); - // demux log queue circuit use crate::witness::individual_circuits::log_demux::process_logs_demux_and_make_circuits; @@ -1238,7 +1229,6 @@ pub(crate) fn create_artifacts_from_tracer< geometry.cycles_per_log_demuxer as usize, round_function, geometry, - &mut cs_for_witness_generation, &mut circuit_callback, &mut recursion_queue_callback, ); @@ -1255,7 +1245,6 @@ pub(crate) fn create_artifacts_from_tracer< io_logs_queues_states, demuxed_log_queries.io, round_function, - &mut cs_for_witness_generation, &mut circuit_callback, &mut recursion_queue_callback, ); @@ -1291,7 +1280,6 @@ pub(crate) fn create_artifacts_from_tracer< executed_decommittment_queries, precompiles_data, round_function, - &mut cs_for_witness_generation, &mut circuit_callback, &mut recursion_queue_callback, ); @@ -1339,7 +1327,6 @@ pub(crate) fn create_artifacts_from_tracer< flat_new_frames_history, vm_snapshots, *round_function, - &mut cs_for_witness_generation, &mut circuit_callback, &mut recursion_queue_callback, ); @@ -1377,7 +1364,6 @@ pub(crate) fn create_artifacts_from_tracer< *round_function, |x| circuit_callback(ZkSyncBaseLayerCircuit::CodeDecommittmentsSorter(x)), &mut recursion_queue_callback, - &mut cs_for_witness_generation, ); // Actual decommitter @@ -1389,7 +1375,6 @@ pub(crate) fn create_artifacts_from_tracer< *round_function, |x| circuit_callback(ZkSyncBaseLayerCircuit::CodeDecommitter(x)), &mut recursion_queue_callback, - &mut cs_for_witness_generation, ); // keccak precompiles @@ -1401,7 +1386,6 @@ pub(crate) fn create_artifacts_from_tracer< *round_function, |x| circuit_callback(ZkSyncBaseLayerCircuit::KeccakRoundFunction(x)), &mut recursion_queue_callback, - &mut cs_for_witness_generation, ); // sha256 precompiles @@ -1413,7 +1397,6 @@ pub(crate) fn create_artifacts_from_tracer< *round_function, |x| circuit_callback(ZkSyncBaseLayerCircuit::Sha256RoundFunction(x)), &mut recursion_queue_callback, - &mut cs_for_witness_generation, ); // ecrecover precompiles @@ -1425,7 +1408,6 @@ pub(crate) fn create_artifacts_from_tracer< *round_function, |x| circuit_callback(ZkSyncBaseLayerCircuit::ECRecover(x)), &mut recursion_queue_callback, - &mut cs_for_witness_generation, ); // secp256r1 verify @@ -1437,7 +1419,6 @@ pub(crate) fn create_artifacts_from_tracer< *round_function, |x| circuit_callback(ZkSyncBaseLayerCircuit::Secp256r1Verify(x)), &mut recursion_queue_callback, - &mut cs_for_witness_generation, ); // storage sorter @@ -1448,7 +1429,6 @@ pub(crate) fn create_artifacts_from_tracer< *round_function, |x| circuit_callback(ZkSyncBaseLayerCircuit::StorageSorter(x)), &mut recursion_queue_callback, - &mut cs_for_witness_generation, ); // events sorter @@ -1459,7 +1439,6 @@ pub(crate) fn create_artifacts_from_tracer< *round_function, |x| circuit_callback(ZkSyncBaseLayerCircuit::EventsSorter(x)), &mut recursion_queue_callback, - &mut cs_for_witness_generation, ); // l1 messages sorter @@ -1471,7 +1450,6 @@ pub(crate) fn create_artifacts_from_tracer< *round_function, |x| circuit_callback(ZkSyncBaseLayerCircuit::L1MessagesSorter(x)), &mut recursion_queue_callback, - &mut cs_for_witness_generation, ); // l1 messages pubdata hasher @@ -1483,7 +1461,6 @@ pub(crate) fn create_artifacts_from_tracer< *round_function, |x| circuit_callback(ZkSyncBaseLayerCircuit::L1MessagesHasher(x)), &mut recursion_queue_callback, - &mut cs_for_witness_generation, ); // transient storage sorter @@ -1497,7 +1474,6 @@ pub(crate) fn create_artifacts_from_tracer< *round_function, |x| circuit_callback(ZkSyncBaseLayerCircuit::TransientStorageSorter(x)), &mut recursion_queue_callback, - &mut cs_for_witness_generation, ); // eip 4844 circuits are basic, but they do not need closed form input commitments @@ -1512,7 +1488,6 @@ pub(crate) fn create_artifacts_from_tracer< *round_function, |x| circuit_callback(ZkSyncBaseLayerCircuit::EIP4844Repack(x)), &mut recursion_queue_callback, - &mut cs_for_witness_generation, ); // All done! diff --git a/src/witness/postprocessing/mod.rs b/src/witness/postprocessing/mod.rs index 4e0dc759..4fcb8d4f 100644 --- a/src/witness/postprocessing/mod.rs +++ b/src/witness/postprocessing/mod.rs @@ -2,6 +2,7 @@ use super::*; use crate::witness::utils::*; use crate::zkevm_circuits::eip_4844::input::EIP4844OutputData; +use boojum::gadgets::traits::encodable::WitnessVarLengthEncodable; use circuit_definitions::aux_definitions::witness_oracle::VmWitnessOracle; use circuit_definitions::boojum::field::U64Representable; use circuit_definitions::boojum::gadgets::traits::allocatable::CSAllocatable; @@ -131,18 +132,21 @@ pub(crate) trait ClosedFormInputField { + std::fmt::Debug + CSAllocatable + CircuitVarLengthEncodable + + WitnessVarLengthEncodable + WitnessHookable; type IN: Clone + std::fmt::Debug + CSAllocatable + CircuitVarLengthEncodable + + WitnessVarLengthEncodable + WitnessHookable; type OUT: Clone + std::fmt::Debug + CSAllocatable + CircuitVarLengthEncodable + + WitnessVarLengthEncodable + WitnessHookable; fn closed_form_input(&mut self) -> &mut ClosedFormInputWitness @@ -334,47 +338,16 @@ impl ClosedFormInputField for EIP4844CircuitInstanceWitness } } -pub struct CsForWitnessGeneration { - cs: ConstraintSystemImpl, - cs_use_counter: usize, -} - -impl CsForWitnessGeneration { - pub fn new() -> Self { - Self { - cs: create_cs_for_witness_generation::( - TRACE_LEN_LOG_2_FOR_CALCULATION, - MAX_VARS_LOG_2_FOR_CALCULATION, - ), - cs_use_counter: 0, - } - } - - pub fn take_cs(&mut self) -> &mut ConstraintSystemImpl { - if self.cs_use_counter == CYCLES_PER_SCRATCH_SPACE { - self.cs = create_cs_for_witness_generation::( - TRACE_LEN_LOG_2_FOR_CALCULATION, - MAX_VARS_LOG_2_FOR_CALCULATION, - ); - self.cs_use_counter = 0; - } - self.cs_use_counter += 1; - - &mut self.cs - } -} - -pub(crate) struct CircuitMaker<'a, T: ClosedFormInputField> { +pub(crate) struct CircuitMaker> { geometry: u32, round_function: Poseidon2Goldilocks, observable_input: Option<>::Witness>, - cs_for_witness_generation: &'a mut CsForWitnessGeneration, recurion_queue_simulator: RecursionQueueSimulator, compact_form_witnesses: Vec>, extremes: FirstAndLastCircuitWitness>, } -impl<'a, T> CircuitMaker<'a, T> +impl CircuitMaker where T: ClosedFormInputField, >::Witness: @@ -384,16 +357,11 @@ where >::Witness: serde::Serialize + serde::de::DeserializeOwned + Eq, { - pub(crate) fn new( - geometry: u32, - round_function: Poseidon2Goldilocks, - cs_for_witness_generation: &'a mut CsForWitnessGeneration, - ) -> Self { + pub(crate) fn new(geometry: u32, round_function: Poseidon2Goldilocks) -> Self { Self { geometry, round_function, observable_input: None, - cs_for_witness_generation, recurion_queue_simulator: RecursionQueueSimulator::empty(), compact_form_witnesses: vec![], extremes: FirstAndLastCircuitWitness::default(), @@ -421,11 +389,11 @@ where self.observable_input.as_ref().unwrap().clone(); } - let (proof_system_input, compact_form_witness) = simulate_public_input_value_from_witness( - self.cs_for_witness_generation.take_cs(), - circuit_input.closed_form_input().clone(), - &self.round_function, - ); + let (proof_system_input, compact_form_witness) = + simulate_public_input_value_from_encodable_witness( + circuit_input.closed_form_input().clone(), + &self.round_function, + ); self.compact_form_witnesses.push(compact_form_witness); @@ -510,7 +478,6 @@ pub(crate) fn make_circuits< round_function: Poseidon2Goldilocks, mut circuit_callback: CB, recursion_queue_callback: &mut QSCB, - cs_for_witness_generation: &mut CsForWitnessGeneration, ) -> ( FirstAndLastCircuitWitness>, Vec>, @@ -529,7 +496,7 @@ where RoundFunction = Poseidon2Goldilocks, >, { - let mut maker = CircuitMaker::new(geometry, round_function.clone(), cs_for_witness_generation); + let mut maker = CircuitMaker::new(geometry, round_function.clone()); for circuit_input in circuits_data.into_iter() { circuit_callback(maker.process(circuit_input, circuit_type)); diff --git a/src/witness/recursive_aggregation.rs b/src/witness/recursive_aggregation.rs index aa183017..0ed36e96 100644 --- a/src/witness/recursive_aggregation.rs +++ b/src/witness/recursive_aggregation.rs @@ -44,29 +44,6 @@ use circuit_definitions::circuit_definitions::recursion_layer::{ use circuit_definitions::encodings::recursion_request::RecursionQueueSimulator; use circuit_definitions::encodings::CircuitEquivalentReflection; -pub(crate) fn compute_encodable_item_from_witness< - T: CSAllocatable + CircuitVarLengthEncodable, - const N: usize, - CS: ConstraintSystem, - R: BuildableCircuitRoundFunction - + AlgebraicRoundFunction - + serde::Serialize - + serde::de::DeserializeOwned, ->( - wit: T::Witness, - cs: &mut CS, - round_function: &R, -) -> [F; N] { - // allocate in full - - let element = T::allocate(cs, wit); - - let commitment = commit_variable_length_encodable_item(cs, &element, round_function); - let commitment = commitment.witness_hook(&*cs)().unwrap(); - - commitment -} - pub fn split_recursion_queue(queue: RecursionQueueSimulator) -> Vec> { let round_function = ZkSyncDefaultRoundFunction::default(); queue.split_by(RECURSION_ARITY, &round_function) @@ -205,33 +182,19 @@ pub fn compute_leaf_params( leaf_layer_vk.numeric_circuit_type() ); - let mut cs_for_witness_generation = - create_cs_for_witness_generation::( - TRACE_LEN_LOG_2_FOR_CALCULATION, - MAX_VARS_LOG_2_FOR_CALCULATION, - ); - - let base_vk_commitment: [_; VK_COMMITMENT_LENGTH] = compute_encodable_item_from_witness::< - AllocatedVerificationKey, - VK_COMMITMENT_LENGTH, - _, - _, - >( - base_layer_vk.into_inner(), - &mut cs_for_witness_generation, - &round_function, - ); + let base_vk_commitment: [_; VK_COMMITMENT_LENGTH] = + compute_encodable_witness_commitment::< + AllocatedVerificationKey, + VK_COMMITMENT_LENGTH, + _, + >(base_layer_vk.into_inner(), &round_function); - let leaf_vk_commitment: [_; VK_COMMITMENT_LENGTH] = compute_encodable_item_from_witness::< - AllocatedVerificationKey, - VK_COMMITMENT_LENGTH, - _, - _, - >( - leaf_layer_vk.into_inner(), - &mut cs_for_witness_generation, - &round_function, - ); + let leaf_vk_commitment: [_; VK_COMMITMENT_LENGTH] = + compute_encodable_witness_commitment::< + AllocatedVerificationKey, + VK_COMMITMENT_LENGTH, + _, + >(leaf_layer_vk.into_inner(), &round_function); let params = RecursionLeafParametersWitness:: { circuit_type: F::from_u64_unchecked(circuit_type as u64), @@ -247,19 +210,13 @@ pub fn compute_leaf_vks_and_params_commitment( ) -> [F; LEAF_LAYER_PARAMETERS_COMMITMENT_LENGTH] { let round_function = ZkSyncDefaultRoundFunction::default(); use crate::witness::utils::*; - let mut cs_for_witness_generation = - create_cs_for_witness_generation::( - TRACE_LEN_LOG_2_FOR_CALCULATION, - MAX_VARS_LOG_2_FOR_CALCULATION, - ); let params_commitment: [_; LEAF_LAYER_PARAMETERS_COMMITMENT_LENGTH] = - compute_encodable_item_from_witness::< + compute_encodable_witness_commitment::< [RecursionLeafParameters; NUM_CIRCUIT_TYPES_TO_SCHEDULE], LEAF_LAYER_PARAMETERS_COMMITMENT_LENGTH, _, - _, - >(leaf_params, &mut cs_for_witness_generation, &round_function); + >(leaf_params, &round_function); params_commitment } @@ -269,22 +226,12 @@ pub fn compute_node_vk_commitment( ) -> [F; VK_COMMITMENT_LENGTH] { let round_function = ZkSyncDefaultRoundFunction::default(); use crate::witness::utils::*; - let mut cs_for_witness_generation = - create_cs_for_witness_generation::( - TRACE_LEN_LOG_2_FOR_CALCULATION, - MAX_VARS_LOG_2_FOR_CALCULATION, - ); - let vk_commitment: [_; VK_COMMITMENT_LENGTH] = compute_encodable_item_from_witness::< + let vk_commitment: [_; VK_COMMITMENT_LENGTH] = compute_encodable_witness_commitment::< AllocatedVerificationKey, VK_COMMITMENT_LENGTH, _, - _, - >( - node_vk.into_inner(), - &mut cs_for_witness_generation, - &round_function, - ); + >(node_vk.into_inner(), &round_function); vk_commitment } diff --git a/src/witness/utils.rs b/src/witness/utils.rs index 709e69fb..1f7c780b 100644 --- a/src/witness/utils.rs +++ b/src/witness/utils.rs @@ -22,6 +22,9 @@ use crate::zkevm_circuits::base_structures::vm_state::{ FULL_SPONGE_QUEUE_STATE_WIDTH, QUEUE_STATE_WIDTH, }; use crate::zkevm_circuits::fsm_input_output::circuit_inputs::INPUT_OUTPUT_COMMITMENT_LENGTH; +use boojum::cs::Place; +use boojum::dag::CSWitnessValues; +use boojum::gadgets::traits::encodable::WitnessVarLengthEncodable; use circuit_definitions::boojum::cs::gates::lookup_marker::LookupFormalGate; use circuit_definitions::boojum::cs::gates::ConstantToVariableMappingToolMarker; use circuit_definitions::boojum::cs::gates::FmaGateInBaseWithoutConstantParams; @@ -32,6 +35,7 @@ use circuit_definitions::boojum::cs::Variable; use circuit_definitions::encodings::*; use individual_circuits::main_vm::VmInCircuitAuxilaryParameters; use individual_circuits::main_vm::VmInstanceWitness; +use serde::Serialize; use super::*; @@ -132,7 +136,7 @@ pub fn transform_queue_witness< const N: usize, D: CircuitEncodable, >( - witness_iter: impl Iterator +'a, + witness_iter: impl Iterator + 'a, ) -> CircuitQueueWitness { let wit: VecDeque<_> = witness_iter .map(|(_enc, old_tail, el)| (el.reflect(), *old_tail)) @@ -192,86 +196,31 @@ pub type ConstraintSystemImpl = CSReferenceImplementation< )>, >; -pub const TRACE_LEN_LOG_2_FOR_CALCULATION: usize = 20; -pub const MAX_VARS_LOG_2_FOR_CALCULATION: usize = 26; -pub const CYCLES_PER_SCRATCH_SPACE: usize = 5000; - -pub fn create_cs_for_witness_generation< - F: SmallField, - R: BuildableCircuitRoundFunction - + AlgebraicRoundFunction - + serde::Serialize - + serde::de::DeserializeOwned, ->( - max_trace_len_log_2: usize, - max_vars_log_2: usize, -) -> ConstraintSystemImpl { - // create temporary cs, and allocate in full - - let geometry = CSGeometry { - num_columns_under_copy_permutation: 140, - num_witness_columns: 0, - num_constant_columns: 4, - max_allowed_constraint_degree: 8, - }; - let max_trace_len = 1 << max_trace_len_log_2; - let num_vars = 1 << max_vars_log_2; - - use crate::boojum::cs::cs_builder_reference::CsReferenceImplementationBuilder; - - let builder_impl = - CsReferenceImplementationBuilder::::new(geometry, max_trace_len); - let builder = boojum::cs::cs_builder::new_builder::<_, F>(builder_impl); - let builder = builder.allow_lookup( - boojum::cs::LookupParameters::UseSpecializedColumnsWithTableIdAsConstant { - width: 3, - num_repetitions: 1, - share_table_id: true, - }, - ); - - let builder = ConstantsAllocatorGate::configure_builder( - builder, - GatePlacementStrategy::UseGeneralPurposeColumns, - ); - let builder = R::configure_builder(builder, GatePlacementStrategy::UseGeneralPurposeColumns); - let builder = FmaGateInBaseFieldWithoutConstant::configure_builder( - builder, - GatePlacementStrategy::UseGeneralPurposeColumns, - ); - let builder = BooleanConstraintGate::configure_builder( - builder, - GatePlacementStrategy::UseGeneralPurposeColumns, - ); - let builder = ReductionGate::::configure_builder( - builder, - GatePlacementStrategy::UseGeneralPurposeColumns, - ); - let builder = - SelectionGate::configure_builder(builder, GatePlacementStrategy::UseGeneralPurposeColumns); - - let mut cs = builder.build(num_vars); - - use crate::boojum::gadgets::tables::*; - - let table = create_binop_table(); - cs.add_lookup_table::(table); - - cs -} - -pub fn simulate_public_input_value_from_witness< +pub fn simulate_public_input_value_from_encodable_witness< F: SmallField, - CS: ConstraintSystem, - R: BuildableCircuitRoundFunction - + AlgebraicRoundFunction - + serde::Serialize - + serde::de::DeserializeOwned, - T: Clone + std::fmt::Debug + CSAllocatable + CircuitVarLengthEncodable + WitnessHookable, - IN: Clone + std::fmt::Debug + CSAllocatable + CircuitVarLengthEncodable + WitnessHookable, - OUT: Clone + std::fmt::Debug + CSAllocatable + CircuitVarLengthEncodable + WitnessHookable, + const AW: usize, + const SW: usize, + const CW: usize, + R: AlgebraicRoundFunction, + T: Clone + + std::fmt::Debug + + CSAllocatable + + CircuitVarLengthEncodable + + WitnessVarLengthEncodable + + WitnessHookable, + IN: Clone + + std::fmt::Debug + + CSAllocatable + + CircuitVarLengthEncodable + + WitnessVarLengthEncodable + + WitnessHookable, + OUT: Clone + + std::fmt::Debug + + CSAllocatable + + CircuitVarLengthEncodable + + WitnessVarLengthEncodable + + WitnessHookable, >( - cs: &mut CS, input_witness: ClosedFormInputWitness, round_function: &R, ) -> ( @@ -283,20 +232,129 @@ where >::Witness: serde::Serialize + serde::de::DeserializeOwned + Eq, >::Witness: serde::Serialize + serde::de::DeserializeOwned + Eq, { - // allocate in full - - let full_input = ClosedFormInput::allocate(cs, input_witness); - // compute the compact form - let compact_form = ClosedFormInputCompactForm::from_full_form(cs, &full_input, round_function); // compute the encoding and committment of compact form - let compact_form_witness = compact_form.witness_hook(&*cs)().unwrap(); + let compact_form_witness = closed_form_witness_from_full_form(&input_witness, round_function); + + let public_input = commit_variable_length_encodable_witness::< + F, + ClosedFormInputCompactForm, + AW, + SW, + CW, + INPUT_OUTPUT_COMMITMENT_LENGTH, + R, + >(&compact_form_witness, round_function); - // dbg!(&compact_form_witness); + (public_input, compact_form_witness) +} - let input_commitment = commit_variable_length_encodable_item(cs, &compact_form, round_function); - let public_input = input_commitment.witness_hook(&*cs)().unwrap(); +pub fn closed_form_witness_from_full_form< + F: SmallField, + const AW: usize, + const SW: usize, + const CW: usize, + T: Clone + + std::fmt::Debug + + CSAllocatable + + CircuitVarLengthEncodable + + WitnessVarLengthEncodable + + WitnessHookable, + IN: Clone + + std::fmt::Debug + + CSAllocatable + + CircuitVarLengthEncodable + + WitnessVarLengthEncodable + + WitnessHookable, + OUT: Clone + + std::fmt::Debug + + CSAllocatable + + CircuitVarLengthEncodable + + WitnessVarLengthEncodable + + WitnessHookable, + R: AlgebraicRoundFunction, +>( + full_form: &ClosedFormInputWitness, + round_function: &R, +) -> ClosedFormInputCompactFormWitness +where + >::Witness: serde::Serialize + serde::de::DeserializeOwned + Eq, + >::Witness: serde::Serialize + serde::de::DeserializeOwned + Eq, + >::Witness: serde::Serialize + serde::de::DeserializeOwned + Eq, +{ + let observable_input_committment = commit_variable_length_encodable_witness::< + F, + IN, + AW, + SW, + CW, + CLOSED_FORM_COMMITTMENT_LENGTH, + R, + >(&full_form.observable_input, round_function); + let observable_output_committment = commit_variable_length_encodable_witness::< + F, + OUT, + AW, + SW, + CW, + CLOSED_FORM_COMMITTMENT_LENGTH, + R, + >(&full_form.observable_output, round_function); + + let hidden_fsm_input_committment = commit_variable_length_encodable_witness::< + F, + T, + AW, + SW, + CW, + CLOSED_FORM_COMMITTMENT_LENGTH, + R, + >(&full_form.hidden_fsm_input, round_function); + let hidden_fsm_output_committment = commit_variable_length_encodable_witness::< + F, + T, + AW, + SW, + CW, + CLOSED_FORM_COMMITTMENT_LENGTH, + R, + >(&full_form.hidden_fsm_output, round_function); + + // mask FSM part. Observable part is NEVER masked + + let empty_committment = [F::ZERO; CLOSED_FORM_COMMITTMENT_LENGTH]; + + // mask FSM part. Observable part is NEVER masked + + let hidden_fsm_input_committment = if full_form.start_flag { + empty_committment.clone() + } else { + hidden_fsm_input_committment.clone() + }; - (public_input, compact_form_witness) + // mask output. Observable output is zero is not the last indeed + let observable_output_committment = if full_form.completion_flag { + observable_output_committment.clone() + } else { + empty_committment.clone() + }; + + // and vice versa for FSM + let hidden_fsm_output_committment = if full_form.completion_flag { + empty_committment.clone() + } else { + hidden_fsm_output_committment.clone() + }; + + let new = ClosedFormInputCompactFormWitness { + start_flag: full_form.start_flag, + completion_flag: full_form.completion_flag, + observable_input_committment, + observable_output_committment, + hidden_fsm_input_committment, + hidden_fsm_output_committment, + }; + + new } pub fn vm_instance_witness_to_vm_formal_state( @@ -696,3 +754,84 @@ pub fn transpose_chunks(original: &Vec>, chunk_size: usize) -> transposed } + +pub fn commit_encoding_round_function< + F: SmallField, + const AW: usize, + const SW: usize, + const CW: usize, + const N: usize, + R: AlgebraicRoundFunction, +>( + input: &[F], + _round_function: &R, +) -> [F; N] { + // we use length specialization here + let expected_length = input.len(); + + let mut state = R::initial_state(); + R::specialize_for_len(expected_length as u32, &mut state); + + // pad with zeroes + + let mut buffer_length = expected_length / AW; + if expected_length % AW != 0 { + buffer_length += 1; + } + + buffer_length *= AW; + + let mut buffer = Vec::with_capacity(buffer_length); + buffer.extend_from_slice(input); + + buffer.resize(buffer_length, F::ZERO); + + for chunk in buffer.array_chunks::() { + R::absorb_into_state::(&mut state, chunk); + R::round_function(&mut state); + } + + let output = R::state_into_commitment::(&state); + output +} + +pub fn commit_variable_length_encodable_witness< + F: SmallField, + T: WitnessVarLengthEncodable, + const AW: usize, + const SW: usize, + const CW: usize, + const N: usize, + R: AlgebraicRoundFunction, +>( + item: &T::Witness, + round_function: &R, +) -> [F; N] { + let expected_length = T::witness_encoding_length(item); + + let mut buffer = Vec::with_capacity(expected_length); + T::encode_witness_to_buffer(item, &mut buffer); + + assert_eq!(buffer.len(), expected_length); + + commit_encoding_round_function::(&buffer, round_function) +} + +pub(crate) fn compute_encodable_witness_commitment< + T: CSAllocatable + + WitnessVarLengthEncodable + + CircuitVarLengthEncodable, + const N: usize, + R: BuildableCircuitRoundFunction + + AlgebraicRoundFunction + + serde::Serialize + + serde::de::DeserializeOwned, +>( + wit: T::Witness, + round_function: &R, +) -> [GoldilocksField; N] { + let commitment = + commit_variable_length_encodable_witness::<_, T, 8, 12, 4, N, R>(&wit, round_function); + + commitment +}