Skip to content

Commit

Permalink
fix(op): fixes impl of eth api for OP (paradigmxyz#9377)
Browse files Browse the repository at this point in the history
  • Loading branch information
emhane authored and smatthewenglish committed Jul 9, 2024
1 parent eb5902b commit ca7a949
Show file tree
Hide file tree
Showing 12 changed files with 417 additions and 91 deletions.
6 changes: 6 additions & 0 deletions Cargo.lock

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

28 changes: 25 additions & 3 deletions crates/optimism/rpc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,47 @@ rust-version.workspace = true
license.workspace = true
homepage.workspace = true
repository.workspace = true
description = "Ethereum RPC implementation for optimism."

[lints]
workspace = true

[dependencies]
# reth
reth-chainspec.workspace = true
reth-errors.workspace = true
reth-evm-optimism.workspace = true
reth-evm.workspace = true
reth-primitives.workspace = true
reth-provider.workspace = true
reth-rpc-eth-api.workspace = true
reth-rpc-eth-types.workspace = true
reth-rpc-server-types.workspace = true
reth-rpc-types.workspace = true
reth-chainspec.workspace = true
reth-provider.workspace = true
reth-tasks = { workspace = true, features = ["rayon"] }
reth-transaction-pool.workspace = true

# ethereum
alloy-primitives.workspace = true
revm.workspace = true

# async
parking_lot.workspace = true
tokio.workspace = true
tokio.workspace = true

# rpc
jsonrpsee.workspace = true

# misc
thiserror.workspace = true

[features]
optimism = [
"reth-chainspec/optimism",
"reth-evm-optimism/optimism",
"reth-primitives/optimism",
"reth-provider/optimism",
"reth-rpc-eth-api/optimism",
"reth-rpc-eth-types/optimism",
"revm/optimism"
]
31 changes: 31 additions & 0 deletions crates/optimism/rpc/src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
//! RPC errors specific to OP.
use jsonrpsee::types::ErrorObject;
use reth_rpc_eth_types::EthApiError;
use reth_rpc_server_types::result::internal_rpc_err;
use reth_rpc_types::ToRpcError;

/// Optimism specific errors, that extend [`EthApiError`].
#[derive(Debug, thiserror::Error)]
pub enum OpEthApiError {
/// Thrown when calculating L1 gas fee.
#[error("failed to calculate l1 gas fee")]
L1BlockFeeError,
/// Thrown when calculating L1 gas used
#[error("failed to calculate l1 gas used")]
L1BlockGasError,
}

impl ToRpcError for OpEthApiError {
fn to_rpc_error(&self) -> ErrorObject<'static> {
match self {
Self::L1BlockFeeError | Self::L1BlockGasError => internal_rpc_err(self.to_string()),
}
}
}

impl From<OpEthApiError> for EthApiError {
fn from(err: OpEthApiError) -> Self {
Self::other(err)
}
}
75 changes: 75 additions & 0 deletions crates/optimism/rpc/src/eth/block.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
//! Loads and formats OP block RPC response.
use reth_primitives::TransactionMeta;
use reth_provider::{BlockReaderIdExt, HeaderProvider};
use reth_rpc_eth_api::helpers::{EthApiSpec, EthBlocks, LoadBlock, LoadReceipt, LoadTransaction};
use reth_rpc_eth_types::{EthResult, EthStateCache, ReceiptBuilder};
use reth_rpc_types::{AnyTransactionReceipt, BlockId};

use crate::{op_receipt_fields, OpEthApi};

