refactor module structure

This commit is contained in:
Noah Citron 2022-08-21 11:21:50 -04:00
parent a7a5942451
commit 5240385dcd
15 changed files with 173 additions and 150 deletions

View File

@ -1,7 +1,9 @@
use ethers::prelude::{Address, U256};
use eyre::Result;
use crate::{consensus::ConsensusClient, execution::ExecutionClient, consensus_rpc::Header};
use crate::consensus::types::Header;
use crate::consensus::ConsensusClient;
use crate::execution::ExecutionClient;
pub struct Client {
consensus: ConsensusClient,

2
src/client/mod.rs Normal file
View File

@ -0,0 +1,2 @@
mod client;
pub use client::*;

1
src/common/mod.rs Normal file
View File

@ -0,0 +1 @@
pub mod utils;

View File

@ -1,7 +1,7 @@
use eyre::Result;
use ssz_rs::{Node, Vector};
use crate::consensus_rpc::Bytes32;
use crate::consensus::types::Bytes32;
pub fn hex_str_to_bytes(s: &str) -> Result<Vec<u8>> {
let stripped = s.strip_prefix("0x").unwrap_or(s);

View File

@ -3,11 +3,12 @@ use blst::BLST_ERROR;
use eyre::Result;
use ssz_rs::prelude::*;
use crate::consensus_rpc::*;
use crate::utils::*;
use crate::common::utils::*;
use super::types::*;
use super::rpc::Rpc;
pub struct ConsensusClient {
consensus_rpc: ConsensusRpc,
rpc: Rpc,
store: Store,
}
@ -20,9 +21,9 @@ struct Store {
impl ConsensusClient {
pub async fn new(nimbus_rpc: &str, checkpoint_block_root: &str) -> Result<ConsensusClient> {
let consensus_rpc = ConsensusRpc::new(nimbus_rpc);
let rpc = Rpc::new(nimbus_rpc);
let mut bootstrap = consensus_rpc.get_bootstrap(checkpoint_block_root).await?;
let mut bootstrap = rpc.get_bootstrap(checkpoint_block_root).await?;
let committee_valid = is_current_committee_proof_valid(
&bootstrap.header,
@ -44,14 +45,14 @@ impl ConsensusClient {
};
Ok(ConsensusClient {
consensus_rpc,
rpc,
store,
})
}
pub async fn get_execution_payload(&mut self) -> Result<ExecutionPayload> {
let slot = self.store.header.slot;
let mut block = self.consensus_rpc.get_block(slot).await?;
let mut block = self.rpc.get_block(slot).await?;
let block_hash = block.hash_tree_root()?;
let verified_block_hash = self.store.header.hash_tree_root()?;
@ -68,14 +69,14 @@ impl ConsensusClient {
pub async fn sync(&mut self) -> Result<()> {
let current_period = calc_sync_period(self.store.header.slot);
let updates = self.consensus_rpc.get_updates(current_period).await?;
let updates = self.rpc.get_updates(current_period).await?;
for mut update in updates {
self.verify_update(&mut update)?;
self.apply_update(&update);
}
let finality_update = self.consensus_rpc.get_finality_update().await?;
let finality_update = self.rpc.get_finality_update().await?;
let mut finality_update_generic = Update {
attested_header: finality_update.attested_header,
next_sync_committee: None,
@ -89,7 +90,7 @@ impl ConsensusClient {
self.verify_update(&mut finality_update_generic)?;
self.apply_update(&finality_update_generic);
self.consensus_rpc.get_block(self.store.header.slot).await?;
self.rpc.get_block(self.store.header.slot).await?;
Ok(())
}

6
src/consensus/mod.rs Normal file
View File

@ -0,0 +1,6 @@
pub mod types;
mod consensus;
pub use consensus::*;
mod rpc;

80
src/consensus/rpc.rs Normal file
View File

@ -0,0 +1,80 @@
use eyre::Result;
use super::types::*;
pub struct Rpc {
rpc: String,
}
impl Rpc {
pub fn new(rpc: &str) -> Self {
Rpc { rpc: rpc.to_string() }
}
pub async fn get_bootstrap(&self, block_root: &str) -> Result<Bootstrap> {
let req = format!(
"{}/eth/v0/beacon/light_client/bootstrap/{}",
self.rpc, block_root
);
let res = reqwest::get(req).await?.json::<BootstrapResponse>().await?;
Ok(res.data.v)
}
pub async fn get_updates(&self, period: u64) -> Result<Vec<Update>> {
let req = format!(
"{}/eth/v0/beacon/light_client/updates?start_period={}&count=1000",
self.rpc, period
);
let res = reqwest::get(req).await?.json::<UpdateResponse>().await?;
Ok(res.data)
}
pub async fn get_finality_update(&self) -> Result<FinalityUpdate> {
let req = format!("{}/eth/v0/beacon/light_client/finality_update", self.rpc);
let res = reqwest::get(req)
.await?
.json::<FinalityUpdateResponse>()
.await?;
Ok(res.data)
}
pub async fn get_block(&self, slot: u64) -> Result<BeaconBlock> {
let req = format!("{}/eth/v2/beacon/blocks/{}", self.rpc, slot);
let res = reqwest::get(req)
.await?
.json::<BeaconBlockResponse>()
.await?;
Ok(res.data.message)
}
}
#[derive(serde::Deserialize, Debug)]
struct BeaconBlockResponse {
data: BeaconBlockData,
}
#[derive(serde::Deserialize, Debug)]
struct BeaconBlockData {
message: BeaconBlock,
}
#[derive(serde::Deserialize, Debug)]
struct UpdateResponse {
data: Vec<Update>,
}
#[derive(serde::Deserialize, Debug)]
struct FinalityUpdateResponse {
data: FinalityUpdate,
}
#[derive(serde::Deserialize, Debug)]
struct BootstrapResponse {
data: BootstrapData,
}
#[derive(serde::Deserialize, Debug)]
struct BootstrapData {
v: Bootstrap,
}

View File

@ -2,55 +2,7 @@ use eyre::Result;
use serde::de::Error;
use ssz_rs::prelude::*;
use crate::utils::*;
pub struct ConsensusRpc {
rpc: String,
}
impl ConsensusRpc {
pub fn new(rpc: &str) -> Self {
ConsensusRpc {
rpc: rpc.to_string(),
}
}
pub async fn get_bootstrap(&self, block_root: &str) -> Result<Bootstrap> {
let req = format!(
"{}/eth/v0/beacon/light_client/bootstrap/{}",
self.rpc, block_root
);
let res = reqwest::get(req).await?.json::<BootstrapResponse>().await?;
Ok(res.data.v)
}
pub async fn get_updates(&self, period: u64) -> Result<Vec<Update>> {
let req = format!(
"{}/eth/v0/beacon/light_client/updates?start_period={}&count=1000",
self.rpc, period
);
let res = reqwest::get(req).await?.json::<UpdateResponse>().await?;
Ok(res.data)
}
pub async fn get_finality_update(&self) -> Result<FinalityUpdate> {
let req = format!("{}/eth/v0/beacon/light_client/finality_update", self.rpc);
let res = reqwest::get(req)
.await?
.json::<FinalityUpdateResponse>()
.await?;
Ok(res.data)
}
pub async fn get_block(&self, slot: u64) -> Result<BeaconBlock> {
let req = format!("{}/eth/v2/beacon/blocks/{}", self.rpc, slot);
let res = reqwest::get(req)
.await?
.json::<BeaconBlockResponse>()
.await?;
Ok(res.data.message)
}
}
use crate::common::utils::hex_str_to_bytes;
pub type BLSPubKey = Vector<u8, 48>;
pub type SignatureBytes = Vector<u8, 96>;
@ -229,36 +181,6 @@ pub struct SyncAggregate {
pub sync_committee_signature: SignatureBytes,
}
#[derive(serde::Deserialize, Debug)]
struct BeaconBlockResponse {
data: BeaconBlockData,
}
#[derive(serde::Deserialize, Debug)]
struct BeaconBlockData {
message: BeaconBlock,
}
#[derive(serde::Deserialize, Debug)]
struct UpdateResponse {
data: Vec<Update>,
}
#[derive(serde::Deserialize, Debug)]
struct FinalityUpdateResponse {
data: FinalityUpdate,
}
#[derive(serde::Deserialize, Debug)]
struct BootstrapResponse {
data: BootstrapData,
}
#[derive(serde::Deserialize, Debug)]
struct BootstrapData {
v: Bootstrap,
}
fn pubkey_deserialize<'de, D>(deserializer: D) -> Result<BLSPubKey, D::Error>
where
D: serde::Deserializer<'de>,

View File

@ -2,9 +2,9 @@ use ethers::prelude::{Address, U256, H256};
use ethers::utils::keccak256;
use eyre::Result;
use crate::consensus_rpc::ExecutionPayload;
use crate::execution_rpc::ExecutionRpc;
use crate::proof::{encode_account, verify_proof};
use crate::consensus::types::ExecutionPayload;
use super::proof::{encode_account, verify_proof};
use super::execution_rpc::ExecutionRpc;
pub struct ExecutionClient {
execution_rpc: ExecutionRpc,

View File

@ -0,0 +1,26 @@
use ethers::prelude::Address;
use eyre::Result;
use jsonrpsee::{core::client::ClientT, http_client::HttpClientBuilder, rpc_params};
use super::types::Proof;
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: &Address, block: u64) -> Result<Proof> {
let client = HttpClientBuilder::default().build(&self.rpc)?;
let block_hex = format!("0x{:x}", block);
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?)
}
}

7
src/execution/mod.rs Normal file
View File

@ -0,0 +1,7 @@
pub mod types;
mod execution;
pub use execution::*;
mod execution_rpc;
mod proof;

View File

@ -1,7 +1,7 @@
use ethers::utils::keccak256;
use ethers::utils::rlp::{decode_list, RlpStream};
use crate::execution_rpc::Proof;
use crate::execution::types::Proof;
pub fn verify_proof(proof: &Vec<Vec<u8>>, root: &Vec<u8>, path: &Vec<u8>, value: &Vec<u8>) -> bool {
let mut expected_hash = root.clone();

30
src/execution/types.rs Normal file
View File

@ -0,0 +1,30 @@
use serde::de::Error;
use serde::Deserialize;
use ethers::prelude::{U256, H256, Address};
use eyre::Result;
use crate::common::utils::hex_str_to_bytes;
#[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)?)
}

View File

@ -1,51 +0,0 @@
use ethers::prelude::{Address, H256, U256};
use eyre::Result;
use jsonrpsee::{core::client::ClientT, http_client::HttpClientBuilder, rpc_params};
use serde::de::Error;
use serde::Deserialize;
use crate::utils::hex_str_to_bytes;
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: &Address, block: u64) -> Result<Proof> {
let client = HttpClientBuilder::default().build(&self.rpc)?;
let block_hex = format!("0x{:x}", block);
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?)
}
}
#[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)?)
}

View File

@ -7,11 +7,8 @@ use client::Client;
pub mod client;
pub mod consensus;
pub mod consensus_rpc;
pub mod execution;
pub mod execution_rpc;
pub mod proof;
pub mod utils;
pub mod common;
#[tokio::main]
async fn main() -> Result<()> {