MPT read for extension nodes

This commit is contained in:
Daniel Lubarov 2022-09-27 10:49:13 -07:00
parent 9e6ba6d5aa
commit 5555085c4c
6 changed files with 93 additions and 35 deletions

View File

@ -110,10 +110,16 @@ load_mpt_extension:
%append_to_trie_data
// stack: retdest
%load_mpt_and_return_root_ptr
// stack: child_ptr, retdest
// Let i be the current trie data size. We still need to expand this node by
// one element, appending our child pointer. Thus our child node will start
// at i + 1. So we will set our child pointer to i + 1.
%get_trie_data_size
%add_const(1)
%append_to_trie_data
// stack: retdest
%load_mpt
// stack: retdest
JUMP
load_mpt_leaf:

View File

@ -63,27 +63,59 @@ mpt_read_branch_end_of_key:
mpt_read_extension:
// stack: node_type, node_payload_ptr, num_nibbles, key, retdest
POP
// stack: node_payload_ptr, num_nibbles, key, retdest
// TODO
%stack (node_type, node_payload_ptr, num_nibbles, key)
-> (num_nibbles, key, node_payload_ptr)
// stack: num_nibbles, key, node_payload_ptr, retdest
DUP3 %mload_trie_data
// stack: node_num_nibbles, num_nibbles, key, node_payload_ptr, retdest
SWAP1
SUB
// stack: future_nibbles, key, node_payload_ptr, retdest
DUP2 DUP2
// stack: future_nibbles, key, future_nibbles, key, node_payload_ptr, retdest
%mul_const(4) SHR // key_part = key >> (future_nibbles * 4)
DUP1
// stack: key_part, key_part, future_nibbles, key, node_payload_ptr, retdest
DUP5 %add_const(1) %mload_trie_data
// stack: node_key, key_part, key_part, future_nibbles, key, node_payload_ptr, retdest
EQ // does the first part of our key match the node's key?
%jumpi(mpt_read_extension_found)
// Not found; return 0.
%stack (key_part, future_nibbles, node_payload_ptr, retdest) -> (retdest, 0)
JUMP
mpt_read_extension_found:
// stack: key_part, future_nibbles, key, node_payload_ptr, retdest
DUP2 %mul_const(4) SHL // key_part_shifted = (key_part << (future_nibbles * 4))
// stack: key_part_shifted, future_nibbles, key, node_payload_ptr, retdest
%stack (key_part_shifted, future_nibbles, key)
-> (key, key_part_shifted, future_nibbles)
SUB // key -= key_part_shifted
// stack: key, future_nibbles, node_payload_ptr, retdest
SWAP2
// stack: node_payload_ptr, future_nibbles, key, retdest
%add_const(2) // child pointer is third field of extension node
%mload_trie_data
// stack: child_ptr, future_nibbles, key, retdest
%jump(mpt_read) // recurse
mpt_read_leaf:
// stack: node_type, node_payload_ptr, key, num_nibbles, retdest
// stack: node_type, node_payload_ptr, num_nibbles, key, retdest
POP
// stack: node_payload_ptr, key, num_nibbles, retdest
// stack: node_payload_ptr, num_nibbles, key, retdest
DUP1 %mload_trie_data
// stack: node_num_nibbles, node_payload_ptr, key, num_nibbles, retdest
// stack: node_num_nibbles, node_payload_ptr, num_nibbles, key, retdest
DUP2 %add_const(1) %mload_trie_data
// stack: node_key, node_num_nibbles, node_payload_ptr, key, num_nibbles, retdest
SWAP4
// stack: num_nibbles, node_num_nibbles, node_payload_ptr, key, node_key, retdest
// stack: node_key, node_num_nibbles, node_payload_ptr, num_nibbles, key, retdest
SWAP3
// stack: num_nibbles, node_num_nibbles, node_payload_ptr, node_key, key, retdest
EQ
%stack (num_nibbles_match, node_payload_ptr, key, node_key)
%stack (num_nibbles_match, node_payload_ptr, node_key, key)
-> (key, node_key, num_nibbles_match, node_payload_ptr)
EQ
AND
// stack: keys_match && num_nibbles_match, node_payload_ptr, retdest
%jumpi(mpt_read_leaf_found)
// Not found; return 0.
%stack (node_payload_ptr, retdest) -> (retdest, 0)
JUMP
mpt_read_leaf_found:

View File

