From 97ac5c59d6b22ea95bc69a74740f04cd2774ca28 Mon Sep 17 00:00:00 2001 From: Daniel Lubarov Date: Wed, 30 Nov 2022 18:12:31 -0800 Subject: [PATCH] Fixes --- evm/src/arithmetic/mod.rs | 72 +++++++++++++++++++++++++++++++++++ evm/src/generation/mod.rs | 2 +- evm/src/witness/memory.rs | 11 ++++++ evm/src/witness/operation.rs | 50 ++++++++++++++++++++++-- evm/src/witness/traces.rs | 5 ++- evm/src/witness/transition.rs | 14 +++++-- 6 files changed, 146 insertions(+), 8 deletions(-) diff --git a/evm/src/arithmetic/mod.rs b/evm/src/arithmetic/mod.rs index e74cac34..88086eec 100644 --- a/evm/src/arithmetic/mod.rs +++ b/evm/src/arithmetic/mod.rs @@ -23,12 +23,49 @@ pub(crate) enum BinaryOperator { Shr, } +impl BinaryOperator { + pub(crate) fn result(&self, input0: U256, input1: U256) -> U256 { + match self { + BinaryOperator::Add => input0 + input1, + BinaryOperator::Mul => input0 * input1, + BinaryOperator::Sub => input0 - input1, + BinaryOperator::Div => input0 / input1, + BinaryOperator::Mod => input0 % input1, + BinaryOperator::Lt => { + if input0 < input1 { + U256::one() + } else { + U256::zero() + } + } + BinaryOperator::Gt => { + if input0 > input1 { + U256::one() + } else { + U256::zero() + } + } + BinaryOperator::Shl => input0 << input1, + BinaryOperator::Shr => input0 >> input1, + } + } +} + #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub(crate) enum TernaryOperator { AddMod, MulMod, } +impl TernaryOperator { + pub(crate) fn result(&self, input0: U256, input1: U256, input2: U256) -> U256 { + match self { + TernaryOperator::AddMod => (input0 + input1) % input2, + TernaryOperator::MulMod => (input0 * input1) % input2, + } + } +} + #[derive(Debug)] pub(crate) enum Operation { BinaryOperation { @@ -45,3 +82,38 @@ pub(crate) enum Operation { result: U256, }, } + +impl Operation { + pub(crate) fn binary(operator: BinaryOperator, input0: U256, input1: U256) -> Self { + let result = operator.result(input0, input1); + Self::BinaryOperation { + operator, + input0, + input1, + result, + } + } + + pub(crate) fn ternary( + operator: TernaryOperator, + input0: U256, + input1: U256, + input2: U256, + ) -> Self { + let result = operator.result(input0, input1, input2); + Self::TernaryOperation { + operator, + input0, + input1, + input2, + result, + } + } + + pub(crate) fn result(&self) -> U256 { + match self { + Operation::BinaryOperation { result, .. } => *result, + Operation::TernaryOperation { result, .. } => *result, + } + } +} diff --git a/evm/src/generation/mod.rs b/evm/src/generation/mod.rs index 855169e5..a90324fa 100644 --- a/evm/src/generation/mod.rs +++ b/evm/src/generation/mod.rs @@ -83,7 +83,7 @@ pub(crate) fn generate_traces, const D: usize>( break; } - registers_state = transition(registers_state, &memory_state, &mut traces); + registers_state = transition(registers_state, &mut memory_state, &mut traces); } let read_metadata = |field| { diff --git a/evm/src/witness/memory.rs b/evm/src/witness/memory.rs index 8294fd96..f80c089b 100644 --- a/evm/src/witness/memory.rs +++ b/evm/src/witness/memory.rs @@ -98,6 +98,17 @@ impl MemoryState { Self { contents } } + pub fn apply_ops(&mut self, ops: &[MemoryOp]) { + for &op in ops { + let MemoryOp { + address, op, value, .. + } = op; + if op == MemoryOpKind::Write { + self.set(address, value); + } + } + } + pub fn get(&self, address: MemoryAddress) -> U256 { self.contents .get(&address) diff --git a/evm/src/witness/operation.rs b/evm/src/witness/operation.rs index 71152b09..3085611e 100644 --- a/evm/src/witness/operation.rs +++ b/evm/src/witness/operation.rs @@ -42,10 +42,11 @@ pub(crate) fn generate_binary_logic_op( ) -> Result { let [(in0, log_in0), (in1, log_in1)] = stack_pop_with_log_and_fill::<2, _>(&mut registers_state, memory_state, traces, &mut row)?; - let result = op.result(in0, in1); - let log_out = stack_push_log_and_fill(&mut registers_state, traces, &mut row, result)?; + let operation = logic::Operation::new(op, in0, in1); + let log_out = + stack_push_log_and_fill(&mut registers_state, traces, &mut row, operation.result)?; - traces.push_logic(logic::Operation::new(op, in0, in1)); + traces.push_logic(operation); traces.push_memory(log_in0); traces.push_memory(log_in1); traces.push_memory(log_out); @@ -53,6 +54,49 @@ pub(crate) fn generate_binary_logic_op( Ok(registers_state) } +pub(crate) fn generate_binary_arithmetic_op( + operator: arithmetic::BinaryOperator, + mut registers_state: RegistersState, + memory_state: &MemoryState, + traces: &mut Traces, + mut row: CpuColumnsView, +) -> Result { + let [(input0, log_in0), (input1, log_in1)] = + stack_pop_with_log_and_fill::<2, _>(&mut registers_state, memory_state, traces, &mut row)?; + let operation = arithmetic::Operation::binary(operator, input0, input1); + let log_out = + stack_push_log_and_fill(&mut registers_state, traces, &mut row, operation.result())?; + + traces.push_arithmetic(operation); + traces.push_memory(log_in0); + traces.push_memory(log_in1); + traces.push_memory(log_out); + traces.push_cpu(row); + Ok(registers_state) +} + +pub(crate) fn generate_ternary_arithmetic_op( + operator: arithmetic::TernaryOperator, + mut registers_state: RegistersState, + memory_state: &MemoryState, + traces: &mut Traces, + mut row: CpuColumnsView, +) -> Result { + let [(input0, log_in0), (input1, log_in1), (input2, log_in2)] = + stack_pop_with_log_and_fill::<3, _>(&mut registers_state, memory_state, traces, &mut row)?; + let operation = arithmetic::Operation::ternary(operator, input0, input1, input2); + let log_out = + stack_push_log_and_fill(&mut registers_state, traces, &mut row, operation.result())?; + + traces.push_arithmetic(operation); + traces.push_memory(log_in0); + traces.push_memory(log_in1); + traces.push_memory(log_in2); + traces.push_memory(log_out); + traces.push_cpu(row); + Ok(registers_state) +} + pub(crate) fn generate_push( n: u8, mut registers_state: RegistersState, diff --git a/evm/src/witness/traces.rs b/evm/src/witness/traces.rs index f0c96e6b..b4de5378 100644 --- a/evm/src/witness/traces.rs +++ b/evm/src/witness/traces.rs @@ -4,7 +4,6 @@ use plonky2::hash::hash_types::RichField; use plonky2::util::timing::TimingTree; use crate::all_stark::{AllStark, NUM_TABLES}; -use crate::arithmetic::columns::NUM_ARITH_COLUMNS; use crate::config::StarkConfig; use crate::cpu::columns::CpuColumnsView; use crate::keccak_memory::keccak_memory_stark::KeccakMemoryOp; @@ -63,6 +62,10 @@ impl Traces { // TODO others } + pub fn mem_ops_since(&self, checkpoint: TraceCheckpoint) -> &[MemoryOp] { + &self.memory_ops[checkpoint.memory_len..] + } + pub fn push_cpu(&mut self, val: CpuColumnsView) { self.cpu.push(val); } diff --git a/evm/src/witness/transition.rs b/evm/src/witness/transition.rs index ac6ce23d..299462fa 100644 --- a/evm/src/witness/transition.rs +++ b/evm/src/witness/transition.rs @@ -5,8 +5,9 @@ use crate::memory::segments::Segment; use crate::witness::errors::ProgramError; use crate::witness::memory::{MemoryAddress, MemoryState}; use crate::witness::operation::{ - generate_binary_logic_op, generate_dup, generate_eq, generate_exit_kernel, generate_iszero, - generate_not, generate_push, generate_swap, generate_syscall, Operation, + generate_binary_arithmetic_op, generate_binary_logic_op, generate_dup, generate_eq, + generate_exit_kernel, generate_iszero, generate_not, generate_push, generate_swap, + generate_syscall, generate_ternary_arithmetic_op, Operation, }; use crate::witness::state::RegistersState; use crate::witness::traces::Traces; @@ -188,6 +189,12 @@ fn perform_op( Operation::BinaryLogic(binary_logic_op) => { generate_binary_logic_op(binary_logic_op, registers_state, memory_state, traces, row)? } + Operation::BinaryArithmetic(op) => { + generate_binary_arithmetic_op(op, registers_state, memory_state, traces, row)? + } + Operation::TernaryArithmetic(op) => { + generate_ternary_arithmetic_op(op, registers_state, memory_state, traces, row)? + } _ => panic!("operation not implemented: {:?}", op), }; @@ -233,11 +240,12 @@ fn handle_error( pub(crate) fn transition( registers_state: RegistersState, - memory_state: &MemoryState, + memory_state: &mut MemoryState, traces: &mut Traces, ) -> RegistersState { let checkpoint = traces.checkpoint(); let result = try_perform_instruction(registers_state, memory_state, traces); + memory_state.apply_ops(traces.mem_ops_since(checkpoint)); match result { Ok(new_registers_state) => new_registers_state,