Skip to content

Commit

Permalink
chore(rpc): EthApiTypes trait for network specific error AT (#9523)
Browse files Browse the repository at this point in the history
Co-authored-by: Matthias Seitz <[email protected]>
  • Loading branch information
emhane and mattsse authored Jul 25, 2024
1 parent f175f6e commit 0be2c17
Show file tree
Hide file tree
Showing 39 changed files with 879 additions and 479 deletions.
2 changes: 2 additions & 0 deletions Cargo.lock

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

1 change: 0 additions & 1 deletion bin/reth/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,6 @@ optimism = [
"reth-blockchain-tree/optimism",
"dep:reth-node-optimism",
"reth-node-core/optimism",
"reth-rpc-eth-types/optimism",
]

# no-op feature flag for switching between the `optimism` and default functionality in CI matrices
Expand Down
11 changes: 4 additions & 7 deletions crates/e2e-test-utils/src/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,9 @@ use alloy_consensus::TxEnvelope;
use alloy_network::eip2718::Decodable2718;
use reth::{
builder::{rpc::RpcRegistry, FullNodeComponents},
rpc::{
api::{
eth::helpers::{EthApiSpec, EthTransactions, TraceExt},
DebugApiServer,
},
server_types::eth::EthResult,
rpc::api::{
eth::helpers::{EthApiSpec, EthTransactions, TraceExt},
DebugApiServer,
},
};
use reth_primitives::{Bytes, B256};
Expand All @@ -21,7 +18,7 @@ where
EthApi: EthApiSpec + EthTransactions + TraceExt,
{
/// Injects a raw transaction into the node tx pool via RPC server
pub async fn inject_tx(&mut self, raw_tx: Bytes) -> EthResult<B256> {
pub async fn inject_tx(&mut self, raw_tx: Bytes) -> Result<B256, EthApi::Error> {
let eth_api = self.inner.eth_api();
eth_api.send_raw_transaction(raw_tx).await
}
Expand Down
1 change: 0 additions & 1 deletion crates/node/core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,6 @@ optimism = [
"reth-provider/optimism",
"reth-rpc-types-compat/optimism",
"reth-rpc-eth-api/optimism",
"reth-rpc-eth-types/optimism",
]


Expand Down
1 change: 0 additions & 1 deletion crates/optimism/node/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@ optimism = [
"reth-beacon-consensus/optimism",
"reth-revm/optimism",
"reth-auto-seal-consensus/optimism",
"reth-rpc-eth-types/optimism",
"reth-optimism-rpc/optimism"
]
test-utils = ["reth-node-builder/test-utils"]
2 changes: 1 addition & 1 deletion crates/optimism/rpc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ tokio.workspace = true

# rpc
jsonrpsee.workspace = true
jsonrpsee-types.workspace = true

# misc
thiserror.workspace = true
Expand All @@ -59,6 +60,5 @@ optimism = [
"reth-primitives/optimism",
"reth-provider/optimism",
"reth-rpc-eth-api/optimism",
"reth-rpc-eth-types/optimism",
"revm/optimism"
]
70 changes: 62 additions & 8 deletions crates/optimism/rpc/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,31 +1,85 @@
//! RPC errors specific to OP.

use jsonrpsee::types::ErrorObject;
use reth_primitives::revm_primitives::{InvalidTransaction, OptimismInvalidTransaction};
use reth_rpc_eth_api::AsEthApiError;
use reth_rpc_eth_types::EthApiError;
use reth_rpc_server_types::result::internal_rpc_err;
use reth_rpc_types::ToRpcError;
use reth_rpc_server_types::result::{internal_rpc_err, rpc_err};
use reth_rpc_types::error::EthRpcErrorCode;

/// Optimism specific errors, that extend [`EthApiError`].
#[derive(Debug, thiserror::Error)]
pub enum OpEthApiError {
/// L1 ethereum error.
#[error(transparent)]
Eth(#[from] EthApiError),
/// 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,
/// Wrapper for [`revm_primitives::InvalidTransaction`](InvalidTransaction).
#[error(transparent)]
InvalidTransaction(OptimismInvalidTransactionError),
}

impl ToRpcError for OpEthApiError {
fn to_rpc_error(&self) -> ErrorObject<'static> {
impl AsEthApiError for OpEthApiError {
fn as_err(&self) -> Option<&EthApiError> {
match self {
Self::L1BlockFeeError | Self::L1BlockGasError => internal_rpc_err(self.to_string()),
Self::Eth(err) => Some(err),
_ => None,
}
}
}

impl From<OpEthApiError> for EthApiError {
impl From<OpEthApiError> for jsonrpsee_types::error::ErrorObject<'static> {
fn from(err: OpEthApiError) -> Self {
Self::other(err)
match err {
OpEthApiError::Eth(err) => err.into(),
OpEthApiError::L1BlockFeeError | OpEthApiError::L1BlockGasError => {
internal_rpc_err(err.to_string())
}
OpEthApiError::InvalidTransaction(err) => err.into(),
}
}
}

/// Optimism specific invalid transaction errors
#[derive(thiserror::Error, Debug)]
pub enum OptimismInvalidTransactionError {
/// A deposit transaction was submitted as a system transaction post-regolith.
#[error("no system transactions allowed after regolith")]
DepositSystemTxPostRegolith,
/// A deposit transaction halted post-regolith
#[error("deposit transaction halted after regolith")]
HaltedDepositPostRegolith,
}

impl From<OptimismInvalidTransactionError> for jsonrpsee_types::error::ErrorObject<'static> {
fn from(err: OptimismInvalidTransactionError) -> Self {
match err {
OptimismInvalidTransactionError::DepositSystemTxPostRegolith |
OptimismInvalidTransactionError::HaltedDepositPostRegolith => {
rpc_err(EthRpcErrorCode::TransactionRejected.code(), err.to_string(), None)
}
}
}
}

impl TryFrom<InvalidTransaction> for OptimismInvalidTransactionError {
type Error = InvalidTransaction;

fn try_from(err: InvalidTransaction) -> Result<Self, Self::Error> {
match err {
InvalidTransaction::OptimismError(err) => match err {
OptimismInvalidTransaction::DepositSystemTxPostRegolith => {
Ok(Self::DepositSystemTxPostRegolith)
}
OptimismInvalidTransaction::HaltedDepositPostRegolith => {
Ok(Self::HaltedDepositPostRegolith)
}
},
_ => Err(err),
}
}
}
19 changes: 12 additions & 7 deletions crates/optimism/rpc/src/eth/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@

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_eth_api::{
helpers::{EthApiSpec, EthBlocks, LoadBlock, LoadReceipt, LoadTransaction},
FromEthApiError,
};
use reth_rpc_eth_types::{EthStateCache, ReceiptBuilder};
use reth_rpc_types::{AnyTransactionReceipt, BlockId};

use crate::{op_receipt_fields, OpEthApi};
Expand All @@ -19,7 +22,7 @@ where
async fn block_receipts(
&self,
block_id: BlockId,
) -> EthResult<Option<Vec<AnyTransactionReceipt>>>
) -> Result<Option<Vec<AnyTransactionReceipt>>, Self::Error>
where
Self: LoadReceipt,
{
Expand Down Expand Up @@ -52,11 +55,13 @@ where
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()
})
ReceiptBuilder::new(tx, meta, receipt, &receipts)
.map(|builder| {
op_receipt_fields(builder, tx, receipt, optimism_tx_meta).build()
})
.map_err(Self::Error::from_eth_err)
})
.collect::<EthResult<Vec<_>>>();
.collect::<Result<Vec<_>, Self::Error>>();
return receipts.map(Some)
}

