diff --git a/src/execution.rs b/src/execution.rs new file mode 100644 index 0000000..fdf7f42 --- /dev/null +++ b/src/execution.rs @@ -0,0 +1,33 @@ +use ethers::utils::keccak256; +use eyre::Result; +use ethers::prelude::{U256, Address}; + +use crate::proof::{encode_account, verify_proof}; +use crate::consensus_rpc::ExecutionPayload; +use crate::execution_rpc::ExecutionRpc; + +pub struct ExecutionClient { + execution_rpc: ExecutionRpc +} + +impl ExecutionClient { + pub fn new(rpc: &str) -> Self { + let execution_rpc = ExecutionRpc::new(rpc); + ExecutionClient { execution_rpc } + } + + pub async fn get_balance(&self, account: &Address, payload: &ExecutionPayload) -> Result { + let proof = self.execution_rpc.get_proof(&account, payload.block_number).await?; + + let account_path = keccak256(account.as_bytes()).to_vec(); + let account_encoded = encode_account(&proof); + + let is_valid = verify_proof(&proof.account_proof, &payload.state_root, &account_path, &account_encoded); + + if !is_valid { + eyre::bail!("Invalid Proof"); + } + + Ok(proof.balance) + } +} diff --git a/src/execution_rpc.rs b/src/execution_rpc.rs index 1f9d30a..2f07e3b 100644 --- a/src/execution_rpc.rs +++ b/src/execution_rpc.rs @@ -14,10 +14,11 @@ impl ExecutionRpc { ExecutionRpc { rpc: rpc.to_string() } } - pub async fn get_proof(&self, address: &str, block: u64) -> Result { + pub async fn get_proof(&self, address: &Address, block: u64) -> Result { let client = HttpClientBuilder::default().build(&self.rpc)?; let block_hex = format!("0x{:x}", block); - let params = rpc_params!(address, [""], block_hex); + let addr_hex = format!("0x{}", hex::encode(address.as_bytes())); + let params = rpc_params!(addr_hex, [""], block_hex); Ok(client.request("eth_getProof", params).await?) } } diff --git a/src/main.rs b/src/main.rs index 7bd443f..ab465c8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,12 +1,14 @@ +use std::str::FromStr; + +use ethers::prelude::Address; use eyre::Result; use consensus::*; -use execution_rpc::*; -use proof::*; -use utils::hex_str_to_bytes; +use execution::*; pub mod consensus; pub mod consensus_rpc; +pub mod execution; pub mod execution_rpc; pub mod utils; pub mod proof; @@ -19,22 +21,16 @@ async fn main() -> Result<()> { let mut client = ConsensusClient::new(rpc, checkpoint).await?; let rpc = "https://eth-goerli.g.alchemy.com:443/v2/o_8Qa9kgwDPf9G8sroyQ-uQtyhyWa3ao"; - let execution = ExecutionRpc::new(rpc); + let execution = ExecutionClient::new(rpc); client.sync().await?; let payload = client.get_execution_payload().await?; - println!("verified execution block hash: {}", hex::encode(payload.block_hash)); + println!("verified execution block hash: {}", hex::encode(&payload.block_hash)); - let addr = "0x25c4a76E7d118705e7Ea2e9b7d8C59930d8aCD3b"; - let proof = execution.get_proof(addr, payload.block_number).await?; - - let account_path = get_account_path(&hex_str_to_bytes(addr)?); - let account_encoded = encode_account(&proof); - - let is_valid = verify_proof(&proof.account_proof, &payload.state_root, &account_path, &account_encoded); - - println!("is account proof valid: {}", is_valid); + let addr = Address::from_str("0x25c4a76E7d118705e7Ea2e9b7d8C59930d8aCD3b")?; + let balance = execution.get_balance(&addr, &payload).await?; + println!("verified account balance: {}", balance); Ok(()) }