mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-03 14:23:07 +00:00
Merge pull request #884 from mir-protocol/evm-kernel-tests
This commit is contained in:
commit
6f2d99c7bc
@ -49,21 +49,20 @@ pub(crate) fn combined_kernel() -> Kernel {
|
||||
include_str!("asm/hash/blake2b/g_functions.asm"),
|
||||
include_str!("asm/hash/blake2b/hash.asm"),
|
||||
include_str!("asm/hash/blake2b/iv.asm"),
|
||||
include_str!("asm/hash/blake2b/main.asm"),
|
||||
include_str!("asm/hash/blake2b/ops.asm"),
|
||||
include_str!("asm/hash/blake2b/permutations.asm"),
|
||||
include_str!("asm/hash/blake2b/store.asm"),
|
||||
include_str!("asm/hash/ripemd/box.asm"),
|
||||
include_str!("asm/hash/ripemd/compression.asm"),
|
||||
include_str!("asm/hash/ripemd/constants.asm"),
|
||||
include_str!("asm/hash/ripemd/functions.asm"),
|
||||
include_str!("asm/hash/ripemd/main.asm"),
|
||||
include_str!("asm/hash/ripemd/memory.asm"),
|
||||
include_str!("asm/hash/ripemd/update.asm"),
|
||||
include_str!("asm/hash/sha2/compression.asm"),
|
||||
include_str!("asm/hash/sha2/constants.asm"),
|
||||
include_str!("asm/hash/sha2/main.asm"),
|
||||
include_str!("asm/hash/sha2/message_schedule.asm"),
|
||||
include_str!("asm/hash/sha2/ops.asm"),
|
||||
include_str!("asm/hash/sha2/store_pad.asm"),
|
||||
include_str!("asm/hash/sha2/temp_words.asm"),
|
||||
include_str!("asm/hash/sha2/write_length.asm"),
|
||||
include_str!("asm/main.asm"),
|
||||
|
||||
15
evm/src/cpu/kernel/asm/hash/blake2b/main.asm
Normal file
15
evm/src/cpu/kernel/asm/hash/blake2b/main.asm
Normal file
@ -0,0 +1,15 @@
|
||||
global blake2b:
|
||||
// stack: virt, num_bytes, retdest
|
||||
DUP2
|
||||
// stack: num_bytes, virt, num_bytes, retdest
|
||||
%add_const(127)
|
||||
%div_const(128)
|
||||
// stack: num_blocks = ceil(num_bytes / 128), virt, num_bytes, retdest
|
||||
DUP2
|
||||
// stack: virt, num_blocks, virt, num_bytes, retdest
|
||||
%mstore_kernel_general
|
||||
// stack: virt, num_bytes, retdest
|
||||
%add_const(1)
|
||||
%mstore_kernel_general
|
||||
// stack: retdest
|
||||
%jump(blake2b_compression)
|
||||
@ -1,45 +0,0 @@
|
||||
global blake2b:
|
||||
%jump(blake2b_store)
|
||||
|
||||
global blake2b_store:
|
||||
// stack: num_bytes, x[0], x[1], ..., x[num_bytes - 1], retdest
|
||||
DUP1
|
||||
// stack: num_bytes, num_bytes, x[0], x[1], ..., x[num_bytes - 1], retdest
|
||||
%add_const(127)
|
||||
%div_const(128)
|
||||
// stack: num_blocks = ceil(num_bytes / 128), num_bytes, x[0], x[1], ..., x[num_bytes - 1], retdest
|
||||
PUSH 0
|
||||
// stack: addr=0, num_blocks, num_bytes, x[0], x[1], ..., x[num_bytes - 1], retdest
|
||||
%mstore_kernel_general
|
||||
// stack: num_bytes, x[0], x[1], ..., x[num_bytes - 1], retdest
|
||||
DUP1
|
||||
// stack: num_bytes, num_bytes, x[0], x[1], ..., x[num_bytes - 1], retdest
|
||||
PUSH 1
|
||||
// stack: 1, num_bytes, num_bytes, x[0], x[1], ..., x[num_bytes - 1], retdest
|
||||
%mstore_kernel_general
|
||||
// stack: num_bytes, x[0], x[1], ..., x[num_bytes - 1], retdest
|
||||
PUSH 2
|
||||
// stack: addr=2, counter=num_bytes, x[0], x[1], x[2], ... , x[num_bytes-1], retdest
|
||||
store_loop:
|
||||
// stack: addr, counter, x[num_bytes-counter], ... , x[num_bytes-1], retdest
|
||||
DUP2
|
||||
// stack: counter, addr, counter, x[num_bytes-counter], ... , x[num_bytes-1], retdest
|
||||
ISZERO
|
||||
%jumpi(store_end)
|
||||
// stack: addr, counter, x[num_bytes-counter], ... , x[num_bytes-1], retdest
|
||||
%stack (addr, counter, val) -> (addr, val, counter, addr)
|
||||
// stack: addr, x[num_bytes-counter], counter, addr, ... , x[num_bytes-1], retdest
|
||||
%mstore_kernel_general
|
||||
// stack: counter, addr, ... , x[num_bytes-1], retdest
|
||||
%decrement
|
||||
// stack: counter-1, addr, ... , x[num_bytes-1], retdest
|
||||
SWAP1
|
||||
// stack: addr, counter-1, ... , x[num_bytes-1], retdest
|
||||
%increment
|
||||
// stack: addr+1, counter-1, ... , x[num_bytes-1], retdest
|
||||
%jump(store_loop)
|
||||
store_end:
|
||||
// stack: addr, counter, retdest
|
||||
%pop2
|
||||
// stack: retdest
|
||||
%jump(blake2b_compression)
|
||||
@ -6,41 +6,56 @@
|
||||
/// STATE, count, _buffer = ripemd_update(STATE, count, _buffer, padlength(len(input)), bytes = [0x80]+[0]*63)
|
||||
/// STATE, count, _buffer = ripemd_update(STATE, count, _buffer, 8, bytes = size(len(_input)))
|
||||
/// return process(STATE)
|
||||
///
|
||||
/// ripemd is called on a stack with ADDR and length
|
||||
/// ripemd_stack is called on a stack with length, followed by the input bytes
|
||||
///
|
||||
/// The hardcoded memory structure, where each register is only a byte, is given as follows
|
||||
/// { 0-63: buffer, 64-71: bytes(8*len(_input)), 72-135: [0x80]+[0]*63 }
|
||||
///
|
||||
/// ripemd_update receives and return the stack in the form:
|
||||
/// stack: STATE, count, length, virt
|
||||
/// where virt is the virtual address of the bytes argument
|
||||
|
||||
global ripemd_stack:
|
||||
// stack: length, INPUT
|
||||
%stack (length) -> (64, length, 0x80, 63, length, length)
|
||||
// stack: 64, length, 0x80, 63, length, length, INPUT
|
||||
%jump(ripemd_storage) // stores the following into memory
|
||||
// init _buffer at virt 0 [consumes 64]
|
||||
// store _size at virt 64 [consumes length]
|
||||
// store _padding at virt 72 [consumes 0x80, 63]
|
||||
// store _input at virt 136 [consumes length]
|
||||
///
|
||||
|
||||
global ripemd:
|
||||
// stack: ADDR, length
|
||||
%stack (ADDR: 3, length) -> (64, length, 0x80, 63, length, ADDR, length)
|
||||
// stack: 64, length, 0x80, 63, length, ADDR, length
|
||||
%jump(ripemd_storage) // stores the following into memory
|
||||
// init _buffer at virt 0 [consumes 64]
|
||||
// store _size at virt 64 [consumes length]
|
||||
// store _padding at virt 72 [consumes 0x80, 63]
|
||||
// store _input at virt 136 [consumes ADDR, length]
|
||||
// stack: virt, length
|
||||
%stack (virt, length) -> (length, 0x80, virt, length)
|
||||
// stack: length, 0x80, virt, length
|
||||
|
||||
global ripemd_init:
|
||||
// stack: length
|
||||
%stack (length) -> ( 0, length, 136, ripemd_1, ripemd_2, process)
|
||||
// stack: count = 0, length, virt = 136, ripemd_1, ripemd_2, process
|
||||
%shl_const(3)
|
||||
// stack: abcdefgh
|
||||
DUP1
|
||||
%extract_and_store_byte(31, 64)
|
||||
// stack: abcdefgh
|
||||
DUP1
|
||||
%extract_and_store_byte(30, 65)
|
||||
// stack: abcdefgh
|
||||
DUP1
|
||||
%extract_and_store_byte(29, 66)
|
||||
// stack: abcdefgh
|
||||
DUP1
|
||||
%extract_and_store_byte(28, 67)
|
||||
// stack: abcdefgh
|
||||
DUP1
|
||||
%extract_and_store_byte(27, 68)
|
||||
// stack: abcdefgh
|
||||
DUP1
|
||||
%extract_and_store_byte(26, 69)
|
||||
// stack: abcdefgh
|
||||
DUP1
|
||||
%extract_and_store_byte(25, 70)
|
||||
// stack: abcdefgh
|
||||
%extract_and_store_byte(24, 71)
|
||||
|
||||
// stack: 0x80
|
||||
%mstore_kernel_general(72)
|
||||
|
||||
// stack: virt, length
|
||||
%stack (virt, length) -> ( 0, length, virt, ripemd_1, ripemd_2, process)
|
||||
// stack: count = 0, length, virt, ripemd_1, ripemd_2, process
|
||||
%stack () -> (0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0)
|
||||
// stack: 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0, count, length, virt, LABELS
|
||||
// stack: STATE, count, length, virt, LABELS
|
||||
%jump(ripemd_update)
|
||||
|
||||
ripemd_1:
|
||||
// stack: STATE, count, length , virt , LABELS
|
||||
DUP7
|
||||
@ -58,7 +73,7 @@ ripemd_2:
|
||||
%stack (STATE: 5, count, length, virt) -> (STATE, count, 8, 64)
|
||||
// stack: STATE, count, length = 8, virt = 64, LABELS
|
||||
%jump(ripemd_update)
|
||||
global process:
|
||||
process:
|
||||
// stack: a , b, c, d, e, count, length, virt
|
||||
%reverse_bytes_u32
|
||||
%shl_const(128)
|
||||
@ -105,3 +120,12 @@ global process:
|
||||
// stack: 56 + 64*(t > 55), t
|
||||
SUB
|
||||
%endmacro
|
||||
|
||||
%macro extract_and_store_byte(byte, offset)
|
||||
// stack: xs
|
||||
PUSH $byte
|
||||
BYTE
|
||||
// stack: xs[byte]
|
||||
%mstore_kernel_general($offset)
|
||||
// stack:
|
||||
%endmacro
|
||||
|
||||
@ -1,137 +0,0 @@
|
||||
global ripemd_storage: // starts by initializing buffer
|
||||
// stack: i [init: 64]
|
||||
%store_zeros(64, ripemd_storage)
|
||||
// stack: (empty)
|
||||
%jump(store_size)
|
||||
|
||||
store_size:
|
||||
// stack: length
|
||||
%shl_const(3)
|
||||
// stack: abcdefgh
|
||||
%extract_and_store_byte(64)
|
||||
// stack: abcdefg
|
||||
%extract_and_store_byte(65)
|
||||
// stack: abcdef
|
||||
%extract_and_store_byte(66)
|
||||
// stack: abcde
|
||||
%extract_and_store_byte(67)
|
||||
// stack: abcd
|
||||
%extract_and_store_byte(68)
|
||||
// stack: abc
|
||||
%extract_and_store_byte(69)
|
||||
// stack: ab
|
||||
%extract_and_store_byte(70)
|
||||
// stack: a
|
||||
%mstore_kernel_general(71)
|
||||
// stack: 0x80 // padding has 0x80 in first position and zeros elsewhere
|
||||
%mstore_kernel_general(72) // store first padding term here so as to avoid extra label
|
||||
%jump(store_padding)
|
||||
|
||||
store_padding:
|
||||
// stack: i [init 63], length
|
||||
%store_zeros(136, store_padding)
|
||||
// stack: length
|
||||
DUP1
|
||||
%jumpi(store_input_stack)
|
||||
POP
|
||||
%jump(ripemd_init)
|
||||
|
||||
store_input_stack:
|
||||
// stack: rem, length, REM_INP
|
||||
%stack (rem, length, head) -> (length, rem, 136, head, rem, length)
|
||||
SUB
|
||||
ADD
|
||||
// stack: offset, byte, rem, length, REM_INP
|
||||
%mstore_kernel_general
|
||||
// stack: rem, length, REM_INP
|
||||
%decrement
|
||||
DUP1
|
||||
// stack: rem - 1, rem - 1, length, REM_INP
|
||||
%jumpi(store_input_stack)
|
||||
// stack: 0, length
|
||||
POP
|
||||
%jump(ripemd_init)
|
||||
|
||||
store_input:
|
||||
// stack: rem , ADDR , length
|
||||
DUP4
|
||||
DUP4
|
||||
DUP4
|
||||
MLOAD_GENERAL
|
||||
// stack: byte, rem , ADDR , length
|
||||
DUP2
|
||||
DUP7
|
||||
SUB
|
||||
%add_const(136)
|
||||
// stack: offset, byte, rem , ADDR , length
|
||||
%mstore_kernel_general
|
||||
// stack: rem , ADDR , length
|
||||
%decrement
|
||||
// stack: rem-1, ADDR , length
|
||||
SWAP3
|
||||
%increment
|
||||
SWAP3
|
||||
// stack: rem-1, ADDR+1, length
|
||||
DUP1
|
||||
%jumpi(store_input)
|
||||
// stack: 0 , ADDR , length
|
||||
%pop4
|
||||
// stack: length
|
||||
%jump(ripemd_init)
|
||||
|
||||
/// def buffer_update(get, set, times):
|
||||
/// for i in range(times):
|
||||
/// buffer[set+i] = bytestring[get+i]
|
||||
|
||||
global buffer_update:
|
||||
// stack: get , set , times , retdest
|
||||
DUP2
|
||||
DUP2
|
||||
// stack: get, set, get , set , times , retdest
|
||||
%mupdate_kernel_general
|
||||
// stack: get , set , times , retdest
|
||||
%increment
|
||||
SWAP1
|
||||
%increment
|
||||
SWAP1
|
||||
SWAP2
|
||||
%decrement
|
||||
SWAP2
|
||||
// stack: get+1, set+1, times-1, retdest
|
||||
DUP3
|
||||
%jumpi(buffer_update)
|
||||
// stack: get , set , 0 , retdest
|
||||
%pop3
|
||||
JUMP
|
||||
|
||||
|
||||
%macro store_zeros(N, label)
|
||||
// stack: i
|
||||
%stack (i) -> ($N, i, 0, i)
|
||||
SUB
|
||||
// stack: offset = N-i, 0, i
|
||||
%mstore_kernel_general
|
||||
// stack: i
|
||||
%decrement
|
||||
DUP1
|
||||
// stack: i-1, i-1
|
||||
%jumpi($label)
|
||||
// stack: 0
|
||||
POP
|
||||
%endmacro
|
||||
|
||||
%macro extract_and_store_byte(offset)
|
||||
// stack: xsy
|
||||
PUSH 0x100
|
||||
DUP2
|
||||
MOD
|
||||
// stack: y, xsy
|
||||
%stack (y, xsy) -> (xsy, y, 0x100, y)
|
||||
// stack: xsy, y, 0x100, y
|
||||
SUB
|
||||
DIV
|
||||
SWAP1
|
||||
// stack: y, xs
|
||||
%mstore_kernel_general($offset)
|
||||
// stack: xs
|
||||
%endmacro
|
||||
@ -106,3 +106,29 @@ update_2:
|
||||
%stack (offset, STATE: 5) -> (STATE, offset, update_2)
|
||||
// stack: STATE, offset, update_2, shift, need, have, count, length, virt, retdest
|
||||
%jump(compress)
|
||||
|
||||
|
||||
/// def buffer_update(get, set, times):
|
||||
/// for i in range(times):
|
||||
/// buffer[set+i] = bytestring[get+i]
|
||||
|
||||
buffer_update:
|
||||
// stack: get , set , times , retdest
|
||||
DUP2
|
||||
DUP2
|
||||
// stack: get, set, get , set , times , retdest
|
||||
%mupdate_kernel_general
|
||||
// stack: get , set , times , retdest
|
||||
%increment
|
||||
SWAP1
|
||||
%increment
|
||||
SWAP1
|
||||
SWAP2
|
||||
%decrement
|
||||
SWAP2
|
||||
// stack: get+1, set+1, times-1, retdest
|
||||
DUP3
|
||||
%jumpi(buffer_update)
|
||||
// stack: get , set , 0 , retdest
|
||||
%pop3
|
||||
JUMP
|
||||
|
||||
@ -1,47 +1,19 @@
|
||||
global sha2:
|
||||
%jump(sha2_store)
|
||||
|
||||
global sha2_store:
|
||||
// stack: num_bytes, x[0], x[1], ..., x[num_bytes - 1], retdest
|
||||
DUP1
|
||||
// stack: num_bytes, num_bytes, x[0], x[1], ..., x[num_bytes - 1], retdest
|
||||
PUSH 0
|
||||
// stack: addr=0, num_bytes, num_bytes, x[0], x[1], ..., x[num_bytes - 1], retdest
|
||||
%mstore_kernel_general
|
||||
// stack: num_bytes, x[0], x[1], ..., x[num_bytes - 1], retdest
|
||||
PUSH 1
|
||||
// stack: addr=1, counter=num_bytes, x[0], x[1], x[2], ... , x[num_bytes-1], retdest
|
||||
store_loop:
|
||||
// stack: addr, counter, x[num_bytes-counter], ... , x[num_bytes-1], retdest
|
||||
DUP2
|
||||
// stack: counter, addr, counter, x[num_bytes-counter], ... , x[num_bytes-1], retdest
|
||||
ISZERO
|
||||
%jumpi(store_end)
|
||||
// stack: addr, counter, x[num_bytes-counter], ... , x[num_bytes-1], retdest
|
||||
%stack (addr, counter, val) -> (addr, val, counter, addr)
|
||||
// stack: addr, x[num_bytes-counter], counter, addr, ... , x[num_bytes-1], retdest
|
||||
%mstore_kernel_general
|
||||
// stack: counter, addr, ... , x[num_bytes-1], retdest
|
||||
%decrement
|
||||
// stack: counter-1, addr, ... , x[num_bytes-1], retdest
|
||||
// stack: virt, num_bytes, retdest
|
||||
SWAP1
|
||||
// stack: addr, counter-1, ... , x[num_bytes-1], retdest
|
||||
%increment
|
||||
// stack: addr+1, counter-1, ... , x[num_bytes-1], retdest
|
||||
%jump(store_loop)
|
||||
store_end:
|
||||
// stack: addr, counter, retdest
|
||||
%pop2
|
||||
// stack: retdest
|
||||
%jump(sha2_pad)
|
||||
// stack: num_bytes, virt, retdest
|
||||
DUP2
|
||||
// stack: virt, num_bytes, virt, retdest
|
||||
%mstore_kernel_general
|
||||
// stack: virt, retdest
|
||||
|
||||
|
||||
// Precodition: input is in memory, starting at 0 of kernel general segment, of the form
|
||||
// Precodition: input is in memory, starting at virt of kernel general segment, of the form
|
||||
// num_bytes, x[0], x[1], ..., x[num_bytes - 1]
|
||||
// Postcodition: output is in memory, starting at 0, of the form
|
||||
// num_blocks, block0[0], ..., block0[63], block1[0], ..., blocklast[63]
|
||||
global sha2_pad:
|
||||
// stack: retdest
|
||||
PUSH 0
|
||||
// stack: virt, retdest
|
||||
%mload_kernel_general
|
||||
// stack: num_bytes, retdest
|
||||
// STEP 1: append 1
|
||||
@ -289,7 +289,7 @@
|
||||
|
||||
// given u32 bytestring abcd return dcba
|
||||
%macro reverse_bytes_u32
|
||||
// stack: abcd
|
||||
// stack: abcd
|
||||
DUP1
|
||||
PUSH 28
|
||||
BYTE
|
||||
@ -308,11 +308,11 @@
|
||||
PUSH 31
|
||||
BYTE
|
||||
%shl_const(24)
|
||||
// stack: d000, b0, a, c00
|
||||
// stack: d000, b0, a, c00
|
||||
OR
|
||||
OR
|
||||
OR
|
||||
// stack: dcba
|
||||
// stack: dcba
|
||||
%endmacro
|
||||
|
||||
%macro reverse_bytes_u64
|
||||
|
||||
@ -65,6 +65,32 @@ pub fn run_interpreter(
|
||||
)
|
||||
}
|
||||
|
||||
pub struct InterpreterMemoryInitialization {
|
||||
pub label: String,
|
||||
pub stack: Vec<U256>,
|
||||
pub segment: Segment,
|
||||
pub memory: Vec<(usize, Vec<U256>)>,
|
||||
}
|
||||
|
||||
pub fn run_interpreter_with_memory(
|
||||
memory_init: InterpreterMemoryInitialization,
|
||||
) -> anyhow::Result<Interpreter<'static>> {
|
||||
let label = KERNEL.global_labels[&memory_init.label];
|
||||
let mut stack = memory_init.stack;
|
||||
stack.reverse();
|
||||
let mut interpreter = Interpreter::new_with_kernel(label, stack);
|
||||
for (pointer, data) in memory_init.memory {
|
||||
for (i, term) in data.iter().enumerate() {
|
||||
interpreter.generation_state.memory.set(
|
||||
MemoryAddress::new(0, memory_init.segment, pointer + i),
|
||||
*term,
|
||||
)
|
||||
}
|
||||
}
|
||||
interpreter.run()?;
|
||||
Ok(interpreter)
|
||||
}
|
||||
|
||||
pub fn run<'a>(
|
||||
code: &'a [u8],
|
||||
initial_offset: usize,
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
use std::str::FromStr;
|
||||
|
||||
use anyhow::Result;
|
||||
use blake2::Blake2b512;
|
||||
use ethereum_types::{U256, U512};
|
||||
@ -7,14 +5,16 @@ use rand::{thread_rng, Rng};
|
||||
use ripemd::{Digest, Ripemd160};
|
||||
use sha2::Sha256;
|
||||
|
||||
use crate::cpu::kernel::aggregator::KERNEL;
|
||||
use crate::cpu::kernel::interpreter::run_interpreter;
|
||||
use crate::cpu::kernel::interpreter::{
|
||||
run_interpreter_with_memory, InterpreterMemoryInitialization,
|
||||
};
|
||||
use crate::memory::segments::Segment::KernelGeneral;
|
||||
|
||||
/// Standard Sha2 implementation.
|
||||
fn sha2(input: Vec<u8>) -> U256 {
|
||||
let mut hasher = Sha256::new();
|
||||
/// Standard Blake2b implementation.
|
||||
fn blake2b(input: Vec<u8>) -> U512 {
|
||||
let mut hasher = Blake2b512::new();
|
||||
hasher.update(input);
|
||||
U256::from(&hasher.finalize()[..])
|
||||
U512::from(&hasher.finalize()[..])
|
||||
}
|
||||
|
||||
/// Standard RipeMD implementation.
|
||||
@ -24,11 +24,11 @@ fn ripemd(input: Vec<u8>) -> U256 {
|
||||
U256::from(&hasher.finalize()[..])
|
||||
}
|
||||
|
||||
/// Standard Blake2b implementation.
|
||||
fn blake2b(input: Vec<u8>) -> U512 {
|
||||
let mut hasher = Blake2b512::new();
|
||||
/// Standard Sha2 implementation.
|
||||
fn sha2(input: Vec<u8>) -> U256 {
|
||||
let mut hasher = Sha256::new();
|
||||
hasher.update(input);
|
||||
U512::from(&hasher.finalize()[..])
|
||||
U256::from(&hasher.finalize()[..])
|
||||
}
|
||||
|
||||
fn make_random_input() -> Vec<u8> {
|
||||
@ -38,109 +38,95 @@ fn make_random_input() -> Vec<u8> {
|
||||
(0..num_bytes).map(|_| rng.gen()).collect()
|
||||
}
|
||||
|
||||
fn make_custom_input() -> Vec<u8> {
|
||||
// Hardcode a custom message
|
||||
vec![
|
||||
86, 124, 206, 245, 74, 57, 250, 43, 60, 30, 254, 43, 143, 144, 242, 215, 13, 103, 237, 61,
|
||||
90, 105, 123, 250, 189, 181, 110, 192, 227, 57, 145, 46, 221, 238, 7, 181, 146, 111, 209,
|
||||
150, 31, 157, 229, 126, 206, 105, 37, 17,
|
||||
]
|
||||
}
|
||||
|
||||
fn make_input_stack(message: Vec<u8>) -> Vec<U256> {
|
||||
let mut initial_stack = vec![U256::from(message.len())];
|
||||
let bytes: Vec<U256> = message.iter().map(|&x| U256::from(x as u32)).collect();
|
||||
initial_stack.extend(bytes);
|
||||
initial_stack.push(U256::from_str("0xdeadbeef").unwrap());
|
||||
initial_stack.reverse();
|
||||
initial_stack
|
||||
fn make_interpreter_setup(
|
||||
message: Vec<u8>,
|
||||
hash_fn_label: &str,
|
||||
hash_input_virt: (usize, usize),
|
||||
) -> InterpreterMemoryInitialization {
|
||||
InterpreterMemoryInitialization {
|
||||
label: hash_fn_label.to_string(),
|
||||
stack: vec![
|
||||
U256::from(hash_input_virt.0),
|
||||
U256::from(message.len()),
|
||||
U256::from(0xdeadbeefu32),
|
||||
],
|
||||
segment: KernelGeneral,
|
||||
memory: vec![(
|
||||
hash_input_virt.1,
|
||||
message.iter().map(|&x| U256::from(x as u32)).collect(),
|
||||
)],
|
||||
}
|
||||
}
|
||||
|
||||
fn combine_u256s(hi: U256, lo: U256) -> U512 {
|
||||
let mut result = U512::from(hi);
|
||||
result <<= 256;
|
||||
result += U512::from(lo);
|
||||
result
|
||||
U512::from(lo) + (U512::from(hi) << 256)
|
||||
}
|
||||
|
||||
fn prepare_test<T>(
|
||||
hash_fn_label: &str,
|
||||
hash_input_virt: (usize, usize),
|
||||
standard_implementation: &dyn Fn(Vec<u8>) -> T,
|
||||
) -> Result<(T, T, Vec<U256>, Vec<U256>)> {
|
||||
) -> Result<(T, Vec<U256>)> {
|
||||
// Make the input.
|
||||
let message_random = make_random_input();
|
||||
let message_custom = make_custom_input();
|
||||
let message = make_random_input();
|
||||
|
||||
// Hash the message using a standard implementation.
|
||||
let expected_random = standard_implementation(message_random.clone());
|
||||
let expected_custom = standard_implementation(message_custom.clone());
|
||||
let expected = standard_implementation(message.clone());
|
||||
|
||||
// Load the message onto the stack.
|
||||
let initial_stack_random = make_input_stack(message_random);
|
||||
let initial_stack_custom = make_input_stack(message_custom);
|
||||
// Load the message into the kernel.
|
||||
let interpreter_setup = make_interpreter_setup(message, hash_fn_label, hash_input_virt);
|
||||
|
||||
// Make the kernel.
|
||||
let kernel_function = KERNEL.global_labels[hash_fn_label];
|
||||
// Run the interpeter
|
||||
let result = run_interpreter_with_memory(interpreter_setup).unwrap();
|
||||
|
||||
// Run the kernel code.
|
||||
let result_random = run_interpreter(kernel_function, initial_stack_random)?;
|
||||
let result_custom = run_interpreter(kernel_function, initial_stack_custom)?;
|
||||
|
||||
Ok((
|
||||
expected_random,
|
||||
expected_custom,
|
||||
result_random.stack().to_vec(),
|
||||
result_custom.stack().to_vec(),
|
||||
))
|
||||
Ok((expected, result.stack().to_vec()))
|
||||
}
|
||||
|
||||
fn test_hash_256(
|
||||
hash_fn_label: &str,
|
||||
hash_input_virt: (usize, usize),
|
||||
standard_implementation: &dyn Fn(Vec<u8>) -> U256,
|
||||
) -> Result<()> {
|
||||
let (expected_random, expected_custom, random_stack, custom_stack) =
|
||||
prepare_test(hash_fn_label, standard_implementation).unwrap();
|
||||
let (expected, result_stack) =
|
||||
prepare_test(hash_fn_label, hash_input_virt, standard_implementation).unwrap();
|
||||
|
||||
// Extract the final output.
|
||||
let actual_random = random_stack[0];
|
||||
let actual_custom = custom_stack[0];
|
||||
let actual = result_stack[0];
|
||||
|
||||
// Check that the result is correct.
|
||||
assert_eq!(expected_random, actual_random);
|
||||
assert_eq!(expected_custom, actual_custom);
|
||||
assert_eq!(expected, actual);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn test_hash_512(
|
||||
hash_fn_label: &str,
|
||||
hash_input_virt: (usize, usize),
|
||||
standard_implementation: &dyn Fn(Vec<u8>) -> U512,
|
||||
) -> Result<()> {
|
||||
let (expected_random, expected_custom, random_stack, custom_stack) =
|
||||
prepare_test(hash_fn_label, standard_implementation).unwrap();
|
||||
let (expected, result_stack) =
|
||||
prepare_test(hash_fn_label, hash_input_virt, standard_implementation).unwrap();
|
||||
|
||||
// Extract the final output.
|
||||
let actual_random = combine_u256s(random_stack[0], random_stack[1]);
|
||||
let actual_custom = combine_u256s(custom_stack[0], custom_stack[1]);
|
||||
let actual = combine_u256s(result_stack[0], result_stack[1]);
|
||||
|
||||
// Check that the result is correct.
|
||||
assert_eq!(expected_random, actual_random);
|
||||
assert_eq!(expected_custom, actual_custom);
|
||||
assert_eq!(expected, actual);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sha2() -> Result<()> {
|
||||
test_hash_256("sha2", &sha2)
|
||||
fn test_blake2b() -> Result<()> {
|
||||
test_hash_512("blake2b", (0, 2), &blake2b)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ripemd() -> Result<()> {
|
||||
test_hash_256("ripemd_stack", &ripemd)
|
||||
test_hash_256("ripemd", (200, 200), &ripemd)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_blake2b() -> Result<()> {
|
||||
test_hash_512("blake2b", &blake2b)
|
||||
fn test_sha2() -> Result<()> {
|
||||
test_hash_256("sha2", (0, 1), &sha2)
|
||||
}
|
||||
|
||||
@ -7,7 +7,6 @@ mod fields;
|
||||
mod hash;
|
||||
mod mpt;
|
||||
mod packing;
|
||||
mod ripemd;
|
||||
mod rlp;
|
||||
mod transaction_parsing;
|
||||
|
||||
|
||||
@ -1,56 +0,0 @@
|
||||
use anyhow::Result;
|
||||
use ethereum_types::U256;
|
||||
use itertools::Itertools;
|
||||
|
||||
use crate::cpu::kernel::aggregator::KERNEL;
|
||||
use crate::cpu::kernel::interpreter::run_interpreter;
|
||||
|
||||
fn make_input(word: &str) -> Vec<u32> {
|
||||
let mut input: Vec<u32> = vec![word.len().try_into().unwrap()];
|
||||
input.append(&mut word.as_bytes().iter().map(|&x| x as u32).collect_vec());
|
||||
input.push(u32::from_str_radix("deadbeef", 16).unwrap());
|
||||
input
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ripemd_reference() -> Result<()> {
|
||||
let reference = vec![
|
||||
("", "0x9c1185a5c5e9fc54612808977ee8f548b2258d31"),
|
||||
("a", "0x0bdc9d2d256b3ee9daae347be6f4dc835a467ffe"),
|
||||
("abc", "0x8eb208f7e05d987a9b044a8e98c6b087f15a0bfc"),
|
||||
(
|
||||
"message digest",
|
||||
"0x5d0689ef49d2fae572b881b123a85ffa21595f36",
|
||||
),
|
||||
(
|
||||
"abcdefghijklmnopqrstuvwxyz",
|
||||
"0xf71c27109c692c1b56bbdceb5b9d2865b3708dbc",
|
||||
),
|
||||
(
|
||||
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
|
||||
"0x12a053384a9c0c88e405a06c27dcf49ada62eb2b",
|
||||
),
|
||||
(
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
|
||||
"0xb0e20b6e3116640286ed3a87a5713079b21f5189",
|
||||
),
|
||||
(
|
||||
"12345678901234567890123456789012345678901234567890123456789012345678901234567890",
|
||||
"0x9b752e45573d4b39f4dbd3323cab82bf63326bfb",
|
||||
),
|
||||
];
|
||||
|
||||
for (x, y) in reference {
|
||||
let input: Vec<u32> = make_input(x);
|
||||
let expected = U256::from(y);
|
||||
|
||||
let initial_offset = KERNEL.global_labels["ripemd_stack"];
|
||||
let initial_stack: Vec<U256> = input.iter().map(|&x| U256::from(x)).rev().collect();
|
||||
let final_stack: Vec<U256> = run_interpreter(initial_offset, initial_stack)?
|
||||
.stack()
|
||||
.to_vec();
|
||||
let actual = final_stack[0];
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
#[allow(dead_code)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Ord, PartialOrd, Debug)]
|
||||
pub(crate) enum Segment {
|
||||
pub enum Segment {
|
||||
/// Contains EVM bytecode.
|
||||
Code = 0,
|
||||
/// The program stack.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user