diff --git a/evm/src/cpu/columns.rs b/evm/src/cpu/columns.rs index c79f9e9d..42b0a5bc 100644 --- a/evm/src/cpu/columns.rs +++ b/evm/src/cpu/columns.rs @@ -78,6 +78,7 @@ pub struct CpuColumnsView { pub is_chainid: T, pub is_selfbalance: T, pub is_basefee: T, + pub is_prover_input: T, pub is_pop: T, pub is_mload: T, pub is_mstore: T, @@ -134,7 +135,6 @@ pub struct CpuColumnsView { pub is_invalid_11: T, pub is_invalid_12: T, pub is_invalid_13: T, - pub is_invalid_14: T, /// If CPU cycle: the opcode, broken up into bits in **big-endian** order. pub opcode_bits: [T; 8], diff --git a/evm/src/cpu/decode.rs b/evm/src/cpu/decode.rs index 22a25dc6..bd7ea5fe 100644 --- a/evm/src/cpu/decode.rs +++ b/evm/src/cpu/decode.rs @@ -75,9 +75,9 @@ const OPCODES: [(u64, usize, usize); 107] = [ (0x46, 0, COL_MAP.is_chainid), (0x47, 0, COL_MAP.is_selfbalance), (0x48, 0, COL_MAP.is_basefee), - (0x49, 0, COL_MAP.is_invalid_6), - (0x4a, 1, COL_MAP.is_invalid_7), // 0x4a-0x4b - (0x4c, 2, COL_MAP.is_invalid_8), // 0x4c-0x4f + (0x49, 0, COL_MAP.is_prover_input), + (0x4a, 1, COL_MAP.is_invalid_6), // 0x4a-0x4b + (0x4c, 2, COL_MAP.is_invalid_7), // 0x4c-0x4f (0x50, 0, COL_MAP.is_pop), (0x51, 0, COL_MAP.is_mload), (0x52, 0, COL_MAP.is_mstore), @@ -103,11 +103,11 @@ const OPCODES: [(u64, usize, usize); 107] = [ (0xa3, 0, COL_MAP.is_log3), (0xa4, 0, COL_MAP.is_log4), (0xa5, 0, COL_MAP.is_panic), - (0xa6, 1, COL_MAP.is_invalid_9), // 0xa6-0xa7 - (0xa8, 3, COL_MAP.is_invalid_10), // 0xa8-0xaf - (0xb0, 4, COL_MAP.is_invalid_11), // 0xb0-0xbf - (0xc0, 5, COL_MAP.is_invalid_12), // 0xc0-0xdf - (0xe0, 4, COL_MAP.is_invalid_13), // 0xe0-0xef + (0xa6, 1, COL_MAP.is_invalid_8), // 0xa6-0xa7 + (0xa8, 3, COL_MAP.is_invalid_9), // 0xa8-0xaf + (0xb0, 4, COL_MAP.is_invalid_10), // 0xb0-0xbf + (0xc0, 5, COL_MAP.is_invalid_11), // 0xc0-0xdf + (0xe0, 4, COL_MAP.is_invalid_12), // 0xe0-0xef (0xf0, 0, COL_MAP.is_create), (0xf1, 0, COL_MAP.is_call), (0xf2, 0, COL_MAP.is_callcode), @@ -122,7 +122,7 @@ const OPCODES: [(u64, usize, usize); 107] = [ (0xfb, 0, COL_MAP.is_mload_general), (0xfc, 0, COL_MAP.is_mstore_general), (0xfd, 0, COL_MAP.is_revert), - (0xfe, 0, COL_MAP.is_invalid_14), + (0xfe, 0, COL_MAP.is_invalid_13), (0xff, 0, COL_MAP.is_selfdestruct), ]; diff --git a/evm/src/cpu/kernel/interpreter.rs b/evm/src/cpu/kernel/interpreter.rs index 452acd93..aa5d1ac3 100644 --- a/evm/src/cpu/kernel/interpreter.rs +++ b/evm/src/cpu/kernel/interpreter.rs @@ -1,4 +1,4 @@ -use anyhow::bail; +use anyhow::{anyhow, bail}; use ethereum_types::{U256, U512}; /// Halt interpreter execution whenever a jump to this offset is done. @@ -49,6 +49,9 @@ pub(crate) struct Interpreter<'a> { offset: usize, pub(crate) stack: Vec, pub(crate) memory: EvmMemory, + /// Non-deterministic prover inputs, stored backwards so that popping the last item gives the + /// next prover input. + prover_inputs: Vec, running: bool, } @@ -57,12 +60,25 @@ pub(crate) fn run( initial_offset: usize, initial_stack: Vec, ) -> anyhow::Result { + run_with_input(code, initial_offset, initial_stack, vec![]) +} + +pub(crate) fn run_with_input( + code: &[u8], + initial_offset: usize, + initial_stack: Vec, + mut prover_inputs: Vec, +) -> anyhow::Result { + // Prover inputs are stored backwards, so that popping the last item gives the next input. + prover_inputs.reverse(); + let mut interpreter = Interpreter { code, jumpdests: find_jumpdests(code), offset: initial_offset, stack: initial_stack, memory: EvmMemory::default(), + prover_inputs, running: true, }; @@ -149,6 +165,7 @@ impl<'a> Interpreter<'a> { 0x45 => todo!(), // "GASLIMIT", 0x46 => todo!(), // "CHAINID", 0x48 => todo!(), // "BASEFEE", + 0x49 => self.run_prover_input()?, // "PROVER_INPUT", 0x50 => self.run_pop(), // "POP", 0x51 => self.run_mload(), // "MLOAD", 0x52 => self.run_mstore(), // "MSTORE", @@ -303,6 +320,15 @@ impl<'a> Interpreter<'a> { self.push(!x); } + fn run_prover_input(&mut self) -> anyhow::Result<()> { + let input = self + .prover_inputs + .pop() + .ok_or_else(|| anyhow!("Out of prover inputs"))?; + self.stack.push(input); + Ok(()) + } + fn run_pop(&mut self) { self.pop(); } diff --git a/evm/src/generation/mod.rs b/evm/src/generation/mod.rs index b73270db..b8ab0376 100644 --- a/evm/src/generation/mod.rs +++ b/evm/src/generation/mod.rs @@ -1,3 +1,4 @@ +use ethereum_types::U256; use plonky2::field::extension::Extendable; use plonky2::field::polynomial::PolynomialValues; use plonky2::field::types::Field; @@ -45,18 +46,28 @@ pub fn generate_traces, const D: usize>( current_cpu_row, memory, keccak_inputs, - logic_ops: logic_inputs, + logic_ops, + prover_inputs, .. } = state; assert_eq!(current_cpu_row, [F::ZERO; NUM_CPU_COLUMNS].into()); + assert_eq!(prover_inputs, vec![], "Not all prover inputs were consumed"); let cpu_trace = trace_rows_to_poly_values(cpu_rows); let keccak_trace = all_stark.keccak_stark.generate_trace(keccak_inputs); - let logic_trace = all_stark.logic_stark.generate_trace(logic_inputs); + let logic_trace = all_stark.logic_stark.generate_trace(logic_ops); let memory_trace = all_stark.memory_stark.generate_trace(memory.log); vec![cpu_trace, keccak_trace, logic_trace, memory_trace] } -fn generate_txn(_state: &mut GenerationState, _txn: &TransactionData) { - todo!() +fn generate_txn(state: &mut GenerationState, txn: &TransactionData) { + // TODO: Add transaction RLP to prover_input. + + // Supply Merkle trie proofs as prover inputs. + for proof in &txn.trie_proofs { + let proof = proof + .iter() + .flat_map(|node_rlp| node_rlp.iter().map(|byte| U256::from(*byte))); + state.prover_inputs.extend(proof); + } } diff --git a/evm/src/generation/state.rs b/evm/src/generation/state.rs index 46ccc4e3..c7f1003e 100644 --- a/evm/src/generation/state.rs +++ b/evm/src/generation/state.rs @@ -19,6 +19,9 @@ pub(crate) struct GenerationState { pub(crate) keccak_inputs: Vec<[u64; keccak::keccak_stark::NUM_INPUTS]>, pub(crate) logic_ops: Vec, + + /// Non-deterministic inputs provided by the prover. + pub(crate) prover_inputs: Vec, } impl GenerationState { @@ -111,6 +114,7 @@ impl Default for GenerationState { memory: MemoryState::default(), keccak_inputs: vec![], logic_ops: vec![], + prover_inputs: vec![], } } }