diff --git a/evm/src/all_stark.rs b/evm/src/all_stark.rs index 1be4c6ea..9e1bcd76 100644 --- a/evm/src/all_stark.rs +++ b/evm/src/all_stark.rs @@ -60,7 +60,7 @@ impl Table { mod tests { use anyhow::Result; use itertools::{izip, Itertools}; - use plonky2::field::field_types::Field; + use plonky2::field::field_types::{Field, PrimeField64}; use plonky2::field::polynomial::PolynomialValues; use plonky2::iop::witness::PartialWitness; use plonky2::plonk::circuit_builder::CircuitBuilder; @@ -136,14 +136,24 @@ mod tests { } trace_rows_to_poly_values(trace_rows) } + + fn make_memory_trace( + num_memory_ops: usize, + memory_stark: &MemoryStark, + rng: &mut R, + ) -> Vec> { + let memory_ops = generate_random_memory_ops(num_memory_ops, rng); + memory_stark.generate_trace(memory_ops) + } fn make_cpu_trace( num_keccak_perms: usize, num_logic_rows: usize, + num_memory_ops: usize, cpu_stark: &CpuStark, keccak_trace: &[PolynomialValues], logic_trace: &[PolynomialValues], - memory_trace: &[PolynomialValues], + memory_trace: &mut [PolynomialValues], ) -> Vec> { let keccak_input_limbs: Vec<[F; 2 * NUM_INPUTS]> = (0..num_keccak_perms) .map(|i| { @@ -257,6 +267,7 @@ mod tests { let keccak_trace = make_keccak_trace(num_keccak_perms, &keccak_stark, &mut rng); let logic_trace = make_logic_trace(num_logic_rows, &logic_stark, &mut rng); + let mut memory_trace = make_memory_trace(num_memory_ops, &memory_stark, &mut rng); let cpu_trace = make_cpu_trace( num_keccak_perms, num_logic_rows, @@ -264,10 +275,9 @@ mod tests { &cpu_stark, &keccak_trace, &logic_trace, + &mut memory_trace, ); - let memory_ops = generate_random_memory_ops(num_memory_ops); - let memory_trace = memory_stark.generate_trace(memory_ops); let mut cpu_keccak_input_output = cpu::columns::KECCAK_INPUT_LIMBS.collect::>(); cpu_keccak_input_output.extend(cpu::columns::KECCAK_OUTPUT_LIMBS); @@ -301,7 +311,34 @@ mod tests { res }; - let cross_table_lookups = vec![ + let cpu_memory_cols: Vec> = (0..NUM_MEMORY_OPS) + .map(|op| { + let mut cols = vec![Column::linear_combination_with_constant( + [(cpu::columns::CLOCK, F::from_canonical_usize(NUM_MEMORY_OPS))], + F::from_canonical_usize(op), + )]; + cols.extend(Column::singles([ + cpu::columns::memop_is_read(op), + cpu::columns::memop_addr_context(op), + cpu::columns::memop_addr_segment(op), + cpu::columns::memop_addr_virtual(op), + ])); + cols.extend(Column::singles( + (0..8).map(|j| cpu::columns::memop_value(op, j)), + )); + cols + }) + .collect(); + let mut memory_memory_cols = vec![ + memory::registers::TIMESTAMP, + memory::registers::IS_READ, + memory::registers::ADDR_CONTEXT, + memory::registers::ADDR_SEGMENT, + memory::registers::ADDR_VIRTUAL, + ]; + memory_memory_cols.extend((0..8).map(memory::registers::value_limb)); + + let mut cross_table_lookups = vec![ CrossTableLookup::new( vec![TableWithColumns::new( Table::Cpu, @@ -325,6 +362,21 @@ mod tests { None, ), ]; + cross_table_lookups.extend((0..NUM_MEMORY_OPS).map(|op| { + CrossTableLookup::new( + vec![TableWithColumns::new( + Table::Cpu, + cpu_memory_cols[op].clone(), + Some(Column::single(cpu::columns::uses_memop(op))), + )], + TableWithColumns::new( + Table::Memory, + Column::singles(memory_memory_cols.clone()).collect(), + Some(Column::single(memory::registers::is_memop(op))), + ), + None, + ) + })); let all_stark = AllStark { cpu_stark, @@ -338,7 +390,7 @@ mod tests { &all_stark, config, vec![cpu_trace, keccak_trace, logic_trace, memory_trace], - vec![vec![]; 3], + vec![vec![]; 4], &mut TimingTree::default(), )?; diff --git a/evm/src/memory/memory_stark.rs b/evm/src/memory/memory_stark.rs index 07afa34d..0a75eaae 100644 --- a/evm/src/memory/memory_stark.rs +++ b/evm/src/memory/memory_stark.rs @@ -8,7 +8,7 @@ use plonky2::field::polynomial::PolynomialValues; use plonky2::hash::hash_types::RichField; use plonky2::timed; use plonky2::util::timing::TimingTree; -use rand::{thread_rng, Rng}; +use rand::Rng; use crate::constraint_consumer::{ConstraintConsumer, RecursiveConstraintConsumer}; use crate::memory::registers::{ @@ -38,11 +38,9 @@ pub struct MemoryOp { value: [F; 8], } -pub fn generate_random_memory_ops(num_ops: usize) -> Vec> { +pub fn generate_random_memory_ops(num_ops: usize, rng: &mut R) -> Vec> { let mut memory_ops = Vec::new(); - let mut rng = thread_rng(); - let mut current_memory_values: HashMap<(F, F, F), [F; 8]> = HashMap::new(); for i in 0..num_ops { let is_read = if i == 0 { false } else { rng.gen() };