add execution_rpc package
This commit is contained in:
parent
2040614e1b
commit
4dd8ba253f
|
@ -0,0 +1,43 @@
|
||||||
|
use ethers::prelude::{Address, U256, H256};
|
||||||
|
use jsonrpsee::{http_client::HttpClientBuilder, rpc_params, core::client::ClientT};
|
||||||
|
use eyre::Result;
|
||||||
|
use serde::Deserialize;
|
||||||
|
use serde::de::Error;
|
||||||
|
use super::utils::*;
|
||||||
|
|
||||||
|
pub struct ExecutionRpc {
|
||||||
|
rpc: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ExecutionRpc {
|
||||||
|
pub fn new(rpc: &str) -> Self {
|
||||||
|
ExecutionRpc { rpc: rpc.to_string() }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get_proof(&self, address: &str, block: u64) -> Result<Proof> {
|
||||||
|
let client = HttpClientBuilder::default().build(&self.rpc)?;
|
||||||
|
let block_hex = format!("0x{:x}", block);
|
||||||
|
let params = rpc_params!(address, [""], block_hex);
|
||||||
|
Ok(client.request("eth_getProof", params).await?)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Debug)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct Proof {
|
||||||
|
pub address: Address,
|
||||||
|
pub balance: U256,
|
||||||
|
pub code_hash: H256,
|
||||||
|
pub nonce: U256,
|
||||||
|
pub storage_hash: H256,
|
||||||
|
#[serde(deserialize_with = "proof_deserialize")]
|
||||||
|
pub account_proof: Vec<Vec<u8>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn proof_deserialize<'de, D>(deserializer: D) -> Result<Vec<Vec<u8>>, D::Error> where D: serde::Deserializer<'de> {
|
||||||
|
let branch: Vec<String> = serde::Deserialize::deserialize(deserializer)?;
|
||||||
|
Ok(branch.iter().map(|elem| {
|
||||||
|
hex_str_to_bytes(elem)
|
||||||
|
}).collect::<Result<_>>().map_err(D::Error::custom)?)
|
||||||
|
}
|
||||||
|
|
17
src/main.rs
17
src/main.rs
|
@ -1,9 +1,13 @@
|
||||||
use eyre::Result;
|
use eyre::Result;
|
||||||
|
|
||||||
use consensus::*;
|
use consensus::*;
|
||||||
|
use execution_rpc::*;
|
||||||
|
use proof::*;
|
||||||
|
use utils::hex_str_to_bytes;
|
||||||
|
|
||||||
pub mod consensus;
|
pub mod consensus;
|
||||||
pub mod consensus_rpc;
|
pub mod consensus_rpc;
|
||||||
|
pub mod execution_rpc;
|
||||||
pub mod utils;
|
pub mod utils;
|
||||||
pub mod proof;
|
pub mod proof;
|
||||||
|
|
||||||
|
@ -14,11 +18,24 @@ async fn main() -> Result<()> {
|
||||||
let checkpoint = "0x172128eadf1da46467f4d6a822206698e2d3f957af117dd650954780d680dc99";
|
let checkpoint = "0x172128eadf1da46467f4d6a822206698e2d3f957af117dd650954780d680dc99";
|
||||||
let mut client = ConsensusClient::new(rpc, checkpoint).await?;
|
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);
|
||||||
|
|
||||||
client.sync().await?;
|
client.sync().await?;
|
||||||
|
|
||||||
let payload = client.get_execution_payload().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);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
40
src/proof.rs
40
src/proof.rs
|
@ -1,26 +1,9 @@
|
||||||
use ethers::utils::keccak256;
|
use ethers::utils::keccak256;
|
||||||
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, decode_list};
|
use ethers::utils::rlp::{RlpStream, decode_list};
|
||||||
use ethers::prelude::{U256, H256, Address};
|
use super::execution_rpc::Proof;
|
||||||
use super::utils::hex_str_to_bytes;
|
|
||||||
|
|
||||||
pub async fn get_proof(address: &str, block: u64) -> Result<Proof> {
|
|
||||||
let rpc = "https://eth-mainnet.g.alchemy.com:443/v2/sUiZsY3BSTYXjSHIvPc9rGDipR7lAlT4";
|
|
||||||
let client = HttpClientBuilder::default().build(rpc)?;
|
|
||||||
let block_hex = format!("0x{:x}", block);
|
|
||||||
let params = rpc_params!(address, [""], block_hex);
|
|
||||||
Ok(client.request("eth_getProof", params).await?)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn verify_proof(proof: &Vec<Vec<u8>>, root: &Vec<u8>, path: &Vec<u8>, value: &Vec<u8>) -> bool {
|
pub fn verify_proof(proof: &Vec<Vec<u8>>, root: &Vec<u8>, path: &Vec<u8>, value: &Vec<u8>) -> bool {
|
||||||
|
|
||||||
// let account_encoded = encode_account(proof);
|
|
||||||
// let state_root = hex_str_to_bytes("0x1d006918a3fef7ff7c843f20747c757a38a0a13fe7723f53e349f462c2cfdd71").unwrap();
|
|
||||||
// let path = keccak256(proof.address).to_vec();
|
|
||||||
|
|
||||||
let mut expected_hash = root.clone();
|
let mut expected_hash = root.clone();
|
||||||
let mut path_offset = 0;
|
let mut path_offset = 0;
|
||||||
|
|
||||||
|
@ -63,7 +46,7 @@ fn get_nibble(path: &Vec<u8>, offset: usize) -> u8 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encode_account(proof: &Proof) -> Vec<u8> {
|
pub fn encode_account(proof: &Proof) -> Vec<u8> {
|
||||||
let mut stream = RlpStream::new_list(4);
|
let mut stream = RlpStream::new_list(4);
|
||||||
stream.append(&proof.nonce);
|
stream.append(&proof.nonce);
|
||||||
stream.append(&proof.balance);
|
stream.append(&proof.balance);
|
||||||
|
@ -73,22 +56,7 @@ fn encode_account(proof: &Proof) -> Vec<u8> {
|
||||||
encoded.to_vec()
|
encoded.to_vec()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
pub fn get_account_path(addr: &Vec<u8>) -> Vec<u8> {
|
||||||
#[serde(rename_all = "camelCase")]
|
keccak256(addr).to_vec()
|
||||||
pub struct Proof {
|
|
||||||
address: Address,
|
|
||||||
balance: U256,
|
|
||||||
code_hash: H256,
|
|
||||||
nonce: U256,
|
|
||||||
storage_hash: H256,
|
|
||||||
#[serde(deserialize_with = "proof_deserialize")]
|
|
||||||
account_proof: Vec<Vec<u8>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn proof_deserialize<'de, D>(deserializer: D) -> Result<Vec<Vec<u8>>, D::Error> where D: serde::Deserializer<'de> {
|
|
||||||
let branch: Vec<String> = serde::Deserialize::deserialize(deserializer)?;
|
|
||||||
Ok(branch.iter().map(|elem| {
|
|
||||||
hex_str_to_bytes(elem)
|
|
||||||
}).collect::<Result<_>>().map_err(D::Error::custom)?)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue