add get_code to client

This commit is contained in:
Noah Citron 2022-08-21 12:59:47 -04:00
parent f3040377c9
commit 787956ccea
9 changed files with 75 additions and 26 deletions

View File

@ -41,6 +41,11 @@ impl Client {
Ok(account.nonce) Ok(account.nonce)
} }
pub async fn get_code(&mut self, address: Address) -> Result<Vec<u8>> {
let payload = self.consensus.get_execution_payload().await?;
self.execution.get_code(&address, &payload).await
}
pub fn get_header(&self) -> &Header { pub fn get_header(&self) -> &Header {
self.consensus.get_head() self.consensus.get_head()
} }

View File

@ -1,3 +1,4 @@
use ethers::prelude::Address;
use eyre::Result; use eyre::Result;
use ssz_rs::{Node, Vector}; use ssz_rs::{Node, Vector};
@ -15,3 +16,11 @@ pub fn bytes32_to_node(bytes: &Bytes32) -> Result<Node> {
pub fn bytes_to_bytes32(bytes: &[u8]) -> Bytes32 { pub fn bytes_to_bytes32(bytes: &[u8]) -> Bytes32 {
Vector::from_iter(bytes.to_vec()) Vector::from_iter(bytes.to_vec())
} }
pub fn address_to_hex_string(address: &Address) -> String {
format!("0x{}", hex::encode(address.as_bytes()))
}
pub fn u64_to_hex_string(val: u64) -> String {
format!("0x{:x}", val)
}

View File

@ -3,9 +3,9 @@ use blst::BLST_ERROR;
use eyre::Result; use eyre::Result;
use ssz_rs::prelude::*; use ssz_rs::prelude::*;
use crate::common::utils::*;
use super::types::*;
use super::rpc::Rpc; use super::rpc::Rpc;
use super::types::*;
use crate::common::utils::*;
pub struct ConsensusClient { pub struct ConsensusClient {
rpc: Rpc, rpc: Rpc,
@ -44,10 +44,7 @@ impl ConsensusClient {
next_sync_committee: None, next_sync_committee: None,
}; };
Ok(ConsensusClient { Ok(ConsensusClient { rpc, store })
rpc,
store,
})
} }
pub async fn get_execution_payload(&mut self) -> Result<ExecutionPayload> { pub async fn get_execution_payload(&mut self) -> Result<ExecutionPayload> {

View File

@ -8,7 +8,9 @@ pub struct Rpc {
impl Rpc { impl Rpc {
pub fn new(rpc: &str) -> Self { pub fn new(rpc: &str) -> Self {
Rpc { rpc: rpc.to_string() } Rpc {
rpc: rpc.to_string(),
}
} }
pub async fn get_bootstrap(&self, block_root: &str) -> Result<Bootstrap> { pub async fn get_bootstrap(&self, block_root: &str) -> Result<Bootstrap> {
@ -77,4 +79,3 @@ struct BootstrapResponse {
struct BootstrapData { struct BootstrapData {
v: Bootstrap, v: Bootstrap,
} }

View File

@ -1,10 +1,10 @@
use ethers::prelude::{Address, U256, H256}; use ethers::prelude::{Address, H256, U256};
use ethers::utils::keccak256; use ethers::utils::keccak256;
use eyre::Result; use eyre::Result;
use crate::consensus::types::ExecutionPayload;
use super::proof::{encode_account, verify_proof}; use super::proof::{encode_account, verify_proof};
use super::rpc::Rpc; use super::rpc::Rpc;
use crate::consensus::types::ExecutionPayload;
pub struct ExecutionClient { pub struct ExecutionClient {
rpc: Rpc, rpc: Rpc,
@ -16,11 +16,12 @@ impl ExecutionClient {
ExecutionClient { rpc } ExecutionClient { rpc }
} }
pub async fn get_account(&self, address: &Address, payload: &ExecutionPayload) -> Result<Account> { pub async fn get_account(
let proof = self &self,
.rpc address: &Address,
.get_proof(&address, payload.block_number) payload: &ExecutionPayload,
.await?; ) -> Result<Account> {
let proof = self.rpc.get_proof(&address, payload.block_number).await?;
let account_path = keccak256(address.as_bytes()).to_vec(); let account_path = keccak256(address.as_bytes()).to_vec();
let account_encoded = encode_account(&proof); let account_encoded = encode_account(&proof);
@ -43,6 +44,19 @@ impl ExecutionClient {
storage_hash: proof.storage_hash, storage_hash: proof.storage_hash,
}) })
} }
pub async fn get_code(&self, address: &Address, payload: &ExecutionPayload) -> Result<Vec<u8>> {
let account = self.get_account(address, payload).await?;
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)
}
} }
pub struct Account { pub struct Account {

View File

@ -3,5 +3,5 @@ pub mod types;
mod execution; mod execution;
pub use execution::*; pub use execution::*;
mod rpc;
mod proof; mod proof;
mod rpc;

View File

@ -1,6 +1,12 @@
use ethers::prelude::Address; use ethers::prelude::Address;
use eyre::Result; use eyre::Result;
use jsonrpsee::{core::client::ClientT, http_client::HttpClientBuilder, rpc_params}; use jsonrpsee::{
core::client::ClientT,
http_client::{HttpClient, HttpClientBuilder},
rpc_params,
};
use crate::common::utils::{address_to_hex_string, hex_str_to_bytes, u64_to_hex_string};
use super::types::Proof; use super::types::Proof;
@ -10,15 +16,29 @@ pub struct Rpc {
impl Rpc { impl Rpc {
pub fn new(rpc: &str) -> Self { pub fn new(rpc: &str) -> Self {
Rpc { rpc: rpc.to_string() } Rpc {
rpc: rpc.to_string(),
}
} }
pub async fn get_proof(&self, address: &Address, block: u64) -> Result<Proof> { pub async fn get_proof(&self, address: &Address, block: u64) -> Result<Proof> {
let client = HttpClientBuilder::default().build(&self.rpc)?; let client = self.client()?;
let block_hex = format!("0x{:x}", block); let block_hex = u64_to_hex_string(block);
let addr_hex = format!("0x{}", hex::encode(address.as_bytes())); let addr_hex = address_to_hex_string(address);
let params = rpc_params!(addr_hex, [""], block_hex); let params = rpc_params!(addr_hex, [""], block_hex);
Ok(client.request("eth_getProof", params).await?) Ok(client.request("eth_getProof", params).await?)
} }
pub async fn get_code(&self, address: &Address, block: u64) -> Result<Vec<u8>> {
let client = self.client()?;
let block_hex = u64_to_hex_string(block);
let addr_hex = address_to_hex_string(address);
let params = rpc_params!(addr_hex, block_hex);
let code: String = client.request("eth_getCode", params).await?;
hex_str_to_bytes(&code)
} }
fn client(&self) -> Result<HttpClient> {
Ok(HttpClientBuilder::default().build(&self.rpc)?)
}
}

View File

@ -1,7 +1,7 @@
use ethers::prelude::{Address, H256, U256};
use eyre::Result;
use serde::de::Error; use serde::de::Error;
use serde::Deserialize; use serde::Deserialize;
use ethers::prelude::{U256, H256, Address};
use eyre::Result;
use crate::common::utils::hex_str_to_bytes; use crate::common::utils::hex_str_to_bytes;

View File

@ -6,9 +6,9 @@ use eyre::Result;
use client::Client; use client::Client;
pub mod client; pub mod client;
pub mod common;
pub mod consensus; pub mod consensus;
pub mod execution; pub mod execution;
pub mod common;
#[tokio::main] #[tokio::main]
async fn main() -> Result<()> { async fn main() -> Result<()> {
@ -22,11 +22,14 @@ async fn main() -> Result<()> {
let header = client.get_header(); let header = client.get_header();
println!("synced up to slot: {}", header.slot); println!("synced up to slot: {}", header.slot);
let address = Address::from_str("0xe0Fa62CD8543473627D337fAe1212d4E639EE932")?; let address = Address::from_str("0x14f9D4aF749609c1438528C0Cce1cC3f6D411c47")?;
let balance = client.get_balance(address).await?; let balance = client.get_balance(address).await?;
let nonce = client.get_nonce(address).await?; let nonce = client.get_nonce(address).await?;
let code = client.get_code(address).await?;
println!("balance: {}", balance); println!("balance: {}", balance);
println!("nonce: {}", nonce); println!("nonce: {}", nonce);
println!("code: 0x{}...", hex::encode(code[..5].to_vec()));
Ok(()) Ok(())
} }