diff --git a/evm/src/arithmetic/mod.rs b/evm/src/arithmetic/mod.rs index 88086eec..6214748a 100644 --- a/evm/src/arithmetic/mod.rs +++ b/evm/src/arithmetic/mod.rs @@ -1,4 +1,8 @@ -use ethereum_types::U256; +use std::ops::Mul; +use std::str::FromStr; + +use ethereum_types::{U256, U512}; +use num::BigUint; mod add; mod compare; @@ -21,6 +25,9 @@ pub(crate) enum BinaryOperator { Gt, Shl, Shr, + AddFp254, + MulFp254, + SubFp254, } impl BinaryOperator { @@ -47,6 +54,9 @@ impl BinaryOperator { } BinaryOperator::Shl => input0 << input1, BinaryOperator::Shr => input0 >> input1, + BinaryOperator::AddFp254 => addmod(input0, input1, bn_base_order()), + BinaryOperator::MulFp254 => mulmod(input0, input1, bn_base_order()), + BinaryOperator::SubFp254 => submod(input0, input1, bn_base_order()), } } } @@ -60,8 +70,8 @@ pub(crate) enum TernaryOperator { 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, + TernaryOperator::AddMod => addmod(input0, input1, input2), + TernaryOperator::MulMod => mulmod(input0, input1, input2), } } } @@ -117,3 +127,51 @@ impl Operation { } } } + +fn addmod(x: U256, y: U256, m: U256) -> U256 { + if m.is_zero() { + return m; + } + let x = to_biguint(x); + let y = to_biguint(y); + let m = to_biguint(m); + from_biguint((x + y) % m) +} + +fn mulmod(x: U256, y: U256, m: U256) -> U256 { + if m.is_zero() { + return m; + } + let x = to_biguint(x); + let y = to_biguint(y); + let m = to_biguint(m); + from_biguint(x * y % m) +} + +fn submod(x: U256, y: U256, m: U256) -> U256 { + if m.is_zero() { + return m; + } + let mut x = to_biguint(x); + let y = to_biguint(y); + let m = to_biguint(m); + while x < y { + x += &m; + } + from_biguint((x - y) % m) +} + +fn to_biguint(x: U256) -> BigUint { + let mut bytes = [0u8; 32]; + x.to_little_endian(&mut bytes); + BigUint::from_bytes_le(&bytes) +} + +fn from_biguint(x: BigUint) -> U256 { + let bytes = x.to_bytes_le(); + U256::from_little_endian(&bytes) +} + +fn bn_base_order() -> U256 { + U256::from_str("0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47").unwrap() +} diff --git a/evm/src/cpu/columns/ops.rs b/evm/src/cpu/columns/ops.rs index ed254bb7..63f6795d 100644 --- a/evm/src/cpu/columns/ops.rs +++ b/evm/src/cpu/columns/ops.rs @@ -41,12 +41,6 @@ pub struct OpsColumnsView { pub pc: T, pub gas: T, pub jumpdest: T, - // TODO: combine GET_STATE_ROOT and SET_STATE_ROOT into one flag - pub get_state_root: T, - pub set_state_root: T, - // TODO: combine GET_RECEIPT_ROOT and SET_RECEIPT_ROOT into one flag - pub get_receipt_root: T, - pub set_receipt_root: 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 63e956e5..c0adc7bd 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; 37] = [ +const NATIVE_INSTRUCTIONS: [usize; 33] = [ COL_MAP.op.add, COL_MAP.op.mul, COL_MAP.op.sub, @@ -37,10 +37,6 @@ const NATIVE_INSTRUCTIONS: [usize; 37] = [ COL_MAP.op.pc, COL_MAP.op.gas, COL_MAP.op.jumpdest, - COL_MAP.op.get_state_root, - COL_MAP.op.set_state_root, - COL_MAP.op.get_receipt_root, - COL_MAP.op.set_receipt_root, // 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 feb672d0..71ffad78 100644 --- a/evm/src/cpu/decode.rs +++ b/evm/src/cpu/decode.rs @@ -22,7 +22,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); 42] = [ +const OPCODES: [(u8, usize, bool, usize); 38] = [ // (start index of block, number of top bits to check (log2), kernel-only, flag column) (0x01, 0, false, COL_MAP.op.add), (0x02, 0, false, COL_MAP.op.mul), @@ -53,10 +53,6 @@ const OPCODES: [(u8, usize, bool, usize); 42] = [ (0x58, 0, false, COL_MAP.op.pc), (0x5a, 0, false, COL_MAP.op.gas), (0x5b, 0, false, COL_MAP.op.jumpdest), - (0x5c, 0, true, COL_MAP.op.get_state_root), - (0x5d, 0, true, COL_MAP.op.set_state_root), - (0x5e, 0, true, COL_MAP.op.get_receipt_root), - (0x5f, 0, true, COL_MAP.op.set_receipt_root), (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 diff --git a/evm/src/cpu/kernel/interpreter.rs b/evm/src/cpu/kernel/interpreter.rs index d9d70232..2fbb75ac 100644 --- a/evm/src/cpu/kernel/interpreter.rs +++ b/evm/src/cpu/kernel/interpreter.rs @@ -318,10 +318,6 @@ impl<'a> Interpreter<'a> { 0x59 => self.run_msize(), // "MSIZE", 0x5a => todo!(), // "GAS", 0x5b => self.run_jumpdest(), // "JUMPDEST", - 0x5c => todo!(), // "GET_STATE_ROOT", - 0x5d => todo!(), // "SET_STATE_ROOT", - 0x5e => todo!(), // "GET_RECEIPT_ROOT", - 0x5f => todo!(), // "SET_RECEIPT_ROOT", x if (0x60..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" @@ -830,10 +826,6 @@ fn get_mnemonic(opcode: u8) -> &'static str { 0x59 => "MSIZE", 0x5a => "GAS", 0x5b => "JUMPDEST", - 0x5c => "GET_STATE_ROOT", - 0x5d => "SET_STATE_ROOT", - 0x5e => "GET_RECEIPT_ROOT", - 0x5f => "SET_RECEIPT_ROOT", 0x60 => "PUSH1", 0x61 => "PUSH2", 0x62 => "PUSH3", diff --git a/evm/src/cpu/kernel/opcodes.rs b/evm/src/cpu/kernel/opcodes.rs index 31074ff6..8b575f79 100644 --- a/evm/src/cpu/kernel/opcodes.rs +++ b/evm/src/cpu/kernel/opcodes.rs @@ -76,10 +76,6 @@ pub(crate) fn get_opcode(mnemonic: &str) -> u8 { "MSIZE" => 0x59, "GAS" => 0x5a, "JUMPDEST" => 0x5b, - "GET_STATE_ROOT" => 0x5c, - "SET_STATE_ROOT" => 0x5d, - "GET_RECEIPT_ROOT" => 0x5e, - "SET_RECEIPT_ROOT" => 0x5f, "DUP1" => 0x80, "DUP2" => 0x81, "DUP3" => 0x82, diff --git a/evm/src/cpu/stack.rs b/evm/src/cpu/stack.rs index ea235578..08ab3044 100644 --- a/evm/src/cpu/stack.rs +++ b/evm/src/cpu/stack.rs @@ -61,19 +61,15 @@ const STACK_BEHAVIORS: OpsColumnsView> = OpsColumnsView { byte: BASIC_BINARY_OP, shl: BASIC_BINARY_OP, shr: BASIC_BINARY_OP, - keccak_general: None, // TODO - prover_input: None, // TODO - pop: None, // TODO - jump: None, // TODO - jumpi: None, // TODO - pc: None, // TODO - gas: None, // TODO - jumpdest: None, // TODO - get_state_root: None, // TODO - set_state_root: None, // TODO - get_receipt_root: None, // TODO - set_receipt_root: None, // TODO - push: None, // TODO + keccak_general: None, // TODO + prover_input: None, // TODO + pop: None, // TODO + jump: None, // TODO + jumpi: None, // TODO + pc: None, // TODO + gas: None, // TODO + jumpdest: None, // TODO + push: None, // TODO dup: None, swap: None, get_context: None, // TODO diff --git a/evm/src/witness/operation.rs b/evm/src/witness/operation.rs index 3085611e..8f25ae6c 100644 --- a/evm/src/witness/operation.rs +++ b/evm/src/witness/operation.rs @@ -24,13 +24,26 @@ pub(crate) enum Operation { Swap(u8), Iszero, Not, + Byte, Syscall(u8), Eq, - ExitKernel, BinaryLogic(logic::Op), BinaryArithmetic(arithmetic::BinaryOperator), TernaryArithmetic(arithmetic::TernaryOperator), - NotImplemented, + KeccakGeneral, + ProverInput, + Pop, + Jump, + Jumpi, + Pc, + Gas, + Jumpdest, + GetContext, + SetContext, + ConsumeGas, + ExitKernel, + MloadGeneral, + MstoreGeneral, } pub(crate) fn generate_binary_logic_op( diff --git a/evm/src/witness/transition.rs b/evm/src/witness/transition.rs index 299462fa..64b52fe5 100644 --- a/evm/src/witness/transition.rs +++ b/evm/src/witness/transition.rs @@ -40,22 +40,32 @@ fn read_code_memory( fn decode(registers_state: RegistersState, opcode: u8) -> Result { match (opcode, registers_state.is_kernel) { (0x00, _) => Ok(Operation::Syscall(opcode)), - (0x01, _) => Ok(Operation::NotImplemented), - (0x02, _) => Ok(Operation::NotImplemented), - (0x03, _) => Ok(Operation::NotImplemented), - (0x04, _) => Ok(Operation::NotImplemented), + (0x01, _) => Ok(Operation::BinaryArithmetic(arithmetic::BinaryOperator::Add)), + (0x02, _) => Ok(Operation::BinaryArithmetic(arithmetic::BinaryOperator::Mul)), + (0x03, _) => Ok(Operation::BinaryArithmetic(arithmetic::BinaryOperator::Sub)), + (0x04, _) => Ok(Operation::BinaryArithmetic(arithmetic::BinaryOperator::Div)), (0x05, _) => Ok(Operation::Syscall(opcode)), - (0x06, _) => Ok(Operation::NotImplemented), + (0x06, _) => Ok(Operation::BinaryArithmetic(arithmetic::BinaryOperator::Mod)), (0x07, _) => Ok(Operation::Syscall(opcode)), - (0x08, _) => Ok(Operation::NotImplemented), - (0x09, _) => Ok(Operation::NotImplemented), + (0x08, _) => Ok(Operation::TernaryArithmetic( + arithmetic::TernaryOperator::AddMod, + )), + (0x09, _) => Ok(Operation::TernaryArithmetic( + arithmetic::TernaryOperator::MulMod, + )), (0x0a, _) => Ok(Operation::Syscall(opcode)), (0x0b, _) => Ok(Operation::Syscall(opcode)), - (0x0c, true) => Ok(Operation::NotImplemented), - (0x0d, true) => Ok(Operation::NotImplemented), - (0x0e, true) => Ok(Operation::NotImplemented), - (0x10, _) => Ok(Operation::NotImplemented), - (0x11, _) => Ok(Operation::NotImplemented), + (0x0c, true) => Ok(Operation::BinaryArithmetic( + arithmetic::BinaryOperator::AddFp254, + )), + (0x0d, true) => Ok(Operation::BinaryArithmetic( + arithmetic::BinaryOperator::MulFp254, + )), + (0x0e, true) => Ok(Operation::BinaryArithmetic( + arithmetic::BinaryOperator::SubFp254, + )), + (0x10, _) => Ok(Operation::BinaryArithmetic(arithmetic::BinaryOperator::Lt)), + (0x11, _) => Ok(Operation::BinaryArithmetic(arithmetic::BinaryOperator::Gt)), (0x12, _) => Ok(Operation::Syscall(opcode)), (0x13, _) => Ok(Operation::Syscall(opcode)), (0x14, _) => Ok(Operation::Eq), @@ -64,12 +74,12 @@ fn decode(registers_state: RegistersState, opcode: u8) -> Result Ok(Operation::BinaryLogic(logic::Op::Or)), (0x18, _) => Ok(Operation::BinaryLogic(logic::Op::Xor)), (0x19, _) => Ok(Operation::Not), - (0x1a, _) => Ok(Operation::NotImplemented), - (0x1b, _) => Ok(Operation::NotImplemented), - (0x1c, _) => Ok(Operation::NotImplemented), + (0x1a, _) => Ok(Operation::Byte), + (0x1b, _) => Ok(Operation::BinaryArithmetic(arithmetic::BinaryOperator::Shl)), + (0x1c, _) => Ok(Operation::BinaryArithmetic(arithmetic::BinaryOperator::Shr)), (0x1d, _) => Ok(Operation::Syscall(opcode)), (0x20, _) => Ok(Operation::Syscall(opcode)), - (0x21, _) => Ok(Operation::NotImplemented), + (0x21, true) => Ok(Operation::KeccakGeneral), (0x30, _) => Ok(Operation::Syscall(opcode)), (0x31, _) => Ok(Operation::Syscall(opcode)), (0x32, _) => Ok(Operation::Syscall(opcode)), @@ -95,23 +105,19 @@ fn decode(registers_state: RegistersState, opcode: u8) -> Result Ok(Operation::Syscall(opcode)), (0x47, _) => Ok(Operation::Syscall(opcode)), (0x48, _) => Ok(Operation::Syscall(opcode)), - (0x49, _) => Ok(Operation::NotImplemented), - (0x50, _) => Ok(Operation::NotImplemented), + (0x49, _) => Ok(Operation::ProverInput), + (0x50, _) => Ok(Operation::Pop), (0x51, _) => Ok(Operation::Syscall(opcode)), (0x52, _) => Ok(Operation::Syscall(opcode)), (0x53, _) => Ok(Operation::Syscall(opcode)), (0x54, _) => Ok(Operation::Syscall(opcode)), (0x55, _) => Ok(Operation::Syscall(opcode)), - (0x56, _) => Ok(Operation::NotImplemented), - (0x57, _) => Ok(Operation::NotImplemented), - (0x58, _) => Ok(Operation::NotImplemented), + (0x56, _) => Ok(Operation::Jump), + (0x57, _) => Ok(Operation::Jumpi), + (0x58, _) => Ok(Operation::Pc), (0x59, _) => Ok(Operation::Syscall(opcode)), - (0x5a, _) => Ok(Operation::NotImplemented), - (0x5b, _) => Ok(Operation::NotImplemented), - (0x5c, true) => Ok(Operation::NotImplemented), - (0x5d, true) => Ok(Operation::NotImplemented), - (0x5e, true) => Ok(Operation::NotImplemented), - (0x5f, true) => Ok(Operation::NotImplemented), + (0x5a, _) => Ok(Operation::Gas), + (0x5b, _) => Ok(Operation::Jumpdest), (0x60..=0x7f, _) => Ok(Operation::Push(opcode & 0x1f)), (0x80..=0x8f, _) => Ok(Operation::Dup(opcode & 0xf)), (0x90..=0x9f, _) => Ok(Operation::Swap(opcode & 0xf)), @@ -126,13 +132,13 @@ fn decode(registers_state: RegistersState, opcode: u8) -> Result Ok(Operation::Syscall(opcode)), (0xf4, _) => Ok(Operation::Syscall(opcode)), (0xf5, _) => Ok(Operation::Syscall(opcode)), - (0xf6, true) => Ok(Operation::NotImplemented), - (0xf7, true) => Ok(Operation::NotImplemented), - (0xf8, true) => Ok(Operation::NotImplemented), + (0xf6, true) => Ok(Operation::GetContext), + (0xf7, true) => Ok(Operation::SetContext), + (0xf8, true) => Ok(Operation::ConsumeGas), (0xf9, true) => Ok(Operation::ExitKernel), (0xfa, _) => Ok(Operation::Syscall(opcode)), - (0xfb, true) => Ok(Operation::NotImplemented), - (0xfc, true) => Ok(Operation::NotImplemented), + (0xfb, true) => Ok(Operation::MloadGeneral), + (0xfc, true) => Ok(Operation::MstoreGeneral), (0xfd, _) => Ok(Operation::Syscall(opcode)), (0xff, _) => Ok(Operation::Syscall(opcode)), _ => Err(ProgramError::InvalidOpcode),