Skip to content

Commit

Permalink
generic execution client
Browse files Browse the repository at this point in the history
  • Loading branch information
ncitron committed Aug 27, 2024
1 parent e393cbc commit 2e0b658
Show file tree
Hide file tree
Showing 16 changed files with 242 additions and 163 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 6 additions & 2 deletions client/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -358,11 +358,15 @@ impl<DB: Database> Client<DB> {
&self,
block: BlockTag,
full_tx: bool,
) -> Result<Option<Block>> {
) -> Result<Option<Block<Transaction>>> {
self.node.get_block_by_number(block, full_tx).await
}

pub async fn get_block_by_hash(&self, hash: B256, full_tx: bool) -> Result<Option<Block>> {
pub async fn get_block_by_hash(
&self,
hash: B256,
full_tx: bool,
) -> Result<Option<Block<Transaction>>> {
self.node.get_block_by_hash(hash, full_tx).await
}

Expand Down
15 changes: 12 additions & 3 deletions client/src/node.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::sync::Arc;

use alloy::network::Ethereum;
use alloy::primitives::{Address, Bytes, B256, U256};
use alloy::rpc::types::{
Filter, Log, SyncInfo, SyncStatus, Transaction, TransactionReceipt, TransactionRequest,
Expand All @@ -21,7 +22,7 @@ use crate::errors::NodeError;

pub struct Node<DB: Database> {
pub consensus: ConsensusClient<NimbusRpc, DB>,
pub execution: Arc<ExecutionClient<HttpRpc>>,
pub execution: Arc<ExecutionClient<Ethereum, HttpRpc<Ethereum>>>,
pub config: Arc<Config>,
pub history_size: usize,
}
Expand Down Expand Up @@ -195,7 +196,11 @@ impl<DB: Database> Node<DB> {
Ok(block.number.to())
}

pub async fn get_block_by_number(&self, tag: BlockTag, full_tx: bool) -> Result<Option<Block>> {
pub async fn get_block_by_number(
&self,
tag: BlockTag,
full_tx: bool,
) -> Result<Option<Block<Transaction>>> {
self.check_blocktag_age(&tag).await?;

match self.execution.get_block(tag, full_tx).await {
Expand All @@ -204,7 +209,11 @@ impl<DB: Database> Node<DB> {
}
}

pub async fn get_block_by_hash(&self, hash: B256, full_tx: bool) -> Result<Option<Block>> {
pub async fn get_block_by_hash(
&self,
hash: B256,
full_tx: bool,
) -> Result<Option<Block<Transaction>>> {
let block = self.execution.get_block_by_hash(hash, full_tx).await;

match block {
Expand Down
16 changes: 12 additions & 4 deletions client/src/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,13 @@ trait EthRpc {
&self,
block: BlockTag,
full_tx: bool,
) -> Result<Option<Block>, Error>;
) -> Result<Option<Block<Transaction>>, Error>;
#[method(name = "getBlockByHash")]
async fn get_block_by_hash(&self, hash: B256, full_tx: bool) -> Result<Option<Block>, Error>;
async fn get_block_by_hash(
&self,
hash: B256,
full_tx: bool,
) -> Result<Option<Block<Transaction>>, Error>;
#[method(name = "sendRawTransaction")]
async fn send_raw_transaction(&self, bytes: Bytes) -> Result<B256, Error>;
#[method(name = "getTransactionReceipt")]
Expand Down Expand Up @@ -193,11 +197,15 @@ impl<DB: Database> EthRpcServer for RpcInner<DB> {
&self,
block: BlockTag,
full_tx: bool,
) -> Result<Option<Block>, Error> {
) -> Result<Option<Block<Transaction>>, Error> {
convert_err(self.node.get_block_by_number(block, full_tx).await)
}

async fn get_block_by_hash(&self, hash: B256, full_tx: bool) -> Result<Option<Block>, Error> {
async fn get_block_by_hash(
&self,
hash: B256,
full_tx: bool,
) -> Result<Option<Block<Transaction>>, Error> {
convert_err(self.node.get_block_by_hash(hash, full_tx).await)
}

Expand Down
3 changes: 2 additions & 1 deletion common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ version = "0.5.5"
edition = "2021"

[dependencies]
alloy = { version = "0.2.1", features = ["rpc-types"] }
alloy = { version = "0.2.1", features = ["rpc-types", "serde"] }
eyre.workspace = true
serde.workspace = true
hex.workspace = true
Expand All @@ -14,3 +14,4 @@ thiserror.workspace = true
tracing.workspace = true
zduny-wasm-timer.workspace = true
milagro_bls.workspace = true
revm.workspace = true
1 change: 1 addition & 0 deletions common/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
pub mod errors;
pub mod network_spec;
pub mod types;

pub mod config {
Expand Down
94 changes: 94 additions & 0 deletions common/src/network_spec.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
use alloy::{
consensus::{Receipt, ReceiptWithBloom, TxReceipt, TxType},
network::{Ethereum, Network, TransactionBuilder},
rpc::types::{Log, Transaction, TransactionReceipt, TransactionRequest},
};
use revm::primitives::{BlobExcessGasAndPrice, BlockEnv, TxEnv, U256};

use crate::types::Block;

pub trait NetworkSpec: Network {
fn encode_receipt(receipt: &Self::ReceiptResponse) -> Vec<u8>;
fn receipt_contains(list: &[Self::ReceiptResponse], elem: &Self::ReceiptResponse) -> bool;
fn receipt_logs(receipt: &Self::ReceiptResponse) -> Vec<Log>;
fn tx_env(request: &Self::TransactionRequest) -> TxEnv;
fn block_env(block: &Block<Self::TransactionResponse>) -> BlockEnv;
}

impl NetworkSpec for Ethereum {
fn encode_receipt(receipt: &TransactionReceipt) -> Vec<u8> {
let tx_type = receipt.transaction_type();
let receipt = receipt.inner.as_receipt_with_bloom().unwrap();
let logs = receipt
.logs()
.iter()
.map(|l| l.inner.clone())
.collect::<Vec<_>>();

let consensus_receipt = Receipt {
cumulative_gas_used: receipt.cumulative_gas_used(),
status: *receipt.status_or_post_state(),
logs,
};

let rwb = ReceiptWithBloom::new(consensus_receipt, receipt.bloom());
let encoded = alloy::rlp::encode(rwb);

match tx_type {
TxType::Legacy => encoded,
_ => [vec![tx_type as u8], encoded].concat(),
}
}

fn receipt_contains(list: &[TransactionReceipt], elem: &TransactionReceipt) -> bool {
for receipt in list {
if receipt == elem {
return true;
}
}

false
}

fn receipt_logs(receipt: &TransactionReceipt) -> Vec<Log> {
receipt.inner.logs().to_vec()
}

fn tx_env(tx: &TransactionRequest) -> TxEnv {
let mut tx_env = TxEnv::default();
tx_env.caller = tx.from.unwrap_or_default();
tx_env.gas_limit = tx.gas_limit().map(|v| v as u64).unwrap_or(u64::MAX);
tx_env.gas_price = tx.gas_price().map(U256::from).unwrap_or_default();
tx_env.transact_to = tx.to.unwrap_or_default();
tx_env.value = tx.value.unwrap_or_default();
tx_env.data = tx.input().unwrap_or_default().clone();
tx_env.nonce = tx.nonce();
tx_env.chain_id = tx.chain_id();
tx_env.access_list = tx.access_list().map(|v| v.to_vec()).unwrap_or_default();
tx_env.gas_priority_fee = tx.max_priority_fee_per_gas().map(U256::from);
tx_env.max_fee_per_blob_gas = tx.max_fee_per_gas().map(U256::from);
tx_env.blob_hashes = tx
.blob_versioned_hashes
.as_ref()
.map(|v| v.to_vec())
.unwrap_or_default();

tx_env
}

fn block_env(block: &Block<Transaction>) -> BlockEnv {
let mut block_env = BlockEnv::default();
block_env.number = block.number.to();
block_env.coinbase = block.miner;
block_env.timestamp = block.timestamp.to();
block_env.gas_limit = block.gas_limit.to();
block_env.basefee = block.base_fee_per_gas;
block_env.difficulty = block.difficulty;
block_env.prevrandao = Some(block.mix_hash);
block_env.blob_excess_gas_and_price = block
.excess_blob_gas
.map(|v| BlobExcessGasAndPrice::new(v.to()));

block_env
}
}
18 changes: 9 additions & 9 deletions common/src/types.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
use std::fmt::Display;

use alloy::network::TransactionResponse;
use alloy::primitives::{Address, Bytes, B256, U256, U64};
use alloy::rpc::types::Transaction;
use serde::{de::Error, ser::SerializeSeq, Deserialize, Serialize};

#[derive(Deserialize, Serialize, Debug, Clone, Default)]
#[serde(rename_all = "camelCase")]
pub struct Block {
pub struct Block<T: TransactionResponse + Serialize> {
pub number: U64,
pub base_fee_per_gas: U256,
pub difficulty: U256,
Expand All @@ -25,35 +25,35 @@ pub struct Block {
pub state_root: B256,
pub timestamp: U64,
pub total_difficulty: U64,
pub transactions: Transactions,
pub transactions: Transactions<T>,
pub transactions_root: B256,
pub uncles: Vec<B256>,
pub blob_gas_used: Option<U64>,
pub excess_blob_gas: Option<U64>,
}

#[derive(Deserialize, Debug, Clone)]
pub enum Transactions {
pub enum Transactions<T: TransactionResponse> {
Hashes(Vec<B256>),
Full(Vec<Transaction>),
Full(Vec<T>),
}

impl Default for Transactions {
impl<T: TransactionResponse> Default for Transactions<T> {
fn default() -> Self {
Self::Full(Vec::new())
}
}

impl Transactions {
impl<T: TransactionResponse> Transactions<T> {
pub fn hashes(&self) -> Vec<B256> {
match self {
Self::Hashes(hashes) => hashes.clone(),
Self::Full(txs) => txs.iter().map(|tx| tx.hash).collect(),
Self::Full(txs) => txs.iter().map(|tx| tx.tx_hash()).collect(),
}
}
}

impl Serialize for Transactions {
impl<T: TransactionResponse + Serialize> Serialize for Transactions<T> {
fn serialize<S>(&self, s: S) -> std::result::Result<S::Ok, S::Error>
where
S: serde::Serializer,
Expand Down
4 changes: 2 additions & 2 deletions consensus-core/src/types/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ use alloy::rpc::types::{Parity, Signature, Transaction};
use super::ExecutionPayload;
use common::types::{Block, Transactions};

impl From<ExecutionPayload> for Block {
fn from(value: ExecutionPayload) -> Block {
impl From<ExecutionPayload> for Block<Transaction> {
fn from(value: ExecutionPayload) -> Block<Transaction> {
let empty_nonce = "0x0000000000000000".to_string();
let empty_uncle_hash = "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347";

Expand Down
13 changes: 7 additions & 6 deletions consensus/src/consensus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use std::process;
use std::sync::Arc;

use alloy::primitives::B256;
use alloy::rpc::types::Transaction;
use chrono::Duration;
use eyre::eyre;
use eyre::Result;
Expand Down Expand Up @@ -35,8 +36,8 @@ use consensus_core::{
};

pub struct ConsensusClient<R: ConsensusRpc, DB: Database> {
pub block_recv: Option<Receiver<Block>>,
pub finalized_block_recv: Option<watch::Receiver<Option<Block>>>,
pub block_recv: Option<Receiver<Block<Transaction>>>,
pub finalized_block_recv: Option<watch::Receiver<Option<Block<Transaction>>>>,
pub checkpoint_recv: watch::Receiver<Option<B256>>,
genesis_time: u64,
db: DB,
Expand All @@ -48,8 +49,8 @@ pub struct Inner<R: ConsensusRpc> {
pub rpc: R,
pub store: LightClientStore,
last_checkpoint: Option<B256>,
block_send: Sender<Block>,
finalized_block_send: watch::Sender<Option<Block>>,
block_send: Sender<Block<Transaction>>,
finalized_block_send: watch::Sender<Option<Block<Transaction>>>,
checkpoint_send: watch::Sender<Option<B256>>,
pub config: Arc<Config>,
}
Expand Down Expand Up @@ -168,8 +169,8 @@ async fn sync_all_fallbacks<R: ConsensusRpc>(inner: &mut Inner<R>, chain_id: u64
impl<R: ConsensusRpc> Inner<R> {
pub fn new(
rpc: &str,
block_send: Sender<Block>,
finalized_block_send: watch::Sender<Option<Block>>,
block_send: Sender<Block<Transaction>>,
finalized_block_send: watch::Sender<Option<Block<Transaction>>>,
checkpoint_send: watch::Sender<Option<B256>>,
config: Arc<Config>,
) -> Inner<R> {
Expand Down
Loading

0 comments on commit 2e0b658

Please sign in to comment.