From e855b09aa664745019ce80f1848049ccd7a8e205 Mon Sep 17 00:00:00 2001 From: Hamy Ratoanina <hamy.ratoanina@toposware.com> Date: Mon, 22 Apr 2024 12:21:19 -0400 Subject: [PATCH 01/11] Add kernel code to MemBefore --- evm_arithmetization/src/fixed_recursive_verifier.rs | 12 ++++++++++++ evm_arithmetization/src/prover.rs | 6 ++++++ 2 files changed, 18 insertions(+) diff --git a/evm_arithmetization/src/fixed_recursive_verifier.rs b/evm_arithmetization/src/fixed_recursive_verifier.rs index b918ad6f3..096ae2365 100644 --- a/evm_arithmetization/src/fixed_recursive_verifier.rs +++ b/evm_arithmetization/src/fixed_recursive_verifier.rs @@ -982,6 +982,18 @@ where // constant and the `ShiftTable`. let mut trace = vec![]; + // TODO: put it in a dedicated function. + // Push kernel code. + for (i, &byte) in KERNEL.code.iter().enumerate() { + let mut row = vec![F::ZERO; crate::memory_continuation::columns::NUM_COLUMNS]; + row[crate::memory_continuation::columns::FILTER] = F::ONE; + row[crate::memory_continuation::columns::ADDR_CONTEXT] = F::ZERO; + row[crate::memory_continuation::columns::ADDR_SEGMENT] = + F::from_canonical_usize(Segment::Code.unscale()); + row[crate::memory_continuation::columns::ADDR_VIRTUAL] = F::from_canonical_usize(i); + row[crate::memory_continuation::columns::value_limb(0)] = F::from_canonical_u8(byte); + trace.push(row); + } // Push shift table. for i in 0..256 { let mut row = vec![F::ZERO; crate::memory_continuation::columns::NUM_COLUMNS]; diff --git a/evm_arithmetization/src/prover.rs b/evm_arithmetization/src/prover.rs index 942246a85..1c5adab6a 100644 --- a/evm_arithmetization/src/prover.rs +++ b/evm_arithmetization/src/prover.rs @@ -91,6 +91,12 @@ where shift_val <<= 1; } + let mut code_addr = MemoryAddress::new(0, Segment::Code, 0); + for &byte in &KERNEL.code { + memory_before.set(code_addr, U256::from(byte)); + code_addr.increment(); + } + let actual_mem_before = { let mut res = vec![]; for (ctx_idx, ctx) in memory_before.contexts.iter().enumerate() { From e4434d453f233674f74339ade4ec08e970dce770 Mon Sep 17 00:00:00 2001 From: Hamy Ratoanina <hamy.ratoanina@toposware.com> Date: Mon, 22 Apr 2024 12:31:40 -0400 Subject: [PATCH 02/11] Remove kernel code hashing from --- evm_arithmetization/src/cpu/kernel/asm/main.asm | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/evm_arithmetization/src/cpu/kernel/asm/main.asm b/evm_arithmetization/src/cpu/kernel/asm/main.asm index d43a41f11..04b3d44e1 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/main.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/main.asm @@ -61,18 +61,6 @@ global init: EXIT_KERNEL global main: - // First, hash the kernel code - // Start with PUSH0 to avoid having a BytePacking operation at timestamp 0. - // Timestamp 0 is reserved for memory initialization. - %mload_global_metadata(@GLOBAL_METADATA_KERNEL_LEN) - PUSH 0 - // stack: addr, len - KECCAK_GENERAL - // stack: hash - %mload_global_metadata(@GLOBAL_METADATA_KERNEL_HASH) - // stack: expected_hash, hash - %assert_eq - // Initialize accessed addresses and storage keys lists %init_access_lists From 770eb2897ba2aa56c831fc1df68a83a86794b61c Mon Sep 17 00:00:00 2001 From: Hamy Ratoanina <hamy.ratoanina@toposware.com> Date: Mon, 22 Apr 2024 14:13:43 -0400 Subject: [PATCH 03/11] Fix comments --- evm_arithmetization/src/fixed_recursive_verifier.rs | 1 - evm_arithmetization/src/prover.rs | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/evm_arithmetization/src/fixed_recursive_verifier.rs b/evm_arithmetization/src/fixed_recursive_verifier.rs index 096ae2365..b27c550e5 100644 --- a/evm_arithmetization/src/fixed_recursive_verifier.rs +++ b/evm_arithmetization/src/fixed_recursive_verifier.rs @@ -982,7 +982,6 @@ where // constant and the `ShiftTable`. let mut trace = vec![]; - // TODO: put it in a dedicated function. // Push kernel code. for (i, &byte) in KERNEL.code.iter().enumerate() { let mut row = vec![F::ZERO; crate::memory_continuation::columns::NUM_COLUMNS]; diff --git a/evm_arithmetization/src/prover.rs b/evm_arithmetization/src/prover.rs index 1c5adab6a..6cc892bb8 100644 --- a/evm_arithmetization/src/prover.rs +++ b/evm_arithmetization/src/prover.rs @@ -85,6 +85,7 @@ where let mut shift_addr = MemoryAddress::new(0, Segment::ShiftTable, 0); let mut shift_val = U256::one(); + // TODO: move to `generate_traces`. for _ in 0..256 { memory_before.set(shift_addr, shift_val); shift_addr.increment(); From 4f1830c50872be9c846c7a4c804b0270c3bbda3d Mon Sep 17 00:00:00 2001 From: Hamy Ratoanina <hamy.ratoanina@toposware.com> Date: Mon, 22 Apr 2024 18:05:01 -0400 Subject: [PATCH 04/11] Add initial memory check to verifier --- .../src/fixed_recursive_verifier.rs | 11 +-- evm_arithmetization/src/verifier.rs | 96 ++++++++++++++++++- 2 files changed, 95 insertions(+), 12 deletions(-) diff --git a/evm_arithmetization/src/fixed_recursive_verifier.rs b/evm_arithmetization/src/fixed_recursive_verifier.rs index b27c550e5..54d4d1eec 100644 --- a/evm_arithmetization/src/fixed_recursive_verifier.rs +++ b/evm_arithmetization/src/fixed_recursive_verifier.rs @@ -58,6 +58,7 @@ use crate::recursive_verifier::{ StarkWrapperCircuit, }; use crate::util::{h160_limbs, h256_limbs, u256_limbs}; +use crate::verifier::initial_memory_merkle_cap; use crate::witness::memory::MemoryAddress; /// The recursion threshold. We end a chain of recursive proofs once we reach @@ -1024,16 +1025,10 @@ where .map(|column| PolynomialValues::new(column)) .collect::<Vec<_>>(); - let cap = PolynomialBatch::<F, C, D>::from_values( - polys, + let cap = initial_memory_merkle_cap::<F, C, D>( stark_config.fri_config.rate_bits, - false, stark_config.fri_config.cap_height, - &mut TimingTree::default(), - None, - ) - .merkle_tree - .cap; + ); let init_cap_target = MemCapTarget { mem_cap: MerkleCapTarget( diff --git a/evm_arithmetization/src/verifier.rs b/evm_arithmetization/src/verifier.rs index 7b109a870..5309bbd6a 100644 --- a/evm_arithmetization/src/verifier.rs +++ b/evm_arithmetization/src/verifier.rs @@ -1,9 +1,14 @@ -use anyhow::Result; +use anyhow::{ensure, Result}; use ethereum_types::{BigEndianHash, U256}; use itertools::Itertools; use plonky2::field::extension::Extendable; -use plonky2::hash::hash_types::RichField; -use plonky2::plonk::config::GenericConfig; +use plonky2::field::polynomial::PolynomialValues; +use plonky2::fri::oracle::PolynomialBatch; +use plonky2::hash::hash_types::{HashOut, RichField}; +use plonky2::hash::merkle_tree::MerkleCap; +use plonky2::plonk::config::{GenericConfig, GenericHashOut}; +use plonky2::util::timing::TimingTree; +use plonky2::util::transpose; use starky::config::StarkConfig; use starky::cross_table_lookup::{get_ctl_vars_from_proofs, verify_cross_table_lookups}; use starky::lookup::GrandProductChallenge; @@ -15,9 +20,75 @@ use crate::cpu::kernel::aggregator::KERNEL; use crate::cpu::kernel::constants::global_metadata::GlobalMetadata; use crate::memory::segments::Segment; use crate::memory::VALUE_LIMBS; -use crate::proof::{AllProof, AllProofChallenges, PublicValues}; +use crate::proof::{AllProof, AllProofChallenges, MemCap, PublicValues}; use crate::util::h2u; +pub(crate) fn initial_memory_merkle_cap< + F: RichField + Extendable<D>, + C: GenericConfig<D, F = F>, + const D: usize, +>( + rate_bits: usize, + cap_height: usize, +) -> MerkleCap<F, C::Hasher> { + // At the start of a transaction proof, `MemBefore` only contains the RLP + // constant and the `ShiftTable`. + let mut trace = vec![]; + + // Push kernel code. + for (i, &byte) in KERNEL.code.iter().enumerate() { + let mut row = vec![F::ZERO; crate::memory_continuation::columns::NUM_COLUMNS]; + row[crate::memory_continuation::columns::FILTER] = F::ONE; + row[crate::memory_continuation::columns::ADDR_CONTEXT] = F::ZERO; + row[crate::memory_continuation::columns::ADDR_SEGMENT] = + F::from_canonical_usize(Segment::Code.unscale()); + row[crate::memory_continuation::columns::ADDR_VIRTUAL] = F::from_canonical_usize(i); + row[crate::memory_continuation::columns::value_limb(0)] = F::from_canonical_u8(byte); + trace.push(row); + } + // Push shift table. + for i in 0..256 { + let mut row = vec![F::ZERO; crate::memory_continuation::columns::NUM_COLUMNS]; + let val = U256::from(1) << i; + row[crate::memory_continuation::columns::FILTER] = F::ONE; + row[crate::memory_continuation::columns::ADDR_CONTEXT] = F::ZERO; + row[crate::memory_continuation::columns::ADDR_SEGMENT] = + F::from_canonical_usize(Segment::ShiftTable.unscale()); + row[crate::memory_continuation::columns::ADDR_VIRTUAL] = F::from_canonical_usize(i); + for j in 0..crate::memory::VALUE_LIMBS { + row[j + 4] = F::from_canonical_u32((val >> (j * 32)).low_u32()); + } + trace.push(row); + } + + // Padding. + let num_rows = trace.len(); + let num_rows_padded = num_rows.next_power_of_two(); + for _ in num_rows..num_rows_padded { + trace.push(vec![ + F::ZERO; + crate::memory_continuation::columns::NUM_COLUMNS + ]); + } + + let cols = transpose(&trace); + let polys = cols + .into_iter() + .map(|column| PolynomialValues::new(column)) + .collect::<Vec<_>>(); + + PolynomialBatch::<F, C, D>::from_values( + polys, + rate_bits, + false, + cap_height, + &mut TimingTree::default(), + None, + ) + .merkle_tree + .cap +} + pub fn verify_proof<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize>( all_stark: &AllStark<F, D>, all_proof: AllProof<F, C, D>, @@ -133,6 +204,23 @@ where let public_values = all_proof.public_values; + // Verify shift table and kernel code. + for (hash1, hash2) in initial_memory_merkle_cap::<F, C, D>( + config.fri_config.rate_bits, + config.fri_config.cap_height, + ) + .0 + .iter() + .zip(public_values.mem_before.mem_cap.iter()) + { + for (&limb1, limb2) in hash1.to_vec().iter().zip(hash2) { + ensure!( + limb1 == F::from_canonical_u64(limb2.as_u64()), + anyhow::Error::msg("Invalid initial MemBefore Merkle cap.") + ); + } + } + // Extra sums to add to the looked last value. // Only necessary for the Memory values. let mut extra_looking_sums = vec![vec![F::ZERO; config.num_challenges]; NUM_TABLES]; From 3f49daa645a6e3333f9f3d7188d67718c7b1df52 Mon Sep 17 00:00:00 2001 From: Hamy Ratoanina <hamy.ratoanina@toposware.com> Date: Tue, 23 Apr 2024 10:01:51 -0400 Subject: [PATCH 05/11] Remove dead code --- .../src/fixed_recursive_verifier.rs | 46 ------------------- 1 file changed, 46 deletions(-) diff --git a/evm_arithmetization/src/fixed_recursive_verifier.rs b/evm_arithmetization/src/fixed_recursive_verifier.rs index 54d4d1eec..097bfdadc 100644 --- a/evm_arithmetization/src/fixed_recursive_verifier.rs +++ b/evm_arithmetization/src/fixed_recursive_verifier.rs @@ -979,52 +979,6 @@ where ) where F: RichField + Extendable<D>, { - // At the start of a transaction proof, `MemBefore` only contains the RLP - // constant and the `ShiftTable`. - let mut trace = vec![]; - - // Push kernel code. - for (i, &byte) in KERNEL.code.iter().enumerate() { - let mut row = vec![F::ZERO; crate::memory_continuation::columns::NUM_COLUMNS]; - row[crate::memory_continuation::columns::FILTER] = F::ONE; - row[crate::memory_continuation::columns::ADDR_CONTEXT] = F::ZERO; - row[crate::memory_continuation::columns::ADDR_SEGMENT] = - F::from_canonical_usize(Segment::Code.unscale()); - row[crate::memory_continuation::columns::ADDR_VIRTUAL] = F::from_canonical_usize(i); - row[crate::memory_continuation::columns::value_limb(0)] = F::from_canonical_u8(byte); - trace.push(row); - } - // Push shift table. - for i in 0..256 { - let mut row = vec![F::ZERO; crate::memory_continuation::columns::NUM_COLUMNS]; - let val = U256::from(1) << i; - row[crate::memory_continuation::columns::FILTER] = F::ONE; - row[crate::memory_continuation::columns::ADDR_CONTEXT] = F::ZERO; - row[crate::memory_continuation::columns::ADDR_SEGMENT] = - F::from_canonical_usize(Segment::ShiftTable.unscale()); - row[crate::memory_continuation::columns::ADDR_VIRTUAL] = F::from_canonical_usize(i); - for j in 0..crate::memory::VALUE_LIMBS { - row[j + 4] = F::from_canonical_u32((val >> (j * 32)).low_u32()); - } - trace.push(row); - } - - // Padding. - let num_rows = trace.len(); - let num_rows_padded = num_rows.next_power_of_two(); - for _ in num_rows..num_rows_padded { - trace.push(vec![ - F::ZERO; - crate::memory_continuation::columns::NUM_COLUMNS - ]); - } - - let cols = transpose(&trace); - let polys = cols - .into_iter() - .map(|column| PolynomialValues::new(column)) - .collect::<Vec<_>>(); - let cap = initial_memory_merkle_cap::<F, C, D>( stark_config.fri_config.rate_bits, stark_config.fri_config.cap_height, From 1f80b2c2b17f8ef5fc7a6938d91aae9733d95618 Mon Sep 17 00:00:00 2001 From: Hamy Ratoanina <hamy.ratoanina@toposware.com> Date: Tue, 23 Apr 2024 10:03:56 -0400 Subject: [PATCH 06/11] Address comment --- evm_arithmetization/src/verifier.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/evm_arithmetization/src/verifier.rs b/evm_arithmetization/src/verifier.rs index 5309bbd6a..11879d147 100644 --- a/evm_arithmetization/src/verifier.rs +++ b/evm_arithmetization/src/verifier.rs @@ -33,7 +33,7 @@ pub(crate) fn initial_memory_merkle_cap< ) -> MerkleCap<F, C::Hasher> { // At the start of a transaction proof, `MemBefore` only contains the RLP // constant and the `ShiftTable`. - let mut trace = vec![]; + let mut trace = Vec::with_capacity((KERNEL.code.len() + 256).next_power_of_two()); // Push kernel code. for (i, &byte) in KERNEL.code.iter().enumerate() { From f50196a97b8eac4dd3e266e0c6c9e32aba08148a Mon Sep 17 00:00:00 2001 From: Linda Guiga <lindaguiga3@gmail.com> Date: Tue, 23 Apr 2024 14:41:08 +0100 Subject: [PATCH 07/11] Add dummy segments to the left. --- .../src/cpu/kernel/interpreter.rs | 26 ++++------ .../src/fixed_recursive_verifier.rs | 6 +-- evm_arithmetization/src/generation/mod.rs | 11 ++-- evm_arithmetization/src/generation/state.rs | 10 ++-- .../src/memory/memory_stark.rs | 26 ++++++++-- evm_arithmetization/src/prover.rs | 52 ++++++++++++++++--- evm_arithmetization/tests/add11_yml.rs | 16 +++--- .../tests/basic_smart_contract.rs | 4 +- evm_arithmetization/tests/empty_txn_list.rs | 4 +- evm_arithmetization/tests/erc20.rs | 4 +- evm_arithmetization/tests/erc721.rs | 4 +- evm_arithmetization/tests/log_opcode.rs | 14 ++--- .../tests/self_balance_gas_cost.rs | 4 +- evm_arithmetization/tests/selfdestruct.rs | 4 +- evm_arithmetization/tests/simple_transfer.rs | 4 +- evm_arithmetization/tests/withdrawals.rs | 4 +- proof_gen/src/proof_gen.rs | 4 +- 17 files changed, 126 insertions(+), 71 deletions(-) diff --git a/evm_arithmetization/src/cpu/kernel/interpreter.rs b/evm_arithmetization/src/cpu/kernel/interpreter.rs index fb9aa22e6..b493c4eba 100644 --- a/evm_arithmetization/src/cpu/kernel/interpreter.rs +++ b/evm_arithmetization/src/cpu/kernel/interpreter.rs @@ -60,7 +60,7 @@ pub(crate) struct Interpreter<F: Field> { /// in the execution. pub(crate) clock: usize, /// Log of the maximal number of CPU cycles in one segment execution. - max_cpu_len_log: Option<usize>, + max_cpu_len: Option<usize>, } /// Structure storing the state of the interpreter's registers. @@ -162,7 +162,7 @@ pub(crate) struct ExtraSegmentData { /// execution stops at segment `index`. These can then be passed to the /// prover for initialization. pub(crate) fn generate_segment<F: Field>( - max_cpu_len_log: usize, + max_cpu_len: usize, index: usize, inputs: &GenerationInputs, ) -> anyhow::Result< @@ -175,12 +175,8 @@ pub(crate) fn generate_segment<F: Field>( > { let init_label = KERNEL.global_labels["init"]; let initial_registers = RegistersState::new(); - let mut interpreter = Interpreter::<F>::new_with_generation_inputs( - init_label, - vec![], - inputs, - Some(max_cpu_len_log), - ); + let mut interpreter = + Interpreter::<F>::new_with_generation_inputs(init_label, vec![], inputs, Some(max_cpu_len)); let (mut registers_before, mut registers_after, mut before_mem_values, mut after_mem_values) = ( initial_registers, @@ -280,11 +276,11 @@ impl<F: Field> Interpreter<F> { initial_offset: usize, initial_stack: Vec<U256>, inputs: &GenerationInputs, - max_cpu_len_log: Option<usize>, + max_cpu_len: Option<usize>, ) -> Self { debug_inputs(inputs); - let mut result = Self::new(initial_offset, initial_stack, max_cpu_len_log); + let mut result = Self::new(initial_offset, initial_stack, max_cpu_len); result.initialize_interpreter_state(inputs); result } @@ -292,7 +288,7 @@ impl<F: Field> Interpreter<F> { pub(crate) fn new( initial_offset: usize, initial_stack: Vec<U256>, - max_cpu_len_log: Option<usize>, + max_cpu_len: Option<usize>, ) -> Self { let mut interpreter = Self { generation_state: GenerationState::new(&GenerationInputs::default(), &KERNEL.code) @@ -305,7 +301,7 @@ impl<F: Field> Interpreter<F> { jumpdest_table: HashMap::new(), is_jumpdest_analysis: false, clock: 0, - max_cpu_len_log, + max_cpu_len, }; interpreter.generation_state.registers.program_counter = initial_offset; let initial_stack_len = initial_stack.len(); @@ -326,7 +322,7 @@ impl<F: Field> Interpreter<F> { state: &GenerationState<F>, halt_offset: usize, halt_context: usize, - max_cpu_len_log: Option<usize>, + max_cpu_len: Option<usize>, ) -> Self { Self { generation_state: state.soft_clone(), @@ -336,7 +332,7 @@ impl<F: Field> Interpreter<F> { jumpdest_table: HashMap::new(), is_jumpdest_analysis: true, clock: 0, - max_cpu_len_log, + max_cpu_len, } } @@ -520,7 +516,7 @@ impl<F: Field> Interpreter<F> { } pub(crate) fn run(&mut self) -> Result<(RegistersState, Option<MemoryState>), anyhow::Error> { - let (final_registers, final_mem) = self.run_cpu(self.max_cpu_len_log)?; + let (final_registers, final_mem) = self.run_cpu(self.max_cpu_len)?; #[cfg(debug_assertions)] { diff --git a/evm_arithmetization/src/fixed_recursive_verifier.rs b/evm_arithmetization/src/fixed_recursive_verifier.rs index 309cb8e13..4b6d0c2d9 100644 --- a/evm_arithmetization/src/fixed_recursive_verifier.rs +++ b/evm_arithmetization/src/fixed_recursive_verifier.rs @@ -1384,19 +1384,19 @@ where all_stark: &AllStark<F, D>, config: &StarkConfig, generation_inputs: GenerationInputs, - max_cpu_len_log: usize, + max_cpu_len: usize, timing: &mut TimingTree, abort_signal: Option<Arc<AtomicBool>>, ) -> anyhow::Result<Vec<ProverOutputData<F, C, D>>> { let mut all_data_segments = - generate_all_data_segments::<F>(Some(max_cpu_len_log), generation_inputs.clone())?; + generate_all_data_segments::<F>(Some(max_cpu_len), generation_inputs.clone())?; let mut proofs = Vec::with_capacity(all_data_segments.len()); for mut data in all_data_segments { let proof = self.prove_segment( all_stark, config, generation_inputs.clone(), - max_cpu_len_log, + max_cpu_len, &mut data, timing, abort_signal.clone(), diff --git a/evm_arithmetization/src/generation/mod.rs b/evm_arithmetization/src/generation/mod.rs index 36084076e..61913f7f9 100644 --- a/evm_arithmetization/src/generation/mod.rs +++ b/evm_arithmetization/src/generation/mod.rs @@ -43,6 +43,9 @@ use crate::witness::util::mem_write_log; /// Number of cycles to go after having reached the halting state. It is /// equal to the number of cycles in `exc_stop` + 1. pub const NUM_EXTRA_CYCLES_AFTER: usize = 81; +/// Number of cycles to go before starting the execution: it is the number of +/// cycles in `init`. +pub const NUM_EXTRA_CYCLES_BEFORE: usize = 64; /// Memory values used to initialize `MemBefore`. pub type MemBeforeValues = Vec<(MemoryAddress, U256)>; @@ -387,7 +390,7 @@ pub fn generate_traces<F: RichField + Extendable<D>, const D: usize>( // Initialize the state with the one at the end of the // previous segment execution, if any. let GenerationSegmentData { - max_cpu_len_log, + max_cpu_len, memory, registers_before, registers_after, @@ -405,7 +408,7 @@ pub fn generate_traces<F: RichField + Extendable<D>, const D: usize>( let cpu_res = timed!( timing, "simulate CPU", - simulate_cpu(&mut state, *max_cpu_len_log) + simulate_cpu(&mut state, *max_cpu_len) ); if cpu_res.is_err() { output_debug_tries(&state)?; @@ -469,9 +472,9 @@ pub fn generate_traces<F: RichField + Extendable<D>, const D: usize>( fn simulate_cpu<F: Field>( state: &mut GenerationState<F>, - max_cpu_len_log: Option<usize>, + max_cpu_len: Option<usize>, ) -> anyhow::Result<(RegistersState, Option<MemoryState>)> { - let (final_registers, mem_after) = state.run_cpu(max_cpu_len_log)?; + let (final_registers, mem_after) = state.run_cpu(max_cpu_len)?; let pc = state.registers.program_counter; // Setting the values of padding rows. diff --git a/evm_arithmetization/src/generation/state.rs b/evm_arithmetization/src/generation/state.rs index dedd4aa37..fdb486978 100644 --- a/evm_arithmetization/src/generation/state.rs +++ b/evm_arithmetization/src/generation/state.rs @@ -76,9 +76,9 @@ pub(crate) trait State<F: Field> { fn get_context(&self) -> usize; /// Checks whether we have reached the maximal cpu length. - fn at_end_segment(&self, opt_max_cpu_len_log: Option<usize>) -> bool { - if let Some(max_cpu_len_log) = opt_max_cpu_len_log { - self.get_clock() == (1 << max_cpu_len_log) - NUM_EXTRA_CYCLES_AFTER + fn at_end_segment(&self, opt_max_cpu_len: Option<usize>) -> bool { + if let Some(max_cpu_len) = opt_max_cpu_len { + self.get_clock() == max_cpu_len - NUM_EXTRA_CYCLES_AFTER } else { false } @@ -167,7 +167,7 @@ pub(crate) trait State<F: Field> { /// `GenerationState`. fn run_cpu( &mut self, - max_cpu_len_log: Option<usize>, + max_cpu_len: Option<usize>, ) -> anyhow::Result<(RegistersState, Option<MemoryState>)> where Self: Transition<F>, @@ -183,7 +183,7 @@ pub(crate) trait State<F: Field> { let pc = registers.program_counter; let halt_final = registers.is_kernel && halt_offsets.contains(&pc); - if running && (self.at_halt() || self.at_end_segment(max_cpu_len_log)) { + if running && (self.at_halt() || self.at_end_segment(max_cpu_len)) { running = false; final_registers = registers; diff --git a/evm_arithmetization/src/memory/memory_stark.rs b/evm_arithmetization/src/memory/memory_stark.rs index d7ba43eff..e229df410 100644 --- a/evm_arithmetization/src/memory/memory_stark.rs +++ b/evm_arithmetization/src/memory/memory_stark.rs @@ -1,4 +1,5 @@ use core::marker::PhantomData; +use std::cmp::max; use ethereum_types::U256; use itertools::Itertools; @@ -29,7 +30,7 @@ use crate::memory::columns::{ TIMESTAMP, TIMESTAMP_INV, VIRTUAL_FIRST_CHANGE, }; use crate::memory::VALUE_LIMBS; -use crate::witness::memory::MemoryOpKind::Read; +use crate::witness::memory::MemoryOpKind::{self, Read}; use crate::witness::memory::{MemoryAddress, MemoryOp}; /// Creates the vector of `Columns` corresponding to: @@ -235,8 +236,9 @@ impl<F: RichField + Extendable<D>, const D: usize> MemoryStark<F, D> { if (trace_col_vecs[CONTEXT_FIRST_CHANGE][i] == F::ONE) || (trace_col_vecs[SEGMENT_FIRST_CHANGE][i] == F::ONE) { - // CONTEXT_FIRST_CHANGE and SEGMENT_FIRST_CHANGE should be 0 at the last row, so - // the index should never be out of bounds. + // CONTEXT_FIRST_CHANGE and SEGMENT_FIRST_CHANGE should be 0 at + // the last row, so the index should never be + // out of bounds. if i < trace_col_vecs[ADDR_VIRTUAL].len() - 1 { let x_val = trace_col_vecs[ADDR_VIRTUAL][i + 1].to_canonical_u64() as usize; trace_col_vecs[FREQUENCIES][x_val] += F::ONE; @@ -275,6 +277,24 @@ impl<F: RichField + Extendable<D>, const D: usize> MemoryStark<F, D> { /// range check, so this method would add two dummy reads to the same /// address, say at timestamps 50 and 80. fn fill_gaps(memory_ops: &mut Vec<MemoryOp>) { + // First, insert padding row at at address (0 0, 0) if the first row doesn't + // have a first virtual address at 0. + if memory_ops[0].address.virt != 0 { + let dummy_addr = MemoryAddress { + context: 0, + segment: 0, + virt: 0, + }; + memory_ops.reverse(); + memory_ops.push(MemoryOp { + filter: false, + timestamp: 1, + address: dummy_addr, + kind: MemoryOpKind::Read, + value: 0.into(), + }); + memory_ops.reverse(); + } let max_rc = memory_ops.len().next_power_of_two() - 1; for (mut curr, mut next) in memory_ops.clone().into_iter().tuple_windows() { if curr.address.context != next.address.context diff --git a/evm_arithmetization/src/prover.rs b/evm_arithmetization/src/prover.rs index 3c92e4726..03135eb93 100644 --- a/evm_arithmetization/src/prover.rs +++ b/evm_arithmetization/src/prover.rs @@ -29,7 +29,9 @@ use crate::cpu::kernel::interpreter::{ generate_segment, set_registers_and_run, ExtraSegmentData, Interpreter, }; use crate::generation::state::GenerationState; -use crate::generation::{generate_traces, GenerationInputs}; +use crate::generation::{ + generate_traces, GenerationInputs, NUM_EXTRA_CYCLES_AFTER, NUM_EXTRA_CYCLES_BEFORE, +}; use crate::get_challenges::observe_public_values; use crate::memory::segments::Segment; use crate::proof::{AllProof, MemCap, PublicValues, RegistersData}; @@ -48,9 +50,10 @@ pub struct GenerationSegmentData { /// Extra data required to initialize a segment. pub(crate) extra_data: ExtraSegmentData, /// Log of the maximal cpu length. - pub(crate) max_cpu_len_log: Option<usize>, + pub(crate) max_cpu_len: Option<usize>, } +/// Generate traces, then create all STARK proofs. /// Generate traces, then create all STARK proofs. pub fn prove<F, C, const D: usize>( all_stark: &AllStark<F, D>, @@ -473,7 +476,7 @@ pub fn check_abort_signal(abort_signal: Option<Arc<AtomicBool>>) -> Result<()> { /// Returns a vector containing the data required to generate all the segments /// of a transaction. pub fn generate_all_data_segments<F: RichField>( - max_cpu_len_log: Option<usize>, + max_cpu_len: Option<usize>, inputs: GenerationInputs, ) -> anyhow::Result<Vec<GenerationSegmentData>> { let mut all_seg_data = vec![]; @@ -482,14 +485,14 @@ pub fn generate_all_data_segments<F: RichField>( KERNEL.global_labels["init"], vec![], &inputs, - max_cpu_len_log, + max_cpu_len, ); let mut segment_data = GenerationSegmentData { registers_before: RegistersState::new(), registers_after: RegistersState::new(), memory: MemoryState::default(), - max_cpu_len_log, + max_cpu_len, extra_data: ExtraSegmentData { trimmed_inputs: interpreter.generation_state.inputs.clone(), bignum_modmul_result_limbs: interpreter @@ -523,7 +526,7 @@ pub fn generate_all_data_segments<F: RichField>( registers_before: updated_registers, // `registers_after` will be set correctly at the next iteration.` registers_after: updated_registers, - max_cpu_len_log, + max_cpu_len, memory: mem_after .expect("The interpreter was running, so it should have returned a MemoryState"), extra_data: ExtraSegmentData { @@ -543,6 +546,39 @@ pub fn generate_all_data_segments<F: RichField>( }; } + // We need at least two segments to prove a segment aggregation. + if all_seg_data.len() == 1 { + let new_max_cpu_len = Some(NUM_EXTRA_CYCLES_AFTER + NUM_EXTRA_CYCLES_BEFORE); + let mut interpreter = Interpreter::<F>::new_with_generation_inputs( + KERNEL.global_labels["init"], + vec![], + &inputs, + new_max_cpu_len, + ); + + let dummy_seg = GenerationSegmentData { + registers_before: RegistersState::new(), + registers_after: RegistersState::new(), + max_cpu_len: new_max_cpu_len, + ..all_seg_data[0].clone() + }; + let (updated_registers, mem_after) = + set_registers_and_run(dummy_seg.registers_after, &mut interpreter)?; + let mut mem_after = mem_after + .expect("The interpreter was running, so it should have returned a MemoryState"); + // During the interpreter initialization, we set the trie data and initialize + // `RlpRaw`. But we do not want to pass this information to the first actual + // segment in `MemBefore` since the values are not actually accesesed in the + // dummy generation. + mem_after.contexts[0].segments[Segment::RlpRaw.unscale()].content = vec![]; + mem_after.contexts[0].segments[Segment::TrieData.unscale()].content = vec![]; + all_seg_data[0].memory = mem_after; + + all_seg_data.reverse(); + all_seg_data.push(dummy_seg); + all_seg_data.reverse(); + } + Ok(all_seg_data) } @@ -603,13 +639,13 @@ pub mod testing { pub fn simulate_all_segments_interpreter<F>( inputs: GenerationInputs, - max_cpu_len_log: usize, + max_cpu_len: usize, ) -> anyhow::Result<()> where F: Field, { let mut index = 0; - while generate_segment::<F>(max_cpu_len_log, index, &inputs)?.is_some() { + while generate_segment::<F>(max_cpu_len, index, &inputs)?.is_some() { index += 1; } Ok(()) diff --git a/evm_arithmetization/tests/add11_yml.rs b/evm_arithmetization/tests/add11_yml.rs index b72ff753c..fe99dc4eb 100644 --- a/evm_arithmetization/tests/add11_yml.rs +++ b/evm_arithmetization/tests/add11_yml.rs @@ -183,8 +183,8 @@ fn add11_yml() -> anyhow::Result<()> { let config = StarkConfig::standard_fast_config(); let inputs = get_generation_inputs(); - let max_cpu_len_log = 20; - let mut data = generate_all_data_segments::<F>(Some(max_cpu_len_log), inputs.clone())?; + let max_cpu_len = 1 << 20; + let mut data = generate_all_data_segments::<F>(Some(max_cpu_len), inputs.clone())?; let mut timing = TimingTree::new("prove", log::Level::Debug); @@ -213,25 +213,25 @@ fn add11_segments_aggreg() -> anyhow::Result<()> { &[ 16..17, 8..15, - 8..16, + 8..17, 4..15, 7..11, 4..13, - 16..19, + 10..20, 7..18, - 11..18, + 10..18, ], // Minimal ranges to prove an empty list &config, ); let mut timing = TimingTree::new("prove", log::Level::Debug); - let max_cpu_len_log = 14; + let max_cpu_len = 1 << 14; let all_segment_proofs = &all_circuits.prove_all_segments( &all_stark, &config, - inputs, - max_cpu_len_log, + inputs.clone(), + max_cpu_len, &mut timing, None, )?; diff --git a/evm_arithmetization/tests/basic_smart_contract.rs b/evm_arithmetization/tests/basic_smart_contract.rs index 14e08ef27..f430fe2ec 100644 --- a/evm_arithmetization/tests/basic_smart_contract.rs +++ b/evm_arithmetization/tests/basic_smart_contract.rs @@ -198,8 +198,8 @@ fn test_basic_smart_contract() -> anyhow::Result<()> { }, }; - let max_cpu_len_log = 20; - let mut data = generate_all_data_segments::<F>(Some(max_cpu_len_log), inputs.clone())?; + let max_cpu_len = 1 << 20; + let mut data = generate_all_data_segments::<F>(Some(max_cpu_len), inputs.clone())?; let mut timing = TimingTree::new("prove", log::Level::Debug); let proof = prove::<F, C, D>(&all_stark, &config, inputs, &mut data[0], &mut timing, None)?; diff --git a/evm_arithmetization/tests/empty_txn_list.rs b/evm_arithmetization/tests/empty_txn_list.rs index 72f9bc3c7..3d03d1c0a 100644 --- a/evm_arithmetization/tests/empty_txn_list.rs +++ b/evm_arithmetization/tests/empty_txn_list.rs @@ -120,14 +120,14 @@ fn test_empty_txn_list() -> anyhow::Result<()> { assert_eq!(all_circuits, all_circuits_from_bytes); } - let max_cpu_len_log = 9; + let max_cpu_len = 1 << 9; let mut timing = TimingTree::new("prove", log::Level::Info); let segment_proofs_data = &all_circuits.prove_all_segments( &all_stark, &config, inputs, - max_cpu_len_log, + max_cpu_len, &mut timing, None, )?; diff --git a/evm_arithmetization/tests/erc20.rs b/evm_arithmetization/tests/erc20.rs index b539a9906..c75d442d4 100644 --- a/evm_arithmetization/tests/erc20.rs +++ b/evm_arithmetization/tests/erc20.rs @@ -174,8 +174,8 @@ fn test_erc20() -> anyhow::Result<()> { }, }; - let max_cpu_len_log = 20; - let mut data = generate_all_data_segments::<F>(Some(max_cpu_len_log), inputs.clone())?; + let max_cpu_len = 1 << 20; + let mut data = generate_all_data_segments::<F>(Some(max_cpu_len), inputs.clone())?; let mut timing = TimingTree::new("prove", log::Level::Debug); let proof = prove::<F, C, D>(&all_stark, &config, inputs, &mut data[0], &mut timing, None)?; diff --git a/evm_arithmetization/tests/erc721.rs b/evm_arithmetization/tests/erc721.rs index 2af6e9ec7..471c71265 100644 --- a/evm_arithmetization/tests/erc721.rs +++ b/evm_arithmetization/tests/erc721.rs @@ -178,8 +178,8 @@ fn test_erc721() -> anyhow::Result<()> { let mut timing = TimingTree::new("prove", log::Level::Debug); - let max_cpu_len_log = 20; - let mut data = generate_all_data_segments::<F>(Some(max_cpu_len_log), inputs.clone())?; + let max_cpu_len = 1 << 20; + let mut data = generate_all_data_segments::<F>(Some(max_cpu_len), inputs.clone())?; let proof = prove::<F, C, D>(&all_stark, &config, inputs, &mut data[0], &mut timing, None)?; timing.filter(Duration::from_millis(100)).print(); diff --git a/evm_arithmetization/tests/log_opcode.rs b/evm_arithmetization/tests/log_opcode.rs index 0eac25d14..73117aded 100644 --- a/evm_arithmetization/tests/log_opcode.rs +++ b/evm_arithmetization/tests/log_opcode.rs @@ -238,8 +238,8 @@ fn test_log_opcodes() -> anyhow::Result<()> { }, }; - let max_cpu_len_log = 20; - let mut data = generate_all_data_segments::<F>(Some(max_cpu_len_log), inputs.clone())?; + let max_cpu_len = 1 << 20; + let mut data = generate_all_data_segments::<F>(Some(max_cpu_len), inputs.clone())?; let mut timing = TimingTree::new("prove", log::Level::Debug); let proof = prove::<F, C, D>(&all_stark, &config, inputs, &mut data[0], &mut timing, None)?; @@ -469,13 +469,13 @@ fn test_log_with_aggreg() -> anyhow::Result<()> { ); let mut timing = TimingTree::new("prove root first", log::Level::Info); - let max_cpu_len_log = 15; + let max_cpu_len = 1 << 15; let segment_proofs_data_first = &all_circuits.prove_all_segments( &all_stark, &config, inputs_first, - max_cpu_len_log, + max_cpu_len, &mut timing, None, )?; @@ -606,7 +606,7 @@ fn test_log_with_aggreg() -> anyhow::Result<()> { &all_stark, &config, inputs, - max_cpu_len_log, + max_cpu_len, &mut timing, None, )?; @@ -685,7 +685,7 @@ fn test_log_with_aggreg() -> anyhow::Result<()> { let mut contract_code = HashMap::new(); contract_code.insert(keccak(vec![]), vec![]); - let max_cpu_len_log = 13; + let max_cpu_len = 1 << 13; let inputs = GenerationInputs { signed_txn: None, withdrawals: vec![], @@ -716,7 +716,7 @@ fn test_log_with_aggreg() -> anyhow::Result<()> { &all_stark, &config, inputs, - max_cpu_len_log, + max_cpu_len, &mut timing, None, )?; diff --git a/evm_arithmetization/tests/self_balance_gas_cost.rs b/evm_arithmetization/tests/self_balance_gas_cost.rs index 9e60cf76e..363dcf162 100644 --- a/evm_arithmetization/tests/self_balance_gas_cost.rs +++ b/evm_arithmetization/tests/self_balance_gas_cost.rs @@ -185,8 +185,8 @@ fn self_balance_gas_cost() -> anyhow::Result<()> { }, }; - let max_cpu_len_log = 20; - let mut data = generate_all_data_segments::<F>(Some(max_cpu_len_log), inputs.clone())?; + let max_cpu_len = 1 << 20; + let mut data = generate_all_data_segments::<F>(Some(max_cpu_len), inputs.clone())?; let mut timing = TimingTree::new("prove", log::Level::Debug); let proof = prove::<F, C, D>(&all_stark, &config, inputs, &mut data[0], &mut timing, None)?; diff --git a/evm_arithmetization/tests/selfdestruct.rs b/evm_arithmetization/tests/selfdestruct.rs index c88bd9b74..56225877f 100644 --- a/evm_arithmetization/tests/selfdestruct.rs +++ b/evm_arithmetization/tests/selfdestruct.rs @@ -137,8 +137,8 @@ fn test_selfdestruct() -> anyhow::Result<()> { }, }; - let max_cpu_len_log = 20; - let mut data = generate_all_data_segments::<F>(Some(max_cpu_len_log), inputs.clone())?; + let max_cpu_len = 1 << 20; + let mut data = generate_all_data_segments::<F>(Some(max_cpu_len), inputs.clone())?; let mut timing = TimingTree::new("prove", log::Level::Debug); let proof = prove::<F, C, D>(&all_stark, &config, inputs, &mut data[0], &mut timing, None)?; diff --git a/evm_arithmetization/tests/simple_transfer.rs b/evm_arithmetization/tests/simple_transfer.rs index 58e8311b6..97903c97a 100644 --- a/evm_arithmetization/tests/simple_transfer.rs +++ b/evm_arithmetization/tests/simple_transfer.rs @@ -153,8 +153,8 @@ fn test_simple_transfer() -> anyhow::Result<()> { }, }; - let max_cpu_len_log = 20; - let mut data = generate_all_data_segments::<F>(Some(max_cpu_len_log), inputs.clone())?; + let max_cpu_len = 1 << 20; + let mut data = generate_all_data_segments::<F>(Some(max_cpu_len), inputs.clone())?; let mut timing = TimingTree::new("prove", log::Level::Debug); let proof = prove::<F, C, D>(&all_stark, &config, inputs, &mut data[0], &mut timing, None)?; diff --git a/evm_arithmetization/tests/withdrawals.rs b/evm_arithmetization/tests/withdrawals.rs index 751fa4486..ff2d50df8 100644 --- a/evm_arithmetization/tests/withdrawals.rs +++ b/evm_arithmetization/tests/withdrawals.rs @@ -82,8 +82,8 @@ fn test_withdrawals() -> anyhow::Result<()> { }, }; - let max_cpu_len_log = 20; - let mut data = generate_all_data_segments::<F>(Some(max_cpu_len_log), inputs.clone())?; + let max_cpu_len = 1 << 20; + let mut data = generate_all_data_segments::<F>(Some(max_cpu_len), inputs.clone())?; let mut timing = TimingTree::new("prove", log::Level::Debug); let proof = prove::<F, C, D>(&all_stark, &config, inputs, &mut data[0], &mut timing, None)?; diff --git a/proof_gen/src/proof_gen.rs b/proof_gen/src/proof_gen.rs index f1f1276dd..dd1f0244a 100644 --- a/proof_gen/src/proof_gen.rs +++ b/proof_gen/src/proof_gen.rs @@ -47,8 +47,8 @@ pub fn generate_txn_proof( segment_data: &mut GenerationSegmentData, abort_signal: Option<Arc<AtomicBool>>, ) -> ProofGenResult<GeneratedTxnProof> { - // TODO: change the `max_cpu_len_log` and `segment_index` arguments once we can - // automatically determine them. + // TODO: change the `max_cpu_len` argument once we can + // automatically determine it. let output_data = p_state .state .prove_segment( From b26073ece5a76f9429fc027953af7fdf3b774672 Mon Sep 17 00:00:00 2001 From: Linda Guiga <lindaguiga3@gmail.com> Date: Wed, 24 Apr 2024 11:48:15 +0100 Subject: [PATCH 08/11] Remove comment and make add11_segments_aggreg use a dummy segment --- evm_arithmetization/src/memory/memory_stark.rs | 3 --- evm_arithmetization/tests/add11_yml.rs | 18 ++++-------------- 2 files changed, 4 insertions(+), 17 deletions(-) diff --git a/evm_arithmetization/src/memory/memory_stark.rs b/evm_arithmetization/src/memory/memory_stark.rs index e229df410..4f2fe66cb 100644 --- a/evm_arithmetization/src/memory/memory_stark.rs +++ b/evm_arithmetization/src/memory/memory_stark.rs @@ -236,9 +236,6 @@ impl<F: RichField + Extendable<D>, const D: usize> MemoryStark<F, D> { if (trace_col_vecs[CONTEXT_FIRST_CHANGE][i] == F::ONE) || (trace_col_vecs[SEGMENT_FIRST_CHANGE][i] == F::ONE) { - // CONTEXT_FIRST_CHANGE and SEGMENT_FIRST_CHANGE should be 0 at - // the last row, so the index should never be - // out of bounds. if i < trace_col_vecs[ADDR_VIRTUAL].len() - 1 { let x_val = trace_col_vecs[ADDR_VIRTUAL][i + 1].to_canonical_u64() as usize; trace_col_vecs[FREQUENCIES][x_val] += F::ONE; diff --git a/evm_arithmetization/tests/add11_yml.rs b/evm_arithmetization/tests/add11_yml.rs index fe99dc4eb..21adeee8c 100644 --- a/evm_arithmetization/tests/add11_yml.rs +++ b/evm_arithmetization/tests/add11_yml.rs @@ -225,12 +225,12 @@ fn add11_segments_aggreg() -> anyhow::Result<()> { ); let mut timing = TimingTree::new("prove", log::Level::Debug); - let max_cpu_len = 1 << 14; + let max_cpu_len = 1 << 20; let all_segment_proofs = &all_circuits.prove_all_segments( &all_stark, &config, - inputs.clone(), + inputs, max_cpu_len, &mut timing, None, @@ -244,7 +244,7 @@ fn add11_segments_aggreg() -> anyhow::Result<()> { all_circuits.verify_root(proof.clone())?; } - assert_eq!(all_segment_proofs.len(), 3); + assert_eq!(all_segment_proofs.len(), 2); let (first_aggreg_proof, first_aggreg_pv) = all_circuits.prove_segment_aggregation( false, @@ -256,18 +256,8 @@ fn add11_segments_aggreg() -> anyhow::Result<()> { )?; all_circuits.verify_segment_aggregation(&first_aggreg_proof)?; - let (second_aggreg_proof, second_aggreg_pv) = all_circuits.prove_segment_aggregation( - true, - &first_aggreg_proof, - first_aggreg_pv, - false, - &all_segment_proofs[2].proof_with_pis, - all_segment_proofs[2].public_values.clone(), - )?; - all_circuits.verify_segment_aggregation(&second_aggreg_proof)?; - let (txn_aggreg_proof, _) = - all_circuits.prove_transaction_aggregation(None, &second_aggreg_proof, second_aggreg_pv)?; + all_circuits.prove_transaction_aggregation(None, &first_aggreg_proof, first_aggreg_pv)?; all_circuits.verify_txn_aggregation(&txn_aggreg_proof) } From 8f86e0ee74b49785e9b84468ddb44aab75e95d5a Mon Sep 17 00:00:00 2001 From: Linda Guiga <lindaguiga3@gmail.com> Date: Wed, 24 Apr 2024 12:09:33 +0100 Subject: [PATCH 09/11] Change dummy insertion. --- evm_arithmetization/src/prover.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/evm_arithmetization/src/prover.rs b/evm_arithmetization/src/prover.rs index 03135eb93..437ef16d6 100644 --- a/evm_arithmetization/src/prover.rs +++ b/evm_arithmetization/src/prover.rs @@ -574,9 +574,7 @@ pub fn generate_all_data_segments<F: RichField>( mem_after.contexts[0].segments[Segment::TrieData.unscale()].content = vec![]; all_seg_data[0].memory = mem_after; - all_seg_data.reverse(); - all_seg_data.push(dummy_seg); - all_seg_data.reverse(); + all_seg_data.insert(0, dummy_seg); } Ok(all_seg_data) From 694f557ab4f9c8df2ffcdfb5ad041b73969935f6 Mon Sep 17 00:00:00 2001 From: Linda Guiga <lindaguiga3@gmail.com> Date: Thu, 25 Apr 2024 13:28:14 +0100 Subject: [PATCH 10/11] Apply comments --- .../src/cpu/kernel/interpreter.rs | 55 +++++++-- .../src/cpu/kernel/tests/init_exc_stop.rs | 107 ++++++++++++++++++ .../src/cpu/kernel/tests/mod.rs | 1 + .../src/fixed_recursive_verifier.rs | 6 +- evm_arithmetization/src/generation/mod.rs | 10 +- evm_arithmetization/src/generation/state.rs | 17 ++- .../src/memory/memory_stark.rs | 21 ++-- evm_arithmetization/src/prover.rs | 32 +++--- evm_arithmetization/tests/add11_yml.rs | 8 +- .../tests/basic_smart_contract.rs | 4 +- evm_arithmetization/tests/empty_txn_list.rs | 4 +- evm_arithmetization/tests/erc20.rs | 4 +- evm_arithmetization/tests/erc721.rs | 4 +- evm_arithmetization/tests/log_opcode.rs | 14 +-- .../tests/self_balance_gas_cost.rs | 4 +- evm_arithmetization/tests/selfdestruct.rs | 4 +- evm_arithmetization/tests/simple_transfer.rs | 4 +- evm_arithmetization/tests/withdrawals.rs | 4 +- proof_gen/src/proof_gen.rs | 2 +- 19 files changed, 226 insertions(+), 79 deletions(-) create mode 100644 evm_arithmetization/src/cpu/kernel/tests/init_exc_stop.rs diff --git a/evm_arithmetization/src/cpu/kernel/interpreter.rs b/evm_arithmetization/src/cpu/kernel/interpreter.rs index b493c4eba..201b40235 100644 --- a/evm_arithmetization/src/cpu/kernel/interpreter.rs +++ b/evm_arithmetization/src/cpu/kernel/interpreter.rs @@ -21,7 +21,9 @@ use crate::generation::rlp::all_rlp_prover_inputs_reversed; use crate::generation::state::{ all_withdrawals_prover_inputs_reversed, GenerationState, GenerationStateCheckpoint, }; -use crate::generation::{debug_inputs, TrimmedGenerationInputs}; +use crate::generation::{ + debug_inputs, TrimmedGenerationInputs, NUM_EXTRA_CYCLES_AFTER, NUM_EXTRA_CYCLES_BEFORE, +}; use crate::generation::{state::State, GenerationInputs}; use crate::keccak_sponge::columns::KECCAK_WIDTH_BYTES; use crate::keccak_sponge::keccak_sponge_stark::KeccakSpongeOp; @@ -60,7 +62,9 @@ pub(crate) struct Interpreter<F: Field> { /// in the execution. pub(crate) clock: usize, /// Log of the maximal number of CPU cycles in one segment execution. - max_cpu_len: Option<usize>, + max_cpu_len_log: Option<usize>, + /// Indicates whethere this is a dummy run. + is_dummy: bool, } /// Structure storing the state of the interpreter's registers. @@ -162,7 +166,7 @@ pub(crate) struct ExtraSegmentData { /// execution stops at segment `index`. These can then be passed to the /// prover for initialization. pub(crate) fn generate_segment<F: Field>( - max_cpu_len: usize, + max_cpu_len_log: usize, index: usize, inputs: &GenerationInputs, ) -> anyhow::Result< @@ -175,8 +179,12 @@ pub(crate) fn generate_segment<F: Field>( > { let init_label = KERNEL.global_labels["init"]; let initial_registers = RegistersState::new(); - let mut interpreter = - Interpreter::<F>::new_with_generation_inputs(init_label, vec![], inputs, Some(max_cpu_len)); + let mut interpreter = Interpreter::<F>::new_with_generation_inputs( + init_label, + vec![], + inputs, + Some(max_cpu_len_log), + ); let (mut registers_before, mut registers_after, mut before_mem_values, mut after_mem_values) = ( initial_registers, @@ -276,19 +284,35 @@ impl<F: Field> Interpreter<F> { initial_offset: usize, initial_stack: Vec<U256>, inputs: &GenerationInputs, - max_cpu_len: Option<usize>, + max_cpu_len_log: Option<usize>, ) -> Self { debug_inputs(inputs); - let mut result = Self::new(initial_offset, initial_stack, max_cpu_len); + let mut result = Self::new(initial_offset, initial_stack, max_cpu_len_log); result.initialize_interpreter_state(inputs); result } + /// Returns an instance of `Interpreter` given `GenerationInputs`, and + /// assuming we are initializing with the `KERNEL` code. + pub(crate) fn new_dummy_with_generation_inputs( + initial_offset: usize, + initial_stack: Vec<U256>, + inputs: &GenerationInputs, + ) -> Self { + debug_inputs(inputs); + + let max_cpu_len = Some(NUM_EXTRA_CYCLES_BEFORE + NUM_EXTRA_CYCLES_AFTER); + let mut result = + Self::new_with_generation_inputs(initial_offset, initial_stack, inputs, max_cpu_len); + result.is_dummy = true; + result + } + pub(crate) fn new( initial_offset: usize, initial_stack: Vec<U256>, - max_cpu_len: Option<usize>, + max_cpu_len_log: Option<usize>, ) -> Self { let mut interpreter = Self { generation_state: GenerationState::new(&GenerationInputs::default(), &KERNEL.code) @@ -301,7 +325,8 @@ impl<F: Field> Interpreter<F> { jumpdest_table: HashMap::new(), is_jumpdest_analysis: false, clock: 0, - max_cpu_len, + max_cpu_len_log, + is_dummy: false, }; interpreter.generation_state.registers.program_counter = initial_offset; let initial_stack_len = initial_stack.len(); @@ -322,7 +347,7 @@ impl<F: Field> Interpreter<F> { state: &GenerationState<F>, halt_offset: usize, halt_context: usize, - max_cpu_len: Option<usize>, + max_cpu_len_log: Option<usize>, ) -> Self { Self { generation_state: state.soft_clone(), @@ -332,7 +357,8 @@ impl<F: Field> Interpreter<F> { jumpdest_table: HashMap::new(), is_jumpdest_analysis: true, clock: 0, - max_cpu_len, + max_cpu_len_log, + is_dummy: false, } } @@ -516,7 +542,7 @@ impl<F: Field> Interpreter<F> { } pub(crate) fn run(&mut self) -> Result<(RegistersState, Option<MemoryState>), anyhow::Error> { - let (final_registers, final_mem) = self.run_cpu(self.max_cpu_len)?; + let (final_registers, final_mem) = self.run_cpu(self.max_cpu_len_log, self.is_dummy)?; #[cfg(debug_assertions)] { @@ -546,6 +572,11 @@ impl<F: Field> Interpreter<F> { .collect::<Vec<_>>() } + /// Returns the max number of CPU cycles. + pub(crate) fn get_max_cpu_len_log(&self) -> Option<usize> { + self.max_cpu_len_log + } + pub(crate) fn get_txn_field(&self, field: NormalizedTxnField) -> U256 { // These fields are already scaled by their respective segment. self.generation_state.memory.contexts[0].segments[Segment::TxnFields.unscale()] diff --git a/evm_arithmetization/src/cpu/kernel/tests/init_exc_stop.rs b/evm_arithmetization/src/cpu/kernel/tests/init_exc_stop.rs new file mode 100644 index 000000000..d63920e19 --- /dev/null +++ b/evm_arithmetization/src/cpu/kernel/tests/init_exc_stop.rs @@ -0,0 +1,107 @@ +use std::collections::HashMap; + +use ethereum_types::U256; +use keccak_hash::keccak; +use keccak_hash::H256; +use mpt_trie::partial_trie::HashedPartialTrie; +use mpt_trie::partial_trie::PartialTrie; +use plonky2::field::goldilocks_field::GoldilocksField as F; + +use crate::cpu::kernel::aggregator::KERNEL; +use crate::cpu::kernel::interpreter::Interpreter; +use crate::generation::state::State; +use crate::generation::TrieInputs; +use crate::generation::NUM_EXTRA_CYCLES_AFTER; +use crate::generation::NUM_EXTRA_CYCLES_BEFORE; +use crate::proof::BlockMetadata; +use crate::proof::TrieRoots; +use crate::witness::state::RegistersState; +use crate::{proof::BlockHashes, GenerationInputs, Node}; + +// Test to check NUM_EXTRA_CYCLES_BEFORE and NUM_EXTRA_CYCLES_AFTER +#[test] +fn test_init_exc_stop() { + let block_metadata = BlockMetadata { + block_number: 1.into(), + ..Default::default() + }; + + let state_trie = HashedPartialTrie::from(Node::Empty); + let transactions_trie = HashedPartialTrie::from(Node::Empty); + let receipts_trie = HashedPartialTrie::from(Node::Empty); + let storage_tries = vec![]; + + let mut contract_code = HashMap::new(); + contract_code.insert(keccak(vec![]), vec![]); + + // No transactions, so no trie roots change. + let trie_roots_after = TrieRoots { + state_root: state_trie.hash(), + transactions_root: transactions_trie.hash(), + receipts_root: receipts_trie.hash(), + }; + + let inputs = GenerationInputs { + signed_txn: None, + withdrawals: vec![], + tries: TrieInputs { + state_trie, + transactions_trie, + receipts_trie, + storage_tries, + }, + trie_roots_after, + contract_code, + checkpoint_state_trie_root: HashedPartialTrie::from(Node::Empty).hash(), + block_metadata, + txn_number_before: 0.into(), + gas_used_before: 0.into(), + gas_used_after: 0.into(), + block_hashes: BlockHashes { + prev_hashes: vec![H256::default(); 256], + cur_hash: H256::default(), + }, + }; + let initial_stack = vec![]; + let initial_offset = KERNEL.global_labels["init"]; + let mut interpreter: Interpreter<F> = + Interpreter::new_with_generation_inputs(initial_offset, initial_stack, &inputs, None); + interpreter.halt_offsets = vec![KERNEL.global_labels["main"]]; + interpreter.set_is_kernel(true); + interpreter.run().expect("Running dummy init failed."); + + assert_eq!( + interpreter.get_clock(), + NUM_EXTRA_CYCLES_BEFORE, + "NUM_EXTRA_CYCLES_BEFORE is set incorrectly." + ); + + // The registers should not have changed, besides the stack top. + let expected_registers = RegistersState { + stack_top: interpreter.get_registers().stack_top, + check_overflow: interpreter.get_registers().check_overflow, + ..RegistersState::new() + }; + + assert_eq!( + interpreter.get_registers(), + expected_registers, + "Incorrect registers for dummy run." + ); + + let main_offset = KERNEL.global_labels["main"]; + let mut interpreter: Interpreter<F> = + Interpreter::new_dummy_with_generation_inputs(initial_offset, vec![], &inputs); + interpreter.halt_offsets = vec![KERNEL.global_labels["halt_final"]]; + interpreter.set_is_kernel(true); + interpreter.clock = 0; + interpreter.run().expect("Running dummy exc_stop failed."); + + // The "-1" comes from the fact that we stop 1 cycle before the max, to allow + // for one padding row, which is needed for CPU STARK. + assert_eq!( + interpreter.get_clock(), + NUM_EXTRA_CYCLES_BEFORE + NUM_EXTRA_CYCLES_AFTER - 1, + "NUM_EXTRA_CYCLES_AFTER is set incorrectly." + ); +} diff --git a/evm_arithmetization/src/cpu/kernel/tests/mod.rs b/evm_arithmetization/src/cpu/kernel/tests/mod.rs index 7581eefe7..818a64588 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/mod.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/mod.rs @@ -10,6 +10,7 @@ mod core; mod ecc; mod exp; mod hash; +mod init_exc_stop; mod kernel_consistency; mod log; mod mpt; diff --git a/evm_arithmetization/src/fixed_recursive_verifier.rs b/evm_arithmetization/src/fixed_recursive_verifier.rs index 4b6d0c2d9..309cb8e13 100644 --- a/evm_arithmetization/src/fixed_recursive_verifier.rs +++ b/evm_arithmetization/src/fixed_recursive_verifier.rs @@ -1384,19 +1384,19 @@ where all_stark: &AllStark<F, D>, config: &StarkConfig, generation_inputs: GenerationInputs, - max_cpu_len: usize, + max_cpu_len_log: usize, timing: &mut TimingTree, abort_signal: Option<Arc<AtomicBool>>, ) -> anyhow::Result<Vec<ProverOutputData<F, C, D>>> { let mut all_data_segments = - generate_all_data_segments::<F>(Some(max_cpu_len), generation_inputs.clone())?; + generate_all_data_segments::<F>(Some(max_cpu_len_log), generation_inputs.clone())?; let mut proofs = Vec::with_capacity(all_data_segments.len()); for mut data in all_data_segments { let proof = self.prove_segment( all_stark, config, generation_inputs.clone(), - max_cpu_len, + max_cpu_len_log, &mut data, timing, abort_signal.clone(), diff --git a/evm_arithmetization/src/generation/mod.rs b/evm_arithmetization/src/generation/mod.rs index 61913f7f9..7b4b57ce6 100644 --- a/evm_arithmetization/src/generation/mod.rs +++ b/evm_arithmetization/src/generation/mod.rs @@ -390,7 +390,8 @@ pub fn generate_traces<F: RichField + Extendable<D>, const D: usize>( // Initialize the state with the one at the end of the // previous segment execution, if any. let GenerationSegmentData { - max_cpu_len, + is_dummy, + max_cpu_len_log, memory, registers_before, registers_after, @@ -408,7 +409,7 @@ pub fn generate_traces<F: RichField + Extendable<D>, const D: usize>( let cpu_res = timed!( timing, "simulate CPU", - simulate_cpu(&mut state, *max_cpu_len) + simulate_cpu(&mut state, *max_cpu_len_log, *is_dummy) ); if cpu_res.is_err() { output_debug_tries(&state)?; @@ -472,9 +473,10 @@ pub fn generate_traces<F: RichField + Extendable<D>, const D: usize>( fn simulate_cpu<F: Field>( state: &mut GenerationState<F>, - max_cpu_len: Option<usize>, + max_cpu_len_log: Option<usize>, + is_dummy: bool, ) -> anyhow::Result<(RegistersState, Option<MemoryState>)> { - let (final_registers, mem_after) = state.run_cpu(max_cpu_len)?; + let (final_registers, mem_after) = state.run_cpu(max_cpu_len_log, is_dummy)?; let pc = state.registers.program_counter; // Setting the values of padding rows. diff --git a/evm_arithmetization/src/generation/state.rs b/evm_arithmetization/src/generation/state.rs index fdb486978..8e5f95a5a 100644 --- a/evm_arithmetization/src/generation/state.rs +++ b/evm_arithmetization/src/generation/state.rs @@ -76,9 +76,13 @@ pub(crate) trait State<F: Field> { fn get_context(&self) -> usize; /// Checks whether we have reached the maximal cpu length. - fn at_end_segment(&self, opt_max_cpu_len: Option<usize>) -> bool { - if let Some(max_cpu_len) = opt_max_cpu_len { - self.get_clock() == max_cpu_len - NUM_EXTRA_CYCLES_AFTER + fn at_end_segment(&self, opt_max_cpu_len: Option<usize>, is_dummy: bool) -> bool { + if let Some(max_cpu_len_log) = opt_max_cpu_len { + if is_dummy { + self.get_clock() == max_cpu_len_log - NUM_EXTRA_CYCLES_AFTER + } else { + self.get_clock() == (1 << max_cpu_len_log) - NUM_EXTRA_CYCLES_AFTER + } } else { false } @@ -167,7 +171,8 @@ pub(crate) trait State<F: Field> { /// `GenerationState`. fn run_cpu( &mut self, - max_cpu_len: Option<usize>, + max_cpu_len_log: Option<usize>, + is_dummy: bool, ) -> anyhow::Result<(RegistersState, Option<MemoryState>)> where Self: Transition<F>, @@ -183,7 +188,7 @@ pub(crate) trait State<F: Field> { let pc = registers.program_counter; let halt_final = registers.is_kernel && halt_offsets.contains(&pc); - if running && (self.at_halt() || self.at_end_segment(max_cpu_len)) { + if running && (self.at_halt() || self.at_end_segment(max_cpu_len_log, is_dummy)) { running = false; final_registers = registers; @@ -206,7 +211,7 @@ pub(crate) trait State<F: Field> { } } else { if !running { - assert_eq!(self.get_clock() - final_clock, NUM_EXTRA_CYCLES_AFTER - 1); + debug_assert!(self.get_clock() - final_clock == NUM_EXTRA_CYCLES_AFTER - 1); } let final_mem = if let Some(mut mem) = self.get_full_memory() { // Clear memory we will not use again. diff --git a/evm_arithmetization/src/memory/memory_stark.rs b/evm_arithmetization/src/memory/memory_stark.rs index 4f2fe66cb..5cac318f2 100644 --- a/evm_arithmetization/src/memory/memory_stark.rs +++ b/evm_arithmetization/src/memory/memory_stark.rs @@ -274,7 +274,7 @@ impl<F: RichField + Extendable<D>, const D: usize> MemoryStark<F, D> { /// range check, so this method would add two dummy reads to the same /// address, say at timestamps 50 and 80. fn fill_gaps(memory_ops: &mut Vec<MemoryOp>) { - // First, insert padding row at at address (0 0, 0) if the first row doesn't + // First, insert padding row at address (0, 0, 0) if the first row doesn't // have a first virtual address at 0. if memory_ops[0].address.virt != 0 { let dummy_addr = MemoryAddress { @@ -282,15 +282,16 @@ impl<F: RichField + Extendable<D>, const D: usize> MemoryStark<F, D> { segment: 0, virt: 0, }; - memory_ops.reverse(); - memory_ops.push(MemoryOp { - filter: false, - timestamp: 1, - address: dummy_addr, - kind: MemoryOpKind::Read, - value: 0.into(), - }); - memory_ops.reverse(); + memory_ops.insert( + 0, + MemoryOp { + filter: false, + timestamp: 1, + address: dummy_addr, + kind: MemoryOpKind::Read, + value: 0.into(), + }, + ); } let max_rc = memory_ops.len().next_power_of_two() - 1; for (mut curr, mut next) in memory_ops.clone().into_iter().tuple_windows() { diff --git a/evm_arithmetization/src/prover.rs b/evm_arithmetization/src/prover.rs index 437ef16d6..351c2a5d5 100644 --- a/evm_arithmetization/src/prover.rs +++ b/evm_arithmetization/src/prover.rs @@ -29,9 +29,7 @@ use crate::cpu::kernel::interpreter::{ generate_segment, set_registers_and_run, ExtraSegmentData, Interpreter, }; use crate::generation::state::GenerationState; -use crate::generation::{ - generate_traces, GenerationInputs, NUM_EXTRA_CYCLES_AFTER, NUM_EXTRA_CYCLES_BEFORE, -}; +use crate::generation::{generate_traces, GenerationInputs}; use crate::get_challenges::observe_public_values; use crate::memory::segments::Segment; use crate::proof::{AllProof, MemCap, PublicValues, RegistersData}; @@ -41,6 +39,8 @@ use crate::witness::state::RegistersState; /// Structure holding the data needed to initialize a segment. #[derive(Clone, Default, Debug)] pub struct GenerationSegmentData { + /// Indicates whether this corresponds to a dummy segment. + pub(crate) is_dummy: bool, /// Registers at the start of the segment execution. pub(crate) registers_before: RegistersState, /// Registers at the end of the segment execution. @@ -50,10 +50,9 @@ pub struct GenerationSegmentData { /// Extra data required to initialize a segment. pub(crate) extra_data: ExtraSegmentData, /// Log of the maximal cpu length. - pub(crate) max_cpu_len: Option<usize>, + pub(crate) max_cpu_len_log: Option<usize>, } -/// Generate traces, then create all STARK proofs. /// Generate traces, then create all STARK proofs. pub fn prove<F, C, const D: usize>( all_stark: &AllStark<F, D>, @@ -476,7 +475,7 @@ pub fn check_abort_signal(abort_signal: Option<Arc<AtomicBool>>) -> Result<()> { /// Returns a vector containing the data required to generate all the segments /// of a transaction. pub fn generate_all_data_segments<F: RichField>( - max_cpu_len: Option<usize>, + max_cpu_len_log: Option<usize>, inputs: GenerationInputs, ) -> anyhow::Result<Vec<GenerationSegmentData>> { let mut all_seg_data = vec![]; @@ -485,14 +484,15 @@ pub fn generate_all_data_segments<F: RichField>( KERNEL.global_labels["init"], vec![], &inputs, - max_cpu_len, + max_cpu_len_log, ); let mut segment_data = GenerationSegmentData { + is_dummy: false, registers_before: RegistersState::new(), registers_after: RegistersState::new(), memory: MemoryState::default(), - max_cpu_len, + max_cpu_len_log, extra_data: ExtraSegmentData { trimmed_inputs: interpreter.generation_state.inputs.clone(), bignum_modmul_result_limbs: interpreter @@ -523,10 +523,11 @@ pub fn generate_all_data_segments<F: RichField>( all_seg_data.push(segment_data); segment_data = GenerationSegmentData { + is_dummy: false, registers_before: updated_registers, // `registers_after` will be set correctly at the next iteration.` registers_after: updated_registers, - max_cpu_len, + max_cpu_len_log, memory: mem_after .expect("The interpreter was running, so it should have returned a MemoryState"), extra_data: ExtraSegmentData { @@ -548,18 +549,17 @@ pub fn generate_all_data_segments<F: RichField>( // We need at least two segments to prove a segment aggregation. if all_seg_data.len() == 1 { - let new_max_cpu_len = Some(NUM_EXTRA_CYCLES_AFTER + NUM_EXTRA_CYCLES_BEFORE); - let mut interpreter = Interpreter::<F>::new_with_generation_inputs( + let mut interpreter = Interpreter::<F>::new_dummy_with_generation_inputs( KERNEL.global_labels["init"], vec![], &inputs, - new_max_cpu_len, ); let dummy_seg = GenerationSegmentData { + is_dummy: true, registers_before: RegistersState::new(), registers_after: RegistersState::new(), - max_cpu_len: new_max_cpu_len, + max_cpu_len_log: interpreter.get_max_cpu_len_log(), ..all_seg_data[0].clone() }; let (updated_registers, mem_after) = @@ -568,7 +568,7 @@ pub fn generate_all_data_segments<F: RichField>( .expect("The interpreter was running, so it should have returned a MemoryState"); // During the interpreter initialization, we set the trie data and initialize // `RlpRaw`. But we do not want to pass this information to the first actual - // segment in `MemBefore` since the values are not actually accesesed in the + // segment in `MemBefore` since the values are not actually accessed in the // dummy generation. mem_after.contexts[0].segments[Segment::RlpRaw.unscale()].content = vec![]; mem_after.contexts[0].segments[Segment::TrieData.unscale()].content = vec![]; @@ -637,13 +637,13 @@ pub mod testing { pub fn simulate_all_segments_interpreter<F>( inputs: GenerationInputs, - max_cpu_len: usize, + max_cpu_len_log: usize, ) -> anyhow::Result<()> where F: Field, { let mut index = 0; - while generate_segment::<F>(max_cpu_len, index, &inputs)?.is_some() { + while generate_segment::<F>(max_cpu_len_log, index, &inputs)?.is_some() { index += 1; } Ok(()) diff --git a/evm_arithmetization/tests/add11_yml.rs b/evm_arithmetization/tests/add11_yml.rs index 21adeee8c..b3ac598e2 100644 --- a/evm_arithmetization/tests/add11_yml.rs +++ b/evm_arithmetization/tests/add11_yml.rs @@ -183,8 +183,8 @@ fn add11_yml() -> anyhow::Result<()> { let config = StarkConfig::standard_fast_config(); let inputs = get_generation_inputs(); - let max_cpu_len = 1 << 20; - let mut data = generate_all_data_segments::<F>(Some(max_cpu_len), inputs.clone())?; + let max_cpu_len_log = 20; + let mut data = generate_all_data_segments::<F>(Some(max_cpu_len_log), inputs.clone())?; let mut timing = TimingTree::new("prove", log::Level::Debug); @@ -225,13 +225,13 @@ fn add11_segments_aggreg() -> anyhow::Result<()> { ); let mut timing = TimingTree::new("prove", log::Level::Debug); - let max_cpu_len = 1 << 20; + let max_cpu_len_log = 20; let all_segment_proofs = &all_circuits.prove_all_segments( &all_stark, &config, inputs, - max_cpu_len, + max_cpu_len_log, &mut timing, None, )?; diff --git a/evm_arithmetization/tests/basic_smart_contract.rs b/evm_arithmetization/tests/basic_smart_contract.rs index f430fe2ec..14e08ef27 100644 --- a/evm_arithmetization/tests/basic_smart_contract.rs +++ b/evm_arithmetization/tests/basic_smart_contract.rs @@ -198,8 +198,8 @@ fn test_basic_smart_contract() -> anyhow::Result<()> { }, }; - let max_cpu_len = 1 << 20; - let mut data = generate_all_data_segments::<F>(Some(max_cpu_len), inputs.clone())?; + let max_cpu_len_log = 20; + let mut data = generate_all_data_segments::<F>(Some(max_cpu_len_log), inputs.clone())?; let mut timing = TimingTree::new("prove", log::Level::Debug); let proof = prove::<F, C, D>(&all_stark, &config, inputs, &mut data[0], &mut timing, None)?; diff --git a/evm_arithmetization/tests/empty_txn_list.rs b/evm_arithmetization/tests/empty_txn_list.rs index 3d03d1c0a..72f9bc3c7 100644 --- a/evm_arithmetization/tests/empty_txn_list.rs +++ b/evm_arithmetization/tests/empty_txn_list.rs @@ -120,14 +120,14 @@ fn test_empty_txn_list() -> anyhow::Result<()> { assert_eq!(all_circuits, all_circuits_from_bytes); } - let max_cpu_len = 1 << 9; + let max_cpu_len_log = 9; let mut timing = TimingTree::new("prove", log::Level::Info); let segment_proofs_data = &all_circuits.prove_all_segments( &all_stark, &config, inputs, - max_cpu_len, + max_cpu_len_log, &mut timing, None, )?; diff --git a/evm_arithmetization/tests/erc20.rs b/evm_arithmetization/tests/erc20.rs index c75d442d4..b539a9906 100644 --- a/evm_arithmetization/tests/erc20.rs +++ b/evm_arithmetization/tests/erc20.rs @@ -174,8 +174,8 @@ fn test_erc20() -> anyhow::Result<()> { }, }; - let max_cpu_len = 1 << 20; - let mut data = generate_all_data_segments::<F>(Some(max_cpu_len), inputs.clone())?; + let max_cpu_len_log = 20; + let mut data = generate_all_data_segments::<F>(Some(max_cpu_len_log), inputs.clone())?; let mut timing = TimingTree::new("prove", log::Level::Debug); let proof = prove::<F, C, D>(&all_stark, &config, inputs, &mut data[0], &mut timing, None)?; diff --git a/evm_arithmetization/tests/erc721.rs b/evm_arithmetization/tests/erc721.rs index 471c71265..2af6e9ec7 100644 --- a/evm_arithmetization/tests/erc721.rs +++ b/evm_arithmetization/tests/erc721.rs @@ -178,8 +178,8 @@ fn test_erc721() -> anyhow::Result<()> { let mut timing = TimingTree::new("prove", log::Level::Debug); - let max_cpu_len = 1 << 20; - let mut data = generate_all_data_segments::<F>(Some(max_cpu_len), inputs.clone())?; + let max_cpu_len_log = 20; + let mut data = generate_all_data_segments::<F>(Some(max_cpu_len_log), inputs.clone())?; let proof = prove::<F, C, D>(&all_stark, &config, inputs, &mut data[0], &mut timing, None)?; timing.filter(Duration::from_millis(100)).print(); diff --git a/evm_arithmetization/tests/log_opcode.rs b/evm_arithmetization/tests/log_opcode.rs index 73117aded..0eac25d14 100644 --- a/evm_arithmetization/tests/log_opcode.rs +++ b/evm_arithmetization/tests/log_opcode.rs @@ -238,8 +238,8 @@ fn test_log_opcodes() -> anyhow::Result<()> { }, }; - let max_cpu_len = 1 << 20; - let mut data = generate_all_data_segments::<F>(Some(max_cpu_len), inputs.clone())?; + let max_cpu_len_log = 20; + let mut data = generate_all_data_segments::<F>(Some(max_cpu_len_log), inputs.clone())?; let mut timing = TimingTree::new("prove", log::Level::Debug); let proof = prove::<F, C, D>(&all_stark, &config, inputs, &mut data[0], &mut timing, None)?; @@ -469,13 +469,13 @@ fn test_log_with_aggreg() -> anyhow::Result<()> { ); let mut timing = TimingTree::new("prove root first", log::Level::Info); - let max_cpu_len = 1 << 15; + let max_cpu_len_log = 15; let segment_proofs_data_first = &all_circuits.prove_all_segments( &all_stark, &config, inputs_first, - max_cpu_len, + max_cpu_len_log, &mut timing, None, )?; @@ -606,7 +606,7 @@ fn test_log_with_aggreg() -> anyhow::Result<()> { &all_stark, &config, inputs, - max_cpu_len, + max_cpu_len_log, &mut timing, None, )?; @@ -685,7 +685,7 @@ fn test_log_with_aggreg() -> anyhow::Result<()> { let mut contract_code = HashMap::new(); contract_code.insert(keccak(vec![]), vec![]); - let max_cpu_len = 1 << 13; + let max_cpu_len_log = 13; let inputs = GenerationInputs { signed_txn: None, withdrawals: vec![], @@ -716,7 +716,7 @@ fn test_log_with_aggreg() -> anyhow::Result<()> { &all_stark, &config, inputs, - max_cpu_len, + max_cpu_len_log, &mut timing, None, )?; diff --git a/evm_arithmetization/tests/self_balance_gas_cost.rs b/evm_arithmetization/tests/self_balance_gas_cost.rs index 363dcf162..9e60cf76e 100644 --- a/evm_arithmetization/tests/self_balance_gas_cost.rs +++ b/evm_arithmetization/tests/self_balance_gas_cost.rs @@ -185,8 +185,8 @@ fn self_balance_gas_cost() -> anyhow::Result<()> { }, }; - let max_cpu_len = 1 << 20; - let mut data = generate_all_data_segments::<F>(Some(max_cpu_len), inputs.clone())?; + let max_cpu_len_log = 20; + let mut data = generate_all_data_segments::<F>(Some(max_cpu_len_log), inputs.clone())?; let mut timing = TimingTree::new("prove", log::Level::Debug); let proof = prove::<F, C, D>(&all_stark, &config, inputs, &mut data[0], &mut timing, None)?; diff --git a/evm_arithmetization/tests/selfdestruct.rs b/evm_arithmetization/tests/selfdestruct.rs index 56225877f..c88bd9b74 100644 --- a/evm_arithmetization/tests/selfdestruct.rs +++ b/evm_arithmetization/tests/selfdestruct.rs @@ -137,8 +137,8 @@ fn test_selfdestruct() -> anyhow::Result<()> { }, }; - let max_cpu_len = 1 << 20; - let mut data = generate_all_data_segments::<F>(Some(max_cpu_len), inputs.clone())?; + let max_cpu_len_log = 20; + let mut data = generate_all_data_segments::<F>(Some(max_cpu_len_log), inputs.clone())?; let mut timing = TimingTree::new("prove", log::Level::Debug); let proof = prove::<F, C, D>(&all_stark, &config, inputs, &mut data[0], &mut timing, None)?; diff --git a/evm_arithmetization/tests/simple_transfer.rs b/evm_arithmetization/tests/simple_transfer.rs index 97903c97a..58e8311b6 100644 --- a/evm_arithmetization/tests/simple_transfer.rs +++ b/evm_arithmetization/tests/simple_transfer.rs @@ -153,8 +153,8 @@ fn test_simple_transfer() -> anyhow::Result<()> { }, }; - let max_cpu_len = 1 << 20; - let mut data = generate_all_data_segments::<F>(Some(max_cpu_len), inputs.clone())?; + let max_cpu_len_log = 20; + let mut data = generate_all_data_segments::<F>(Some(max_cpu_len_log), inputs.clone())?; let mut timing = TimingTree::new("prove", log::Level::Debug); let proof = prove::<F, C, D>(&all_stark, &config, inputs, &mut data[0], &mut timing, None)?; diff --git a/evm_arithmetization/tests/withdrawals.rs b/evm_arithmetization/tests/withdrawals.rs index ff2d50df8..751fa4486 100644 --- a/evm_arithmetization/tests/withdrawals.rs +++ b/evm_arithmetization/tests/withdrawals.rs @@ -82,8 +82,8 @@ fn test_withdrawals() -> anyhow::Result<()> { }, }; - let max_cpu_len = 1 << 20; - let mut data = generate_all_data_segments::<F>(Some(max_cpu_len), inputs.clone())?; + let max_cpu_len_log = 20; + let mut data = generate_all_data_segments::<F>(Some(max_cpu_len_log), inputs.clone())?; let mut timing = TimingTree::new("prove", log::Level::Debug); let proof = prove::<F, C, D>(&all_stark, &config, inputs, &mut data[0], &mut timing, None)?; diff --git a/proof_gen/src/proof_gen.rs b/proof_gen/src/proof_gen.rs index dd1f0244a..d3fa627ef 100644 --- a/proof_gen/src/proof_gen.rs +++ b/proof_gen/src/proof_gen.rs @@ -47,7 +47,7 @@ pub fn generate_txn_proof( segment_data: &mut GenerationSegmentData, abort_signal: Option<Arc<AtomicBool>>, ) -> ProofGenResult<GeneratedTxnProof> { - // TODO: change the `max_cpu_len` argument once we can + // TODO: change the `max_cpu_len_log` argument once we can // automatically determine it. let output_data = p_state .state From 0744c7ee0d7da7a0250b294223e8f147e03e2c33 Mon Sep 17 00:00:00 2001 From: Linda Guiga <lindaguiga3@gmail.com> Date: Thu, 25 Apr 2024 14:16:24 +0100 Subject: [PATCH 11/11] Fix Clippy --- evm_arithmetization/src/prover.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/evm_arithmetization/src/prover.rs b/evm_arithmetization/src/prover.rs index 69af85cf7..5e76b0452 100644 --- a/evm_arithmetization/src/prover.rs +++ b/evm_arithmetization/src/prover.rs @@ -553,7 +553,7 @@ pub fn generate_all_data_segments<F: RichField>( let mut interpreter = Interpreter::<F>::new_dummy_with_generation_inputs( KERNEL.global_labels["init"], vec![], - &inputs, + inputs, ); let dummy_seg = GenerationSegmentData {