verify mpt proofs

This commit is contained in:
Noah Citron 2022-08-19 18:02:06 -04:00
parent f71bff19f6
commit c21f431673
2 changed files with 46 additions and 10 deletions

View File

@ -22,9 +22,9 @@ async fn main() -> Result<()> {
// let payload = client.get_execution_payload().await?;
// println!("verified execution block hash: {}", hex::encode(payload.block_hash));
let proof = get_proof("0xf6401adc23Faa6B9AD83eA8604CA7254CB7F53e7", 15365978).await?;
verify(&proof)?;
// println!("{:?}", proof);
let proof = get_proof("0x88A83e0F661447576fb1f50e5d90d571E379cd72", 15365981).await?;
let is_valid = verify(&proof);
println!("{:?}", is_valid);
Ok(())
}

View File

@ -3,7 +3,7 @@ use eyre::Result;
use serde::Deserialize;
use serde::de::Error;
use jsonrpsee::{http_client::HttpClientBuilder, rpc_params, core::client::ClientT};
use ethers::utils::rlp::RlpStream;
use ethers::utils::rlp::{RlpStream, decode_list};
use ethers::prelude::{U256, H256, Address};
use super::utils::hex_str_to_bytes;
@ -15,16 +15,52 @@ pub async fn get_proof(address: &str, block: u64) -> Result<Proof> {
Ok(client.request("eth_getProof", params).await?)
}
pub fn verify(proof: &Proof) -> Result<()> {
pub fn verify_proof(proof: &Vec<Vec<u8>>, root: &Vec<u8>, path: &Vec<u8>, value: &Vec<u8>) -> bool {
let account_encoded = encode_account(proof);
println!("{:?}", account_encoded);
// let account_encoded = encode_account(proof);
// let state_root = hex_str_to_bytes("0x1d006918a3fef7ff7c843f20747c757a38a0a13fe7723f53e349f462c2cfdd71").unwrap();
// let path = keccak256(proof.address).to_vec();
let state_root = hex_str_to_bytes("0xeb5eb01bd4f503a5698d136c75b37ef2660d6842bf77d0453f2a7fa4a6780d91")?;
let address_hash = keccak256(proof.address);
let mut expected_hash = root;
let mut path_offset = 0;
for (i, node) in proof.iter().enumerate() {
if expected_hash != &keccak256(node).to_vec() {
return false;
}
Ok(())
let node_list: Vec<Vec<u8>> = decode_list(node);
if node_list.len() == 17 {
let nibble = get_nibble(&path, path_offset);
expected_hash = &node_list[nibble as usize].clone();
path_offset += 1;
} else if node_list.len() == 2 {
if i == proof.len() - 1 {
if &node_list[1] != value {
return false;
}
} else {
expected_hash = &node_list[1].clone();
}
} else {
return false;
}
}
true
}
fn get_nibble(path: &Vec<u8>, offset: usize) -> u8 {
let byte = path[offset / 2];
if offset % 2 == 0 {
byte >> 4
} else {
byte & 0xF
}
}
fn encode_account(proof: &Proof) -> Vec<u8> {