use eth_valkyoth_codec::DecodeLimits;
use eth_valkyoth_hash::{Keccak256, hash_one};
use eth_valkyoth_primitives::{Address, B256};
use crate::mpt_proof::{MptProofRoot, MptProofVerificationError, verify_key_inclusion};
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct AccountTrieRoot(B256);
impl AccountTrieRoot {
#[must_use]
pub const fn from_b256(value: B256) -> Self {
Self(value)
}
#[must_use]
pub const fn to_b256(self) -> B256 {
self.0
}
}
impl From<AccountTrieRoot> for MptProofRoot {
fn from(value: AccountTrieRoot) -> Self {
Self::from_b256(value.to_b256())
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct StorageTrieRoot(B256);
impl StorageTrieRoot {
#[must_use]
pub const fn from_b256(value: B256) -> Self {
Self(value)
}
#[must_use]
pub const fn to_b256(self) -> B256 {
self.0
}
}
impl From<StorageTrieRoot> for MptProofRoot {
fn from(value: StorageTrieRoot) -> Self {
Self::from_b256(value.to_b256())
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct StorageSlotKey(B256);
impl StorageSlotKey {
#[must_use]
pub const fn from_b256(value: B256) -> Self {
Self(value)
}
#[must_use]
pub const fn to_b256(self) -> B256 {
self.0
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct VerifiedAccountInclusion {
address: Address,
root: AccountTrieRoot,
}
impl VerifiedAccountInclusion {
const fn new(address: Address, root: AccountTrieRoot) -> Self {
Self { address, root }
}
#[must_use]
pub const fn address(self) -> Address {
self.address
}
#[must_use]
pub const fn root(self) -> AccountTrieRoot {
self.root
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct VerifiedStorageInclusion {
slot: StorageSlotKey,
root: StorageTrieRoot,
}
impl VerifiedStorageInclusion {
const fn new(slot: StorageSlotKey, root: StorageTrieRoot) -> Self {
Self { slot, root }
}
#[must_use]
pub const fn slot(self) -> StorageSlotKey {
self.slot
}
#[must_use]
pub const fn root(self) -> StorageTrieRoot {
self.root
}
}
pub fn verify_account_inclusion<H>(
root: AccountTrieRoot,
address: Address,
encoded_account: &[u8],
proof_nodes: &[&[u8]],
limits: DecodeLimits,
mut new_hasher: impl FnMut() -> H,
) -> Result<VerifiedAccountInclusion, MptProofVerificationError>
where
H: Keccak256,
{
let key = hash_one(new_hasher(), &address.to_bytes()).to_bytes();
verify_key_inclusion(
root.into(),
&key,
encoded_account,
proof_nodes,
limits,
new_hasher,
)?;
Ok(VerifiedAccountInclusion::new(address, root))
}
pub fn verify_storage_inclusion<H>(
root: StorageTrieRoot,
slot: StorageSlotKey,
encoded_storage_value: &[u8],
proof_nodes: &[&[u8]],
limits: DecodeLimits,
mut new_hasher: impl FnMut() -> H,
) -> Result<VerifiedStorageInclusion, MptProofVerificationError>
where
H: Keccak256,
{
let key = hash_one(new_hasher(), &slot.to_b256().to_bytes()).to_bytes();
verify_key_inclusion(
root.into(),
&key,
encoded_storage_value,
proof_nodes,
limits,
new_hasher,
)?;
Ok(VerifiedStorageInclusion::new(slot, root))
}
#[cfg(test)]
#[path = "state_proof_tests.rs"]
mod tests;