From cedeff5219446ac840d1a47397dc34f23742db4c Mon Sep 17 00:00:00 2001 From: Jacqueline Nabaglo Date: Tue, 13 Jun 2023 13:29:30 -0700 Subject: [PATCH] PUSH0 --- evm/src/cpu/columns/ops.rs | 1 + evm/src/cpu/control_flow.rs | 3 +- evm/src/cpu/cpu_stark.rs | 4 ++- evm/src/cpu/decode.rs | 3 +- evm/src/cpu/gas.rs | 1 + evm/src/cpu/kernel/asm/core/exception.asm | 4 +-- evm/src/cpu/kernel/constants/exc_bitfields.rs | 4 +-- evm/src/cpu/kernel/interpreter.rs | 3 +- evm/src/cpu/kernel/opcodes.rs | 3 +- evm/src/cpu/kernel/utils.rs | 6 ++-- evm/src/cpu/mod.rs | 1 + evm/src/cpu/push0.rs | 32 +++++++++++++++++++ evm/src/cpu/stack.rs | 5 +++ evm/src/witness/gas.rs | 3 +- evm/src/witness/operation.rs | 2 +- evm/src/witness/transition.rs | 7 ++-- 16 files changed, 65 insertions(+), 17 deletions(-) create mode 100644 evm/src/cpu/push0.rs diff --git a/evm/src/cpu/columns/ops.rs b/evm/src/cpu/columns/ops.rs index c37ddbf3..663653ad 100644 --- a/evm/src/cpu/columns/ops.rs +++ b/evm/src/cpu/columns/ops.rs @@ -41,6 +41,7 @@ pub struct OpsColumnsView { pub jumpi: T, // Note: This column must be 0 when is_cpu_cycle = 0. pub pc: T, pub jumpdest: T, + pub push0: T, pub push: T, pub dup: T, pub swap: T, diff --git a/evm/src/cpu/control_flow.rs b/evm/src/cpu/control_flow.rs index 55da50c4..35546bb7 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; 31] = [ +const NATIVE_INSTRUCTIONS: [usize; 32] = [ COL_MAP.op.add, COL_MAP.op.mul, COL_MAP.op.sub, @@ -36,6 +36,7 @@ const NATIVE_INSTRUCTIONS: [usize; 31] = [ // not JUMPI (possible need to jump) COL_MAP.op.pc, 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/cpu_stark.rs b/evm/src/cpu/cpu_stark.rs index b29f27a4..e4224bad 100644 --- a/evm/src/cpu/cpu_stark.rs +++ b/evm/src/cpu/cpu_stark.rs @@ -14,7 +14,7 @@ use crate::cpu::columns::{CpuColumnsView, COL_MAP, NUM_CPU_COLUMNS}; use crate::cpu::membus::NUM_GP_CHANNELS; use crate::cpu::{ bootstrap_kernel, contextops, control_flow, decode, dup_swap, exceptions, gas, jumps, membus, - memio, modfp254, pc, shift, simple_logic, stack, stack_bounds, syscalls, + memio, modfp254, pc, push0, shift, simple_logic, stack, stack_bounds, syscalls, }; use crate::cross_table_lookup::{Column, TableWithColumns}; use crate::memory::segments::Segment; @@ -197,6 +197,7 @@ impl, const D: usize> Stark for CpuStark, const D: usize> Stark for CpuStark> = OpsColumnsView { jumpi: G_HIGH, pc: G_BASE, jumpdest: G_JUMPDEST, + push0: G_BASE, push: G_VERYLOW, dup: G_VERYLOW, swap: G_VERYLOW, diff --git a/evm/src/cpu/kernel/asm/core/exception.asm b/evm/src/cpu/kernel/asm/core/exception.asm index 70e8550b..49ccf6dc 100644 --- a/evm/src/cpu/kernel/asm/core/exception.asm +++ b/evm/src/cpu/kernel/asm/core/exception.asm @@ -227,11 +227,11 @@ min_stack_len_for_opcode: BYTES 0 // 0x59, MSIZE BYTES 0 // 0x5a, GAS BYTES 0 // 0x5b, JUMPDEST - %rep 4 // 0x5c-0x5f, invalid + %rep 3 // 0x5c-0x5e, invalid BYTES 0 %endrep - %rep 32 // 0x60-0x7f, PUSH1-PUSH32 + %rep 33 // 0x5f-0x7f, PUSH0-PUSH32 BYTES 0 %endrep diff --git a/evm/src/cpu/kernel/constants/exc_bitfields.rs b/evm/src/cpu/kernel/constants/exc_bitfields.rs index 2a6eaf0e..2f62b032 100644 --- a/evm/src/cpu/kernel/constants/exc_bitfields.rs +++ b/evm/src/cpu/kernel/constants/exc_bitfields.rs @@ -37,7 +37,7 @@ pub const STACK_LENGTH_INCREASING_OPCODES_USER: U256 = u256_from_set_index_range 0x3d..=0x3d, // RETURNDATASIZE 0x41..=0x48, // COINBASE, TIMESTAMP, NUMBER, DIFFICULTY, GASLIMIT, CHAINID, SELFBALANCE, BASEFEE 0x58..=0x5a, // PC, MSIZE, GAS - 0x60..=0x8f, // PUSH*, DUP* + 0x5f..=0x8f, // PUSH*, DUP* ]); pub const INVALID_OPCODES_USER: U256 = u256_from_set_index_ranges([ @@ -45,7 +45,7 @@ pub const INVALID_OPCODES_USER: U256 = u256_from_set_index_ranges([ 0x1e..=0x1f, 0x21..=0x2f, 0x49..=0x4f, - 0x5c..=0x5f, + 0x5c..=0x5e, 0xa5..=0xef, 0xf6..=0xf9, 0xfb..=0xfc, diff --git a/evm/src/cpu/kernel/interpreter.rs b/evm/src/cpu/kernel/interpreter.rs index 4f47c91f..821ff51b 100644 --- a/evm/src/cpu/kernel/interpreter.rs +++ b/evm/src/cpu/kernel/interpreter.rs @@ -369,7 +369,7 @@ impl<'a> Interpreter<'a> { 0x59 => self.run_msize(), // "MSIZE", 0x5a => todo!(), // "GAS", 0x5b => self.run_jumpdest(), // "JUMPDEST", - x if (0x60..0x80).contains(&x) => self.run_push(x - 0x5f), // "PUSH" + x if (0x5f..0x80).contains(&x) => self.run_push(x - 0x5f), // "PUSH" x if (0x80..0x90).contains(&x) => self.run_dup(x - 0x7f), // "DUP" x if (0x90..0xa0).contains(&x) => self.run_swap(x - 0x8f)?, // "SWAP" 0xa0 => todo!(), // "LOG0", @@ -1189,6 +1189,7 @@ fn get_mnemonic(opcode: u8) -> &'static str { 0x59 => "MSIZE", 0x5a => "GAS", 0x5b => "JUMPDEST", + 0x5f => "PUSH0", 0x60 => "PUSH1", 0x61 => "PUSH2", 0x62 => "PUSH3", diff --git a/evm/src/cpu/kernel/opcodes.rs b/evm/src/cpu/kernel/opcodes.rs index be17f6f4..09c493e0 100644 --- a/evm/src/cpu/kernel/opcodes.rs +++ b/evm/src/cpu/kernel/opcodes.rs @@ -1,8 +1,7 @@ /// The opcode of the `PUSH[n]` instruction, given a byte count `n`. pub fn get_push_opcode(n: u8) -> u8 { - assert!(n > 0); assert!(n <= 32); - 0x60 + n - 1 + 0x5f + n } /// The opcode of a standard instruction (not a `PUSH`). diff --git a/evm/src/cpu/kernel/utils.rs b/evm/src/cpu/kernel/utils.rs index 8900b8e2..3470904c 100644 --- a/evm/src/cpu/kernel/utils.rs +++ b/evm/src/cpu/kernel/utils.rs @@ -26,7 +26,7 @@ where } pub(crate) fn u256_to_trimmed_be_bytes(u256: &U256) -> Vec { - let num_bytes = ceil_div_usize(u256.bits(), 8).max(1); + let num_bytes = ceil_div_usize(u256.bits(), 8); // `byte` is little-endian, so we manually reverse it. (0..num_bytes).rev().map(|i| u256.byte(i)).collect() } @@ -60,7 +60,9 @@ mod tests { #[test] fn literal_to_be_bytes() { - assert_eq!(u256_to_trimmed_be_bytes(&0.into()), vec![0x00]); + assert_eq!(u256_to_trimmed_be_bytes(&0.into()), Vec::::new()); + + assert_eq!(u256_to_trimmed_be_bytes(&1.into()), vec![0x01]); assert_eq!(u256_to_trimmed_be_bytes(&768.into()), vec![0x03, 0x00]); diff --git a/evm/src/cpu/mod.rs b/evm/src/cpu/mod.rs index a5128599..411ddb76 100644 --- a/evm/src/cpu/mod.rs +++ b/evm/src/cpu/mod.rs @@ -13,6 +13,7 @@ pub(crate) mod membus; mod memio; mod modfp254; mod pc; +mod push0; mod shift; pub(crate) mod simple_logic; mod stack; diff --git a/evm/src/cpu/push0.rs b/evm/src/cpu/push0.rs new file mode 100644 index 00000000..212315ae --- /dev/null +++ b/evm/src/cpu/push0.rs @@ -0,0 +1,32 @@ +use plonky2::field::extension::Extendable; +use plonky2::field::packed::PackedField; +use plonky2::hash::hash_types::RichField; +use plonky2::iop::ext_target::ExtensionTarget; + +use crate::constraint_consumer::{ConstraintConsumer, RecursiveConstraintConsumer}; +use crate::cpu::columns::CpuColumnsView; +use crate::cpu::membus::NUM_GP_CHANNELS; + +pub fn eval_packed( + lv: &CpuColumnsView

, + yield_constr: &mut ConstraintConsumer

, +) { + let filter = lv.op.push0; + let push_value = lv.mem_channels[NUM_GP_CHANNELS - 1].value; + for &limb in &push_value[0..] { + yield_constr.constraint(filter * limb); + } +} + +pub fn eval_ext_circuit, const D: usize>( + builder: &mut plonky2::plonk::circuit_builder::CircuitBuilder, + lv: &CpuColumnsView>, + yield_constr: &mut RecursiveConstraintConsumer, +) { + let filter = lv.op.push0; + let push_value = lv.mem_channels[NUM_GP_CHANNELS - 1].value; + for &limb in &push_value[0..] { + let constr = builder.mul_extension(filter, limb); + yield_constr.constraint(builder, constr); + } +} diff --git a/evm/src/cpu/stack.rs b/evm/src/cpu/stack.rs index 3a8945a5..34e36b1e 100644 --- a/evm/src/cpu/stack.rs +++ b/evm/src/cpu/stack.rs @@ -97,6 +97,11 @@ 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/gas.rs b/evm/src/witness/gas.rs index 0acb04e4..4c7947bb 100644 --- a/evm/src/witness/gas.rs +++ b/evm/src/witness/gas.rs @@ -38,7 +38,8 @@ pub(crate) fn gas_to_charge(op: Operation) -> u64 { Jumpi => G_HIGH, Pc => G_BASE, Jumpdest => G_JUMPDEST, - Push(_) => G_VERYLOW, + Push(0) => G_BASE, + Push(1..) => G_VERYLOW, Dup(_) => G_VERYLOW, Swap(_) => G_VERYLOW, GetContext => KERNEL_ONLY_INSTR, diff --git a/evm/src/witness/operation.rs b/evm/src/witness/operation.rs index 78bcd45d..cfced651 100644 --- a/evm/src/witness/operation.rs +++ b/evm/src/witness/operation.rs @@ -335,7 +335,7 @@ pub(crate) fn generate_push( mut row: CpuColumnsView, ) -> Result<(), ProgramError> { let code_context = state.registers.code_context(); - let num_bytes = n as usize + 1; + let num_bytes = n as usize; let initial_offset = state.registers.program_counter + 1; // First read val without going through `mem_read_with_log` type methods, so we can pass it diff --git a/evm/src/witness/transition.rs b/evm/src/witness/transition.rs index ecf79c0e..c5937c7f 100644 --- a/evm/src/witness/transition.rs +++ b/evm/src/witness/transition.rs @@ -113,7 +113,7 @@ fn decode(registers: RegistersState, opcode: u8) -> Result Ok(Operation::Syscall(opcode, 0, true)), // MSIZE (0x5a, _) => Ok(Operation::Syscall(opcode, 0, true)), // GAS (0x5b, _) => Ok(Operation::Jumpdest), - (0x60..=0x7f, _) => Ok(Operation::Push(opcode & 0x1f)), + (0x5f..=0x7f, _) => Ok(Operation::Push(opcode - 0x5f)), (0x80..=0x8f, _) => Ok(Operation::Dup(opcode & 0xf)), (0x90..=0x9f, _) => Ok(Operation::Swap(opcode & 0xf)), (0xa0, _) => Ok(Operation::Syscall(opcode, 2, false)), // LOG0 @@ -152,7 +152,8 @@ fn decode(registers: RegistersState, opcode: u8) -> Result(op: Operation, row: &mut CpuColumnsView) { let flags = &mut row.op; *match op { - Operation::Push(_) => &mut flags.push, + Operation::Push(0) => &mut flags.push0, + Operation::Push(1..) => &mut flags.push, Operation::Dup(_) => &mut flags.dup, Operation::Swap(_) => &mut flags.swap, Operation::Iszero => &mut flags.iszero, @@ -231,7 +232,7 @@ fn perform_op( state.registers.program_counter += match op { Operation::Syscall(_, _, _) | Operation::ExitKernel => 0, - Operation::Push(n) => n as usize + 2, + Operation::Push(n) => n as usize + 1, Operation::Jump | Operation::Jumpi => 0, _ => 1, };