mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-04 23:03:08 +00:00
Test for parsing type 0 transactions
I made a couple related changes to `Interpreter`: - Only enforce the `JUMPDEST` rule if we're in kernel mode. - Convenience methods for dealing with the RLP and txn field segments of memory.
This commit is contained in:
parent
4fc7f3cd6e
commit
3618793706
@ -7,11 +7,12 @@ use keccak_hash::keccak;
|
||||
use crate::cpu::kernel::aggregator::KERNEL;
|
||||
use crate::cpu::kernel::assembler::Kernel;
|
||||
use crate::cpu::kernel::prover_input::ProverInputFn;
|
||||
use crate::cpu::kernel::txn_fields::NormalizedTxnField;
|
||||
use crate::generation::memory::{MemoryContextState, MemorySegmentState};
|
||||
use crate::memory::segments::Segment;
|
||||
|
||||
/// Halt interpreter execution whenever a jump to this offset is done.
|
||||
const HALT_OFFSET: usize = 0xdeadbeef;
|
||||
const DEFAULT_HALT_OFFSET: usize = 0xdeadbeef;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct InterpreterMemory {
|
||||
@ -49,12 +50,14 @@ impl InterpreterMemory {
|
||||
}
|
||||
|
||||
pub struct Interpreter<'a> {
|
||||
kernel_mode: bool,
|
||||
jumpdests: Vec<usize>,
|
||||
offset: usize,
|
||||
context: usize,
|
||||
pub(crate) memory: InterpreterMemory,
|
||||
prover_inputs_map: &'a HashMap<usize, ProverInputFn>,
|
||||
prover_inputs: Vec<U256>,
|
||||
pub(crate) halt_offsets: Vec<usize>,
|
||||
running: bool,
|
||||
}
|
||||
|
||||
@ -100,12 +103,14 @@ impl<'a> Interpreter<'a> {
|
||||
prover_inputs: &'a HashMap<usize, ProverInputFn>,
|
||||
) -> Self {
|
||||
Self {
|
||||
kernel_mode: true,
|
||||
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,
|
||||
halt_offsets: vec![DEFAULT_HALT_OFFSET],
|
||||
running: true,
|
||||
}
|
||||
}
|
||||
@ -128,6 +133,15 @@ impl<'a> Interpreter<'a> {
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
|
||||
pub(crate) fn get_txn_field(&self, field: NormalizedTxnField) -> U256 {
|
||||
self.memory.context_memory[0].segments[Segment::TxnFields as usize].content[field as usize]
|
||||
}
|
||||
|
||||
pub(crate) fn set_rlp_memory(&mut self, rlp: Vec<u8>) {
|
||||
self.memory.context_memory[0].segments[Segment::RlpRaw as usize].content =
|
||||
rlp.into_iter().map(U256::from).collect();
|
||||
}
|
||||
|
||||
fn incr(&mut self, n: usize) {
|
||||
self.offset += n;
|
||||
}
|
||||
@ -435,24 +449,27 @@ impl<'a> Interpreter<'a> {
|
||||
|
||||
fn run_jump(&mut self) {
|
||||
let x = self.pop().as_usize();
|
||||
self.offset = x;
|
||||
if self.offset == HALT_OFFSET {
|
||||
self.running = false;
|
||||
} else if self.jumpdests.binary_search(&self.offset).is_err() {
|
||||
panic!("Destination is not a JUMPDEST.");
|
||||
}
|
||||
self.jump_to(x);
|
||||
}
|
||||
|
||||
fn run_jumpi(&mut self) {
|
||||
let x = self.pop().as_usize();
|
||||
let b = self.pop();
|
||||
if !b.is_zero() {
|
||||
self.offset = x;
|
||||
if self.offset == HALT_OFFSET {
|
||||
self.running = false;
|
||||
} else if self.jumpdests.binary_search(&self.offset).is_err() {
|
||||
panic!("Destination is not a JUMPDEST.");
|
||||
}
|
||||
self.jump_to(x);
|
||||
}
|
||||
}
|
||||
|
||||
fn jump_to(&mut self, offset: usize) {
|
||||
// The JUMPDEST rule is not enforced in kernel mode.
|
||||
if !self.kernel_mode && self.jumpdests.binary_search(&offset).is_err() {
|
||||
panic!("Destination is not a JUMPDEST.");
|
||||
}
|
||||
|
||||
self.offset = offset;
|
||||
|
||||
if self.halt_offsets.contains(&offset) {
|
||||
self.running = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -2,6 +2,7 @@ mod curve_ops;
|
||||
mod ecrecover;
|
||||
mod exp;
|
||||
mod rlp;
|
||||
mod type_0_txn;
|
||||
|
||||
use std::str::FromStr;
|
||||
|
||||
|
||||
@ -15,7 +15,7 @@ fn test_decode_rlp_string_len_short() -> Result<()> {
|
||||
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.set_rlp_memory(vec![123, 234, 0x70]);
|
||||
|
||||
interpreter.run()?;
|
||||
let expected_stack = vec![1.into(), 2.into()]; // len, pos
|
||||
@ -32,7 +32,7 @@ fn test_decode_rlp_string_len_medium() -> Result<()> {
|
||||
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.set_rlp_memory(vec![123, 234, 0x85, 1, 2, 3, 4, 5]);
|
||||
|
||||
interpreter.run()?;
|
||||
let expected_stack = vec![5.into(), 3.into()]; // len, pos
|
||||
@ -49,14 +49,11 @@ fn test_decode_rlp_string_len_long() -> Result<()> {
|
||||
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.set_rlp_memory(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
|
||||
@ -73,7 +70,7 @@ fn test_decode_rlp_list_len_short() -> Result<()> {
|
||||
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.set_rlp_memory(vec![0xc5, 1, 2, 0xc2, 3, 4]);
|
||||
|
||||
interpreter.run()?;
|
||||
let expected_stack = vec![5.into(), 1.into()]; // len, pos
|
||||
@ -90,14 +87,11 @@ fn test_decode_rlp_list_len_long() -> Result<()> {
|
||||
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.set_rlp_memory(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
|
||||
@ -114,7 +108,7 @@ fn test_decode_rlp_scalar() -> Result<()> {
|
||||
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.set_rlp_memory(vec![0x83, 0x12, 0x34, 0x56]);
|
||||
|
||||
interpreter.run()?;
|
||||
let expected_stack = vec![0x123456.into(), 4.into()]; // scalar, pos
|
||||
@ -122,8 +116,3 @@ fn test_decode_rlp_scalar() -> Result<()> {
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
63
evm/src/cpu/kernel/tests/type_0_txn.rs
Normal file
63
evm/src/cpu/kernel/tests/type_0_txn.rs
Normal file
@ -0,0 +1,63 @@
|
||||
use std::str::FromStr;
|
||||
|
||||
use anyhow::Result;
|
||||
use ethereum_types::U256;
|
||||
use hex_literal::hex;
|
||||
use NormalizedTxnField::*;
|
||||
|
||||
use crate::cpu::kernel::aggregator::KERNEL;
|
||||
use crate::cpu::kernel::interpreter::Interpreter;
|
||||
use crate::cpu::kernel::tests::rlp::set_rlp_memory;
|
||||
use crate::cpu::kernel::txn_fields::NormalizedTxnField;
|
||||
|
||||
#[test]
|
||||
fn process_type_0_txn() -> Result<()> {
|
||||
let process_type_0_txn = KERNEL.global_labels["process_type_0_txn"];
|
||||
let process_normalized_txn = KERNEL.global_labels["process_normalized_txn"];
|
||||
|
||||
let mut interpreter = Interpreter::new_with_kernel(process_type_0_txn, vec![]);
|
||||
|
||||
// When we reach process_normalized_txn, we're done with parsing and normalizing.
|
||||
// Processing normalized transactions is outside the scope of this test.
|
||||
interpreter.halt_offsets.push(process_normalized_txn);
|
||||
|
||||
// Generated with py-evm:
|
||||
// unsigned_txn = chain.create_unsigned_transaction(
|
||||
// nonce=5,
|
||||
// gas_price=10,
|
||||
// gas=22_000,
|
||||
// to=constants.ZERO_ADDRESS,
|
||||
// value=100,
|
||||
// data=b'\x42\x42',
|
||||
// )
|
||||
// my_txn = unsigned_txn.as_signed_transaction(my_sk)
|
||||
// rlp.encode(my_txn)
|
||||
interpreter.set_rlp_memory(hex!("f861050a8255f0940000000000000000000000000000000000000000648242421ca07c5c61ed975ebd286f6b027b8c504842e50a47d318e1e801719dd744fe93e6c6a01e7b5119b57dd54e175ff2f055c91f3ab1b53eba0b2c184f347cdff0e745aca2").to_vec());
|
||||
|
||||
interpreter.run()?;
|
||||
|
||||
assert_eq!(interpreter.get_txn_field(ChainIdPresent), 0.into());
|
||||
assert_eq!(interpreter.get_txn_field(ChainId), 0.into());
|
||||
assert_eq!(interpreter.get_txn_field(Nonce), 5.into());
|
||||
assert_eq!(interpreter.get_txn_field(MaxPriorityFeePerGas), 10.into());
|
||||
assert_eq!(interpreter.get_txn_field(MaxPriorityFeePerGas), 10.into());
|
||||
assert_eq!(interpreter.get_txn_field(MaxFeePerGas), 10.into());
|
||||
assert_eq!(interpreter.get_txn_field(To), 0.into());
|
||||
assert_eq!(interpreter.get_txn_field(Value), 100.into());
|
||||
assert_eq!(interpreter.get_txn_field(DataLen), 2.into());
|
||||
assert_eq!(interpreter.get_txn_field(YParity), 1.into());
|
||||
assert_eq!(
|
||||
interpreter.get_txn_field(R),
|
||||
U256::from_big_endian(&hex!(
|
||||
"7c5c61ed975ebd286f6b027b8c504842e50a47d318e1e801719dd744fe93e6c6"
|
||||
))
|
||||
);
|
||||
assert_eq!(
|
||||
interpreter.get_txn_field(S),
|
||||
U256::from_big_endian(&hex!(
|
||||
"1e7b5119b57dd54e175ff2f055c91f3ab1b53eba0b2c184f347cdff0e745aca2"
|
||||
))
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user