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 {