mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-10 17:53:06 +00:00
Merge pull request #746 from mir-protocol/mpt_hashing
MPT hashing logic, part 1
This commit is contained in:
commit
6b8a18b3ef
@ -43,6 +43,7 @@ pub(crate) fn combined_kernel() -> Kernel {
|
||||
include_str!("asm/rlp/decode.asm"),
|
||||
include_str!("asm/rlp/read_to_memory.asm"),
|
||||
include_str!("asm/mpt/hash.asm"),
|
||||
include_str!("asm/mpt/hex_prefix.asm"),
|
||||
include_str!("asm/mpt/load.asm"),
|
||||
include_str!("asm/mpt/read.asm"),
|
||||
include_str!("asm/mpt/storage_read.asm"),
|
||||
|
||||
@ -1,8 +1,20 @@
|
||||
global main:
|
||||
// First, load all MPT data from the prover.
|
||||
PUSH txn_loop
|
||||
%jump(load_all_mpts)
|
||||
|
||||
hash_initial_tries:
|
||||
// TODO: Hash each trie and set @GLOBAL_METADATA_STATE_TRIE_DIGEST_BEFORE, etc.
|
||||
|
||||
txn_loop:
|
||||
// If the prover has no more txns for us to process, halt.
|
||||
PROVER_INPUT(end_of_txns)
|
||||
%jumpi(halt)
|
||||
%jumpi(hash_final_tries)
|
||||
|
||||
// Call route_txn, returning to main to continue the loop.
|
||||
PUSH main
|
||||
// Call route_txn. When we return, continue the txn loop.
|
||||
PUSH txn_loop
|
||||
%jump(route_txn)
|
||||
|
||||
hash_final_tries:
|
||||
// TODO: Hash each trie and set @GLOBAL_METADATA_STATE_TRIE_DIGEST_AFTER, etc.
|
||||
%jump(halt)
|
||||
|
||||
@ -98,3 +98,10 @@
|
||||
%mstore_kernel(@SEGMENT_CODE)
|
||||
// stack: (empty)
|
||||
%endmacro
|
||||
|
||||
// Store a single value to @SEGMENT_KERNEL_GENERAL.
|
||||
%macro mstore_kernel_general
|
||||
// stack: offset, value
|
||||
%mstore_kernel(@SEGMENT_KERNEL_GENERAL)
|
||||
// stack: (empty)
|
||||
%endmacro
|
||||
|
||||
@ -1,2 +1,48 @@
|
||||
global mpt_hash:
|
||||
// TODO
|
||||
// stack: node_ptr, retdest
|
||||
DUP1
|
||||
%mload_trie_data
|
||||
// stack: node_type, node_ptr, retdest
|
||||
// Increment node_ptr, so it points to the node payload instead of its type.
|
||||
SWAP1 %add_const(1) SWAP1
|
||||
// stack: node_type, node_payload_ptr, retdest
|
||||
|
||||
DUP1 %eq_const(@MPT_NODE_EMPTY) %jumpi(mpt_hash_empty)
|
||||
DUP1 %eq_const(@MPT_NODE_HASH) %jumpi(mpt_hash_hash)
|
||||
DUP1 %eq_const(@MPT_NODE_BRANCH) %jumpi(mpt_hash_branch)
|
||||
DUP1 %eq_const(@MPT_NODE_EXTENSION) %jumpi(mpt_hash_extension)
|
||||
DUP1 %eq_const(@MPT_NODE_LEAF) %jumpi(mpt_hash_leaf)
|
||||
PANIC // Invalid node type? Shouldn't get here.
|
||||
|
||||
mpt_hash_empty:
|
||||
%stack (node_type, node_payload_ptr, retdest) -> (retdest, @EMPTY_NODE_HASH)
|
||||
JUMP
|
||||
|
||||
mpt_hash_hash:
|
||||
// stack: node_type, node_payload_ptr, retdest
|
||||
POP
|
||||
// stack: node_payload_ptr, retdest
|
||||
%mload_trie_data
|
||||
// stack: hash, retdest
|
||||
SWAP1
|
||||
JUMP
|
||||
|
||||
mpt_hash_branch:
|
||||
// stack: node_type, node_payload_ptr, retdest
|
||||
POP
|
||||
// stack: node_payload_ptr, retdest
|
||||
PANIC // TODO
|
||||
|
||||
mpt_hash_extension:
|
||||
// stack: node_type, node_payload_ptr, retdest
|
||||
POP
|
||||
// stack: node_payload_ptr, retdest
|
||||
PANIC // TODO
|
||||
|
||||
mpt_hash_leaf:
|
||||
// stack: node_type, node_payload_ptr, retdest
|
||||
POP
|
||||
// stack: node_payload_ptr, retdest
|
||||
DUP1 %mload_trie_data
|
||||
// stack: node_nibbles, node_payload_ptr, retdest
|
||||
PANIC // TODO
|
||||
|
||||
51
evm/src/cpu/kernel/asm/mpt/hex_prefix.asm
Normal file
51
evm/src/cpu/kernel/asm/mpt/hex_prefix.asm
Normal file
@ -0,0 +1,51 @@
|
||||
// Computes the hex-prefix encoding of the given nibble list and termination
|
||||
// flag. Writes the result to the @KERNEL_GENERAL segment of memory, and returns
|
||||
// its length on the stack.
|
||||
global hex_prefix:
|
||||
// stack: num_nibbles, packed_nibbles, terminated, retdest
|
||||
// We will iterate backwards, from i = num_nibbles/2 to i=0, so that we can
|
||||
// take nibbles from the least-significant end of packed_nibbles.
|
||||
PUSH 2 DUP2 DIV // i = num_nibbles / 2
|
||||
// stack: i, num_nibbles, packed_nibbles, terminated, retdest
|
||||
|
||||
loop:
|
||||
// If i == 0, break to first_byte.
|
||||
DUP1 ISZERO %jumpi(first_byte)
|
||||
|
||||
// stack: i, num_nibbles, packed_nibbles, terminated, retdest
|
||||
DUP3 // packed_nibbles
|
||||
%and_const(0xFF)
|
||||
// stack: byte_i, i, num_nibbles, packed_nibbles, terminated, retdest
|
||||
DUP2 // i
|
||||
%mstore_kernel_general
|
||||
// stack: i, num_nibbles, packed_nibbles, terminated, retdest
|
||||
%sub_const(1)
|
||||
SWAP2 %shr_const(8) SWAP2 // packed_nibbles >>= 8
|
||||
// stack: i, num_nibbles, packed_nibbles, terminated, retdest
|
||||
%jump(loop)
|
||||
|
||||
first_byte:
|
||||
// stack: 0, num_nibbles, first_nibble_or_zero, terminated, retdest
|
||||
POP
|
||||
DUP1
|
||||
// stack: num_nibbles, num_nibbles, first_nibble_or_zero, terminated, retdest
|
||||
%div_const(2)
|
||||
%add_const(1)
|
||||
// stack: result_len, num_nibbles, first_nibble_or_zero, terminated, retdest
|
||||
SWAP3
|
||||
// stack: terminated, num_nibbles, first_nibble_or_zero, result_len, retdest
|
||||
%mul_const(2)
|
||||
SWAP1
|
||||
// stack: num_nibbles, terminated * 2, first_nibble_or_zero, result_len, retdest
|
||||
%mod_const(2)
|
||||
ADD
|
||||
// stack: parity + terminated * 2, first_nibble_or_zero, result_len, retdest
|
||||
%mul_const(16)
|
||||
ADD
|
||||
// stack: 16 * (parity + terminated * 2) + first_nibble_or_zero, result_len, retdest
|
||||
PUSH 0
|
||||
%mstore_kernel_general
|
||||
|
||||
// stack: result_len, retdest
|
||||
SWAP1
|
||||
JUMP
|
||||
@ -39,7 +39,6 @@ storage_trie_loop:
|
||||
// stack: i, num_storage_tries, retdest
|
||||
%jump(storage_trie_loop)
|
||||
storage_trie_loop_end:
|
||||
// TODO: Hash tries and set @GLOBAL_METADATA_STATE_TRIE_DIGEST_BEFORE, etc.
|
||||
// stack: i, num_storage_tries, retdest
|
||||
%pop2
|
||||
// stack: retdest
|
||||
|
||||
@ -18,6 +18,9 @@ pub fn evm_constants() -> HashMap<String, U256> {
|
||||
for (name, value) in EC_CONSTANTS {
|
||||
c.insert(name.into(), U256::from_big_endian(&value));
|
||||
}
|
||||
for (name, value) in HASH_CONSTANTS {
|
||||
c.insert(name.into(), U256::from_big_endian(&value));
|
||||
}
|
||||
for (name, value) in GAS_CONSTANTS {
|
||||
c.insert(name.into(), U256::from(value));
|
||||
}
|
||||
@ -43,6 +46,14 @@ pub fn evm_constants() -> HashMap<String, U256> {
|
||||
c
|
||||
}
|
||||
|
||||
const HASH_CONSTANTS: [(&str, [u8; 32]); 1] = [
|
||||
// Hash of an empty node: keccak(rlp.encode(b'')).hex()
|
||||
(
|
||||
"EMPTY_NODE_HASH",
|
||||
hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"),
|
||||
),
|
||||
];
|
||||
|
||||
const EC_CONSTANTS: [(&str, [u8; 32]); 3] = [
|
||||
(
|
||||
"BN_BASE",
|
||||
|
||||
@ -161,6 +161,10 @@ impl<'a> Interpreter<'a> {
|
||||
&self.memory.context_memory[0].segments[Segment::TrieData as usize].content
|
||||
}
|
||||
|
||||
pub(crate) fn get_kernel_general_data(&self) -> &[U256] {
|
||||
&self.memory.context_memory[0].segments[Segment::KernelGeneral as usize].content
|
||||
}
|
||||
|
||||
pub(crate) fn get_rlp_memory(&self) -> Vec<u8> {
|
||||
self.memory.context_memory[self.context].segments[Segment::RlpRaw as usize]
|
||||
.content
|
||||
|
||||
50
evm/src/cpu/kernel/tests/mpt/hex_prefix.rs
Normal file
50
evm/src/cpu/kernel/tests/mpt/hex_prefix.rs
Normal file
@ -0,0 +1,50 @@
|
||||
use anyhow::Result;
|
||||
|
||||
use crate::cpu::kernel::aggregator::KERNEL;
|
||||
use crate::cpu::kernel::interpreter::Interpreter;
|
||||
|
||||
#[test]
|
||||
fn hex_prefix_even_nonterminated() -> Result<()> {
|
||||
let hex_prefix = KERNEL.global_labels["hex_prefix"];
|
||||
|
||||
let retdest = 0xDEADBEEFu32.into();
|
||||
let terminated = 0.into();
|
||||
let packed_nibbles = 0xABCDEF.into();
|
||||
let num_nibbles = 6.into();
|
||||
let initial_stack = vec![retdest, terminated, packed_nibbles, num_nibbles];
|
||||
let mut interpreter = Interpreter::new_with_kernel(hex_prefix, initial_stack);
|
||||
interpreter.run()?;
|
||||
assert_eq!(interpreter.stack(), vec![4.into()]);
|
||||
|
||||
assert_eq!(
|
||||
interpreter.get_kernel_general_data(),
|
||||
vec![0.into(), 0xAB.into(), 0xCD.into(), 0xEF.into(),]
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hex_prefix_odd_terminated() -> Result<()> {
|
||||
let hex_prefix = KERNEL.global_labels["hex_prefix"];
|
||||
|
||||
let retdest = 0xDEADBEEFu32.into();
|
||||
let terminated = 1.into();
|
||||
let packed_nibbles = 0xABCDE.into();
|
||||
let num_nibbles = 5.into();
|
||||
let initial_stack = vec![retdest, terminated, packed_nibbles, num_nibbles];
|
||||
let mut interpreter = Interpreter::new_with_kernel(hex_prefix, initial_stack);
|
||||
interpreter.run()?;
|
||||
assert_eq!(interpreter.stack(), vec![3.into()]);
|
||||
|
||||
assert_eq!(
|
||||
interpreter.get_kernel_general_data(),
|
||||
vec![
|
||||
(terminated * 2 + 1u32) * 16 + 0xAu32,
|
||||
0xBC.into(),
|
||||
0xDE.into(),
|
||||
]
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -1,5 +1,6 @@
|
||||
use eth_trie_utils::partial_trie::{Nibbles, PartialTrie};
|
||||
|
||||
mod hex_prefix;
|
||||
mod load;
|
||||
mod read;
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user