impl<Eth> EthBlocks for OpEthApi<Eth>
where
Eth: EthBlocks + EthApiSpec + LoadTransaction,
{
fn provider(&self) -> impl HeaderProvider {
EthBlocks::provider(&self.inner)
}

async fn block_receipts(
&self,
block_id: BlockId,
) -> EthResult<Option<Vec<AnyTransactionReceipt>>>
where
Self: LoadReceipt,
{
if let Some((block, receipts)) = self.load_block_and_receipts(block_id).await? {
let block_number = block.number;
let base_fee = block.base_fee_per_gas;
let block_hash = block.hash();
let excess_blob_gas = block.excess_blob_gas;
let timestamp = block.timestamp;
let block = block.unseal();

let l1_block_info = reth_evm_optimism::extract_l1_info(&block).ok();

let receipts = block
.body
.into_iter()
.zip(receipts.iter())
.enumerate()
.map(|(idx, (ref tx, receipt))| {
let meta = TransactionMeta {
tx_hash: tx.hash,
index: idx as u64,
block_hash,
block_number,
base_fee,
excess_blob_gas,
timestamp,
};

let optimism_tx_meta =
self.build_op_tx_meta(tx, l1_block_info.clone(), timestamp)?;

ReceiptBuilder::new(tx, meta, receipt, &receipts).map(|builder| {
op_receipt_fields(builder, tx, receipt, optimism_tx_meta).build()
})
})
.collect::<EthResult<Vec<_>>>();
return receipts.map(Some)
}

Ok(None)
}
}

impl<Eth: LoadBlock> LoadBlock for OpEthApi<Eth> {
fn provider(&self) -> impl BlockReaderIdExt {
LoadBlock::provider(&self.inner)
}

fn cache(&self) -> &EthStateCache {
self.inner.cache()
}
}
100 changes: 16 additions & 84 deletions crates/optimism/rpc/src/eth/mod.rs
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
//! OP-Reth `eth_` endpoint implementation.
pub mod receipt;
pub mod transaction;

mod block;
mod pending_block;

use std::{future::Future, sync::Arc};