@ -226,7 +226,7 @@ impl<'a> Interpreter<'a> {
0x19 => self.run_not(), // "NOT",
0x1a => self.run_byte(), // "BYTE",
0x1b => self.run_shl(), // "SHL",
0x1c => todo!(), // "SHR",
0x1c => self.run_shr(), // "SHR",
0x1d => todo!(), // "SAR",
0x20 => self.run_keccak256(), // "KECCAK256",
0x30 => todo!(), // "ADDRESS",
@ -427,6 +427,12 @@ impl<'a> Interpreter<'a> {
self.push(x << shift);
}
fn run_shr(&mut self) {
let shift = self.pop();
let x = self.pop();
self.push(x >> shift);
}
fn run_keccak256(&mut self) {
let offset = self.pop().as_usize();
let size = self.pop().as_usize();

View File

@ -1,11 +1,11 @@
use anyhow::Result;
use eth_trie_utils::partial_trie::{Nibbles, PartialTrie};
use ethereum_types::U256;
use crate::cpu::kernel::aggregator::KERNEL;
use crate::cpu::kernel::constants::trie_type::PartialTrieType;
use crate::cpu::kernel::global_metadata::GlobalMetadata;
use crate::cpu::kernel::interpreter::Interpreter;
use crate::cpu::kernel::tests::mpt::state_trie_ext_to_account_leaf;
use crate::generation::mpt::all_mpt_prover_inputs_reversed;
use crate::generation::TrieInputs;
@ -19,13 +19,7 @@ fn load_all_mpts() -> Result<()> {
let account_rlp = rlp::encode_list(&[nonce, balance, storage_root, code_hash]);
let trie_inputs = TrieInputs {
state_trie: PartialTrie::Leaf {
nibbles: Nibbles {
count: 2,
packed: 123.into(),
},
value: account_rlp.to_vec(),
},
state_trie: state_trie_ext_to_account_leaf(account_rlp.to_vec()),
transactions_trie: Default::default(),
receipts_trie: Default::default(),
storage_tries: vec![],
@ -40,14 +34,19 @@ fn load_all_mpts() -> Result<()> {
assert_eq!(interpreter.stack(), vec![]);
let type_empty = U256::from(PartialTrieType::Empty as u32);
let type_extension = U256::from(PartialTrieType::Extension as u32);
let type_leaf = U256::from(PartialTrieType::Leaf as u32);
assert_eq!(
interpreter.get_trie_data(),
vec![
0.into(), // First address is unused, so 0 can be treated as a null pointer.
0.into(), // First address is unused, so that 0 can be treated as a null pointer.
type_extension,
3.into(), // 3 nibbles
0xABC.into(), // key part
5.into(), // Pointer to the leaf node immediately below.
type_leaf,
2.into(),
123.into(),
3.into(), // 3 nibbles
0xDEF.into(), // key part
nonce,
balance,
storage_root,

View File

@ -1,2 +1,21 @@
use eth_trie_utils::partial_trie::{Nibbles, PartialTrie};
mod load;
mod read;
/// A `PartialTrie` where an extension node leads to a leaf node containing an account.
pub(crate) fn state_trie_ext_to_account_leaf(value: Vec<u8>) -> PartialTrie {
PartialTrie::Extension {
nibbles: Nibbles {
count: 3,
packed: 0xABC.into(),
},
child: Box::new(PartialTrie::Leaf {
nibbles: Nibbles {
count: 3,
packed: 0xDEF.into(),
},
value,
}),
}
}

View File

@ -1,10 +1,10 @@
use anyhow::Result;
use eth_trie_utils::partial_trie::{Nibbles, PartialTrie};
use ethereum_types::U256;
use crate::cpu::kernel::aggregator::KERNEL;
use crate::cpu::kernel::global_metadata::GlobalMetadata;
use crate::cpu::kernel::interpreter::Interpreter;
use crate::cpu::kernel::tests::mpt::state_trie_ext_to_account_leaf;
use crate::generation::mpt::all_mpt_prover_inputs_reversed;
use crate::generation::TrieInputs;
@ -19,13 +19,7 @@ fn mpt_read() -> Result<()> {
let account_rlp = rlp::encode_list(account);
let trie_inputs = TrieInputs {
state_trie: PartialTrie::Leaf {
nibbles: Nibbles {
count: 2,
packed: 123.into(),
},
value: account_rlp.to_vec(),
},
state_trie: state_trie_ext_to_account_leaf(account_rlp.to_vec()),
transactions_trie: Default::default(),
receipts_trie: Default::default(),
storage_tries: vec![],
@ -43,14 +37,16 @@ fn mpt_read() -> Result<()> {
// Now, execute mpt_read on the state trie.
interpreter.offset = mpt_read;
interpreter.push(0xdeadbeefu32.into());
interpreter.push(2.into());
interpreter.push(123.into());
interpreter.push(0xABCDEFu64.into());
interpreter.push(6.into());
interpreter.push(interpreter.get_global_metadata_field(GlobalMetadata::StateTrieRoot));
interpreter.run()?;
dbg!(interpreter.stack());
assert_eq!(interpreter.stack().len(), 1);
let result_ptr = interpreter.stack()[0].as_usize();
let result = &interpreter.get_trie_data()[result_ptr..result_ptr + 4];
dbg!(result_ptr);
let result = &interpreter.get_trie_data()[result_ptr..][..account.len()];
assert_eq!(result, account);
Ok(())