Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(op): fixes impl of eth api for OP #9377

Merged
merged 5 commits into from
Jul 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading