diff --git a/evm/src/cpu/kernel/assembler.rs b/evm/src/cpu/kernel/assembler.rs index 334220fd..6d2b0ff2 100644 --- a/evm/src/cpu/kernel/assembler.rs +++ b/evm/src/cpu/kernel/assembler.rs @@ -29,6 +29,7 @@ pub struct Kernel { pub(crate) global_labels: HashMap, + /// Map from `PROVER_INPUT` offsets to their corresponding `ProverInputFn`. pub(crate) prover_inputs: HashMap, } diff --git a/evm/src/cpu/kernel/evm_asm.pest b/evm/src/cpu/kernel/evm_asm.pest index b0033391..0703798e 100644 --- a/evm/src/cpu/kernel/evm_asm.pest +++ b/evm/src/cpu/kernel/evm_asm.pest @@ -29,7 +29,7 @@ local_label = { identifier ~ ":" } bytes_item = { ^"BYTES " ~ literal ~ ("," ~ literal)* } push_instruction = { ^"PUSH " ~ push_target } push_target = { literal | identifier | variable | constant } -prover_input_instruction = { ^"PROVER_INPUT" ~ "(" ~ prover_input_fn ~ ")" } // TODO: Could also support extra arguments. +prover_input_instruction = { ^"PROVER_INPUT" ~ "(" ~ prover_input_fn ~ ")" } prover_input_fn = { identifier ~ ("::" ~ identifier)*} nullary_instruction = { identifier } diff --git a/evm/src/cpu/kernel/prover_input.rs b/evm/src/cpu/kernel/prover_input.rs index 5f3ecd42..733cbef7 100644 --- a/evm/src/cpu/kernel/prover_input.rs +++ b/evm/src/cpu/kernel/prover_input.rs @@ -7,6 +7,8 @@ use crate::cpu::kernel::prover_input::Field::{ }; use crate::cpu::kernel::prover_input::FieldOp::{Inverse, Sqrt}; +/// Prover input function represented as a scoped function name. +/// Example: `PROVER_INPUT(ff::bn254_base::inverse)` is represented as `ProverInputFn([ff, bn254_base, inverse])`. #[derive(PartialEq, Eq, Debug, Clone)] pub struct ProverInputFn(Vec); @@ -17,20 +19,27 @@ impl From> for ProverInputFn { } impl ProverInputFn { + /// Run the function on the stack. pub(crate) fn run(&self, stack: Vec) -> U256 { match self.0[0].as_str() { "ff" => self.run_ff(stack), - "storage" => todo!(), + "mpt" => todo!(), _ => panic!("Unrecognized prover input function."), } } + // Finite field operations. fn run_ff(&self, mut stack: Vec) -> U256 { let field = Field::from_str(self.0[1].as_str()).unwrap(); let op = FieldOp::from_str(self.0[2].as_str()).unwrap(); let x = stack.pop().expect("Empty stack"); field.op(op, x) } + + // MPT operations. + fn run_mpt(&self, mut stack: Vec) -> U256 { + todo!() + } } enum Field { diff --git a/evm/src/cpu/kernel/tests/ecrecover.rs b/evm/src/cpu/kernel/tests/ecrecover.rs index 790a4a2c..b105cf47 100644 --- a/evm/src/cpu/kernel/tests/ecrecover.rs +++ b/evm/src/cpu/kernel/tests/ecrecover.rs @@ -5,7 +5,7 @@ use ethereum_types::U256; use crate::cpu::kernel::aggregator::combined_kernel; use crate::cpu::kernel::assembler::Kernel; -use crate::cpu::kernel::interpreter::run; +use crate::cpu::kernel::interpreter::run_with_kernel; use crate::cpu::kernel::tests::u256ify; fn test_valid_ecrecover( @@ -18,13 +18,7 @@ fn test_valid_ecrecover( ) -> Result<()> { let ecrecover = kernel.global_labels["ecrecover"]; let initial_stack = u256ify(["0xdeadbeef", s, r, v, hash])?; - let stack = run( - &kernel.code, - ecrecover, - initial_stack, - &kernel.prover_inputs, - )? - .stack; + let stack = run_with_kernel(kernel, ecrecover, initial_stack)?.stack; assert_eq!(stack[0], U256::from_str(expected).unwrap()); Ok(()) @@ -33,13 +27,7 @@ fn test_valid_ecrecover( fn test_invalid_ecrecover(hash: &str, v: &str, r: &str, s: &str, kernel: &Kernel) -> Result<()> { let ecrecover = kernel.global_labels["ecrecover"]; let initial_stack = u256ify(["0xdeadbeef", s, r, v, hash])?; - let stack = run( - &kernel.code, - ecrecover, - initial_stack, - &kernel.prover_inputs, - )? - .stack; + let stack = run_with_kernel(kernel, ecrecover, initial_stack)?.stack; assert_eq!(stack, vec![U256::MAX]); Ok(()) diff --git a/evm/src/cpu/kernel/tests/exp.rs b/evm/src/cpu/kernel/tests/exp.rs index 0858c37c..049fd23a 100644 --- a/evm/src/cpu/kernel/tests/exp.rs +++ b/evm/src/cpu/kernel/tests/exp.rs @@ -5,7 +5,7 @@ use ethereum_types::U256; use rand::{thread_rng, Rng}; use crate::cpu::kernel::aggregator::combined_kernel; -use crate::cpu::kernel::interpreter::run; +use crate::cpu::kernel::interpreter::{run, run_with_kernel}; #[test] fn test_exp() -> Result<()> { @@ -18,7 +18,7 @@ fn test_exp() -> Result<()> { // Random input let initial_stack = vec![U256::from_str("0xdeadbeef")?, b, a]; - let stack_with_kernel = run(&kernel.code, exp, initial_stack, &kernel.prover_inputs)?.stack; + let stack_with_kernel = run_with_kernel(&kernel, exp, initial_stack)?.stack; let initial_stack = vec![b, a]; let code = [0xa, 0x63, 0xde, 0xad, 0xbe, 0xef, 0x56]; // EXP, PUSH4 deadbeef, JUMP let stack_with_opcode = run(&code, 0, initial_stack, &kernel.prover_inputs)?.stack; @@ -26,7 +26,7 @@ fn test_exp() -> Result<()> { // 0 base let initial_stack = vec![U256::from_str("0xdeadbeef")?, b, U256::zero()]; - let stack_with_kernel = run(&kernel.code, exp, initial_stack, &kernel.prover_inputs)?.stack; + let stack_with_kernel = run_with_kernel(&kernel, exp, initial_stack)?.stack; let initial_stack = vec![b, U256::zero()]; let code = [0xa, 0x63, 0xde, 0xad, 0xbe, 0xef, 0x56]; // EXP, PUSH4 deadbeef, JUMP let stack_with_opcode = run(&code, 0, initial_stack, &kernel.prover_inputs)?.stack; @@ -34,7 +34,7 @@ fn test_exp() -> Result<()> { // 0 exponent let initial_stack = vec![U256::from_str("0xdeadbeef")?, U256::zero(), a]; - let stack_with_kernel = run(&kernel.code, exp, initial_stack, &kernel.prover_inputs)?.stack; + let stack_with_kernel = run_with_kernel(&kernel, exp, initial_stack)?.stack; let initial_stack = vec![U256::zero(), a]; let code = [0xa, 0x63, 0xde, 0xad, 0xbe, 0xef, 0x56]; // EXP, PUSH4 deadbeef, JUMP let stack_with_opcode = run(&code, 0, initial_stack, &kernel.prover_inputs)?.stack;