diff --git a/evm/src/all_stark.rs b/evm/src/all_stark.rs index 15d0a6f8..e8b44d23 100644 --- a/evm/src/all_stark.rs +++ b/evm/src/all_stark.rs @@ -318,45 +318,18 @@ mod tests { cpu_trace_rows.push(row.into()); } - for i in 0..num_logic_rows { + // Pad to `num_memory_ops` for memory testing. + for _ in cpu_trace_rows.len()..num_memory_ops { let mut row: cpu::columns::CpuColumnsView = [F::ZERO; CpuStark::::COLUMNS].into(); + row.opcode_bits = bits_from_opcode(0x5b); row.is_cpu_cycle = F::ONE; row.is_kernel_mode = F::ONE; - - // Since these are the first cycle rows, we must start with PC=route_txn then increment. - row.program_counter = F::from_canonical_usize(KERNEL.global_labels["route_txn"] + i); - row.opcode_bits = bits_from_opcode( - if logic_trace[logic::columns::IS_AND].values[i] != F::ZERO { - 0x16 - } else if logic_trace[logic::columns::IS_OR].values[i] != F::ZERO { - 0x17 - } else if logic_trace[logic::columns::IS_XOR].values[i] != F::ZERO { - 0x18 - } else { - panic!() - }, - ); - - let logic = row.general.logic_mut(); - - let input0_bit_cols = logic::columns::limb_bit_cols_for_input(logic::columns::INPUT0); - for (col_cpu, limb_cols_logic) in logic.input0.iter_mut().zip(input0_bit_cols) { - *col_cpu = limb_from_bits_le(limb_cols_logic.map(|col| logic_trace[col].values[i])); - } - - let input1_bit_cols = logic::columns::limb_bit_cols_for_input(logic::columns::INPUT1); - for (col_cpu, limb_cols_logic) in logic.input1.iter_mut().zip(input1_bit_cols) { - *col_cpu = limb_from_bits_le(limb_cols_logic.map(|col| logic_trace[col].values[i])); - } - - for (col_cpu, col_logic) in logic.output.iter_mut().zip(logic::columns::RESULT) { - *col_cpu = logic_trace[col_logic].values[i]; - } - + row.program_counter = F::from_canonical_usize(KERNEL.global_labels["route_txn"]); cpu_stark.generate(row.borrow_mut()); cpu_trace_rows.push(row.into()); } + for i in 0..num_memory_ops { let mem_timestamp: usize = memory_trace[memory::columns::TIMESTAMP].values[i] .to_canonical_u64() @@ -388,6 +361,44 @@ mod tests { } } + for i in 0..num_logic_rows { + let mut row: cpu::columns::CpuColumnsView = + [F::ZERO; CpuStark::::COLUMNS].into(); + row.is_cpu_cycle = F::ONE; + row.is_kernel_mode = F::ONE; + + // Since these are the first cycle rows, we must start with PC=route_txn then increment. + row.program_counter = F::from_canonical_usize(KERNEL.global_labels["route_txn"] + i); + row.opcode_bits = bits_from_opcode( + if logic_trace[logic::columns::IS_AND].values[i] != F::ZERO { + 0x16 + } else if logic_trace[logic::columns::IS_OR].values[i] != F::ZERO { + 0x17 + } else if logic_trace[logic::columns::IS_XOR].values[i] != F::ZERO { + 0x18 + } else { + panic!() + }, + ); + + let input0_bit_cols = logic::columns::limb_bit_cols_for_input(logic::columns::INPUT0); + for (col_cpu, limb_cols_logic) in row.mem_value[0].iter_mut().zip(input0_bit_cols) { + *col_cpu = limb_from_bits_le(limb_cols_logic.map(|col| logic_trace[col].values[i])); + } + + let input1_bit_cols = logic::columns::limb_bit_cols_for_input(logic::columns::INPUT1); + for (col_cpu, limb_cols_logic) in row.mem_value[1].iter_mut().zip(input1_bit_cols) { + *col_cpu = limb_from_bits_le(limb_cols_logic.map(|col| logic_trace[col].values[i])); + } + + for (col_cpu, col_logic) in row.mem_value[2].iter_mut().zip(logic::columns::RESULT) { + *col_cpu = logic_trace[col_logic].values[i]; + } + + cpu_stark.generate(row.borrow_mut()); + cpu_trace_rows.push(row.into()); + } + // Trap to kernel { let mut row: cpu::columns::CpuColumnsView = @@ -398,7 +409,7 @@ mod tests { row.opcode_bits = bits_from_opcode(0x0a); // `EXP` is implemented in software row.is_kernel_mode = F::ONE; row.program_counter = last_row.program_counter + F::ONE; - row.general.syscalls_mut().output = [ + row.mem_value[0] = [ row.program_counter, F::ONE, F::ZERO, @@ -420,7 +431,7 @@ mod tests { row.opcode_bits = bits_from_opcode(0xf9); row.is_kernel_mode = F::ONE; row.program_counter = F::from_canonical_usize(KERNEL.global_labels["sys_exp"]); - row.general.jumps_mut().input0 = [ + row.mem_value[0] = [ F::from_canonical_u16(15682), F::ONE, F::ZERO, @@ -442,7 +453,7 @@ mod tests { row.opcode_bits = bits_from_opcode(0x56); row.is_kernel_mode = F::ONE; row.program_counter = F::from_canonical_u16(15682); - row.general.jumps_mut().input0 = [ + row.mem_value[0] = [ F::from_canonical_u16(15106), F::ZERO, F::ZERO, @@ -452,7 +463,7 @@ mod tests { F::ZERO, F::ZERO, ]; - row.general.jumps_mut().input1 = [ + row.mem_value[1] = [ F::ONE, F::ZERO, F::ZERO, @@ -479,7 +490,7 @@ mod tests { row.opcode_bits = bits_from_opcode(0xf9); row.is_kernel_mode = F::ONE; row.program_counter = F::from_canonical_u16(15106); - row.general.jumps_mut().input0 = [ + row.mem_value[0] = [ F::from_canonical_u16(63064), F::ZERO, F::ZERO, @@ -501,7 +512,7 @@ mod tests { row.opcode_bits = bits_from_opcode(0x56); row.is_kernel_mode = F::ZERO; row.program_counter = F::from_canonical_u16(63064); - row.general.jumps_mut().input0 = [ + row.mem_value[0] = [ F::from_canonical_u16(3754), F::ZERO, F::ZERO, @@ -511,7 +522,7 @@ mod tests { F::ZERO, F::ZERO, ]; - row.general.jumps_mut().input1 = [ + row.mem_value[1] = [ F::ONE, F::ZERO, F::ZERO, @@ -539,7 +550,7 @@ mod tests { row.opcode_bits = bits_from_opcode(0x57); row.is_kernel_mode = F::ZERO; row.program_counter = F::from_canonical_u16(3754); - row.general.jumps_mut().input0 = [ + row.mem_value[0] = [ F::from_canonical_u16(37543), F::ZERO, F::ZERO, @@ -549,7 +560,7 @@ mod tests { F::ZERO, F::ZERO, ]; - row.general.jumps_mut().input1 = [ + row.mem_value[1] = [ F::ZERO, F::ZERO, F::ZERO, @@ -577,7 +588,7 @@ mod tests { row.opcode_bits = bits_from_opcode(0x57); row.is_kernel_mode = F::ZERO; row.program_counter = F::from_canonical_u16(37543); - row.general.jumps_mut().input0 = [ + row.mem_value[0] = [ F::from_canonical_u16(37543), F::ZERO, F::ZERO, @@ -606,7 +617,7 @@ mod tests { row.opcode_bits = bits_from_opcode(0x56); row.is_kernel_mode = F::ZERO; row.program_counter = last_row.program_counter + F::ONE; - row.general.jumps_mut().input0 = [ + row.mem_value[0] = [ F::from_canonical_u16(37543), F::ZERO, F::ZERO, @@ -616,7 +627,7 @@ mod tests { F::ZERO, F::ZERO, ]; - row.general.jumps_mut().input1 = [ + row.mem_value[1] = [ F::ONE, F::ZERO, F::ZERO, diff --git a/evm/src/cpu/columns/general.rs b/evm/src/cpu/columns/general.rs index affd676d..43f987e9 100644 --- a/evm/src/cpu/columns/general.rs +++ b/evm/src/cpu/columns/general.rs @@ -9,7 +9,6 @@ pub(crate) union CpuGeneralColumnsView { arithmetic: CpuArithmeticView, logic: CpuLogicView, jumps: CpuJumpsView, - syscalls: CpuSyscallsView, } impl CpuGeneralColumnsView { @@ -52,16 +51,6 @@ impl CpuGeneralColumnsView { pub(crate) fn jumps_mut(&mut self) -> &mut CpuJumpsView { unsafe { &mut self.jumps } } - - // SAFETY: Each view is a valid interpretation of the underlying array. - pub(crate) fn syscalls(&self) -> &CpuSyscallsView { - unsafe { &self.syscalls } - } - - // SAFETY: Each view is a valid interpretation of the underlying array. - pub(crate) fn syscalls_mut(&mut self) -> &mut CpuSyscallsView { - unsafe { &mut self.syscalls } - } } impl PartialEq for CpuGeneralColumnsView { @@ -107,23 +96,16 @@ pub(crate) struct CpuArithmeticView { #[derive(Copy, Clone)] pub(crate) struct CpuLogicView { - // Assuming a limb size of 32 bits. - pub(crate) input0: [T; 8], - pub(crate) input1: [T; 8], - pub(crate) output: [T; 8], - - // Pseudoinverse of `(input0 - input1)`. Used prove that they are unequal. + // Pseudoinverse of `(input0 - input1)`. Used prove that they are unequal. Assumes 32-bit limbs. pub(crate) diff_pinv: [T; 8], } #[derive(Copy, Clone)] pub(crate) struct CpuJumpsView { - /// Assuming a limb size of 32 bits. - /// The top stack value at entry (for jumps, the address; for `EXIT_KERNEL`, the address and new - /// privilege level). - pub(crate) input0: [T; 8], - /// For `JUMPI`, the second stack value (the predicate). For `JUMP`, 1. - pub(crate) input1: [T; 8], + /// `input0` is `mem_value[0]`. It's the top stack value at entry (for jumps, the address; for + /// `EXIT_KERNEL`, the address and new privilege level). + /// `input1` is `mem_value[1]`. For `JUMPI`, it's the second stack value (the predicate). For + /// `JUMP`, 1. /// Inverse of `input0[1] + ... + input0[7]`, if one exists; otherwise, an arbitrary value. /// Needed to prove that `input0` is nonzero. @@ -162,15 +144,5 @@ pub(crate) struct CpuJumpsView { pub(crate) should_trap: T, } -#[derive(Copy, Clone)] -pub(crate) struct CpuSyscallsView { - /// Assuming a limb size of 32 bits. - /// The output contains the context that is required to from the system call in `EXIT_KERNEL`. - /// `output[0]` contains the program counter at the time the system call was made (the address - /// of the syscall instruction). `output[1]` is 1 if we were in kernel mode at the time and 0 - /// otherwise. `output[2]`, ..., `output[7]` are zero. - pub(crate) output: [T; 8], -} - // `u8` is guaranteed to have a `size_of` of 1. pub const NUM_SHARED_COLUMNS: usize = size_of::>(); diff --git a/evm/src/cpu/cpu_stark.rs b/evm/src/cpu/cpu_stark.rs index 852b7b54..39518a43 100644 --- a/evm/src/cpu/cpu_stark.rs +++ b/evm/src/cpu/cpu_stark.rs @@ -48,10 +48,9 @@ pub fn ctl_filter_keccak_memory() -> Column { pub fn ctl_data_logic() -> Vec> { let mut res = Column::singles([COL_MAP.is_and, COL_MAP.is_or, COL_MAP.is_xor]).collect_vec(); - let logic = COL_MAP.general.logic(); - res.extend(Column::singles(logic.input0)); - res.extend(Column::singles(logic.input1)); - res.extend(Column::singles(logic.output)); + res.extend(Column::singles(COL_MAP.mem_value[0])); + res.extend(Column::singles(COL_MAP.mem_value[1])); + res.extend(Column::singles(COL_MAP.mem_value[2])); res } diff --git a/evm/src/cpu/jumps.rs b/evm/src/cpu/jumps.rs index 10c9503a..bac10eb6 100644 --- a/evm/src/cpu/jumps.rs +++ b/evm/src/cpu/jumps.rs @@ -17,16 +17,16 @@ pub fn eval_packed_exit_kernel( nv: &CpuColumnsView

, yield_constr: &mut ConstraintConsumer

, ) { - let jumps_lv = lv.general.jumps(); + let input = lv.mem_value[0]; // If we are executing `EXIT_KERNEL` then we simply restore the program counter and kernel mode // flag. The top 6 (32-bit) limbs are ignored (this is not part of the spec, but we trust the // kernel to set them to zero). yield_constr.constraint_transition( - lv.is_cpu_cycle * lv.is_exit_kernel * (jumps_lv.input0[0] - nv.program_counter), + lv.is_cpu_cycle * lv.is_exit_kernel * (input[0] - nv.program_counter), ); yield_constr.constraint_transition( - lv.is_cpu_cycle * lv.is_exit_kernel * (jumps_lv.input0[1] - nv.is_kernel_mode), + lv.is_cpu_cycle * lv.is_exit_kernel * (input[1] - nv.is_kernel_mode), ); } @@ -36,18 +36,18 @@ pub fn eval_ext_circuit_exit_kernel, const D: usize nv: &CpuColumnsView>, yield_constr: &mut RecursiveConstraintConsumer, ) { - let jumps_lv = lv.general.jumps(); + let input = lv.mem_value[0]; let filter = builder.mul_extension(lv.is_cpu_cycle, lv.is_exit_kernel); // If we are executing `EXIT_KERNEL` then we simply restore the program counter and kernel mode // flag. The top 6 (32-bit) limbs are ignored (this is not part of the spec, but we trust the // kernel to set them to zero). - let pc_constr = builder.sub_extension(jumps_lv.input0[0], nv.program_counter); + let pc_constr = builder.sub_extension(input[0], nv.program_counter); let pc_constr = builder.mul_extension(filter, pc_constr); yield_constr.constraint_transition(builder, pc_constr); - let kernel_constr = builder.sub_extension(jumps_lv.input0[1], nv.is_kernel_mode); + let kernel_constr = builder.sub_extension(input[1], nv.is_kernel_mode); let kernel_constr = builder.mul_extension(filter, kernel_constr); yield_constr.constraint_transition(builder, kernel_constr); } @@ -58,12 +58,14 @@ pub fn eval_packed_jump_jumpi( yield_constr: &mut ConstraintConsumer

, ) { let jumps_lv = lv.general.jumps(); + let input0 = lv.mem_value[0]; + let input1 = lv.mem_value[1]; let filter = lv.is_jump + lv.is_jumpi; // `JUMP` or `JUMPI` // If `JUMP`, re-use the `JUMPI` logic, but setting the second input (the predicate) to be 1. // In other words, we implement `JUMP(addr)` as `JUMPI(addr, cond=1)`. - yield_constr.constraint(lv.is_jump * (jumps_lv.input1[0] - P::ONES)); - for &limb in &jumps_lv.input1[1..] { + yield_constr.constraint(lv.is_jump * (input1[0] - P::ONES)); + for &limb in &input1[1..] { // Set all limbs (other than the least-significant limb) to 0. // NB: Technically, they don't have to be 0, as long as the sum // `input1[0] + ... + input1[7]` cannot overflow. @@ -75,7 +77,7 @@ pub fn eval_packed_jump_jumpi( yield_constr .constraint(filter * jumps_lv.input0_upper_zero * (jumps_lv.input0_upper_zero - P::ONES)); // The below sum cannot overflow due to the limb size. - let input0_upper_sum: P = jumps_lv.input0[1..].iter().copied().sum(); + let input0_upper_sum: P = input0[1..].iter().copied().sum(); // `input0_upper_zero` = 1 implies `input0_upper_sum` = 0. yield_constr.constraint(filter * jumps_lv.input0_upper_zero * input0_upper_sum); // `input0_upper_zero` = 0 implies `input0_upper_sum_inv * input0_upper_sum` = 1, which can only @@ -113,7 +115,7 @@ pub fn eval_packed_jump_jumpi( // Validate `should_continue` // This sum cannot overflow (due to limb size). - let input1_sum: P = jumps_lv.input1.into_iter().sum(); + let input1_sum: P = input1.into_iter().sum(); // `should_continue` = 1 implies `input1_sum` = 0. yield_constr.constraint(filter * jumps_lv.should_continue * input1_sum); // `should_continue` = 0 implies `input1_sum * input1_sum_inv` = 1, which can only happen if @@ -147,9 +149,8 @@ pub fn eval_packed_jump_jumpi( yield_constr.constraint_transition( filter * jumps_lv.should_continue * (nv.program_counter - lv.program_counter - P::ONES), ); - yield_constr.constraint_transition( - filter * jumps_lv.should_jump * (nv.program_counter - jumps_lv.input0[0]), - ); + yield_constr + .constraint_transition(filter * jumps_lv.should_jump * (nv.program_counter - input0[0])); } pub fn eval_ext_circuit_jump_jumpi, const D: usize>( @@ -159,15 +160,17 @@ pub fn eval_ext_circuit_jump_jumpi, const D: usize> yield_constr: &mut RecursiveConstraintConsumer, ) { let jumps_lv = lv.general.jumps(); + let input0 = lv.mem_value[0]; + let input1 = lv.mem_value[1]; let filter = builder.add_extension(lv.is_jump, lv.is_jumpi); // `JUMP` or `JUMPI` // If `JUMP`, re-use the `JUMPI` logic, but setting the second input (the predicate) to be 1. // In other words, we implement `JUMP(addr)` as `JUMPI(addr, cond=1)`. { - let constr = builder.mul_sub_extension(lv.is_jump, jumps_lv.input1[0], lv.is_jump); + let constr = builder.mul_sub_extension(lv.is_jump, input1[0], lv.is_jump); yield_constr.constraint(builder, constr); } - for &limb in &jumps_lv.input1[1..] { + for &limb in &input1[1..] { // Set all limbs (other than the least-significant limb) to 0. // NB: Technically, they don't have to be 0, as long as the sum // `input1[0] + ... + input1[7]` cannot overflow. @@ -188,7 +191,7 @@ pub fn eval_ext_circuit_jump_jumpi, const D: usize> } { // The below sum cannot overflow due to the limb size. - let input0_upper_sum = builder.add_many_extension(jumps_lv.input0[1..].iter()); + let input0_upper_sum = builder.add_many_extension(input0[1..].iter()); // `input0_upper_zero` = 1 implies `input0_upper_sum` = 0. let constr = builder.mul_extension(jumps_lv.input0_upper_zero, input0_upper_sum); @@ -251,7 +254,7 @@ pub fn eval_ext_circuit_jump_jumpi, const D: usize> // Validate `should_continue` { // This sum cannot overflow (due to limb size). - let input1_sum = builder.add_many_extension(jumps_lv.input1.into_iter()); + let input1_sum = builder.add_many_extension(input1.into_iter()); // `should_continue` = 1 implies `input1_sum` = 0. let constr = builder.mul_extension(jumps_lv.should_continue, input1_sum); @@ -326,7 +329,7 @@ pub fn eval_ext_circuit_jump_jumpi, const D: usize> } // ...or jumping. { - let constr = builder.sub_extension(nv.program_counter, jumps_lv.input0[0]); + let constr = builder.sub_extension(nv.program_counter, input0[0]); let constr = builder.mul_extension(jumps_lv.should_jump, constr); let constr = builder.mul_extension(filter, constr); yield_constr.constraint_transition(builder, constr); diff --git a/evm/src/cpu/simple_logic/eq_iszero.rs b/evm/src/cpu/simple_logic/eq_iszero.rs index e1b33dc9..c3d9bc99 100644 --- a/evm/src/cpu/simple_logic/eq_iszero.rs +++ b/evm/src/cpu/simple_logic/eq_iszero.rs @@ -8,7 +8,8 @@ use crate::constraint_consumer::{ConstraintConsumer, RecursiveConstraintConsumer use crate::cpu::columns::CpuColumnsView; pub fn generate(lv: &mut CpuColumnsView) { - let logic = lv.general.logic_mut(); + let input0 = lv.mem_value[0]; + let eq_filter = lv.is_eq.to_canonical_u64(); let iszero_filter = lv.is_iszero.to_canonical_u64(); assert!(eq_filter <= 1); @@ -19,19 +20,22 @@ pub fn generate(lv: &mut CpuColumnsView) { return; } + let input1 = &mut lv.mem_value[1]; if iszero_filter != 0 { - for limb in logic.input1.iter_mut() { + for limb in input1.iter_mut() { *limb = F::ZERO; } } - let num_unequal_limbs = izip!(logic.input0, logic.input1) + let input1 = lv.mem_value[1]; + let num_unequal_limbs = izip!(input0, input1) .map(|(limb0, limb1)| (limb0 != limb1) as usize) .sum(); let equal = num_unequal_limbs == 0; - logic.output[0] = F::from_bool(equal); - for limb in &mut logic.output[1..] { + let output = &mut lv.mem_value[2]; + output[0] = F::from_bool(equal); + for limb in &mut output[1..] { *limb = F::ZERO; } @@ -40,10 +44,11 @@ pub fn generate(lv: &mut CpuColumnsView) { // Then `diff @ x = num_unequal_limbs`, where `@` denotes the dot product. We set // `diff_pinv = num_unequal_limbs^-1 * x` if `num_unequal_limbs != 0` and 0 otherwise. We have // `diff @ diff_pinv = 1 - equal` as desired. + let logic = lv.general.logic_mut(); let num_unequal_limbs_inv = F::from_canonical_usize(num_unequal_limbs) .try_inverse() .unwrap_or(F::ZERO); - for (limb_pinv, limb0, limb1) in izip!(logic.diff_pinv.iter_mut(), logic.input0, logic.input1) { + for (limb_pinv, limb0, limb1) in izip!(logic.diff_pinv.iter_mut(), input0, input1) { *limb_pinv = (limb0 - limb1).try_inverse().unwrap_or(F::ZERO) * num_unequal_limbs_inv; } } @@ -53,27 +58,31 @@ pub fn eval_packed( yield_constr: &mut ConstraintConsumer

, ) { let logic = lv.general.logic(); + let input0 = lv.mem_value[0]; + let input1 = lv.mem_value[1]; + let output = lv.mem_value[2]; + let eq_filter = lv.is_eq; let iszero_filter = lv.is_iszero; let eq_or_iszero_filter = eq_filter + iszero_filter; - let equal = logic.output[0]; + let equal = output[0]; let unequal = P::ONES - equal; // Handle `EQ` and `ISZERO`. Most limbs of the output are 0, but the least-significant one is // either 0 or 1. yield_constr.constraint(eq_or_iszero_filter * equal * unequal); - for &limb in &logic.output[1..] { + for &limb in &output[1..] { yield_constr.constraint(eq_or_iszero_filter * limb); } // If `ISZERO`, constrain input1 to be zero, effectively implementing ISZERO(x) as EQ(x, 0). - for limb in logic.input1 { + for limb in input1 { yield_constr.constraint(iszero_filter * limb); } // `equal` implies `input0[i] == input1[i]` for all `i`. - for (limb0, limb1) in izip!(logic.input0, logic.input1) { + for (limb0, limb1) in izip!(input0, input1) { let diff = limb0 - limb1; yield_constr.constraint(eq_or_iszero_filter * equal * diff); } @@ -82,7 +91,7 @@ pub fn eval_packed( // If `unequal`, find `diff_pinv` such that `(input0 - input1) @ diff_pinv == 1`, where `@` // denotes the dot product (there will be many such `diff_pinv`). This can only be done if // `input0 != input1`. - let dot: P = izip!(logic.input0, logic.input1, logic.diff_pinv) + let dot: P = izip!(input0, input1, logic.diff_pinv) .map(|(limb0, limb1, diff_pinv_el)| (limb0 - limb1) * diff_pinv_el) .sum(); yield_constr.constraint(eq_or_iszero_filter * (dot - unequal)); @@ -97,11 +106,15 @@ pub fn eval_ext_circuit, const D: usize>( let one = builder.one_extension(); let logic = lv.general.logic(); + let input0 = lv.mem_value[0]; + let input1 = lv.mem_value[1]; + let output = lv.mem_value[2]; + let eq_filter = lv.is_eq; let iszero_filter = lv.is_iszero; let eq_or_iszero_filter = builder.add_extension(eq_filter, iszero_filter); - let equal = logic.output[0]; + let equal = output[0]; let unequal = builder.sub_extension(one, equal); // Handle `EQ` and `ISZERO`. Most limbs of the output are 0, but the least-significant one is @@ -111,19 +124,19 @@ pub fn eval_ext_circuit, const D: usize>( let constr = builder.mul_extension(eq_or_iszero_filter, constr); yield_constr.constraint(builder, constr); } - for &limb in &logic.output[1..] { + for &limb in &output[1..] { let constr = builder.mul_extension(eq_or_iszero_filter, limb); yield_constr.constraint(builder, constr); } // If `ISZERO`, constrain input1 to be zero, effectively implementing ISZERO(x) as EQ(x, 0). - for limb in logic.input1 { + for limb in input1 { let constr = builder.mul_extension(iszero_filter, limb); yield_constr.constraint(builder, constr); } // `equal` implies `input0[i] == input1[i]` for all `i`. - for (limb0, limb1) in izip!(logic.input0, logic.input1) { + for (limb0, limb1) in izip!(input0, input1) { let diff = builder.sub_extension(limb0, limb1); let constr = builder.mul_extension(equal, diff); let constr = builder.mul_extension(eq_or_iszero_filter, constr); @@ -135,7 +148,7 @@ pub fn eval_ext_circuit, const D: usize>( // denotes the dot product (there will be many such `diff_pinv`). This can only be done if // `input0 != input1`. { - let dot: ExtensionTarget = izip!(logic.input0, logic.input1, logic.diff_pinv).fold( + let dot: ExtensionTarget = izip!(input0, input1, logic.diff_pinv).fold( zero, |cumul, (limb0, limb1, diff_pinv_el)| { let diff = builder.sub_extension(limb0, limb1); diff --git a/evm/src/cpu/simple_logic/not.rs b/evm/src/cpu/simple_logic/not.rs index bcff3344..d9a16a66 100644 --- a/evm/src/cpu/simple_logic/not.rs +++ b/evm/src/cpu/simple_logic/not.rs @@ -17,8 +17,9 @@ pub fn generate(lv: &mut CpuColumnsView) { } assert_eq!(is_not_filter, 1); - let logic = lv.general.logic_mut(); - for (input, output_ref) in logic.input0.into_iter().zip(logic.output.iter_mut()) { + let input = lv.mem_value[0]; + let output = &mut lv.mem_value[1]; + for (input, output_ref) in input.into_iter().zip(output.iter_mut()) { let input = input.to_canonical_u64(); assert_eq!(input >> LIMB_SIZE, 0); let output = input ^ ALL_1_LIMB; @@ -30,14 +31,16 @@ pub fn eval_packed( lv: &CpuColumnsView

, yield_constr: &mut ConstraintConsumer

, ) { - // This is simple: just do output = 0xffff - input. - let logic = lv.general.logic(); + // This is simple: just do output = 0xffffffff - input. + let input = lv.mem_value[0]; + let output = lv.mem_value[1]; let cycle_filter = lv.is_cpu_cycle; let is_not_filter = lv.is_not; let filter = cycle_filter * is_not_filter; - for (input, output) in logic.input0.into_iter().zip(logic.output) { - yield_constr - .constraint(filter * (output + input - P::Scalar::from_canonical_u64(ALL_1_LIMB))); + for (input_limb, output_limb) in input.into_iter().zip(output) { + yield_constr.constraint( + filter * (output_limb + input_limb - P::Scalar::from_canonical_u64(ALL_1_LIMB)), + ); } } @@ -46,12 +49,13 @@ pub fn eval_ext_circuit, const D: usize>( lv: &CpuColumnsView>, yield_constr: &mut RecursiveConstraintConsumer, ) { - let logic = lv.general.logic(); + let input = lv.mem_value[0]; + let output = lv.mem_value[1]; let cycle_filter = lv.is_cpu_cycle; let is_not_filter = lv.is_not; let filter = builder.mul_extension(cycle_filter, is_not_filter); - for (input, output) in logic.input0.into_iter().zip(logic.output) { - let constr = builder.add_extension(output, input); + for (input_limb, output_limb) in input.into_iter().zip(output) { + let constr = builder.add_extension(output_limb, input_limb); let constr = builder.arithmetic_extension( F::ONE, -F::from_canonical_u64(ALL_1_LIMB), diff --git a/evm/src/cpu/syscalls.rs b/evm/src/cpu/syscalls.rs index a676a6a2..1ca45bc3 100644 --- a/evm/src/cpu/syscalls.rs +++ b/evm/src/cpu/syscalls.rs @@ -28,7 +28,6 @@ pub fn eval_packed( nv: &CpuColumnsView

, yield_constr: &mut ConstraintConsumer

, ) { - let lv_syscalls = lv.general.syscalls(); let syscall_list = Lazy::force(&TRAP_LIST); // 1 if _any_ syscall, else 0. let should_syscall: P = syscall_list @@ -48,12 +47,14 @@ pub fn eval_packed( yield_constr.constraint_transition(filter * (nv.program_counter - syscall_dst)); // If syscall: set kernel mode yield_constr.constraint_transition(filter * (nv.is_kernel_mode - P::ONES)); + + let output = lv.mem_value[0]; // If syscall: push current PC to stack - yield_constr.constraint(filter * (lv_syscalls.output[0] - lv.program_counter)); + yield_constr.constraint(filter * (output[0] - lv.program_counter)); // If syscall: push current kernel flag to stack (share register with PC) - yield_constr.constraint(filter * (lv_syscalls.output[1] - lv.is_kernel_mode)); + yield_constr.constraint(filter * (output[1] - lv.is_kernel_mode)); // If syscall: zero the rest of that register - for &limb in &lv_syscalls.output[2..] { + for &limb in &output[2..] { yield_constr.constraint(filter * limb); } } @@ -64,7 +65,6 @@ pub fn eval_ext_circuit, const D: usize>( nv: &CpuColumnsView>, yield_constr: &mut RecursiveConstraintConsumer, ) { - let lv_syscalls = lv.general.syscalls(); let syscall_list = Lazy::force(&TRAP_LIST); // 1 if _any_ syscall, else 0. let should_syscall = @@ -90,20 +90,22 @@ pub fn eval_ext_circuit, const D: usize>( let constr = builder.mul_sub_extension(filter, nv.is_kernel_mode, filter); yield_constr.constraint_transition(builder, constr); } + + let output = lv.mem_value[0]; // If syscall: push current PC to stack { - let constr = builder.sub_extension(lv_syscalls.output[0], lv.program_counter); + let constr = builder.sub_extension(output[0], lv.program_counter); let constr = builder.mul_extension(filter, constr); yield_constr.constraint(builder, constr); } // If syscall: push current kernel flag to stack (share register with PC) { - let constr = builder.sub_extension(lv_syscalls.output[1], lv.is_kernel_mode); + let constr = builder.sub_extension(output[1], lv.is_kernel_mode); let constr = builder.mul_extension(filter, constr); yield_constr.constraint(builder, constr); } // If syscall: zero the rest of that register - for &limb in &lv_syscalls.output[2..] { + for &limb in &output[2..] { let constr = builder.mul_extension(filter, limb); yield_constr.constraint(builder, constr); }