diff --git a/src/main.rs b/src/main.rs index e6ae779..e48b1ed 100644 --- a/src/main.rs +++ b/src/main.rs @@ -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(()) } diff --git a/src/proof.rs b/src/proof.rs index 67f9fa6..a2eaeb0 100644 --- a/src/proof.rs +++ b/src/proof.rs @@ -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 { Ok(client.request("eth_getProof", params).await?) } -pub fn verify(proof: &Proof) -> Result<()> { +pub fn verify_proof(proof: &Vec>, root: &Vec, path: &Vec, value: &Vec) -> 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> = 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, offset: usize) -> u8 { + let byte = path[offset / 2]; + if offset % 2 == 0 { + byte >> 4 + } else { + byte & 0xF + } } fn encode_account(proof: &Proof) -> Vec {