fix(trie): witness empty root node (#10972)

This commit is contained in:
Roman Krasiuk
2024-09-30 10:08:45 +02:00
committed by GitHub
parent e02a2de2d0
commit 17aa3d61f6
5 changed files with 93 additions and 14 deletions

View File

@ -1,6 +1,7 @@
#![allow(missing_docs)]
use alloy_primitives::{keccak256, Address, Bytes, B256, U256};
use alloy_rlp::EMPTY_STRING_CODE;
use reth_chainspec::{Chain, ChainSpec, HOLESKY, MAINNET};
use reth_primitives::{constants::EMPTY_ROOT_HASH, Account};
use reth_provider::test_utils::{create_test_provider_factory, insert_genesis};
@ -111,7 +112,10 @@ fn testspec_empty_storage_proof() {
assert_eq!(slots.len(), account_proof.storage_proofs.len());
for (idx, slot) in slots.into_iter().enumerate() {
let proof = account_proof.storage_proofs.get(idx).unwrap();
assert_eq!(proof, &StorageProof::new(slot));
assert_eq!(
proof,
&StorageProof::new(slot).with_proof(vec![Bytes::from([EMPTY_STRING_CODE])])
);
assert_eq!(proof.verify(account_proof.storage_root), Ok(()));
}
assert_eq!(account_proof.verify(root), Ok(()));

View File

@ -0,0 +1,57 @@
#![allow(missing_docs)]
use alloy_primitives::{
keccak256,
map::{HashMap, HashSet},
Address, Bytes, B256, U256,
};
use alloy_rlp::EMPTY_STRING_CODE;
use reth_primitives::{constants::EMPTY_ROOT_HASH, Account};
use reth_provider::{test_utils::create_test_provider_factory, HashingWriter};
use reth_trie::{proof::Proof, witness::TrieWitness, HashedPostState, HashedStorage, StateRoot};
use reth_trie_db::{DatabaseProof, DatabaseStateRoot, DatabaseTrieWitness};
#[test]
fn includes_empty_node_preimage() {
let factory = create_test_provider_factory();
let provider = factory.provider_rw().unwrap();
let address = Address::random();
let hashed_address = keccak256(address);
let hashed_slot = B256::random();
// witness includes empty state trie root node
assert_eq!(
TrieWitness::from_tx(provider.tx_ref())
.compute(HashedPostState {
accounts: HashMap::from([(hashed_address, Some(Account::default()))]),
storages: HashMap::default(),
})
.unwrap(),
HashMap::from_iter([(EMPTY_ROOT_HASH, Bytes::from([EMPTY_STRING_CODE]))])
);
// Insert account into database
provider.insert_account_for_hashing([(address, Some(Account::default()))]).unwrap();
let state_root = StateRoot::from_tx(provider.tx_ref()).root().unwrap();
let multiproof = Proof::from_tx(provider.tx_ref())
.multiproof(HashMap::from_iter([(hashed_address, HashSet::from_iter([hashed_slot]))]))
.unwrap();
let witness = TrieWitness::from_tx(provider.tx_ref())
.compute(HashedPostState {
accounts: HashMap::from([(hashed_address, Some(Account::default()))]),
storages: HashMap::from([(
hashed_address,
HashedStorage::from_iter(false, [(hashed_slot, U256::from(1))]),
)]),
})
.unwrap();
assert!(witness.contains_key(&state_root));
for node in multiproof.account_subtree.values() {
assert_eq!(witness.get(&keccak256(node)), Some(node));
}
// witness includes empty state trie root node
assert_eq!(witness.get(&EMPTY_ROOT_HASH), Some(&Bytes::from([EMPTY_STRING_CODE])));
}