diff --git a/evm/src/cpu/columns.rs b/evm/src/cpu/columns.rs index 2f4fe7de..f7b42143 100644 --- a/evm/src/cpu/columns.rs +++ b/evm/src/cpu/columns.rs @@ -90,6 +90,10 @@ pub struct CpuColumnsView { pub is_msize: T, pub is_gas: T, pub is_jumpdest: T, + pub is_get_state_root: T, + pub is_set_state_root: T, + pub is_get_receipt_root: T, + pub is_set_receipt_root: T, pub is_push: T, pub is_dup: T, pub is_swap: T, @@ -98,13 +102,20 @@ pub struct CpuColumnsView { pub is_log2: T, pub is_log3: T, pub is_log4: T, + pub is_panic: T, pub is_create: T, pub is_call: T, pub is_callcode: T, pub is_return: T, pub is_delegatecall: T, pub is_create2: T, + pub is_get_context: T, + pub is_set_context: T, + pub is_consume_gas: T, + pub is_exit_kernel: T, pub is_staticcall: T, + pub is_mload_general: T, + pub is_mstore_general: T, pub is_revert: T, pub is_selfdestruct: T, @@ -124,12 +135,6 @@ pub struct CpuColumnsView { pub is_invalid_12: T, pub is_invalid_13: T, pub is_invalid_14: T, - pub is_invalid_15: T, - pub is_invalid_16: T, - pub is_invalid_17: T, - pub is_invalid_18: T, - pub is_invalid_19: T, - pub is_invalid_20: 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 dce88b3e..fe7c875c 100644 --- a/evm/src/cpu/decode.rs +++ b/evm/src/cpu/decode.rs @@ -15,7 +15,7 @@ use crate::cpu::columns::{CpuColumnsView, COL_MAP}; // - its start index is a multiple of its length (it is aligned) // These properties permit us to check if an opcode belongs to a block of length 2^n by checking its // top 8-n bits. -const OPCODES: [(u64, usize, usize); 102] = [ +const OPCODES: [(u64, usize, usize); 107] = [ // (start index of block, number of top bits to check (log2), flag column) (0x00, 0, COL_MAP.is_stop), (0x01, 0, COL_MAP.is_add), @@ -90,34 +90,39 @@ const OPCODES: [(u64, usize, usize); 102] = [ (0x59, 0, COL_MAP.is_msize), (0x5a, 0, COL_MAP.is_gas), (0x5b, 0, COL_MAP.is_jumpdest), - (0x5c, 2, COL_MAP.is_invalid_9), // 0x5c-0x5f - (0x60, 5, COL_MAP.is_push), // 0x60-0x7f - (0x80, 4, COL_MAP.is_dup), // 0x80-0x8f - (0x90, 4, COL_MAP.is_swap), // 0x90-0x9f + (0x5c, 0, COL_MAP.is_get_state_root), + (0x5d, 0, COL_MAP.is_set_state_root), + (0x5e, 0, COL_MAP.is_get_receipt_root), + (0x5f, 0, COL_MAP.is_set_receipt_root), + (0x60, 5, COL_MAP.is_push), // 0x60-0x7f + (0x80, 4, COL_MAP.is_dup), // 0x80-0x8f + (0x90, 4, COL_MAP.is_swap), // 0x90-0x9f (0xa0, 0, COL_MAP.is_log0), (0xa1, 0, COL_MAP.is_log1), (0xa2, 0, COL_MAP.is_log2), (0xa3, 0, COL_MAP.is_log3), (0xa4, 0, COL_MAP.is_log4), - (0xa5, 0, COL_MAP.is_invalid_10), - (0xa6, 1, COL_MAP.is_invalid_11), // 0xa6-0xa7 - (0xa8, 3, COL_MAP.is_invalid_12), // 0xa8-0xaf - (0xb0, 4, COL_MAP.is_invalid_13), // 0xb0-0xbf - (0xc0, 5, COL_MAP.is_invalid_14), // 0xc0-0xdf - (0xe0, 4, COL_MAP.is_invalid_15), // 0xe0-0xef + (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 (0xf0, 0, COL_MAP.is_create), (0xf1, 0, COL_MAP.is_call), (0xf2, 0, COL_MAP.is_callcode), (0xf3, 0, COL_MAP.is_return), (0xf4, 0, COL_MAP.is_delegatecall), (0xf5, 0, COL_MAP.is_create2), - (0xf6, 1, COL_MAP.is_invalid_16), // 0xf6-0xf7 - (0xf8, 1, COL_MAP.is_invalid_17), // 0xf8-0xf9 + (0xf6, 0, COL_MAP.is_get_context), + (0xf7, 0, COL_MAP.is_set_context), + (0xf8, 0, COL_MAP.is_consume_gas), + (0xf9, 0, COL_MAP.is_exit_kernel), (0xfa, 0, COL_MAP.is_staticcall), - (0xfb, 0, COL_MAP.is_invalid_18), - (0xfc, 0, COL_MAP.is_invalid_19), + (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_20), + (0xfe, 0, COL_MAP.is_invalid_14), (0xff, 0, COL_MAP.is_selfdestruct), ]; diff --git a/evm/src/cpu/kernel/aggregator.rs b/evm/src/cpu/kernel/aggregator.rs index 81243e6c..c6c47387 100644 --- a/evm/src/cpu/kernel/aggregator.rs +++ b/evm/src/cpu/kernel/aggregator.rs @@ -23,6 +23,7 @@ pub fn evm_constants() -> HashMap { #[allow(dead_code)] // TODO: Should be used once witness generation is done. pub(crate) fn combined_kernel() -> Kernel { let files = vec![ + include_str!("asm/assertions.asm"), include_str!("asm/basic_macros.asm"), include_str!("asm/exp.asm"), include_str!("asm/curve_mul.asm"), diff --git a/evm/src/cpu/kernel/asm/assertions.asm b/evm/src/cpu/kernel/asm/assertions.asm new file mode 100644 index 00000000..a8e65036 --- /dev/null +++ b/evm/src/cpu/kernel/asm/assertions.asm @@ -0,0 +1,82 @@ +// It is convenient to have a single panic routine, which we can jump to from +// anywhere. +global panic: + JUMPDEST + PANIC + +// Consumes the top element and asserts that it is zero. +%macro assert_zero + %jumpi panic +%endmacro + +// Consumes the top element and asserts that it is nonzero. +%macro assert_nonzero + ISZERO + %jumpi panic +%endmacro + +%macro assert_eq + EQ + %assert_nonzero +%endmacro + +%macro assert_lt + // %assert_zero is cheaper than %assert_nonzero, so we will leverage the + // fact that (x < y) == !(x >= y). + GE + %assert_zero +%endmacro + +%macro assert_le + // %assert_zero is cheaper than %assert_nonzero, so we will leverage the + // fact that (x <= y) == !(x > y). + GT + %assert_zero +%endmacro + +%macro assert_gt + // %assert_zero is cheaper than %assert_nonzero, so we will leverage the + // fact that (x > y) == !(x <= y). + LE + %assert_zero +%endmacro + +%macro assert_ge + // %assert_zero is cheaper than %assert_nonzero, so we will leverage the + // fact that (x >= y) == !(x < y). + LT + %assert_zero +%endmacro + +%macro assert_eq_const(c) + %eq_const(c) + %assert_nonzero +%endmacro + +%macro assert_lt_const(c) + // %assert_zero is cheaper than %assert_nonzero, so we will leverage the + // fact that (x < c) == !(x >= c). + %ge_const(c) + %assert_zero +%endmacro + +%macro assert_le_const(c) + // %assert_zero is cheaper than %assert_nonzero, so we will leverage the + // fact that (x <= c) == !(x > c). + %gt_const(c) + %assert_zero +%endmacro + +%macro assert_gt_const(c) + // %assert_zero is cheaper than %assert_nonzero, so we will leverage the + // fact that (x > c) == !(x <= c). + %le_const(c) + %assert_zero +%endmacro + +%macro assert_ge_const(c) + // %assert_zero is cheaper than %assert_nonzero, so we will leverage the + // fact that (x >= c) == !(x < c). + %lt_const(c) + %assert_zero +%endmacro diff --git a/evm/src/cpu/kernel/asm/basic_macros.asm b/evm/src/cpu/kernel/asm/basic_macros.asm index db53bff5..7bf001b4 100644 --- a/evm/src/cpu/kernel/asm/basic_macros.asm +++ b/evm/src/cpu/kernel/asm/basic_macros.asm @@ -26,6 +26,83 @@ %endrep %endmacro +%macro add_const(c) + // stack: input, ... + PUSH $c + ADD + // stack: input + c, ... +%endmacro + +// Slightly inefficient as we need to swap the inputs. +// Consider avoiding this in performance-critical code. +%macro sub_const(c) + // stack: input, ... + PUSH $c + // stack: c, input, ... + SWAP1 + // stack: input, c, ... + SUB + // stack: input - c, ... +%endmacro + +%macro mul_const(c) + // stack: input, ... + PUSH $c + MUL + // stack: input * c, ... +%endmacro + +// Slightly inefficient as we need to swap the inputs. +// Consider avoiding this in performance-critical code. +%macro div_const(c) + // stack: input, ... + PUSH $c + // stack: c, input, ... + SWAP1 + // stack: input, c, ... + SUB + // stack: input / c, ... +%endmacro + +%macro eq_const(c) + // stack: input, ... + PUSH $c + EQ + // stack: input == c, ... +%endmacro + +%macro lt_const(c) + // stack: input, ... + PUSH $c + // stack: c, input, ... + GT // Check it backwards: (input < c) == (c > input) + // stack: input <= c, ... +%endmacro + +%macro le_const(c) + // stack: input, ... + PUSH $c + // stack: c, input, ... + GE // Check it backwards: (input <= c) == (c >= input) + // stack: input <= c, ... +%endmacro + +%macro gt_const(c) + // stack: input, ... + PUSH $c + // stack: c, input, ... + LT // Check it backwards: (input > c) == (c < input) + // stack: input >= c, ... +%endmacro + +%macro ge_const(c) + // stack: input, ... + PUSH $c + // stack: c, input, ... + LE // Check it backwards: (input >= c) == (c <= input) + // stack: input >= c, ... +%endmacro + // If pred is zero, yields z; otherwise, yields nz %macro select // stack: pred, nz, z diff --git a/evm/src/cpu/kernel/asm/memory.asm b/evm/src/cpu/kernel/asm/memory.asm new file mode 100644 index 00000000..e3af9954 --- /dev/null +++ b/evm/src/cpu/kernel/asm/memory.asm @@ -0,0 +1,27 @@ +// Load a byte from the given segment of the current context's memory space. +// Note that main memory values are one byte each, but in general memory values +// can be 256 bits. This macro deals with a single address (unlike MLOAD), so +// if it is used with main memory, it will load a single byte. +%macro mload_current(segment) + // stack: offset + PUSH $segment + // stack: segment, offset + CURRENT_CONTEXT + // stack: context, segment, offset + MLOAD_GENERAL + // stack: value +%endmacro + +// Store a byte to the given segment of the current context's memory space. +// Note that main memory values are one byte each, but in general memory values +// can be 256 bits. This macro deals with a single address (unlike MSTORE), so +// if it is used with main memory, it will store a single byte. +%macro mstore_current(segment) + // stack: offset, value + PUSH $segment + // stack: segment, offset, value + CURRENT_CONTEXT + // stack: context, segment, offset, value + MSTORE_GENERAL + // stack: (empty) +%endmacro diff --git a/evm/src/cpu/kernel/interpreter.rs b/evm/src/cpu/kernel/interpreter.rs index cc5b870d..3ee95e22 100644 --- a/evm/src/cpu/kernel/interpreter.rs +++ b/evm/src/cpu/kernel/interpreter.rs @@ -1,4 +1,6 @@ +use anyhow::bail; use ethereum_types::{BigEndianHash, U256, U512}; +use ethereum_types::{U256, U512}; use keccak_hash::keccak; /// Halt interpreter execution whenever a jump to this offset is done. @@ -57,7 +59,11 @@ pub(crate) struct Interpreter<'a> { running: bool, } -pub(crate) fn run(code: &[u8], initial_offset: usize, initial_stack: Vec) -> Interpreter { +pub(crate) fn run( + code: &[u8], + initial_offset: usize, + initial_stack: Vec, +) -> anyhow::Result { let mut interpreter = Interpreter { code, jumpdests: find_jumpdests(code), @@ -68,10 +74,10 @@ pub(crate) fn run(code: &[u8], initial_offset: usize, initial_stack: Vec) }; while interpreter.running { - interpreter.run_opcode(); + interpreter.run_opcode()?; } - interpreter + Ok(interpreter) } impl<'a> Interpreter<'a> { @@ -95,7 +101,7 @@ impl<'a> Interpreter<'a> { self.stack.pop().expect("Pop on empty stack.") } - fn run_opcode(&mut self) { + fn run_opcode(&mut self) -> anyhow::Result<()> { let opcode = self.code.get(self.offset).copied().unwrap_or_default(); self.incr(1); match opcode { @@ -162,6 +168,10 @@ impl<'a> Interpreter<'a> { 0x59 => todo!(), // "MSIZE", 0x5a => todo!(), // "GAS", 0x5b => (), // "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" @@ -170,18 +180,26 @@ impl<'a> Interpreter<'a> { 0xa2 => todo!(), // "LOG2", 0xa3 => todo!(), // "LOG3", 0xa4 => todo!(), // "LOG4", + 0xa5 => bail!("Executed PANIC"), // "PANIC", 0xf0 => todo!(), // "CREATE", 0xf1 => todo!(), // "CALL", 0xf2 => todo!(), // "CALLCODE", 0xf3 => todo!(), // "RETURN", 0xf4 => todo!(), // "DELEGATECALL", 0xf5 => todo!(), // "CREATE2", + 0xf6 => todo!(), // "GET_CONTEXT", + 0xf7 => todo!(), // "SET_CONTEXT", + 0xf8 => todo!(), // "CONSUME_GAS", + 0xf9 => todo!(), // "EXIT_KERNEL", 0xfa => todo!(), // "STATICCALL", + 0xfb => todo!(), // "MLOAD_GENERAL", + 0xfc => todo!(), // "MSTORE_GENERAL", 0xfd => todo!(), // "REVERT", - 0xfe => todo!(), // "INVALID", + 0xfe => bail!("Executed INVALID"), // "INVALID", 0xff => todo!(), // "SELFDESTRUCT", - _ => panic!("Unrecognized opcode {}.", opcode), + _ => bail!("Unrecognized opcode {}.", opcode), }; + Ok(()) } fn run_stop(&mut self) { @@ -386,15 +404,16 @@ mod tests { use crate::cpu::kernel::interpreter::{run, Interpreter}; #[test] - fn test_run() { + fn test_run() -> anyhow::Result<()> { let code = vec![ 0x60, 0x1, 0x60, 0x2, 0x1, 0x63, 0xde, 0xad, 0xbe, 0xef, 0x56, ]; // PUSH1, 1, PUSH1, 2, ADD, PUSH4 deadbeef, JUMP - assert_eq!(run(&code, 0, vec![]).stack, vec![0x3.into()]); + assert_eq!(run(&code, 0, vec![])?.stack, vec![0x3.into()]); + Ok(()) } #[test] - fn test_run_with_memory() { + fn test_run_with_memory() -> anyhow::Result<()> { // PUSH1 0xff // PUSH1 0 // MSTORE @@ -412,9 +431,10 @@ mod tests { 0x60, 0xff, 0x60, 0x0, 0x52, 0x60, 0, 0x51, 0x60, 0x1, 0x51, 0x60, 0x42, 0x60, 0x27, 0x53, ]; - let run = run(&code, 0, vec![]); + let run = run(&code, 0, vec![])?; let Interpreter { stack, memory, .. } = run; assert_eq!(stack, vec![0xff.into(), 0xff00.into()]); assert_eq!(&memory.memory, &hex!("00000000000000000000000000000000000000000000000000000000000000ff0000000000000042000000000000000000000000000000000000000000000000")); + Ok(()) } } diff --git a/evm/src/cpu/kernel/opcodes.rs b/evm/src/cpu/kernel/opcodes.rs index b8633178..b9ef7d5e 100644 --- a/evm/src/cpu/kernel/opcodes.rs +++ b/evm/src/cpu/kernel/opcodes.rs @@ -71,6 +71,10 @@ 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, @@ -108,13 +112,20 @@ pub(crate) fn get_opcode(mnemonic: &str) -> u8 { "LOG2" => 0xa2, "LOG3" => 0xa3, "LOG4" => 0xa4, + "PANIC" => 0xa5, "CREATE" => 0xf0, "CALL" => 0xf1, "CALLCODE" => 0xf2, "RETURN" => 0xf3, "DELEGATECALL" => 0xf4, "CREATE2" => 0xf5, + "GET_CONTEXT" => 0xf6, + "SET_CONTEXT" => 0xf7, + "CONSUME_GAS" => 0xf8, + "EXIT_KERNEL" => 0xf9, "STATICCALL" => 0xfa, + "MLOAD_GENERAL" => 0xfb, + "MSTORE_GENERAL" => 0xfc, "REVERT" => 0xfd, "INVALID" => 0xfe, "SELFDESTRUCT" => 0xff, diff --git a/evm/src/cpu/kernel/tests/curve_ops.rs b/evm/src/cpu/kernel/tests/curve_ops.rs index 7d7f042a..6d8c6696 100644 --- a/evm/src/cpu/kernel/tests/curve_ops.rs +++ b/evm/src/cpu/kernel/tests/curve_ops.rs @@ -43,76 +43,76 @@ mod bn { // Standard addition #1 let initial_stack = u256ify(["0xdeadbeef", point0.1, point0.0, point1.1, point1.0])?; - let stack = run(&kernel.code, ec_add, initial_stack).stack; + let stack = run(&kernel.code, ec_add, initial_stack)?.stack; assert_eq!(stack, u256ify([point2.1, point2.0])?); // Standard addition #2 let initial_stack = u256ify(["0xdeadbeef", point1.1, point1.0, point0.1, point0.0])?; - let stack = run(&kernel.code, ec_add, initial_stack).stack; + let stack = run(&kernel.code, ec_add, initial_stack)?.stack; assert_eq!(stack, u256ify([point2.1, point2.0])?); // Standard doubling #1 let initial_stack = u256ify(["0xdeadbeef", point0.1, point0.0, point0.1, point0.0])?; - let stack = run(&kernel.code, ec_add, initial_stack).stack; + let stack = run(&kernel.code, ec_add, initial_stack)?.stack; assert_eq!(stack, u256ify([point3.1, point3.0])?); // Standard doubling #2 let initial_stack = u256ify(["0xdeadbeef", point0.1, point0.0])?; - let stack = run(&kernel.code, ec_double, initial_stack).stack; + let stack = run(&kernel.code, ec_double, initial_stack)?.stack; assert_eq!(stack, u256ify([point3.1, point3.0])?); // Standard doubling #3 let initial_stack = u256ify(["0xdeadbeef", "0x2", point0.1, point0.0])?; - let stack = run(&kernel.code, ec_mul, initial_stack).stack; + let stack = run(&kernel.code, ec_mul, initial_stack)?.stack; assert_eq!(stack, u256ify([point3.1, point3.0])?); // Addition with identity #1 let initial_stack = u256ify(["0xdeadbeef", identity.1, identity.0, point1.1, point1.0])?; - let stack = run(&kernel.code, ec_add, initial_stack).stack; + let stack = run(&kernel.code, ec_add, initial_stack)?.stack; assert_eq!(stack, u256ify([point1.1, point1.0])?); // Addition with identity #2 let initial_stack = u256ify(["0xdeadbeef", point1.1, point1.0, identity.1, identity.0])?; - let stack = run(&kernel.code, ec_add, initial_stack).stack; + let stack = run(&kernel.code, ec_add, initial_stack)?.stack; assert_eq!(stack, u256ify([point1.1, point1.0])?); // Addition with identity #3 let initial_stack = u256ify(["0xdeadbeef", identity.1, identity.0, identity.1, identity.0])?; - let stack = run(&kernel.code, ec_add, initial_stack).stack; + let stack = run(&kernel.code, ec_add, initial_stack)?.stack; assert_eq!(stack, u256ify([identity.1, identity.0])?); // Addition with invalid point(s) #1 let initial_stack = u256ify(["0xdeadbeef", point0.1, point0.0, invalid.1, invalid.0])?; - let stack = run(&kernel.code, ec_add, initial_stack).stack; + let stack = run(&kernel.code, ec_add, initial_stack)?.stack; assert_eq!(stack, vec![U256::MAX, U256::MAX]); // Addition with invalid point(s) #2 let initial_stack = u256ify(["0xdeadbeef", invalid.1, invalid.0, point0.1, point0.0])?; - let stack = run(&kernel.code, ec_add, initial_stack).stack; + let stack = run(&kernel.code, ec_add, initial_stack)?.stack; assert_eq!(stack, vec![U256::MAX, U256::MAX]); // Addition with invalid point(s) #3 let initial_stack = u256ify(["0xdeadbeef", invalid.1, invalid.0, identity.1, identity.0])?; - let stack = run(&kernel.code, ec_add, initial_stack).stack; + let stack = run(&kernel.code, ec_add, initial_stack)?.stack; assert_eq!(stack, vec![U256::MAX, U256::MAX]); // Addition with invalid point(s) #4 let initial_stack = u256ify(["0xdeadbeef", invalid.1, invalid.0, invalid.1, invalid.0])?; - let stack = run(&kernel.code, ec_add, initial_stack).stack; + let stack = run(&kernel.code, ec_add, initial_stack)?.stack; assert_eq!(stack, vec![U256::MAX, U256::MAX]); // Scalar multiplication #1 let initial_stack = u256ify(["0xdeadbeef", s, point0.1, point0.0])?; - let stack = run(&kernel.code, ec_mul, initial_stack).stack; + let stack = run(&kernel.code, ec_mul, initial_stack)?.stack; assert_eq!(stack, u256ify([point4.1, point4.0])?); // Scalar multiplication #2 let initial_stack = u256ify(["0xdeadbeef", "0x0", point0.1, point0.0])?; - let stack = run(&kernel.code, ec_mul, initial_stack).stack; + let stack = run(&kernel.code, ec_mul, initial_stack)?.stack; assert_eq!(stack, u256ify([identity.1, identity.0])?); // Scalar multiplication #3 let initial_stack = u256ify(["0xdeadbeef", "0x1", point0.1, point0.0])?; - let stack = run(&kernel.code, ec_mul, initial_stack).stack; + let stack = run(&kernel.code, ec_mul, initial_stack)?.stack; assert_eq!(stack, u256ify([point0.1, point0.0])?); // Scalar multiplication #4 let initial_stack = u256ify(["0xdeadbeef", s, identity.1, identity.0])?; - let stack = run(&kernel.code, ec_mul, initial_stack).stack; + let stack = run(&kernel.code, ec_mul, initial_stack)?.stack; assert_eq!(stack, u256ify([identity.1, identity.0])?); // Scalar multiplication #5 let initial_stack = u256ify(["0xdeadbeef", s, invalid.1, invalid.0])?; - let stack = run(&kernel.code, ec_mul, initial_stack).stack; + let stack = run(&kernel.code, ec_mul, initial_stack)?.stack; assert_eq!(stack, vec![U256::MAX, U256::MAX]); // Multiple calls @@ -126,7 +126,7 @@ mod bn { point0.1, point0.0, ])?; - let stack = run(&kernel.code, ec_add, initial_stack).stack; + let stack = run(&kernel.code, ec_add, initial_stack)?.stack; assert_eq!(stack, u256ify([point4.1, point4.0])?); Ok(()) @@ -176,55 +176,55 @@ mod secp { // Standard addition #1 let initial_stack = u256ify(["0xdeadbeef", point0.1, point0.0, point1.1, point1.0])?; - let stack = run(&kernel.code, ec_add, initial_stack).stack; + let stack = run(&kernel.code, ec_add, initial_stack)?.stack; assert_eq!(stack, u256ify([point2.1, point2.0])?); // Standard addition #2 let initial_stack = u256ify(["0xdeadbeef", point1.1, point1.0, point0.1, point0.0])?; - let stack = run(&kernel.code, ec_add, initial_stack).stack; + let stack = run(&kernel.code, ec_add, initial_stack)?.stack; assert_eq!(stack, u256ify([point2.1, point2.0])?); // Standard doubling #1 let initial_stack = u256ify(["0xdeadbeef", point0.1, point0.0, point0.1, point0.0])?; - let stack = run(&kernel.code, ec_add, initial_stack).stack; + let stack = run(&kernel.code, ec_add, initial_stack)?.stack; assert_eq!(stack, u256ify([point3.1, point3.0])?); // Standard doubling #2 let initial_stack = u256ify(["0xdeadbeef", point0.1, point0.0])?; - let stack = run(&kernel.code, ec_double, initial_stack).stack; + let stack = run(&kernel.code, ec_double, initial_stack)?.stack; assert_eq!(stack, u256ify([point3.1, point3.0])?); // Standard doubling #3 let initial_stack = u256ify(["0xdeadbeef", "0x2", point0.1, point0.0])?; - let stack = run(&kernel.code, ec_mul, initial_stack).stack; + let stack = run(&kernel.code, ec_mul, initial_stack)?.stack; assert_eq!(stack, u256ify([point3.1, point3.0])?); // Addition with identity #1 let initial_stack = u256ify(["0xdeadbeef", identity.1, identity.0, point1.1, point1.0])?; - let stack = run(&kernel.code, ec_add, initial_stack).stack; + let stack = run(&kernel.code, ec_add, initial_stack)?.stack; assert_eq!(stack, u256ify([point1.1, point1.0])?); // Addition with identity #2 let initial_stack = u256ify(["0xdeadbeef", point1.1, point1.0, identity.1, identity.0])?; - let stack = run(&kernel.code, ec_add, initial_stack).stack; + let stack = run(&kernel.code, ec_add, initial_stack)?.stack; assert_eq!(stack, u256ify([point1.1, point1.0])?); // Addition with identity #3 let initial_stack = u256ify(["0xdeadbeef", identity.1, identity.0, identity.1, identity.0])?; - let stack = run(&kernel.code, ec_add, initial_stack).stack; + let stack = run(&kernel.code, ec_add, initial_stack)?.stack; assert_eq!(stack, u256ify([identity.1, identity.0])?); // Scalar multiplication #1 let initial_stack = u256ify(["0xdeadbeef", s, point0.1, point0.0])?; - let stack = run(&kernel.code, ec_mul, initial_stack).stack; + let stack = run(&kernel.code, ec_mul, initial_stack)?.stack; assert_eq!(stack, u256ify([point4.1, point4.0])?); // Scalar multiplication #2 let initial_stack = u256ify(["0xdeadbeef", "0x0", point0.1, point0.0])?; - let stack = run(&kernel.code, ec_mul, initial_stack).stack; + let stack = run(&kernel.code, ec_mul, initial_stack)?.stack; assert_eq!(stack, u256ify([identity.1, identity.0])?); // Scalar multiplication #3 let initial_stack = u256ify(["0xdeadbeef", "0x1", point0.1, point0.0])?; - let stack = run(&kernel.code, ec_mul, initial_stack).stack; + let stack = run(&kernel.code, ec_mul, initial_stack)?.stack; assert_eq!(stack, u256ify([point0.1, point0.0])?); // Scalar multiplication #4 let initial_stack = u256ify(["0xdeadbeef", s, identity.1, identity.0])?; - let stack = run(&kernel.code, ec_mul, initial_stack).stack; + let stack = run(&kernel.code, ec_mul, initial_stack)?.stack; assert_eq!(stack, u256ify([identity.1, identity.0])?); // Multiple calls @@ -238,7 +238,7 @@ mod secp { point0.1, point0.0, ])?; - let stack = run(&kernel.code, ec_add, initial_stack).stack; + let stack = run(&kernel.code, ec_add, initial_stack)?.stack; assert_eq!(stack, u256ify([point4.1, point4.0])?); Ok(()) diff --git a/evm/src/cpu/kernel/tests/ecrecover.rs b/evm/src/cpu/kernel/tests/ecrecover.rs index 80257222..78bdea3e 100644 --- a/evm/src/cpu/kernel/tests/ecrecover.rs +++ b/evm/src/cpu/kernel/tests/ecrecover.rs @@ -18,7 +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).stack; + let stack = run(&kernel.code, ecrecover, initial_stack)?.stack; assert_eq!(stack[0], U256::from_str(expected).unwrap()); Ok(()) @@ -27,7 +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).stack; + let stack = run(&kernel.code, 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 b12b943e..25c88623 100644 --- a/evm/src/cpu/kernel/tests/exp.rs +++ b/evm/src/cpu/kernel/tests/exp.rs @@ -18,26 +18,26 @@ 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).stack; + let stack_with_kernel = run(&kernel.code, 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).stack; + let stack_with_opcode = run(&code, 0, initial_stack)?.stack; assert_eq!(stack_with_kernel, stack_with_opcode); // 0 base let initial_stack = vec![U256::from_str("0xdeadbeef")?, b, U256::zero()]; - let stack_with_kernel = run(&kernel.code, exp, initial_stack).stack; + let stack_with_kernel = run(&kernel.code, 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).stack; + let stack_with_opcode = run(&code, 0, initial_stack)?.stack; assert_eq!(stack_with_kernel, stack_with_opcode); // 0 exponent let initial_stack = vec![U256::from_str("0xdeadbeef")?, U256::zero(), a]; - let stack_with_kernel = run(&kernel.code, exp, initial_stack).stack; + let stack_with_kernel = run(&kernel.code, 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).stack; + let stack_with_opcode = run(&code, 0, initial_stack)?.stack; assert_eq!(stack_with_kernel, stack_with_opcode); Ok(()) diff --git a/plonky2/src/gates/gate.rs b/plonky2/src/gates/gate.rs index 2e6b36ef..781e0cbd 100644 --- a/plonky2/src/gates/gate.rs +++ b/plonky2/src/gates/gate.rs @@ -244,7 +244,7 @@ fn compute_filter(row: usize, group_range: Range, s: K, many_se debug_assert!(group_range.contains(&row)); group_range .filter(|&i| i != row) - .chain(many_selector.then(|| UNUSED_SELECTOR)) + .chain(many_selector.then_some(UNUSED_SELECTOR)) .map(|i| K::from_canonical_usize(i) - s) .product() } @@ -259,7 +259,7 @@ fn compute_filter_circuit, const D: usize>( debug_assert!(group_range.contains(&row)); let v = group_range .filter(|&i| i != row) - .chain(many_selectors.then(|| UNUSED_SELECTOR)) + .chain(many_selectors.then_some(UNUSED_SELECTOR)) .map(|i| { let c = builder.constant_extension(F::Extension::from_canonical_usize(i)); builder.sub_extension(c, s)