2022-08-21 21:51:11 +00:00
|
|
|
use std::collections::HashMap;
|
|
|
|
|
|
|
|
use ethers::abi::AbiEncode;
|
|
|
|
use ethers::prelude::{Address, U256};
|
2022-08-20 17:18:40 +00:00
|
|
|
use ethers::utils::keccak256;
|
2022-08-21 21:51:11 +00:00
|
|
|
use ethers::utils::rlp::encode;
|
2022-08-20 17:18:40 +00:00
|
|
|
use eyre::Result;
|
|
|
|
|
2022-08-21 15:21:50 +00:00
|
|
|
use super::proof::{encode_account, verify_proof};
|
2022-08-21 16:27:19 +00:00
|
|
|
use super::rpc::Rpc;
|
2022-08-21 21:51:11 +00:00
|
|
|
use super::types::Account;
|
|
|
|
use crate::common::utils::hex_str_to_bytes;
|
2022-08-21 16:59:47 +00:00
|
|
|
use crate::consensus::types::ExecutionPayload;
|
2022-08-20 17:18:40 +00:00
|
|
|
|
2022-08-24 01:33:48 +00:00
|
|
|
#[derive(Clone)]
|
2022-08-20 17:18:40 +00:00
|
|
|
pub struct ExecutionClient {
|
2022-08-21 16:27:19 +00:00
|
|
|
rpc: Rpc,
|
2022-08-20 17:18:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl ExecutionClient {
|
|
|
|
pub fn new(rpc: &str) -> Self {
|
2022-08-21 16:27:19 +00:00
|
|
|
let rpc = Rpc::new(rpc);
|
|
|
|
ExecutionClient { rpc }
|
2022-08-20 17:18:40 +00:00
|
|
|
}
|
|
|
|
|
2022-08-21 16:59:47 +00:00
|
|
|
pub async fn get_account(
|
|
|
|
&self,
|
|
|
|
address: &Address,
|
2022-08-21 21:51:11 +00:00
|
|
|
slots: Option<&[U256]>,
|
2022-08-21 16:59:47 +00:00
|
|
|
payload: &ExecutionPayload,
|
|
|
|
) -> Result<Account> {
|
2022-08-21 21:51:11 +00:00
|
|
|
let slots = slots.unwrap_or(&[]);
|
|
|
|
let proof = self
|
|
|
|
.rpc
|
|
|
|
.get_proof(&address, slots, payload.block_number)
|
|
|
|
.await?;
|
2022-08-20 17:18:40 +00:00
|
|
|
|
2022-08-21 13:13:56 +00:00
|
|
|
let account_path = keccak256(address.as_bytes()).to_vec();
|
2022-08-20 17:18:40 +00:00
|
|
|
let account_encoded = encode_account(&proof);
|
|
|
|
|
2022-08-20 20:33:32 +00:00
|
|
|
let is_valid = verify_proof(
|
|
|
|
&proof.account_proof,
|
|
|
|
&payload.state_root,
|
|
|
|
&account_path,
|
|
|
|
&account_encoded,
|
|
|
|
);
|
2022-08-20 17:18:40 +00:00
|
|
|
|
|
|
|
if !is_valid {
|
|
|
|
eyre::bail!("Invalid Proof");
|
|
|
|
}
|
|
|
|
|
2022-08-21 21:51:11 +00:00
|
|
|
let mut slot_map = HashMap::new();
|
|
|
|
|
|
|
|
for storage_proof in proof.storage_proof {
|
|
|
|
let key = hex_str_to_bytes(&storage_proof.key.encode_hex())?;
|
|
|
|
let value = encode(&storage_proof.value).to_vec();
|
|
|
|
|
|
|
|
let key_hash = keccak256(key);
|
|
|
|
|
|
|
|
let is_valid = verify_proof(
|
|
|
|
&storage_proof.proof,
|
|
|
|
&proof.storage_hash.as_bytes().to_vec(),
|
|
|
|
&key_hash.to_vec(),
|
|
|
|
&value,
|
|
|
|
);
|
|
|
|
|
|
|
|
if !is_valid {
|
|
|
|
eyre::bail!("Invalid Proof");
|
|
|
|
}
|
|
|
|
|
|
|
|
slot_map.insert(storage_proof.key, storage_proof.value);
|
|
|
|
}
|
|
|
|
|
2022-08-21 13:13:56 +00:00
|
|
|
Ok(Account {
|
|
|
|
balance: proof.balance,
|
|
|
|
nonce: proof.nonce,
|
|
|
|
code_hash: proof.code_hash,
|
|
|
|
storage_hash: proof.storage_hash,
|
2022-08-21 21:51:11 +00:00
|
|
|
slots: slot_map,
|
2022-08-21 13:13:56 +00:00
|
|
|
})
|
2022-08-20 17:18:40 +00:00
|
|
|
}
|
2022-08-21 16:59:47 +00:00
|
|
|
|
|
|
|
pub async fn get_code(&self, address: &Address, payload: &ExecutionPayload) -> Result<Vec<u8>> {
|
2022-08-21 21:51:11 +00:00
|
|
|
let account = self.get_account(address, None, payload).await?;
|
2022-08-21 16:59:47 +00:00
|
|
|
let code = self.rpc.get_code(address, payload.block_number).await?;
|
|
|
|
|
|
|
|
let code_hash = keccak256(&code).into();
|
|
|
|
|
|
|
|
if account.code_hash != code_hash {
|
|
|
|
eyre::bail!("Invalid Proof");
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(code)
|
|
|
|
}
|
2022-08-20 17:18:40 +00:00
|
|
|
}
|