use alloy_primitives::{Address, U64};
use reth_chainspec::ChainInfo;
use reth_chainspec::{ChainInfo, ChainSpec};
use reth_errors::RethResult;
use reth_evm::ConfigureEvm;
use reth_provider::{
BlockReaderIdExt, ChainSpecProvider, EvmEnvProvider, HeaderProvider, StateProviderFactory,
use reth_provider::{BlockReaderIdExt, ChainSpecProvider, HeaderProvider, StateProviderFactory};
use reth_rpc_eth_api::helpers::{
Call, EthApiSpec, EthCall, EthFees, EthState, LoadFee, LoadState, SpawnBlocking, Trace,
};
use reth_rpc_eth_api::{
helpers::{
Call, EthApiSpec, EthBlocks, EthCall, EthFees, EthSigner, EthState, EthTransactions,
LoadBlock, LoadFee, LoadPendingBlock, LoadReceipt, LoadState, LoadTransaction,
SpawnBlocking, Trace,
},
RawTransactionForwarder,
};
use reth_rpc_eth_types::{EthStateCache, PendingBlock};
use reth_rpc_eth_types::EthStateCache;
use reth_rpc_types::SyncStatus;
use reth_tasks::{pool::BlockingTaskPool, TaskSpawner};
use reth_transaction_pool::TransactionPool;
use std::future::Future;
use tokio::sync::{AcquireError, Mutex, OwnedSemaphorePermit};
use tokio::sync::{AcquireError, OwnedSemaphorePermit};

/// OP-Reth `Eth` API implementation.
///
Expand Down Expand Up @@ -68,35 +68,9 @@ impl<Eth: EthApiSpec> EthApiSpec for OpEthApi<Eth> {
fn sync_status(&self) -> RethResult<SyncStatus> {
self.inner.sync_status()
}
}

impl<Eth: LoadBlock> LoadBlock for OpEthApi<Eth> {
fn provider(&self) -> impl BlockReaderIdExt {
LoadBlock::provider(&self.inner)
}

fn cache(&self) -> &reth_rpc_eth_types::EthStateCache {
self.inner.cache()
}
}

impl<Eth: LoadPendingBlock> LoadPendingBlock for OpEthApi<Eth> {
fn provider(
&self,
) -> impl BlockReaderIdExt + EvmEnvProvider + ChainSpecProvider + StateProviderFactory {
self.inner.provider()
}

fn pool(&self) -> impl TransactionPool {
self.inner.pool()
}

fn pending_block(&self) -> &Mutex<Option<PendingBlock>> {
self.inner.pending_block()
}

fn evm_config(&self) -> &impl ConfigureEvm {
self.inner.evm_config()
fn chain_spec(&self) -> Arc<ChainSpec> {
self.inner.chain_spec()
}
}

Expand All @@ -123,12 +97,6 @@ impl<Eth: SpawnBlocking> SpawnBlocking for OpEthApi<Eth> {
}
}

impl<Eth: LoadReceipt> LoadReceipt for OpEthApi<Eth> {
fn cache(&self) -> &EthStateCache {
self.inner.cache()
}
}

impl<Eth: LoadFee> LoadFee for OpEthApi<Eth> {
fn provider(&self) -> impl reth_provider::BlockIdReader + HeaderProvider + ChainSpecProvider {
LoadFee::provider(&self.inner)
Expand Down Expand Up @@ -171,42 +139,6 @@ impl<Eth: LoadState> LoadState for OpEthApi<Eth> {
}
}

impl<Eth: LoadTransaction> LoadTransaction for OpEthApi<Eth> {
type Pool = Eth::Pool;

fn provider(&self) -> impl reth_provider::TransactionsProvider {
LoadTransaction::provider(&self.inner)
}

fn cache(&self) -> &EthStateCache {
LoadTransaction::cache(&self.inner)
}

fn pool(&self) -> &Self::Pool {
LoadTransaction::pool(&self.inner)
}
}

impl<Eth: EthTransactions> EthTransactions for OpEthApi<Eth> {
fn provider(&self) -> impl BlockReaderIdExt {
EthTransactions::provider(&self.inner)
}

fn raw_tx_forwarder(&self) -> Option<std::sync::Arc<dyn RawTransactionForwarder>> {
self.inner.raw_tx_forwarder()
}

fn signers(&self) -> &parking_lot::RwLock<Vec<Box<dyn EthSigner>>> {
self.inner.signers()
}
}

impl<Eth: EthBlocks> EthBlocks for OpEthApi<Eth> {
fn provider(&self) -> impl HeaderProvider {
EthBlocks::provider(&self.inner)
}
}

impl<Eth: EthState> EthState for OpEthApi<Eth> {
fn max_proof_window(&self) -> u64 {
self.inner.max_proof_window()
Expand Down
72 changes: 72 additions & 0 deletions crates/optimism/rpc/src/eth/pending_block.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
//! Loads OP pending block for a RPC response.
use reth_primitives::{
revm_primitives::{BlockEnv, ExecutionResult},
BlockNumber, Receipt, TransactionSignedEcRecovered, B256,
};
use reth_provider::{ChainSpecProvider, ExecutionOutcome};
use reth_rpc_eth_api::helpers::LoadPendingBlock;
use reth_rpc_eth_types::PendingBlock;

use crate::OpEthApi;

impl<Eth> LoadPendingBlock for OpEthApi<Eth>
where
Eth: LoadPendingBlock,
{
#[inline]
fn provider(
&self,
) -> impl reth_provider::BlockReaderIdExt
+ reth_provider::EvmEnvProvider
+ reth_provider::ChainSpecProvider
+ reth_provider::StateProviderFactory {
self.inner.provider()
}

#[inline]
fn pool(&self) -> impl reth_transaction_pool::TransactionPool {
self.inner.pool()
}

#[inline]
fn pending_block(&self) -> &tokio::sync::Mutex<Option<PendingBlock>> {
self.inner.pending_block()
}

#[inline]
fn evm_config(&self) -> &impl reth_evm::ConfigureEvm {
self.inner.evm_config()
}

fn assemble_receipt(
&self,
tx: &TransactionSignedEcRecovered,
result: ExecutionResult,
cumulative_gas_used: u64,
) -> Receipt {
Receipt {
tx_type: tx.tx_type(),
success: result.is_success(),
cumulative_gas_used,
logs: result.into_logs().into_iter().map(Into::into).collect(),
deposit_nonce: None,
deposit_receipt_version: None,
}
}

fn receipts_root(
&self,
_block_env: &BlockEnv,
execution_outcome: &ExecutionOutcome,
block_number: BlockNumber,
) -> B256 {
execution_outcome
.optimism_receipts_root_slow(
block_number,
self.provider().chain_spec().as_ref(),
_block_env.timestamp.to::<u64>(),
)
.expect("Block is present")
}
}
Loading

0 comments on commit ca7a949

Please sign in to comment.