Expand Down
20 changes: 15 additions & 5 deletions crates/optimism/rpc/src/eth/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,22 @@ use reth_primitives::{
revm_primitives::{BlockEnv, OptimismFields, TxEnv},
Bytes,
};
use reth_rpc_eth_api::helpers::Call;
use reth_rpc_eth_types::EthResult;
use reth_rpc_eth_api::{
helpers::{Call, EthCall},
EthApiTypes, FromEthApiError,
};
use reth_rpc_eth_types::EthApiError;
use reth_rpc_types::TransactionRequest;

use crate::OpEthApi;

impl<Eth: Call> Call for OpEthApi<Eth> {
impl<Eth: EthCall> EthCall for OpEthApi<Eth> where EthApiError: From<Eth::Error> {}

impl<Eth> Call for OpEthApi<Eth>
where
Eth: Call + EthApiTypes,
EthApiError: From<Eth::Error>,
{
fn call_gas_limit(&self) -> u64 {
self.inner.call_gas_limit()
}
Expand All @@ -22,8 +31,9 @@ impl<Eth: Call> Call for OpEthApi<Eth> {
&self,
block_env: &BlockEnv,
request: TransactionRequest,
) -> EthResult<TxEnv> {
let mut env = Eth::create_txn_env(&self.inner, block_env, request)?;
) -> Result<TxEnv, Self::Error> {
let mut env =
self.inner.create_txn_env(block_env, request).map_err(Self::Error::from_eth_err)?;

env.optimism = OptimismFields { enveloped_tx: Some(Bytes::new()), ..Default::default() };

Expand Down
17 changes: 12 additions & 5 deletions crates/optimism/rpc/src/eth/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,19 @@ use reth_provider::{BlockReaderIdExt, ChainSpecProvider, HeaderProvider, StatePr
use reth_rpc::eth::DevSigner;
use reth_rpc_eth_api::{
helpers::{
AddDevSigners, EthApiSpec, EthCall, EthFees, EthSigner, EthState, LoadFee, LoadState,
SpawnBlocking, Trace, UpdateRawTxForwarder,
AddDevSigners, EthApiSpec, EthFees, EthSigner, EthState, LoadFee, LoadState, SpawnBlocking,
Trace, UpdateRawTxForwarder,
},
RawTransactionForwarder,
EthApiTypes, RawTransactionForwarder,
};
use reth_rpc_eth_types::EthStateCache;
use reth_rpc_types::SyncStatus;
use reth_tasks::{pool::BlockingTaskPool, TaskSpawner};
use reth_transaction_pool::TransactionPool;
use tokio::sync::{AcquireError, OwnedSemaphorePermit};

use crate::OpEthApiError;

/// OP-Reth `Eth` API implementation.
///
/// This type provides the functionality for handling `eth_` related requests.
Expand All @@ -51,6 +53,13 @@ impl<Eth> OpEthApi<Eth> {
}
}

impl<Eth> EthApiTypes for OpEthApi<Eth>
where
Eth: Send + Sync,
{
type Error = OpEthApiError;
}

impl<Eth: EthApiSpec> EthApiSpec for OpEthApi<Eth> {
fn protocol_version(&self) -> impl Future<Output = RethResult<U64>> + Send {
self.inner.protocol_version()
Expand Down Expand Up @@ -142,8 +151,6 @@ impl<Eth: EthState> EthState for OpEthApi<Eth> {
}
}

impl<Eth: EthCall> EthCall for OpEthApi<Eth> {}

impl<Eth: EthFees> EthFees for OpEthApi<Eth> {}

impl<Eth: Trace> Trace for OpEthApi<Eth> {
Expand Down
17 changes: 11 additions & 6 deletions crates/optimism/rpc/src/eth/receipt.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
//! Loads and formats OP receipt RPC response.

use reth_primitives::{Receipt, TransactionMeta, TransactionSigned};
use reth_rpc_eth_api::helpers::{EthApiSpec, LoadReceipt, LoadTransaction};
use reth_rpc_eth_types::{EthApiError, EthResult, EthStateCache, ReceiptBuilder};
use reth_rpc_eth_api::{
helpers::{EthApiSpec, LoadReceipt, LoadTransaction},
FromEthApiError,
};
use reth_rpc_eth_types::{EthApiError, EthStateCache, ReceiptBuilder};
use reth_rpc_types::{AnyTransactionReceipt, OptimismTransactionReceiptFields};

use crate::{OpEthApi, OptimismTxMeta};
Expand All @@ -21,17 +24,19 @@ where
tx: TransactionSigned,
meta: TransactionMeta,
receipt: Receipt,
) -> EthResult<AnyTransactionReceipt> {
) -> Result<AnyTransactionReceipt, Self::Error> {
let (block, receipts) = LoadReceipt::cache(self)
.get_block_and_receipts(meta.block_hash)
.await?
.ok_or(EthApiError::UnknownBlockNumber)?;
.await
.map_err(Self::Error::from_eth_err)?
.ok_or(Self::Error::from_eth_err(EthApiError::UnknownBlockNumber))?;

let block = block.unseal();
let l1_block_info = reth_evm_optimism::extract_l1_info(&block).ok();
let optimism_tx_meta = self.build_op_tx_meta(&tx, l1_block_info, block.timestamp)?;

let resp_builder = ReceiptBuilder::new(&tx, meta, &receipt, &receipts)?;
let resp_builder = ReceiptBuilder::new(&tx, meta, &receipt, &receipts)
.map_err(Self::Error::from_eth_err)?;
let resp_builder = op_receipt_fields(resp_builder, &tx, &receipt, optimism_tx_meta);

Ok(resp_builder.build())
Expand Down
6 changes: 3 additions & 3 deletions crates/optimism/rpc/src/eth/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ use reth_primitives::TransactionSigned;
use reth_provider::{BlockReaderIdExt, TransactionsProvider};
use reth_rpc_eth_api::{
helpers::{EthApiSpec, EthSigner, EthTransactions, LoadTransaction},
RawTransactionForwarder,
EthApiTypes, RawTransactionForwarder,
};
use reth_rpc_eth_types::{EthResult, EthStateCache};
use reth_rpc_eth_types::EthStateCache;
use revm::L1BlockInfo;

use crate::{OpEthApi, OpEthApiError};
Expand Down Expand Up @@ -79,7 +79,7 @@ where
tx: &TransactionSigned,
l1_block_info: Option<L1BlockInfo>,
block_timestamp: u64,
) -> EthResult<OptimismTxMeta> {
) -> Result<OptimismTxMeta, <Self as EthApiTypes>::Error> {
let Some(l1_block_info) = l1_block_info else { return Ok(OptimismTxMeta::default()) };

let (l1_fee, l1_data_gas) = if !tx.is_deposit() {
Expand Down
2 changes: 1 addition & 1 deletion crates/rpc/rpc-eth-api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ alloy-dyn-abi = { workspace = true, features = ["eip712"] }

# rpc
jsonrpsee = { workspace = true, features = ["server", "macros"] }
jsonrpsee-types.workspace = true

# async
async-trait.workspace = true
Expand All @@ -53,5 +54,4 @@ optimism = [
"reth-primitives/optimism",
"revm/optimism",
"reth-provider/optimism",
"reth-rpc-eth-types/optimism"
]
3 changes: 2 additions & 1 deletion crates/rpc/rpc-eth-api/src/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,8 @@ pub trait EthApi {
#[async_trait::async_trait]
impl<T> EthApiServer for T
where
Self: FullEthApi,
T: FullEthApi,
jsonrpsee_types::error::ErrorObject<'static>: From<T::Error>,
{
/// Handler for: `eth_protocolVersion`
async fn protocol_version(&self) -> RpcResult<U64> {
Expand Down
Loading

0 comments on commit 0be2c17

Please sign in to comment.