mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-05 23:33:07 +00:00
commit
4fc7f3cd6e
@ -32,6 +32,7 @@ global decode_rlp_string_len:
|
|||||||
JUMP
|
JUMP
|
||||||
|
|
||||||
decode_rlp_string_len_medium:
|
decode_rlp_string_len_medium:
|
||||||
|
JUMPDEST
|
||||||
// String is 0-55 bytes long. First byte contains the len.
|
// String is 0-55 bytes long. First byte contains the len.
|
||||||
// stack: first_byte, pos, retdest
|
// stack: first_byte, pos, retdest
|
||||||
%sub_const(0x80)
|
%sub_const(0x80)
|
||||||
@ -43,6 +44,7 @@ decode_rlp_string_len_medium:
|
|||||||
JUMP
|
JUMP
|
||||||
|
|
||||||
decode_rlp_string_len_large:
|
decode_rlp_string_len_large:
|
||||||
|
JUMPDEST
|
||||||
// String is >55 bytes long. First byte contains the len of the len.
|
// String is >55 bytes long. First byte contains the len of the len.
|
||||||
// stack: first_byte, pos, retdest
|
// stack: first_byte, pos, retdest
|
||||||
%sub_const(0xb7)
|
%sub_const(0xb7)
|
||||||
|
|||||||
@ -4,6 +4,7 @@ use anyhow::{anyhow, bail};
|
|||||||
use ethereum_types::{BigEndianHash, U256, U512};
|
use ethereum_types::{BigEndianHash, U256, U512};
|
||||||
use keccak_hash::keccak;
|
use keccak_hash::keccak;
|
||||||
|
|
||||||
|
use crate::cpu::kernel::aggregator::KERNEL;
|
||||||
use crate::cpu::kernel::assembler::Kernel;
|
use crate::cpu::kernel::assembler::Kernel;
|
||||||
use crate::cpu::kernel::prover_input::ProverInputFn;
|
use crate::cpu::kernel::prover_input::ProverInputFn;
|
||||||
use crate::generation::memory::{MemoryContextState, MemorySegmentState};
|
use crate::generation::memory::{MemoryContextState, MemorySegmentState};
|
||||||
@ -14,7 +15,7 @@ const HALT_OFFSET: usize = 0xdeadbeef;
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) struct InterpreterMemory {
|
pub(crate) struct InterpreterMemory {
|
||||||
context_memory: Vec<MemoryContextState>,
|
pub(crate) context_memory: Vec<MemoryContextState>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for InterpreterMemory {
|
impl Default for InterpreterMemory {
|
||||||
@ -51,13 +52,14 @@ pub struct Interpreter<'a> {
|
|||||||
jumpdests: Vec<usize>,
|
jumpdests: Vec<usize>,
|
||||||
offset: usize,
|
offset: usize,
|
||||||
context: usize,
|
context: usize,
|
||||||
memory: InterpreterMemory,
|
pub(crate) memory: InterpreterMemory,
|
||||||
prover_inputs_map: &'a HashMap<usize, ProverInputFn>,
|
prover_inputs_map: &'a HashMap<usize, ProverInputFn>,
|
||||||
prover_inputs: Vec<U256>,
|
prover_inputs: Vec<U256>,
|
||||||
running: bool,
|
running: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run_with_kernel(
|
pub fn run_with_kernel(
|
||||||
|
// TODO: Remove param and just use KERNEL.
|
||||||
kernel: &Kernel,
|
kernel: &Kernel,
|
||||||
initial_offset: usize,
|
initial_offset: usize,
|
||||||
initial_stack: Vec<U256>,
|
initial_stack: Vec<U256>,
|
||||||
@ -76,24 +78,45 @@ pub fn run<'a>(
|
|||||||
initial_stack: Vec<U256>,
|
initial_stack: Vec<U256>,
|
||||||
prover_inputs: &'a HashMap<usize, ProverInputFn>,
|
prover_inputs: &'a HashMap<usize, ProverInputFn>,
|
||||||
) -> anyhow::Result<Interpreter<'a>> {
|
) -> anyhow::Result<Interpreter<'a>> {
|
||||||
let mut interpreter = Interpreter {
|
let mut interpreter = Interpreter::new(code, initial_offset, initial_stack, prover_inputs);
|
||||||
jumpdests: find_jumpdests(code),
|
interpreter.run()?;
|
||||||
offset: initial_offset,
|
|
||||||
memory: InterpreterMemory::with_code_and_stack(code, initial_stack),
|
|
||||||
prover_inputs_map: prover_inputs,
|
|
||||||
prover_inputs: Vec::new(),
|
|
||||||
context: 0,
|
|
||||||
running: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
while interpreter.running {
|
|
||||||
interpreter.run_opcode()?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(interpreter)
|
Ok(interpreter)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Interpreter<'a> {
|
impl<'a> Interpreter<'a> {
|
||||||
|
pub(crate) fn new_with_kernel(initial_offset: usize, initial_stack: Vec<U256>) -> Self {
|
||||||
|
Self::new(
|
||||||
|
&KERNEL.code,
|
||||||
|
initial_offset,
|
||||||
|
initial_stack,
|
||||||
|
&KERNEL.prover_inputs,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn new(
|
||||||
|
code: &'a [u8],
|
||||||
|
initial_offset: usize,
|
||||||
|
initial_stack: Vec<U256>,
|
||||||
|
prover_inputs: &'a HashMap<usize, ProverInputFn>,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
jumpdests: find_jumpdests(code),
|
||||||
|
offset: initial_offset,
|
||||||
|
memory: InterpreterMemory::with_code_and_stack(code, initial_stack),
|
||||||
|
prover_inputs_map: prover_inputs,
|
||||||
|
prover_inputs: Vec::new(),
|
||||||
|
context: 0,
|
||||||
|
running: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn run(&mut self) -> anyhow::Result<()> {
|
||||||
|
while self.running {
|
||||||
|
self.run_opcode()?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn code(&self) -> &MemorySegmentState {
|
fn code(&self) -> &MemorySegmentState {
|
||||||
&self.memory.context_memory[self.context].segments[Segment::Code as usize]
|
&self.memory.context_memory[self.context].segments[Segment::Code as usize]
|
||||||
}
|
}
|
||||||
@ -156,7 +179,7 @@ impl<'a> Interpreter<'a> {
|
|||||||
0x18 => self.run_xor(), // "XOR",
|
0x18 => self.run_xor(), // "XOR",
|
||||||
0x19 => self.run_not(), // "NOT",
|
0x19 => self.run_not(), // "NOT",
|
||||||
0x1a => todo!(), // "BYTE",
|
0x1a => todo!(), // "BYTE",
|
||||||
0x1b => todo!(), // "SHL",
|
0x1b => self.run_shl(), // "SHL",
|
||||||
0x1c => todo!(), // "SHR",
|
0x1c => todo!(), // "SHR",
|
||||||
0x1d => todo!(), // "SAR",
|
0x1d => todo!(), // "SAR",
|
||||||
0x20 => self.run_keccak256(), // "KECCAK256",
|
0x20 => self.run_keccak256(), // "KECCAK256",
|
||||||
@ -339,6 +362,12 @@ impl<'a> Interpreter<'a> {
|
|||||||
self.push(!x);
|
self.push(!x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn run_shl(&mut self) {
|
||||||
|
let shift = self.pop();
|
||||||
|
let x = self.pop();
|
||||||
|
self.push(x << shift);
|
||||||
|
}
|
||||||
|
|
||||||
fn run_keccak256(&mut self) {
|
fn run_keccak256(&mut self) {
|
||||||
let offset = self.pop().as_usize();
|
let offset = self.pop().as_usize();
|
||||||
let size = self.pop().as_usize();
|
let size = self.pop().as_usize();
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
mod curve_ops;
|
mod curve_ops;
|
||||||
mod ecrecover;
|
mod ecrecover;
|
||||||
mod exp;
|
mod exp;
|
||||||
|
mod rlp;
|
||||||
|
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
|||||||
129
evm/src/cpu/kernel/tests/rlp.rs
Normal file
129
evm/src/cpu/kernel/tests/rlp.rs
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
use anyhow::Result;
|
||||||
|
use ethereum_types::U256;
|
||||||
|
|
||||||
|
use crate::cpu::kernel::aggregator::KERNEL;
|
||||||
|
use crate::cpu::kernel::interpreter::Interpreter;
|
||||||
|
use crate::memory::segments::Segment;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_decode_rlp_string_len_short() -> Result<()> {
|
||||||
|
let decode_rlp_string_len = KERNEL.global_labels["decode_rlp_string_len"];
|
||||||
|
|
||||||
|
let initial_stack = vec![U256::from_str("0xdeadbeef")?, 2.into()];
|
||||||
|
let mut interpreter = Interpreter::new_with_kernel(decode_rlp_string_len, initial_stack);
|
||||||
|
|
||||||
|
// A couple dummy bytes, followed by "0x70" which is its own encoding.
|
||||||
|
set_rlp_memory(&mut interpreter, vec![123, 234, 0x70]);
|
||||||
|
|
||||||
|
interpreter.run()?;
|
||||||
|
let expected_stack = vec![1.into(), 2.into()]; // len, pos
|
||||||
|
assert_eq!(interpreter.stack(), expected_stack);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_decode_rlp_string_len_medium() -> Result<()> {
|
||||||
|
let decode_rlp_string_len = KERNEL.global_labels["decode_rlp_string_len"];
|
||||||
|
|
||||||
|
let initial_stack = vec![U256::from_str("0xdeadbeef")?, 2.into()];
|
||||||
|
let mut interpreter = Interpreter::new_with_kernel(decode_rlp_string_len, initial_stack);
|
||||||
|
|
||||||
|
// A couple dummy bytes, followed by the RLP encoding of "1 2 3 4 5".
|
||||||
|
set_rlp_memory(&mut interpreter, vec![123, 234, 0x85, 1, 2, 3, 4, 5]);
|
||||||
|
|
||||||
|
interpreter.run()?;
|
||||||
|
let expected_stack = vec![5.into(), 3.into()]; // len, pos
|
||||||
|
assert_eq!(interpreter.stack(), expected_stack);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_decode_rlp_string_len_long() -> Result<()> {
|
||||||
|
let decode_rlp_string_len = KERNEL.global_labels["decode_rlp_string_len"];
|
||||||
|
|
||||||
|
let initial_stack = vec![U256::from_str("0xdeadbeef")?, 2.into()];
|
||||||
|
let mut interpreter = Interpreter::new_with_kernel(decode_rlp_string_len, initial_stack);
|
||||||
|
|
||||||
|
// The RLP encoding of the string "1 2 3 ... 56".
|
||||||
|
set_rlp_memory(
|
||||||
|
&mut interpreter,
|
||||||
|
vec![
|
||||||
|
123, 234, 0xb8, 56, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
|
||||||
|
20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
|
||||||
|
42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
interpreter.run()?;
|
||||||
|
let expected_stack = vec![56.into(), 4.into()]; // len, pos
|
||||||
|
assert_eq!(interpreter.stack(), expected_stack);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_decode_rlp_list_len_short() -> Result<()> {
|
||||||
|
let decode_rlp_list_len = KERNEL.global_labels["decode_rlp_list_len"];
|
||||||
|
|
||||||
|
let initial_stack = vec![U256::from_str("0xdeadbeef")?, 0.into()];
|
||||||
|
let mut interpreter = Interpreter::new_with_kernel(decode_rlp_list_len, initial_stack);
|
||||||
|
|
||||||
|
// The RLP encoding of [1, 2, [3, 4]].
|
||||||
|
set_rlp_memory(&mut interpreter, vec![0xc5, 1, 2, 0xc2, 3, 4]);
|
||||||
|
|
||||||
|
interpreter.run()?;
|
||||||
|
let expected_stack = vec![5.into(), 1.into()]; // len, pos
|
||||||
|
assert_eq!(interpreter.stack(), expected_stack);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_decode_rlp_list_len_long() -> Result<()> {
|
||||||
|
let decode_rlp_list_len = KERNEL.global_labels["decode_rlp_list_len"];
|
||||||
|
|
||||||
|
let initial_stack = vec![U256::from_str("0xdeadbeef")?, 0.into()];
|
||||||
|
let mut interpreter = Interpreter::new_with_kernel(decode_rlp_list_len, initial_stack);
|
||||||
|
|
||||||
|
// The RLP encoding of [1, ..., 56].
|
||||||
|
set_rlp_memory(
|
||||||
|
&mut interpreter,
|
||||||
|
vec![
|
||||||
|
0xf8, 56, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
|
||||||
|
22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
|
||||||
|
44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
interpreter.run()?;
|
||||||
|
let expected_stack = vec![56.into(), 2.into()]; // len, pos
|
||||||
|
assert_eq!(interpreter.stack(), expected_stack);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_decode_rlp_scalar() -> Result<()> {
|
||||||
|
let decode_rlp_scalar = KERNEL.global_labels["decode_rlp_scalar"];
|
||||||
|
|
||||||
|
let initial_stack = vec![U256::from_str("0xdeadbeef")?, 0.into()];
|
||||||
|
let mut interpreter = Interpreter::new_with_kernel(decode_rlp_scalar, initial_stack);
|
||||||
|
|
||||||
|
// The RLP encoding of "12 34 56".
|
||||||
|
set_rlp_memory(&mut interpreter, vec![0x83, 0x12, 0x34, 0x56]);
|
||||||
|
|
||||||
|
interpreter.run()?;
|
||||||
|
let expected_stack = vec![0x123456.into(), 4.into()]; // scalar, pos
|
||||||
|
assert_eq!(interpreter.stack(), expected_stack);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_rlp_memory(interpreter: &mut Interpreter, rlp: Vec<u8>) {
|
||||||
|
interpreter.memory.context_memory[0].segments[Segment::RlpRaw as usize].content =
|
||||||
|
rlp.into_iter().map(U256::from).collect();
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user