cfxcore/transaction_pool/
error.rs

1use cfx_rpc_utils::error::errors::{
2    EthApiError, RpcInvalidTransactionError, RpcPoolError,
3};
4use cfx_types::{H256, U256};
5use primitives::transaction::TransactionError;
6
7#[derive(Debug, Clone, thiserror::Error, PartialEq, Eq)]
8pub enum TransactionPoolError {
9    ///
10    #[error("{0:?}")]
11    TransactionError(TransactionError),
12    /// gas limit exceeded maximum value
13    #[error("transaction gas {have} exceeds the maximum value {max:?}")]
14    GasLimitExceeded { max: U256, have: U256 },
15
16    #[error("transaction gas price {have} less than the minimum value {min}")]
17    GasPriceLessThanMinimum { min: U256, have: U256 },
18
19    #[error("{0}")]
20    RlpDecodeError(String),
21
22    #[error("Transaction {hash:?} is discarded due to in too distant future")]
23    NonceTooDistant { hash: H256, nonce: U256 },
24
25    #[error("Transaction {hash:?} is discarded due to a too stale nonce")]
26    NonceTooStale { hash: H256, nonce: U256 },
27
28    #[error("Transaction {hash:?} is discarded due to out of balance, needs {need:?} but account balance is {have:?}")]
29    OutOfBalance { need: U256, have: U256, hash: H256 },
30
31    #[error("txpool is full")]
32    TxPoolFull,
33
34    #[error("Tx with same nonce already inserted. To replace it, you need to specify a gas price > {expected:?}")]
35    HigherGasPriceNeeded { expected: U256 },
36
37    #[error("db error: {0}")]
38    StateDbError(String),
39}
40
41impl From<cfx_statedb::Error> for TransactionPoolError {
42    fn from(value: cfx_statedb::Error) -> Self {
43        TransactionPoolError::StateDbError(format!(
44            "Failed to read account_cache from storage: {}",
45            value
46        ))
47    }
48}
49
50impl From<TransactionPoolError> for EthApiError {
51    fn from(err: TransactionPoolError) -> Self {
52        match err {
53            TransactionPoolError::TransactionError(tx_err) => match tx_err {
54                TransactionError::AlreadyImported => Self::PoolError(RpcPoolError::ReplaceUnderpriced),
55                TransactionError::ChainIdMismatch { .. } => Self::InvalidTransaction(RpcInvalidTransactionError::InvalidChainId),
56                TransactionError::EpochHeightOutOfBound { .. } => Self::InvalidBlockRange,
57                TransactionError::NotEnoughBaseGas { .. } => Self::InvalidTransaction(RpcInvalidTransactionError::GasTooLow),
58                TransactionError::Stale => Self::InvalidTransaction(RpcInvalidTransactionError::NonceTooLow),
59                TransactionError::TooCheapToReplace => Self::PoolError(RpcPoolError::ReplaceUnderpriced),
60                TransactionError::LimitReached => Self::PoolError(RpcPoolError::TxPoolOverflow),
61                TransactionError::InsufficientGasPrice { .. } => Self::PoolError(RpcPoolError::Underpriced),
62                TransactionError::InsufficientGas { .. } => Self::InvalidTransaction(RpcInvalidTransactionError::GasTooLow),
63                TransactionError::InsufficientBalance { .. } => Self::InvalidTransaction(RpcInvalidTransactionError::InsufficientFundsForTransfer),
64                TransactionError::GasLimitExceeded { .. } => Self::InvalidTransaction(RpcInvalidTransactionError::GasTooHigh),
65                TransactionError::InvalidGasLimit(_) => Self::InvalidTransaction(RpcInvalidTransactionError::GasUintOverflow),
66                TransactionError::InvalidSignature(_) => Self::InvalidTransactionSignature,
67                TransactionError::TooBig => Self::InvalidTransaction(RpcInvalidTransactionError::MaxInitCodeSizeExceeded),
68                TransactionError::InvalidRlp(_) => Self::FailedToDecodeSignedTransaction,
69                TransactionError::ZeroGasPrice => Self::PoolError(RpcPoolError::Underpriced),
70                TransactionError::FutureTransactionType { .. } => Self::InvalidTransaction(RpcInvalidTransactionError::TxTypeNotSupported),
71                TransactionError::InvalidReceiver => Self::Other("Invalid receiver".to_string()),
72                TransactionError::TooLargeNonce => Self::InvalidTransaction(RpcInvalidTransactionError::NonceMaxValue),
73                TransactionError::CreateInitCodeSizeLimit => Self::InvalidTransaction(RpcInvalidTransactionError::MaxInitCodeSizeExceeded),
74                TransactionError::EmptyAuthorizationList => Self::InvalidTransaction(RpcInvalidTransactionError::EmptyAuthorizationList),
75                TransactionError::PriortyGreaterThanMaxFee => Self::InvalidTransaction(RpcInvalidTransactionError::PriortyGreaterThanMaxFee),
76            },
77            TransactionPoolError::GasLimitExceeded { .. } => Self::PoolError(RpcPoolError::ExceedsGasLimit),
78            TransactionPoolError::GasPriceLessThanMinimum { .. } => Self::PoolError(RpcPoolError::Underpriced),
79            TransactionPoolError::RlpDecodeError(_) => Self::FailedToDecodeSignedTransaction,
80            TransactionPoolError::NonceTooDistant { .. } => Self::InvalidTransaction(RpcInvalidTransactionError::NonceTooHigh),
81            TransactionPoolError::NonceTooStale { .. } => Self::InvalidTransaction(RpcInvalidTransactionError::NonceTooLow),
82            TransactionPoolError::OutOfBalance { .. } => Self::InvalidTransaction(RpcInvalidTransactionError::InsufficientFundsForTransfer),
83            TransactionPoolError::TxPoolFull => Self::PoolError(RpcPoolError::TxPoolOverflow),
84            TransactionPoolError::HigherGasPriceNeeded {..} => Self::PoolError(RpcPoolError::ReplaceUnderpriced),
85            TransactionPoolError::StateDbError(_) => Self::InternalEthError,
86        }
87    }
88}