Merge pull request #884 from mir-protocol/evm-kernel-tests

This commit is contained in:
Dima V 2023-02-17 03:20:04 +01:00 committed by GitHub
commit 6f2d99c7bc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 187 additions and 378 deletions

View File

@ -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"),

View 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)

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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)
}

View File

@ -7,7 +7,6 @@ mod fields;
mod hash;
mod mpt;
mod packing;
mod ripemd;
mod rlp;
mod transaction_parsing;

View File

@ -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(())
}

View File

@ -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.