chore(rpc): EthApiTypes trait for network specific error AT (#9523)

Co-authored-by: Matthias Seitz <matthias.seitz@outlook.de>
This commit is contained in:
Emilia Hane
2024-07-25 19:30:30 +02:00
committed by GitHub
parent f175f6ec9f
commit 0be2c17a9f
39 changed files with 878 additions and 478 deletions

View File

@ -38,6 +38,7 @@ tokio.workspace = true
# rpc
jsonrpsee.workspace = true
jsonrpsee-types.workspace = true
# misc
thiserror.workspace = true
@ -59,6 +60,5 @@ optimism = [
"reth-primitives/optimism",
"reth-provider/optimism",
"reth-rpc-eth-api/optimism",
"reth-rpc-eth-types/optimism",
"revm/optimism"
]

View File

@ -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),
}
}
}

View File

@ -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};
@ -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,
{
@ -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)
}

View File

@ -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()
}
@ -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() };

View File

@ -18,10 +18,10 @@ 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;
@ -29,6 +29,8 @@ 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.
@ -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()
@ -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> {

View File

@ -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};
@ -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())

View File

@ -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};
@ -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() {