diff --git a/bus-mapping/src/circuit_input_builder/chunk.rs b/bus-mapping/src/circuit_input_builder/chunk.rs index 17859e9447..6fbb9f4db1 100644 --- a/bus-mapping/src/circuit_input_builder/chunk.rs +++ b/bus-mapping/src/circuit_input_builder/chunk.rs @@ -25,6 +25,7 @@ pub struct ChunkContext { /// Index of current chunk, start from 0 pub idx: usize, /// Used to track the inner chunk counter in every operation in the chunk. + /// it will be reset for every new chunk. /// Contains the next available value. pub rwc: RWCounter, /// Number of chunks @@ -41,7 +42,7 @@ pub struct ChunkContext { pub initial_copy_index: usize, /// pub end_copy_index: usize, - /// Druing dry run, chuncking is desabled + /// Druing dry run, chuncking is disabled pub enable: bool, } diff --git a/circuit-benchmarks/src/copy_circuit.rs b/circuit-benchmarks/src/copy_circuit.rs index e35464ed7f..8638b1a1e1 100644 --- a/circuit-benchmarks/src/copy_circuit.rs +++ b/circuit-benchmarks/src/copy_circuit.rs @@ -156,7 +156,7 @@ mod tests { .handle_block(&block.eth_block, &block.geth_traces) .unwrap(); let block = block_convert(&builder).unwrap(); - let chunk = chunk_convert(&builder, 0).unwrap(); + let chunk = chunk_convert(&block, &builder).unwrap().remove(0); assert_eq!(block.copy_events.len(), copy_event_num); (block, chunk) } diff --git a/circuit-benchmarks/src/evm_circuit.rs b/circuit-benchmarks/src/evm_circuit.rs index 44e42c0aa7..10af1a3e10 100644 --- a/circuit-benchmarks/src/evm_circuit.rs +++ b/circuit-benchmarks/src/evm_circuit.rs @@ -54,7 +54,7 @@ mod evm_circ_benches { .unwrap(); let block = block_convert(&builder).unwrap(); - let chunk = chunk_convert(&builder, 0).unwrap(); + let chunk = chunk_convert(&block, &builder).unwrap().remove(0); let circuit = TestEvmCircuit::::new(block, chunk); let mut rng = XorShiftRng::from_seed([ diff --git a/circuit-benchmarks/src/exp_circuit.rs b/circuit-benchmarks/src/exp_circuit.rs index 610da7d910..5468a4fa3f 100644 --- a/circuit-benchmarks/src/exp_circuit.rs +++ b/circuit-benchmarks/src/exp_circuit.rs @@ -149,9 +149,8 @@ mod tests { .new_circuit_input_builder() .handle_block(&block.eth_block, &block.geth_traces) .unwrap(); - ( - block_convert(&builder).unwrap(), - chunk_convert(&builder, 0).unwrap(), - ) + let block = block_convert(&builder).unwrap(); + let chunk = chunk_convert(&block, &builder).unwrap().remove(0); + (block, chunk) } } diff --git a/integration-tests/src/integration_test_circuits.rs b/integration-tests/src/integration_test_circuits.rs index 62d8858507..3cab71fda2 100644 --- a/integration-tests/src/integration_test_circuits.rs +++ b/integration-tests/src/integration_test_circuits.rs @@ -424,7 +424,7 @@ impl + Circuit> IntegrationTest { block_tag, ); let mut block = block_convert(&builder).unwrap(); - let chunk = chunk_convert(&builder, 0).unwrap(); + let chunk = chunk_convert(&block, &builder).unwrap().remove(0); block.randomness = Fr::from(TEST_MOCK_RANDOMNESS); let circuit = C::new_from_block(&block, &chunk); let instance = circuit.instance(); @@ -441,7 +441,7 @@ impl + Circuit> IntegrationTest { ); // get chronological_rwtable and byaddr_rwtable columns index - let mut cs = ConstraintSystem::<::Scalar>::default(); + let mut cs = ConstraintSystem::<::Fr>::default(); let config = SuperCircuit::configure(&mut cs); let rwtable_columns = config.get_rwtable_columns(); @@ -515,10 +515,9 @@ fn new_empty_block_chunk() -> (Block, Chunk) { .new_circuit_input_builder() .handle_block(&block.eth_block, &block.geth_traces) .unwrap(); - ( - block_convert(&builder).unwrap(), - chunk_convert(&builder, 0).unwrap(), - ) + let block = block_convert(&builder).unwrap(); + let chunk = chunk_convert(&block, &builder).unwrap().remove(0); + (block, chunk) } fn get_general_params(degree: u32) -> ParamsKZG { diff --git a/testool/src/statetest/executor.rs b/testool/src/statetest/executor.rs index 9c60dff085..824370510e 100644 --- a/testool/src/statetest/executor.rs +++ b/testool/src/statetest/executor.rs @@ -16,13 +16,8 @@ use std::{collections::HashMap, str::FromStr}; use thiserror::Error; use zkevm_circuits::{ super_circuit::SuperCircuit, -<<<<<<< HEAD - test_util::CircuitTestBuilder, - witness::{Block, Chunk}, -======= test_util::{CircuitTestBuilder, CircuitTestError}, - witness::Block, ->>>>>>> main + witness::{Block, Chunk}, }; #[derive(PartialEq, Eq, Error, Debug)] @@ -354,12 +349,11 @@ pub fn run_test( let block: Block = zkevm_circuits::evm_circuit::witness::block_convert(&builder).unwrap(); let chunk: Chunk = - zkevm_circuits::evm_circuit::witness::chunk_convert(&builder, 0).unwrap(); + zkevm_circuits::evm_circuit::witness::chunk_convert(&block, &builder) + .unwrap() + .remove(0); -<<<<<<< HEAD - CircuitTestBuilder::<1, 1>::new_from_block(block, chunk).run(); -======= - CircuitTestBuilder::<1, 1>::new_from_block(block) + CircuitTestBuilder::<1, 1>::new_from_block(block, chunk) .run_with_result() .map_err(|err| match err { CircuitTestError::VerificationFailed { reasons, .. } => { @@ -373,7 +367,6 @@ pub fn run_test( found: err.to_string(), }, })?; ->>>>>>> main } else { geth_data.sign(&wallets); diff --git a/zkevm-circuits/src/copy_circuit.rs b/zkevm-circuits/src/copy_circuit.rs index 178202d150..dd65fbb85c 100644 --- a/zkevm-circuits/src/copy_circuit.rs +++ b/zkevm-circuits/src/copy_circuit.rs @@ -859,8 +859,8 @@ impl SubCircuit for CopyCircuit { max_calldata: chunk.fixed_param.max_calldata, txs: block.txs.clone(), max_rws: chunk.fixed_param.max_rws, - rws: chunk.rws.clone(), - prev_chunk_last_rw: chunk.prev_chunk_last_rw, + rws: chunk.chrono_rws.clone(), + prev_chunk_last_rw: chunk.prev_chunk_last_chrono_rw, bytecodes: block.bytecodes.clone(), }, ) diff --git a/zkevm-circuits/src/copy_circuit/test.rs b/zkevm-circuits/src/copy_circuit/test.rs index d392aa0137..7f2056847b 100644 --- a/zkevm-circuits/src/copy_circuit/test.rs +++ b/zkevm-circuits/src/copy_circuit/test.rs @@ -58,8 +58,8 @@ pub fn test_copy_circuit_from_block( max_calldata: chunk.fixed_param.max_calldata, txs: block.txs, max_rws: chunk.fixed_param.max_rws, - rws: chunk.rws, - prev_chunk_last_rw: chunk.prev_chunk_last_rw, + rws: chunk.chrono_rws, + prev_chunk_last_rw: chunk.prev_chunk_last_chrono_rw, bytecodes: block.bytecodes, }, ) @@ -180,7 +180,7 @@ fn gen_tx_log_data() -> CircuitInputBuilder { fn copy_circuit_valid_calldatacopy() { let builder = gen_calldatacopy_data(); let block = block_convert::(&builder).unwrap(); - let chunk = chunk_convert::(&builder, 0).unwrap(); + let chunk = chunk_convert::(&block, &builder).unwrap().remove(0); assert_eq!(test_copy_circuit_from_block(14, block, chunk), Ok(())); } @@ -188,7 +188,7 @@ fn copy_circuit_valid_calldatacopy() { fn copy_circuit_valid_codecopy() { let builder = gen_codecopy_data(); let block = block_convert::(&builder).unwrap(); - let chunk = chunk_convert::(&builder, 0).unwrap(); + let chunk = chunk_convert::(&block, &builder).unwrap().remove(0); assert_eq!(test_copy_circuit_from_block(10, block, chunk), Ok(())); } @@ -196,7 +196,7 @@ fn copy_circuit_valid_codecopy() { fn copy_circuit_valid_extcodecopy() { let builder = gen_extcodecopy_data(); let block = block_convert::(&builder).unwrap(); - let chunk = chunk_convert::(&builder, 0).unwrap(); + let chunk = chunk_convert::(&block, &builder).unwrap().remove(0); assert_eq!(test_copy_circuit_from_block(14, block, chunk), Ok(())); } @@ -204,7 +204,7 @@ fn copy_circuit_valid_extcodecopy() { fn copy_circuit_valid_sha3() { let builder = gen_sha3_data(); let block = block_convert::(&builder).unwrap(); - let chunk = chunk_convert::(&builder, 0).unwrap(); + let chunk = chunk_convert::(&block, &builder).unwrap().remove(0); assert_eq!(test_copy_circuit_from_block(14, block, chunk), Ok(())); } @@ -212,7 +212,7 @@ fn copy_circuit_valid_sha3() { fn copy_circuit_valid_tx_log() { let builder = gen_tx_log_data(); let block = block_convert::(&builder).unwrap(); - let chunk = chunk_convert::(&builder, 0).unwrap(); + let chunk = chunk_convert::(&block, &builder).unwrap().remove(0); assert_eq!(test_copy_circuit_from_block(10, block, chunk), Ok(())); } @@ -225,7 +225,7 @@ fn copy_circuit_invalid_calldatacopy() { builder.block.copy_events[0].bytes[0].0.wrapping_add(1); let block = block_convert::(&builder).unwrap(); - let chunk = chunk_convert::(&builder, 0).unwrap(); + let chunk = chunk_convert::(&block, &builder).unwrap().remove(0); assert_error_matches( test_copy_circuit_from_block(14, block, chunk), @@ -242,7 +242,7 @@ fn copy_circuit_invalid_codecopy() { builder.block.copy_events[0].bytes[0].0.wrapping_add(1); let block = block_convert::(&builder).unwrap(); - let chunk = chunk_convert::(&builder, 0).unwrap(); + let chunk = chunk_convert::(&block, &builder).unwrap().remove(0); assert_error_matches( test_copy_circuit_from_block(10, block, chunk), @@ -259,7 +259,7 @@ fn copy_circuit_invalid_extcodecopy() { builder.block.copy_events[0].bytes[0].0.wrapping_add(1); let block = block_convert::(&builder).unwrap(); - let chunk = chunk_convert::(&builder, 0).unwrap(); + let chunk = chunk_convert::(&block, &builder).unwrap().remove(0); assert_error_matches( test_copy_circuit_from_block(14, block, chunk), @@ -276,7 +276,7 @@ fn copy_circuit_invalid_sha3() { builder.block.copy_events[0].bytes[0].0.wrapping_add(1); let block = block_convert::(&builder).unwrap(); - let chunk = chunk_convert::(&builder, 0).unwrap(); + let chunk = chunk_convert::(&block, &builder).unwrap().remove(0); assert_error_matches( test_copy_circuit_from_block(14, block, chunk), @@ -293,7 +293,7 @@ fn copy_circuit_invalid_tx_log() { builder.block.copy_events[0].bytes[0].0.wrapping_add(1); let block = block_convert::(&builder).unwrap(); - let chunk = chunk_convert::(&builder, 0).unwrap(); + let chunk = chunk_convert::(&block, &builder).unwrap().remove(0); assert_error_matches( test_copy_circuit_from_block(10, block, chunk), diff --git a/zkevm-circuits/src/evm_circuit.rs b/zkevm-circuits/src/evm_circuit.rs index 189ad8d7e3..d8037ae570 100644 --- a/zkevm-circuits/src/evm_circuit.rs +++ b/zkevm-circuits/src/evm_circuit.rs @@ -334,9 +334,9 @@ impl SubCircuit for EvmCircuit { .assign_block(layouter, block, chunk, challenges)?; let (rw_rows_padding, _) = RwMap::table_assignments_padding( - &chunk.rws.table_assignments(true), + &chunk.chrono_rws.table_assignments(true), chunk.fixed_param.max_rws, - chunk.prev_chunk_last_rw, + chunk.prev_chunk_last_chrono_rw, ); let ( alpha_cell, @@ -353,10 +353,10 @@ impl SubCircuit for EvmCircuit { &mut region, // pass non-padding rws to `load_with_region` since it will be padding // inside - &chunk.rws.table_assignments(true), + &chunk.chrono_rws.table_assignments(true), // align with state circuit to padding to same max_rws chunk.fixed_param.max_rws, - chunk.prev_chunk_last_rw, + chunk.prev_chunk_last_chrono_rw, )?; let permutation_cells = config.rw_permutation_config.assign( &mut region, @@ -565,7 +565,7 @@ impl Circuit for EvmCircuit { chunk.fixed_param.max_txs, chunk.fixed_param.max_calldata, )?; - chunk.rws.check_rw_counter_sanity(); + chunk.chrono_rws.check_rw_counter_sanity(); config .bytecode_table .load(&mut layouter, block.bytecodes.clone())?; @@ -698,7 +698,7 @@ mod evm_circuit_stats { .handle_block(&block.eth_block, &block.geth_traces) .unwrap(); let block = block_convert::(&builder).unwrap(); - let chunk = chunk_convert::(&builder, 0).unwrap(); + let chunk = chunk_convert::(&block, &builder).unwrap().remove(0); let k = block.get_test_degree(&chunk); let circuit = EvmCircuit::::get_test_circuit_from_block(block, chunk); let instance = circuit.instance_extend_chunk_ctx(); @@ -723,7 +723,7 @@ mod evm_circuit_stats { .handle_block(&block.eth_block, &block.geth_traces) .unwrap(); let block = block_convert::(&builder).unwrap(); - let chunk = chunk_convert::(&builder, 0).unwrap(); + let chunk = chunk_convert::(&block, &builder).unwrap().remove(0); let k = block.get_test_degree(&chunk); let circuit = EvmCircuit::::get_test_circuit_from_block(block, chunk); @@ -746,7 +746,7 @@ mod evm_circuit_stats { .handle_block(&block.eth_block, &block.geth_traces) .unwrap(); let block = block_convert::(&builder).unwrap(); - let chunk = chunk_convert::(&builder, 0).unwrap(); + let chunk = chunk_convert::(&block, &builder).unwrap().remove(0); let k = block.get_test_degree(&chunk); let circuit = EvmCircuit::::get_test_circuit_from_block(block, chunk); let instance = circuit.instance_extend_chunk_ctx(); diff --git a/zkevm-circuits/src/evm_circuit/execution/end_chunk.rs b/zkevm-circuits/src/evm_circuit/execution/end_chunk.rs index 2b964c6607..08c89791dd 100644 --- a/zkevm-circuits/src/evm_circuit/execution/end_chunk.rs +++ b/zkevm-circuits/src/evm_circuit/execution/end_chunk.rs @@ -29,7 +29,8 @@ impl ExecutionGadget for EndChunkGadget { const EXECUTION_STATE: ExecutionState = ExecutionState::EndChunk; fn configure(cb: &mut EVMConstraintBuilder) -> Self { - // State transition + // State transition on non-last evm step + // TODO/FIXME make EndChunk must be in last evm step and remove below constraint cb.not_step_last(|cb| { // Propagate all the way down. cb.require_step_state_transition(StepStateTransition::same()); @@ -102,7 +103,7 @@ mod test { // } println!( "=> FIXME is fixed? {:?}", - chunk.rws.0.get_mut(&Target::Start) + chunk.chrono_rws.0.get_mut(&Target::Start) ); })) .run_dynamic_chunk(4, 2); diff --git a/zkevm-circuits/src/exp_circuit/test.rs b/zkevm-circuits/src/exp_circuit/test.rs index 5d3f1f5394..6f2129bda6 100644 --- a/zkevm-circuits/src/exp_circuit/test.rs +++ b/zkevm-circuits/src/exp_circuit/test.rs @@ -67,7 +67,7 @@ fn test_ok(base: Word, exponent: Word, k: Option) { let code = gen_code_single(base, exponent); let builder = gen_data(code, false); let block = block_convert::(&builder).unwrap(); - let chunk = chunk_convert::(&builder, 0).unwrap(); + let chunk = chunk_convert::(&block, &builder).unwrap().remove(0); test_exp_circuit(k.unwrap_or(18), block, chunk); } @@ -75,7 +75,7 @@ fn test_ok_multiple(args: Vec<(Word, Word)>) { let code = gen_code_multiple(args); let builder = gen_data(code, false); let block = block_convert::(&builder).unwrap(); - let chunk = chunk_convert::(&builder, 0).unwrap(); + let chunk = chunk_convert::(&block, &builder).unwrap().remove(0); test_exp_circuit(20, block, chunk); } @@ -125,7 +125,7 @@ fn variadic_size_check() { .handle_block(&block.eth_block, &block.geth_traces) .unwrap(); let block = block_convert::(&builder).unwrap(); - let chunk = chunk_convert::(&builder, 0).unwrap(); + let chunk = chunk_convert::(&block, &builder).unwrap().remove(0); let circuit = ExpCircuit::::new(block.exp_events, chunk.fixed_param.max_exp_steps); let prover1 = MockProver::::run(k, &circuit, vec![]).unwrap(); @@ -141,7 +141,7 @@ fn variadic_size_check() { }; let builder = gen_data(code, true); let block = block_convert::(&builder).unwrap(); - let chunk = chunk_convert::(&builder, 0).unwrap(); + let chunk = chunk_convert::(&block, &builder).unwrap().remove(0); let circuit = ExpCircuit::::new(block.exp_events, chunk.fixed_param.max_exp_steps); let prover2 = MockProver::::run(k, &circuit, vec![]).unwrap(); diff --git a/zkevm-circuits/src/pi_circuit/test.rs b/zkevm-circuits/src/pi_circuit/test.rs index 927acb4332..e8f39ed19e 100644 --- a/zkevm-circuits/src/pi_circuit/test.rs +++ b/zkevm-circuits/src/pi_circuit/test.rs @@ -149,7 +149,7 @@ fn test_1tx_1maxtx() { block.sign(&wallets); let block = block_convert(&builder).unwrap(); - let chunk = chunk_convert(&builder, 0).unwrap(); + let chunk = chunk_convert(&block, &builder).unwrap().remove(0); // MAX_TXS, MAX_TXS align with `CircuitsParams` let circuit = PiCircuit::::new_from_block(&block, &chunk); let public_inputs = circuit.instance(); @@ -230,7 +230,7 @@ fn test_1wd_1wdmax() { .unwrap(); let block = block_convert(&builder).unwrap(); - let chunk = chunk_convert(&builder, 0).unwrap(); + let chunk = chunk_convert(&block, &builder).unwrap().remove(0); // MAX_TXS, MAX_TXS align with `CircuitsParams` let circuit = PiCircuit::::new_from_block(&block, &chunk); let public_inputs = circuit.instance(); diff --git a/zkevm-circuits/src/state_circuit.rs b/zkevm-circuits/src/state_circuit.rs index 9b5c6258fe..31657cdfe7 100644 --- a/zkevm-circuits/src/state_circuit.rs +++ b/zkevm-circuits/src/state_circuit.rs @@ -471,7 +471,7 @@ pub struct StateCircuit { impl StateCircuit { /// make a new state circuit from an RwMap pub fn new(chunk: &Chunk) -> Self { - let rows = chunk.rws.table_assignments(false); // address sorted + let rows = chunk.by_address_rws.table_assignments(false); // address sorted let updates = MptUpdates::mock_from(&rows); Self { rows, @@ -483,8 +483,8 @@ impl StateCircuit { overrides: HashMap::new(), permu_alpha: chunk.permu_alpha, permu_gamma: chunk.permu_gamma, - rw_fingerprints: chunk.rw_fingerprints.clone(), - prev_chunk_last_rw: chunk.prev_chunk_last_rw, + rw_fingerprints: chunk.by_address_rw_fingerprints.clone(), + prev_chunk_last_rw: chunk.prev_chunk_last_chrono_rw, _marker: PhantomData::default(), } } @@ -506,7 +506,7 @@ impl SubCircuit for StateCircuit { /// Return the minimum number of rows required to prove the block fn min_num_rows_block(_block: &witness::Block, chunk: &Chunk) -> (usize, usize) { ( - chunk.rws.0.values().flatten().count() + 1, + chunk.chrono_rws.0.values().flatten().count() + 1, chunk.fixed_param.max_rws, ) } diff --git a/zkevm-circuits/src/state_circuit/test.rs b/zkevm-circuits/src/state_circuit/test.rs index ffe06afabe..a00b45c798 100644 --- a/zkevm-circuits/src/state_circuit/test.rs +++ b/zkevm-circuits/src/state_circuit/test.rs @@ -1012,7 +1012,7 @@ fn prover(rows: Vec, overrides: HashMap<(AdviceColumn, isize), Fr>) -> MockP let rw_rows: Vec>> = rw_overrides_skip_first_padding(&rw_rows, &overrides); let rwtable_fingerprints = - get_permutation_fingerprint_of_rwrowvec(&rw_rows, N_ROWS, Fr::ONE, Fr::ONE, Fr::ONE); + get_permutation_fingerprint_of_rwrowvec(&rw_rows, N_ROWS, Fr::ONE, Fr::ONE, Fr::ONE, None); let row_padding_and_overridess = rw_rows.to2dvec(); let updates = MptUpdates::mock_from(&rows); diff --git a/zkevm-circuits/src/super_circuit.rs b/zkevm-circuits/src/super_circuit.rs index df39cbdc42..c19a9247d7 100644 --- a/zkevm-circuits/src/super_circuit.rs +++ b/zkevm-circuits/src/super_circuit.rs @@ -581,7 +581,7 @@ impl SuperCircuit { mock_randomness: F, ) -> Result<(u32, Self, Vec>), bus_mapping::Error> { let mut block = block_convert(builder).unwrap(); - let chunk = chunk_convert(builder, 0).unwrap(); + let chunk = chunk_convert(&block, builder).unwrap().remove(0); block.randomness = mock_randomness; let (_, rows_needed) = Self::min_num_rows_block(&block, &chunk); diff --git a/zkevm-circuits/src/super_circuit/test.rs b/zkevm-circuits/src/super_circuit/test.rs index 2ff959e47a..0acb919ec7 100644 --- a/zkevm-circuits/src/super_circuit/test.rs +++ b/zkevm-circuits/src/super_circuit/test.rs @@ -201,7 +201,7 @@ fn test_rw_table_commitment() { rw_table_commitment::>(¶ms); } -fn rw_table_commitment<'params, Scheme: CommitmentScheme>(params: &'params Scheme::ParamsProver) +fn rw_table_commitment(params: &Scheme::ParamsProver) where ::Scalar: WithSmallOrderMulGroup<3> + eth_types::Field, { diff --git a/zkevm-circuits/src/table/rw_table.rs b/zkevm-circuits/src/table/rw_table.rs index 5535d8e42e..c20da18c60 100644 --- a/zkevm-circuits/src/table/rw_table.rs +++ b/zkevm-circuits/src/table/rw_table.rs @@ -5,14 +5,17 @@ use halo2_proofs::{ }; use halo2_proofs::{ - halo2curves::{bn256::Fr, group::Curve, CurveAffine}, + halo2curves::{ + bn256::Fr, + group::{prime::PrimeCurveAffine, Curve}, + CurveAffine, + }, plonk::{Advice, Assigned, Assignment, Challenge, Fixed, FloorPlanner, Instance, Selector}, poly::{ commitment::{Blind, CommitmentScheme, Params}, EvaluationDomain, LagrangeCoeff, Polynomial, }, }; -use snark_verifier::util::arithmetic::PrimeCurveAffine; use super::*; @@ -186,11 +189,12 @@ impl RwTable { /// get rw table column commitment /// implementation snippet from halo2 `create_proof` https://github.com/privacy-scaling-explorations/halo2/blob/9b33f9ce524dbb9133fc8b9638b2afd0571659a8/halo2_proofs/src/plonk/prover.rs#L37 -pub fn get_rwtable_cols_commitment<'params, Scheme: CommitmentScheme>( +#[allow(unused)] +pub fn get_rwtable_cols_commitment( degree: usize, rws: &[Rw], n_rows: usize, - params_prover: &'params Scheme::ParamsProver, + params_prover: &Scheme::ParamsProver, ) -> Vec<::Curve> where ::Scalar: WithSmallOrderMulGroup<3> + Field, @@ -200,7 +204,7 @@ where _marker: std::marker::PhantomData, } - impl<'a, F: Field> Assignment for WitnessCollection { + impl Assignment for WitnessCollection { fn enter_region(&mut self, _: N) where NR: Into, @@ -319,7 +323,7 @@ where } } - let rwtable_circuit = RwTableCircuit::new(&rws, n_rows, None); + let rwtable_circuit = RwTableCircuit::new(rws, n_rows, None); let domain = EvaluationDomain::<::Scalar>::new( degree as u32, @@ -392,7 +396,7 @@ struct RwTableCircuitConfig { pub rw_table: RwTable, } -impl<'a> RwTableCircuitConfig {} +impl RwTableCircuitConfig {} impl<'a, F: Field> Circuit for RwTableCircuit<'a> { type Config = RwTableCircuitConfig; @@ -432,6 +436,7 @@ impl<'a, F: Field> Circuit for RwTableCircuit<'a> { } // migrate from halo2 library +#[allow(unused)] fn batch_invert_assigned>( domain: EvaluationDomain, assigned: Vec, LagrangeCoeff>>, diff --git a/zkevm-circuits/src/test_util.rs b/zkevm-circuits/src/test_util.rs index b8e901f19d..9617ad38ec 100644 --- a/zkevm-circuits/src/test_util.rs +++ b/zkevm-circuits/src/test_util.rs @@ -195,7 +195,9 @@ impl CircuitTestBuilder { // Build a witness block from trace result. let mut block = crate::witness::block_convert(&builder) .map_err(|err| CircuitTestError::CannotConvertBlock(err.to_string()))?; - let mut chunk = crate::witness::chunk_convert(&builder, chunk_index).unwrap(); + let mut chunk = crate::witness::chunk_convert(&block, &builder) + .unwrap() + .remove(chunk_index); for modifier_fn in &self.block_modifiers { modifier_fn.as_ref()(&mut block, &mut chunk); @@ -217,10 +219,12 @@ impl CircuitTestBuilder { // No cache for EVM circuit with customized features let prover = if block.feature_config.is_mainnet() { let circuit = EvmCircuitCached::get_test_circuit_from_block(block, chunk); - MockProver::::run(k, &circuit, vec![]) + let instance = circuit.instance(); + MockProver::::run(k, &circuit, instance) } else { let circuit = EvmCircuit::get_test_circuit_from_block(block, chunk); - MockProver::::run(k, &circuit, vec![]) + let instance = circuit.instance(); + MockProver::::run(k, &circuit, instance) }; let prover = prover.map_err(|err| CircuitTestError::SynthesisFailure { @@ -285,6 +289,9 @@ impl CircuitTestBuilder { } } + /// Triggers the `CircuitTestBuilder` to convert the [`TestContext`] if any, + /// into a [`Block`] and apply the default or provided block_modifiers or + /// circuit checks to the provers generated for the State and EVM circuits. pub fn run_with_result(self) -> Result<(), CircuitTestError> { let (block, chunk) = self.build_block(0, 1)?; @@ -345,7 +352,9 @@ impl CircuitTestBuilder { // Build a witness block from trace result. let mut block = crate::witness::block_convert(&builder).unwrap(); - let mut chunk = crate::witness::chunk_convert(&builder, chunk_index).unwrap(); + let mut chunk = crate::witness::chunk_convert(&block, &builder) + .unwrap() + .remove(chunk_index); println!("fingerprints = {:?}", chunk.chrono_rw_fingerprints); diff --git a/zkevm-circuits/src/witness/block.rs b/zkevm-circuits/src/witness/block.rs index 4032ad416b..d62a0700ec 100644 --- a/zkevm-circuits/src/witness/block.rs +++ b/zkevm-circuits/src/witness/block.rs @@ -1,3 +1,5 @@ +use std::collections::BTreeMap; + use super::{ rw::{RwFingerprints, ToVec}, ExecStep, Rw, RwMap, Transaction, @@ -35,6 +37,8 @@ pub struct Block { pub end_block: ExecStep, /// Read write events in the RwTable pub rws: RwMap, + /// Read write events in the RwTable, sorted by address + pub by_address_rws: Vec, /// Bytecode used in the block pub bytecodes: CodeDB, /// The block context @@ -57,6 +61,8 @@ pub struct Block { pub keccak_inputs: Vec>, /// Original Block from geth pub eth_block: eth_types::Block, + /// rw_table padding meta data + pub rw_padding_meta: BTreeMap, } impl Block { @@ -280,12 +286,29 @@ pub fn block_convert( let block = &builder.block; let code_db = &builder.code_db; let rws = RwMap::from(&block.container); + let by_address_rws = rws.table_assignments(false); rws.check_value(); + + // get padding statistics data via BtreeMap + // TODO we can implement it in more efficient version via range sum + let rw_padding_meta = builder + .chunks + .iter() + .fold(BTreeMap::new(), |mut map, chunk| { + assert!(chunk.ctx.rwc.0.saturating_sub(1) <= builder.circuits_params.max_rws); + // [chunk.ctx.rwc.0, builder.circuits_params.max_rws + 1) + (chunk.ctx.rwc.0..builder.circuits_params.max_rws + 1).for_each(|padding_rw_counter| { + *map.entry(padding_rw_counter).or_insert(0) += 1; + }); + map + }); + let mut block = Block { // randomness: F::from(0x100), // Special value to reveal elements after RLC randomness: F::from(0xcafeu64), context: block.into(), rws, + by_address_rws, txs: block.txs().to_vec(), bytecodes: code_db.clone(), copy_events: block.copy_events.clone(), @@ -298,6 +321,7 @@ pub fn block_convert( keccak_inputs: circuit_input_builder::keccak_inputs(block, code_db)?, eth_block: block.eth_block.clone(), end_block: block.end_block.clone(), + rw_padding_meta, }; let public_data = public_data_convert(&block); diff --git a/zkevm-circuits/src/witness/chunk.rs b/zkevm-circuits/src/witness/chunk.rs index f92c0b0abc..0ad3907310 100755 --- a/zkevm-circuits/src/witness/chunk.rs +++ b/zkevm-circuits/src/witness/chunk.rs @@ -1,7 +1,9 @@ +use std::{cmp::min, iter}; + /// use super::{ rw::{RwFingerprints, ToVec}, - ExecStep, Rw, RwMap, RwRow, + Block, ExecStep, Rw, RwMap, RwRow, }; use crate::util::unwrap_value; use bus_mapping::{ @@ -11,6 +13,7 @@ use bus_mapping::{ use eth_types::Field; use gadgets::permutation::get_permutation_fingerprints; use halo2_proofs::circuit::Value; +use itertools::Itertools; /// [`Chunk`]` is the struct used by all circuits, which contains chunkwise /// data for witness generation. Used with [`Block`] for blockwise witness. @@ -24,15 +27,17 @@ pub struct Chunk { pub padding: Option, /// Chunk context pub chunk_context: ChunkContext, - /// Read write events in the RwTable - pub rws: RwMap, + /// Read write events in the chronological sorted RwTable + pub chrono_rws: RwMap, + /// Read write events in the by address sorted RwTable + pub by_address_rws: RwMap, /// Permutation challenge alpha pub permu_alpha: F, /// Permutation challenge gamma pub permu_gamma: F, /// Current rw_table permutation fingerprint - pub rw_fingerprints: RwFingerprints, + pub by_address_rw_fingerprints: RwFingerprints, /// Current chronological rw_table permutation fingerprint pub chrono_rw_fingerprints: RwFingerprints, @@ -42,7 +47,9 @@ pub struct Chunk { /// The last call of previous chunk if any, used for assigning continuation pub prev_last_call: Option, /// - pub prev_chunk_last_rw: Option, + pub prev_chunk_last_chrono_rw: Option, + /// + pub prev_chunk_last_by_address_rw: Option, } impl Default for Chunk { @@ -54,20 +61,22 @@ impl Default for Chunk { end_chunk: None, padding: None, chunk_context: ChunkContext::default(), - rws: RwMap::default(), + chrono_rws: RwMap::default(), + by_address_rws: RwMap::default(), permu_alpha: F::from(1), permu_gamma: F::from(1), - rw_fingerprints: RwFingerprints::default(), + by_address_rw_fingerprints: RwFingerprints::default(), chrono_rw_fingerprints: RwFingerprints::default(), fixed_param: FixedCParams::default(), prev_last_call: None, - prev_chunk_last_rw: None, + prev_chunk_last_chrono_rw: None, + prev_chunk_last_by_address_rw: None, } } } impl Chunk { - #[allow(dead_code)] + #[cfg(test)] pub(crate) fn new_from_rw_map( rws: &RwMap, padding_start_rw: Option, @@ -93,8 +102,8 @@ impl Chunk { true, chrono_padding_start_rw, ); - chunk.rws = rws.clone(); - chunk.rw_fingerprints = rw_fingerprints; + chunk.chrono_rws = rws.clone(); + chunk.by_address_rw_fingerprints = rw_fingerprints; chunk.chrono_rw_fingerprints = chrono_rw_fingerprints; chunk } @@ -102,93 +111,142 @@ impl Chunk { /// Convert the idx-th chunk struct in bus-mapping to a witness chunk used in circuits pub fn chunk_convert( + block: &Block, builder: &circuit_input_builder::CircuitInputBuilder, - idx: usize, -) -> Result, Error> { - let block = &builder.block; - let chunk = builder.get_chunk(idx); - let mut rws = RwMap::default(); - let prev_chunk_last_rw = builder.prev_chunk().map(|chunk| { - // rws range [chunk.ctx.initial_rwc, chunk.ctx.end_rwc) - RwMap::get_rw(&block.container, chunk.ctx.end_rwc - 1).expect("Rw does not exist") - }); +) -> Result>, Error> { + let (by_address_rws, padding_meta) = (&block.by_address_rws, &block.rw_padding_meta); - // FIXME(Cecilia): debug - println!( - "| {:?} ... {:?} | @chunk_convert", - chunk.ctx.initial_rwc, chunk.ctx.end_rwc - ); + // Todo: poseidon hash to compute alpha/gamma + let alpha = F::from(103); + let gamma = F::from(101); - // Compute fingerprints of all chunks - let mut challenges = Vec::with_capacity(builder.chunks.len()); - let mut rw_fingerprints: Vec> = Vec::with_capacity(builder.chunks.len()); - let mut chrono_rw_fingerprints: Vec> = - Vec::with_capacity(builder.chunks.len()); + let mut chunks: Vec> = Vec::with_capacity(builder.chunks.len()); + for (i, (prev_chunk, chunk)) in iter::once(None) // left append `None` to make iteration easier + .chain(builder.chunks.iter().map(Some)) + .tuple_windows() + .enumerate() + { + let chunk = chunk.unwrap(); // current chunk always there + let (prev_chunk_last_chrono_rw, prev_chunk_last_by_address_rw) = prev_chunk + .map(|prev_chunk| { + let prev_chunk_last_chrono_rw = { + assert!(builder.circuits_params.max_rws > 0); + let chunk_inner_rwc = prev_chunk.ctx.rwc.0; + if chunk_inner_rwc.saturating_sub(1) == builder.circuits_params.max_rws { + // if prev chunk rws are full, then get the last rwc + RwMap::get_rw(&builder.block.container, prev_chunk.ctx.end_rwc - 1) + .expect("Rw does not exist") + } else { + // last is the padding row + Rw::Padding { + rw_counter: builder.circuits_params.max_rws, + } + } + }; + // get prev_chunk last by_address sorted rw + let prev_chunk_by_address_last_rw = { + let by_address_last_rwc_index = + (prev_chunk.ctx.idx + 1) * builder.circuits_params.max_rws; + let prev_chunk_by_address_last_rwc = by_address_rws + .get(by_address_last_rwc_index - 1) + .cloned() + .or_else(|| { + let target_padding_count = + (by_address_last_rwc_index + 1) - by_address_rws.len(); + let mut accu_count = 0; + padding_meta + .iter() + .find(|(_, count)| { + accu_count += **count; + target_padding_count <= accu_count.try_into().unwrap() + }) + .map(|(padding_rwc, _)| Rw::Padding { + rw_counter: *padding_rwc, + }) + }); - for (i, chunk) in builder.chunks.iter().enumerate() { - // Get the Rws in the i-th chunk + prev_chunk_by_address_last_rwc + }; + (prev_chunk_last_chrono_rw, prev_chunk_by_address_last_rw) + }) + .map(|(prev_chunk_last_rwc, prev_chunk_by_address_last_rwc)| { + (Some(prev_chunk_last_rwc), prev_chunk_by_address_last_rwc) + }) + .unwrap_or_else(|| (None, None)); - // TODO this is just chronological rws, not by address sorted rws - // need another sorted method - let cur_rws = - RwMap::from_chunked(&block.container, chunk.ctx.initial_rwc, chunk.ctx.end_rwc); - cur_rws.check_value(); + println!( + "| {:?} ... {:?} | @chunk_convert", + chunk.ctx.initial_rwc, chunk.ctx.end_rwc + ); + + // Get the rws in the i-th chunk + let chrono_rws = RwMap::from(&builder.block.container) + .take_rw_counter_range(chunk.ctx.initial_rwc, chunk.ctx.end_rwc); - // Todo: poseidon hash - let alpha = F::from(103); - let gamma = F::from(101); + chrono_rws.check_value(); + + let by_address_rws = RwMap::from({ + // by_address_rws + let start = min( + chunk.ctx.idx * builder.circuits_params.max_rws, + by_address_rws.len() - 1, + ); + let end = min( + (chunk.ctx.idx + 1) * builder.circuits_params.max_rws, + by_address_rws.len(), + ); + by_address_rws[start..end].to_vec() + }) + .take_rw_counter_range(chunk.ctx.initial_rwc, chunk.ctx.end_rwc); // Comupute cur fingerprints from last fingerprints and current Rw rows - let cur_fingerprints = get_permutation_fingerprint_of_rwmap( - &cur_rws, + let by_address_rw_fingerprints = get_permutation_fingerprint_of_rwmap( + &by_address_rws, chunk.fixed_param.max_rws, alpha, gamma, if i == 0 { F::from(1) } else { - rw_fingerprints[i - 1].mul_acc + chunks[i - 1].by_address_rw_fingerprints.mul_acc }, false, + prev_chunk_last_by_address_rw, ); - let cur_chrono_fingerprints = get_permutation_fingerprint_of_rwmap( - &cur_rws, + + let chrono_rw_fingerprints = get_permutation_fingerprint_of_rwmap( + &chrono_rws, chunk.fixed_param.max_rws, alpha, gamma, if i == 0 { F::from(1) } else { - chrono_rw_fingerprints[i - 1].mul_acc + chunks[i - 1].chrono_rw_fingerprints.mul_acc }, true, + prev_chunk_last_chrono_rw, ); - challenges.push(vec![alpha, gamma]); - rw_fingerprints.push(cur_fingerprints); - chrono_rw_fingerprints.push(cur_chrono_fingerprints); - if i == idx { - rws = cur_rws; - } + chunks.push(Chunk { + permu_alpha: alpha, + permu_gamma: gamma, + by_address_rw_fingerprints, + chrono_rw_fingerprints, + begin_chunk: chunk.begin_chunk.clone(), + end_chunk: chunk.end_chunk.clone(), + padding: chunk.padding.clone(), + chunk_context: chunk.ctx.clone(), + chrono_rws, + by_address_rws, + fixed_param: chunk.fixed_param, + prev_last_call: chunk.prev_last_call.clone(), + prev_chunk_last_chrono_rw, + prev_chunk_last_by_address_rw, + }); } - // TODO(Cecilia): if we chunk across blocks then need to store the prev_block - let chunk = Chunk { - permu_alpha: challenges[idx][0], - permu_gamma: challenges[idx][1], - rw_fingerprints: rw_fingerprints[idx].clone(), - chrono_rw_fingerprints: chrono_rw_fingerprints[idx].clone(), - begin_chunk: chunk.begin_chunk.clone(), - end_chunk: chunk.end_chunk.clone(), - padding: chunk.padding.clone(), - chunk_context: chunk.ctx.clone(), - rws, - fixed_param: chunk.fixed_param, - prev_last_call: chunk.prev_last_call, - prev_chunk_last_rw, - }; - - Ok(chunk) + Ok(chunks) } /// diff --git a/zkevm-circuits/src/witness/rw.rs b/zkevm-circuits/src/witness/rw.rs index 2076e56a26..907472b900 100644 --- a/zkevm-circuits/src/witness/rw.rs +++ b/zkevm-circuits/src/witness/rw.rs @@ -190,19 +190,13 @@ impl RwMap { rows } - /// Get RwMap for a chunk specified by start and end - pub fn from_chunked( - container: &operation::OperationContainer, - start: usize, - end: usize, - ) -> Self { - let mut rws: Self = container.into(); - for rw in rws.0.values_mut() { + /// take only rw_counter within range + pub fn take_rw_counter_range(mut self, start: usize, end: usize) -> Self { + for rw in self.0.values_mut() { rw.retain(|r| r.rw_counter() >= start && r.rw_counter() < end) } - rws + self } - /// Get one Rw for a chunk specified by index pub fn get_rw(container: &operation::OperationContainer, counter: usize) -> Option { let rws: Self = container.into(); diff --git a/zkevm-circuits/tests/prover_error.rs b/zkevm-circuits/tests/prover_error.rs index bd8cb386c1..3b6ef967df 100644 --- a/zkevm-circuits/tests/prover_error.rs +++ b/zkevm-circuits/tests/prover_error.rs @@ -97,7 +97,9 @@ fn prover_error() { .expect("handle_block"); let (block, chunk) = { let mut block = block_convert(&builder).expect("block_convert"); - let chunk = chunk_convert(&builder, 0).expect("chunk_convert"); + let chunk = chunk_convert(&block, &builder) + .expect("chunk_convert") + .remove(0); block.randomness = Fr::from(MOCK_RANDOMNESS); (block, chunk)