diff --git a/evm/src/cpu/columns/ops.rs b/evm/src/cpu/columns/ops.rs index feeb3f5f..270b0ab8 100644 --- a/evm/src/cpu/columns/ops.rs +++ b/evm/src/cpu/columns/ops.rs @@ -22,8 +22,7 @@ pub struct OpsColumnsView { pub jumpdest: T, pub push0: T, pub push: T, - pub dup: T, - pub swap: T, + pub dup_swap: T, pub get_context: T, pub set_context: T, pub mstore_32bytes: T, diff --git a/evm/src/cpu/control_flow.rs b/evm/src/cpu/control_flow.rs index a192ffb1..2f496b51 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; 18] = [ +const NATIVE_INSTRUCTIONS: [usize; 17] = [ COL_MAP.op.binary_op, COL_MAP.op.ternary_op, COL_MAP.op.fp254_op, @@ -24,8 +24,7 @@ const NATIVE_INSTRUCTIONS: [usize; 18] = [ 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, + COL_MAP.op.dup_swap, COL_MAP.op.get_context, COL_MAP.op.set_context, // not EXIT_KERNEL (performs a jump) diff --git a/evm/src/cpu/decode.rs b/evm/src/cpu/decode.rs index 4e2bff5c..a4756684 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); 17] = [ +const OPCODES: [(u8, usize, bool, usize); 16] = [ // (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. @@ -39,9 +39,8 @@ const OPCODES: [(u8, usize, bool, usize); 17] = [ (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 + (0x60, 5, false, COL_MAP.op.push), // 0x60-0x7f + (0x80, 5, false, COL_MAP.op.dup_swap), // 0x80-0x9f (0xee, 0, true, COL_MAP.op.mstore_32bytes), (0xf6, 0, true, COL_MAP.op.get_context), (0xf7, 0, true, COL_MAP.op.set_context), diff --git a/evm/src/cpu/dup_swap.rs b/evm/src/cpu/dup_swap.rs index d5bc49a0..0cc6c67c 100644 --- a/evm/src/cpu/dup_swap.rs +++ b/evm/src/cpu/dup_swap.rs @@ -114,7 +114,8 @@ fn eval_packed_dup( nv: &CpuColumnsView

, yield_constr: &mut ConstraintConsumer

, ) { - let filter = lv.op.dup; + // DUP opcodes have 0 at the 5-th position, while SWAP opcodes have 1. + let filter = lv.op.dup_swap * (P::ONES - lv.opcode_bits[4]); let write_channel = &lv.mem_channels[1]; let read_channel = &lv.mem_channels[2]; @@ -139,8 +140,10 @@ fn eval_ext_circuit_dup, const D: usize>( yield_constr: &mut RecursiveConstraintConsumer, ) { let zero = builder.zero_extension(); - - let filter = lv.op.dup; + let one = builder.one_extension(); + // DUP opcodes have 0 at the 5-th position, while SWAP opcodes have 1. + let mut filter = builder.sub_extension(one, lv.opcode_bits[4]); + filter = builder.mul_extension(lv.op.dup_swap, filter); let write_channel = &lv.mem_channels[1]; let read_channel = &lv.mem_channels[2]; @@ -187,7 +190,8 @@ fn eval_packed_swap( ) { let n_plus_one = n + P::ONES; - let filter = lv.op.swap; + // DUP opcodes have 0 at the 5-th position, while SWAP opcodes have 1. + let filter = lv.op.dup_swap * lv.opcode_bits[4]; let in1_channel = &lv.mem_channels[0]; let in2_channel = &lv.mem_channels[1]; @@ -215,7 +219,8 @@ fn eval_ext_circuit_swap, const D: usize>( let one = builder.one_extension(); let n_plus_one = builder.add_extension(n, one); - let filter = lv.op.swap; + // DUP opcodes have 0 at the 5-th position, while SWAP opcodes have 1. + let filter = builder.mul_extension(lv.op.dup_swap, lv.opcode_bits[4]); let in1_channel = &lv.mem_channels[0]; let in2_channel = &lv.mem_channels[1]; diff --git a/evm/src/cpu/gas.rs b/evm/src/cpu/gas.rs index 1434efd9..1a908d6d 100644 --- a/evm/src/cpu/gas.rs +++ b/evm/src/cpu/gas.rs @@ -34,8 +34,7 @@ const SIMPLE_OPCODES: OpsColumnsView> = OpsColumnsView { jumpdest: G_JUMPDEST, push0: G_BASE, push: G_VERYLOW, - dup: G_VERYLOW, - swap: G_VERYLOW, + dup_swap: G_VERYLOW, get_context: KERNEL_ONLY_INSTR, set_context: KERNEL_ONLY_INSTR, mstore_32bytes: KERNEL_ONLY_INSTR, diff --git a/evm/src/cpu/stack.rs b/evm/src/cpu/stack.rs index 31d0405c..db0c480d 100644 --- a/evm/src/cpu/stack.rs +++ b/evm/src/cpu/stack.rs @@ -109,8 +109,7 @@ pub(crate) const STACK_BEHAVIORS: OpsColumnsView> = OpsCol disable_other_channels: true, }), push: None, // TODO - dup: None, - swap: None, + dup_swap: None, get_context: Some(StackBehavior { num_pops: 0, pushes: true, diff --git a/evm/src/witness/transition.rs b/evm/src/witness/transition.rs index 00030110..312b8591 100644 --- a/evm/src/witness/transition.rs +++ b/evm/src/witness/transition.rs @@ -162,8 +162,7 @@ fn fill_op_flag(op: Operation, row: &mut CpuColumnsView) { *match op { Operation::Push(0) => &mut flags.push0, Operation::Push(1..) => &mut flags.push, - Operation::Dup(_) => &mut flags.dup, - Operation::Swap(_) => &mut flags.swap, + Operation::Dup(_) | Operation::Swap(_) => &mut flags.dup_swap, Operation::Iszero | Operation::Eq => &mut flags.eq_iszero, Operation::Not => &mut flags.not, Operation::Syscall(_, _, _) => &mut flags.syscall, @@ -195,8 +194,7 @@ fn get_op_special_length(op: Operation) -> Option { let behavior_opt = match op { Operation::Push(0) => STACK_BEHAVIORS.push0, Operation::Push(1..) => STACK_BEHAVIORS.push, - Operation::Dup(_) => STACK_BEHAVIORS.dup, - Operation::Swap(_) => STACK_BEHAVIORS.swap, + Operation::Dup(_) | Operation::Swap(_) => STACK_BEHAVIORS.dup_swap, Operation::Iszero => IS_ZERO_STACK_BEHAVIOR, Operation::Not => STACK_BEHAVIORS.not, Operation::Syscall(_, _, _) => STACK_BEHAVIORS.syscall,