mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-02-18 12:53:08 +00:00
simplify ripe md test
This commit is contained in:
parent
f3946f75bf
commit
bce867188c
@ -57,7 +57,6 @@ pub(crate) fn combined_kernel() -> Kernel {
|
||||
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"),
|
||||
|
||||
@ -7,40 +7,47 @@
|
||||
/// 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
|
||||
/// ripemd is called on
|
||||
/// // stack: length
|
||||
///
|
||||
/// 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
|
||||
%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
|
||||
%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
|
||||
%jump(ripemd_update)
|
||||
|
||||
ripemd_1:
|
||||
// stack: STATE, count, length , virt , LABELS
|
||||
DUP7
|
||||
@ -105,3 +112,20 @@ global process:
|
||||
// stack: 56 + 64*(t > 55), t
|
||||
SUB
|
||||
%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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -65,6 +65,32 @@ pub fn run_interpreter(
|
||||
)
|
||||
}
|
||||
|
||||
pub struct InterpreterSetup {
|
||||
pub label: String,
|
||||
pub stack: Vec<U256>,
|
||||
pub segment: Segment,
|
||||
pub memory: Vec<(usize, Vec<U256>)>,
|
||||
}
|
||||
|
||||
impl InterpreterSetup {
|
||||
pub fn run(self) -> anyhow::Result<Interpreter<'static>> {
|
||||
let label = KERNEL.global_labels[&self.label];
|
||||
let mut stack = self.stack;
|
||||
stack.reverse();
|
||||
let mut interpreter = Interpreter::new_with_kernel(label, stack);
|
||||
for (pointer, data) in self.memory {
|
||||
for (i, term) in data.iter().enumerate() {
|
||||
interpreter
|
||||
.generation_state
|
||||
.memory
|
||||
.set(MemoryAddress::new(0, self.segment, pointer + i), *term)
|
||||
}
|
||||
}
|
||||
interpreter.run()?;
|
||||
Ok(interpreter)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run<'a>(
|
||||
code: &'a [u8],
|
||||
initial_offset: usize,
|
||||
@ -223,6 +249,15 @@ impl<'a> Interpreter<'a> {
|
||||
.content
|
||||
}
|
||||
|
||||
pub fn extract_kernel_memory(self, locs: Vec<MemoryAddress>) -> Vec<U256> {
|
||||
let mut output: Vec<U256> = vec![];
|
||||
for loc in locs {
|
||||
let term = self.generation_state.memory.get(loc);
|
||||
output.push(term);
|
||||
}
|
||||
output
|
||||
}
|
||||
|
||||
pub(crate) fn push(&mut self, x: U256) {
|
||||
self.stack_mut().push(x);
|
||||
self.generation_state.registers.stack_len += 1;
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
use std::str::FromStr;
|
||||
|
||||
use anyhow::Result;
|
||||
use blake2::Blake2b512;
|
||||
use ethereum_types::{U256, U512};
|
||||
@ -7,14 +5,14 @@ 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::InterpreterSetup;
|
||||
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 +22,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> {
|
||||
@ -47,15 +45,6 @@ fn make_custom_input() -> Vec<u8> {
|
||||
]
|
||||
}
|
||||
|
||||
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 combine_u256s(hi: U256, lo: U256) -> U512 {
|
||||
let mut result = U512::from(hi);
|
||||
result <<= 256;
|
||||
@ -75,16 +64,46 @@ fn prepare_test<T>(
|
||||
let expected_random = standard_implementation(message_random.clone());
|
||||
let expected_custom = standard_implementation(message_custom.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);
|
||||
let inp: usize = 136;
|
||||
|
||||
// Make the kernel.
|
||||
let kernel_function = KERNEL.global_labels[hash_fn_label];
|
||||
// Load the message into the kernel.
|
||||
let interpreter_setup_random = InterpreterSetup {
|
||||
label: hash_fn_label.to_string(),
|
||||
stack: vec![
|
||||
U256::from(inp),
|
||||
U256::from(message_random.len()),
|
||||
U256::from(0xdeadbeefu32),
|
||||
],
|
||||
segment: KernelGeneral,
|
||||
memory: vec![(
|
||||
inp,
|
||||
message_random
|
||||
.iter()
|
||||
.map(|&x| U256::from(x as u32))
|
||||
.collect(),
|
||||
)],
|
||||
};
|
||||
|
||||
let interpreter_setup_custom = InterpreterSetup {
|
||||
label: hash_fn_label.to_string(),
|
||||
stack: vec![
|
||||
U256::from(inp),
|
||||
U256::from(message_custom.len()),
|
||||
U256::from(0xdeadbeefu32),
|
||||
],
|
||||
segment: KernelGeneral,
|
||||
memory: vec![(
|
||||
inp,
|
||||
message_custom
|
||||
.iter()
|
||||
.map(|&x| U256::from(x as u32))
|
||||
.collect(),
|
||||
)],
|
||||
};
|
||||
|
||||
// Run the kernel code.
|
||||
let result_random = run_interpreter(kernel_function, initial_stack_random)?;
|
||||
let result_custom = run_interpreter(kernel_function, initial_stack_custom)?;
|
||||
let result_random = interpreter_setup_random.run().unwrap();
|
||||
let result_custom = interpreter_setup_custom.run().unwrap();
|
||||
|
||||
Ok((
|
||||
expected_random,
|
||||
@ -130,17 +149,17 @@ fn test_hash_512(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sha2() -> Result<()> {
|
||||
test_hash_256("sha2", &sha2)
|
||||
}
|
||||
// #[test]
|
||||
// fn test_blake2b() -> Result<()> {
|
||||
// test_hash_512("blake2b", &blake2b)
|
||||
// }
|
||||
|
||||
#[test]
|
||||
fn test_ripemd() -> Result<()> {
|
||||
test_hash_256("ripemd_stack", &ripemd)
|
||||
test_hash_256("ripemd", &ripemd)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_blake2b() -> Result<()> {
|
||||
test_hash_512("blake2b", &blake2b)
|
||||
}
|
||||
// #[test]
|
||||
// fn test_sha2() -> Result<()> {
|
||||
// test_hash_256("sha2", &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(())
|
||||
}
|
||||
35
evm/src/cpu/kernel/tests/test_utils.rs
Normal file
35
evm/src/cpu/kernel/tests/test_utils.rs
Normal file
@ -0,0 +1,35 @@
|
||||
use std::ops::Range;
|
||||
|
||||
use anyhow::Result;
|
||||
use ethereum_types::U256;
|
||||
|
||||
use crate::cpu::kernel::aggregator::KERNEL;
|
||||
use crate::cpu::kernel::interpreter::Interpreter;
|
||||
use crate::memory::segments::Segment;
|
||||
use crate::witness::memory::MemoryAddress;
|
||||
|
||||
pub struct InterpreterSetup {
|
||||
pub label: String,
|
||||
pub stack: Vec<U256>,
|
||||
pub segment: Segment,
|
||||
pub memory: Vec<(usize, Vec<U256>)>,
|
||||
}
|
||||
|
||||
impl InterpreterSetup {
|
||||
pub fn run(self) -> Result<Interpreter<'static>> {
|
||||
let label = KERNEL.global_labels[&self.label];
|
||||
let mut stack = self.stack;
|
||||
stack.reverse();
|
||||
let mut interpreter = Interpreter::new_with_kernel(label, stack);
|
||||
for (pointer, data) in self.memory {
|
||||
for (i, term) in data.iter().enumerate() {
|
||||
interpreter
|
||||
.generation_state
|
||||
.memory
|
||||
.set(MemoryAddress::new(0, self.segment, pointer + i), *term)
|
||||
}
|
||||
}
|
||||
interpreter.run()?;
|
||||
Ok(interpreter)
|
||||
}
|
||||
}
|
||||
@ -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