mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-03 14:23:07 +00:00
Merge branch 'main' into sha3_interpreter_ecrecover
# Conflicts: # evm/src/cpu/kernel/interpreter.rs # evm/src/cpu/kernel/tests/ecrecover.rs
This commit is contained in:
commit
54629a0ef9
@ -90,6 +90,10 @@ pub struct CpuColumnsView<T> {
|
||||
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<T> {
|
||||
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<T> {
|
||||
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],
|
||||
|
||||
@ -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),
|
||||
];
|
||||
|
||||
|
||||
@ -23,6 +23,7 @@ pub fn evm_constants() -> HashMap<String, U256> {
|
||||
#[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"),
|
||||
|
||||
82
evm/src/cpu/kernel/asm/assertions.asm
Normal file
82
evm/src/cpu/kernel/asm/assertions.asm
Normal file
@ -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
|
||||
@ -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
|
||||
|
||||
27
evm/src/cpu/kernel/asm/memory.asm
Normal file
27
evm/src/cpu/kernel/asm/memory.asm
Normal file
@ -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
|
||||
@ -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<U256>) -> Interpreter {
|
||||
pub(crate) fn run(
|
||||
code: &[u8],
|
||||
initial_offset: usize,
|
||||
initial_stack: Vec<U256>,
|
||||
) -> anyhow::Result<Interpreter> {
|
||||
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<U256>)
|
||||
};
|
||||
|
||||
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(())
|
||||
}
|
||||
}
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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(())
|
||||
|
||||
@ -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(())
|
||||
|
||||
@ -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(())
|
||||
|
||||
@ -244,7 +244,7 @@ fn compute_filter<K: Field>(row: usize, group_range: Range<usize>, 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<F: RichField + Extendable<D>, 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)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user