From 8e8e02cbb40efb7713fb9c55a2964309d5d855d3 Mon Sep 17 00:00:00 2001 From: Linda Guiga Date: Tue, 26 Sep 2023 14:24:47 -0400 Subject: [PATCH] Combine PUSH0 and PC flags. --- evm/src/cpu/columns/ops.rs | 3 +-- evm/src/cpu/control_flow.rs | 5 ++--- evm/src/cpu/decode.rs | 22 ++++++++++++++++++---- evm/src/cpu/gas.rs | 3 +-- evm/src/cpu/pc.rs | 8 ++++++-- evm/src/cpu/push0.rs | 6 ++++-- evm/src/cpu/stack.rs | 7 +------ evm/src/witness/transition.rs | 3 +-- 8 files changed, 34 insertions(+), 23 deletions(-) diff --git a/evm/src/cpu/columns/ops.rs b/evm/src/cpu/columns/ops.rs index d4d753f7cf..db1604c52f 100644 --- a/evm/src/cpu/columns/ops.rs +++ b/evm/src/cpu/columns/ops.rs @@ -18,9 +18,7 @@ pub struct OpsColumnsView { pub prover_input: T, pub pop: T, pub jumps: T, // Combines JUMP and JUMPI flags. - pub pc: T, pub jumpdest: T, - pub push0: T, pub push: T, pub dup: T, pub swap: T, @@ -29,6 +27,7 @@ pub struct OpsColumnsView { pub mload_32bytes: T, pub exit_kernel: T, pub m_op_general: T, + pub pc_push0: T, // Combines PC and PUSH0 pub syscall: T, pub exception: T, diff --git a/evm/src/cpu/control_flow.rs b/evm/src/cpu/control_flow.rs index 9c17367aa2..c343860c12 100644 --- a/evm/src/cpu/control_flow.rs +++ b/evm/src/cpu/control_flow.rs @@ -8,7 +8,7 @@ use crate::constraint_consumer::{ConstraintConsumer, RecursiveConstraintConsumer use crate::cpu::columns::{CpuColumnsView, COL_MAP}; use crate::cpu::kernel::aggregator::KERNEL; -const NATIVE_INSTRUCTIONS: [usize; 17] = [ +const NATIVE_INSTRUCTIONS: [usize; 16] = [ COL_MAP.op.binary_op, COL_MAP.op.ternary_op, COL_MAP.op.fp254_op, @@ -21,9 +21,8 @@ const NATIVE_INSTRUCTIONS: [usize; 17] = [ COL_MAP.op.pop, // not JUMP (need to jump) // not JUMPI (possible need to jump) - COL_MAP.op.pc, + COL_MAP.op.pc_push0, COL_MAP.op.jumpdest, - COL_MAP.op.push0, // not PUSH (need to increment by more than 1) COL_MAP.op.dup, COL_MAP.op.swap, diff --git a/evm/src/cpu/decode.rs b/evm/src/cpu/decode.rs index c1c43a0bb1..dc871d5690 100644 --- a/evm/src/cpu/decode.rs +++ b/evm/src/cpu/decode.rs @@ -23,7 +23,7 @@ use crate::cpu::columns::{CpuColumnsView, COL_MAP}; /// behavior. /// Note: invalid opcodes are not represented here. _Any_ opcode is permitted to decode to /// `is_invalid`. The kernel then verifies that the opcode was _actually_ invalid. -const OPCODES: [(u8, usize, bool, usize); 16] = [ +const OPCODES: [(u8, usize, bool, usize); 14] = [ // (start index of block, number of top bits to check (log2), kernel-only, flag column) // ADD, MUL, SUB, DIV, MOD, LT, GT and BYTE flags are handled partly manually here, and partly through the Arithmetic table CTL. // ADDMOD, MULMOD and SUBMOD flags are handled partly manually here, and partly through the Arithmetic table CTL. @@ -36,9 +36,7 @@ const OPCODES: [(u8, usize, bool, usize); 16] = [ (0x49, 0, true, COL_MAP.op.prover_input), (0x50, 0, false, COL_MAP.op.pop), (0x56, 1, false, COL_MAP.op.jumps), // 0x56-0x57 - (0x58, 0, false, COL_MAP.op.pc), (0x5b, 0, false, COL_MAP.op.jumpdest), - (0x5f, 0, false, COL_MAP.op.push0), (0x60, 5, false, COL_MAP.op.push), // 0x60-0x7f (0x80, 4, false, COL_MAP.op.dup), // 0x80-0x8f (0x90, 4, false, COL_MAP.op.swap), // 0x90-0x9f @@ -52,13 +50,14 @@ const OPCODES: [(u8, usize, bool, usize); 16] = [ /// List of combined opcodes requiring a special handling. /// Each index in the list corresponds to an arbitrary combination /// of opcodes defined in evm/src/cpu/columns/ops.rs. -const COMBINED_OPCODES: [usize; 6] = [ +const COMBINED_OPCODES: [usize; 7] = [ COL_MAP.op.logic_op, COL_MAP.op.fp254_op, COL_MAP.op.binary_op, COL_MAP.op.ternary_op, COL_MAP.op.shift, COL_MAP.op.m_op_general, + COL_MAP.op.pc_push0, ]; pub fn generate(lv: &mut CpuColumnsView) { @@ -192,6 +191,12 @@ pub fn eval_packed_generic( * (opcode - P::Scalar::from_canonical_usize(0xfc_usize)) * lv.op.m_op_general; yield_constr.constraint(m_op_constr); + + // Manually check lv.op.pc_push0. + let pc_push0_constr = (opcode - P::Scalar::from_canonical_usize(0x58_usize)) + * (opcode - P::Scalar::from_canonical_usize(0x5f_usize)) + * lv.op.pc_push0; + yield_constr.constraint(pc_push0_constr); } pub fn eval_ext_circuit, const D: usize>( @@ -294,4 +299,13 @@ pub fn eval_ext_circuit, const D: usize>( m_op_constr = builder.mul_extension(m_op_constr, lv.op.m_op_general); yield_constr.constraint(builder, m_op_constr); + + // Manually check lv.op.pc_push0. + let pc_opcode = builder.constant_extension(F::Extension::from_canonical_usize(0x58_usize)); + let push0_opcode = builder.constant_extension(F::Extension::from_canonical_usize(0x5f_usize)); + let pc_constr = builder.sub_extension(opcode, pc_opcode); + let push0_constr = builder.sub_extension(opcode, push0_opcode); + let mut pc_push0_constr = builder.mul_extension(pc_constr, push0_constr); + pc_push0_constr = builder.mul_extension(pc_push0_constr, lv.op.pc_push0); + yield_constr.constraint(builder, pc_push0_constr); } diff --git a/evm/src/cpu/gas.rs b/evm/src/cpu/gas.rs index 51f375c056..c200c263da 100644 --- a/evm/src/cpu/gas.rs +++ b/evm/src/cpu/gas.rs @@ -30,9 +30,8 @@ const SIMPLE_OPCODES: OpsColumnsView> = OpsColumnsView { prover_input: KERNEL_ONLY_INSTR, pop: G_BASE, jumps: None, // Combined flag handled separately. - pc: G_BASE, + pc_push0: G_BASE, jumpdest: G_JUMPDEST, - push0: G_BASE, push: G_VERYLOW, dup: G_VERYLOW, swap: G_VERYLOW, diff --git a/evm/src/cpu/pc.rs b/evm/src/cpu/pc.rs index 26731c92c2..bd3eb422dd 100644 --- a/evm/src/cpu/pc.rs +++ b/evm/src/cpu/pc.rs @@ -11,7 +11,8 @@ pub fn eval_packed( lv: &CpuColumnsView

, yield_constr: &mut ConstraintConsumer

, ) { - let filter = lv.op.pc; + // `PUSH0`'s opcode is odd, while `PC`'s opcode is even. + let filter = lv.op.pc_push0 * (P::ONES - lv.opcode_bits[0]); let push_value = lv.mem_channels[NUM_GP_CHANNELS - 1].value; yield_constr.constraint(filter * (push_value[0] - lv.program_counter)); for &limb in &push_value[1..] { @@ -24,7 +25,10 @@ pub fn eval_ext_circuit, const D: usize>( lv: &CpuColumnsView>, yield_constr: &mut RecursiveConstraintConsumer, ) { - let filter = lv.op.pc; + // `PUSH0`'s opcode is odd, while `PC`'s opcode is even. + let one = builder.one_extension(); + let mut filter = builder.sub_extension(one, lv.opcode_bits[0]); + filter = builder.mul_extension(lv.op.pc_push0, filter); let push_value = lv.mem_channels[NUM_GP_CHANNELS - 1].value; { let diff = builder.sub_extension(push_value[0], lv.program_counter); diff --git a/evm/src/cpu/push0.rs b/evm/src/cpu/push0.rs index 30f6d0ae0f..2adda9331e 100644 --- a/evm/src/cpu/push0.rs +++ b/evm/src/cpu/push0.rs @@ -11,7 +11,8 @@ pub fn eval_packed( lv: &CpuColumnsView

, yield_constr: &mut ConstraintConsumer

, ) { - let filter = lv.op.push0; + // `PUSH0`'s opcode is odd, while `PC`'s opcode is even. + let filter = lv.op.pc_push0 * lv.opcode_bits[0]; let push_value = lv.mem_channels[NUM_GP_CHANNELS - 1].value; for limb in push_value { yield_constr.constraint(filter * limb); @@ -23,7 +24,8 @@ pub fn eval_ext_circuit, const D: usize>( lv: &CpuColumnsView>, yield_constr: &mut RecursiveConstraintConsumer, ) { - let filter = lv.op.push0; + // `PUSH0`'s opcode is odd, while `PC`'s opcode is even. + let filter = builder.mul_extension(lv.op.pc_push0, lv.opcode_bits[0]); let push_value = lv.mem_channels[NUM_GP_CHANNELS - 1].value; for limb in push_value { let constr = builder.mul_extension(filter, limb); diff --git a/evm/src/cpu/stack.rs b/evm/src/cpu/stack.rs index 28abf077cb..d79f0cb71d 100644 --- a/evm/src/cpu/stack.rs +++ b/evm/src/cpu/stack.rs @@ -85,7 +85,7 @@ const STACK_BEHAVIORS: OpsColumnsView> = OpsColumnsView { disable_other_channels: true, }), jumps: None, // Depends on whether it's a JUMP or a JUMPI. - pc: Some(StackBehavior { + pc_push0: Some(StackBehavior { num_pops: 0, pushes: true, disable_other_channels: true, @@ -95,11 +95,6 @@ const STACK_BEHAVIORS: OpsColumnsView> = OpsColumnsView { pushes: false, disable_other_channels: true, }), - push0: Some(StackBehavior { - num_pops: 0, - pushes: true, - disable_other_channels: true, - }), push: None, // TODO dup: None, swap: None, diff --git a/evm/src/witness/transition.rs b/evm/src/witness/transition.rs index 1418beba8d..1c1f164885 100644 --- a/evm/src/witness/transition.rs +++ b/evm/src/witness/transition.rs @@ -154,7 +154,6 @@ fn decode(registers: RegistersState, opcode: u8) -> Result(op: Operation, row: &mut CpuColumnsView) { let flags = &mut row.op; *match op { - Operation::Push(0) => &mut flags.push0, Operation::Push(1..) => &mut flags.push, Operation::Dup(_) => &mut flags.dup, Operation::Swap(_) => &mut flags.swap, @@ -173,7 +172,7 @@ fn fill_op_flag(op: Operation, row: &mut CpuColumnsView) { Operation::ProverInput => &mut flags.prover_input, Operation::Pop => &mut flags.pop, Operation::Jump | Operation::Jumpi => &mut flags.jumps, - Operation::Pc => &mut flags.pc, + Operation::Pc | Operation::Push(0) => &mut flags.pc_push0, Operation::Jumpdest => &mut flags.jumpdest, Operation::GetContext | Operation::SetContext => &mut flags.context_op, Operation::Mload32Bytes => &mut flags.mload_32bytes,