foundry_fork_db/
error.rs

1use alloy_primitives::{Address, B256, U256};
2use alloy_rpc_types::BlockId;
3use futures::channel::mpsc::{SendError, TrySendError};
4use std::{
5    convert::Infallible,
6    sync::{mpsc::RecvError, Arc},
7};
8
9/// Result alias with `DatabaseError` as error
10pub type DatabaseResult<T> = Result<T, DatabaseError>;
11
12/// Errors that can happen when working with [`revm::Database`]
13#[derive(Debug, thiserror::Error)]
14#[allow(missing_docs)]
15pub enum DatabaseError {
16    #[error("missing bytecode for code hash {0}")]
17    MissingCode(B256),
18    #[error(transparent)]
19    Recv(#[from] RecvError),
20    #[error(transparent)]
21    Send(#[from] SendError),
22    #[error("failed to get account for {0}: {1}")]
23    GetAccount(Address, Arc<eyre::Error>),
24    #[error("failed to get storage for {0} at {1}: {2}")]
25    GetStorage(Address, U256, Arc<eyre::Error>),
26    #[error("failed to get block hash for {0}: {1}")]
27    GetBlockHash(u64, Arc<eyre::Error>),
28    #[error("failed to get full block for {0:?}: {1}")]
29    GetFullBlock(BlockId, Arc<eyre::Error>),
30    #[error("block {0:?} does not exist")]
31    BlockNotFound(BlockId),
32    #[error("failed to get transaction {0}: {1}")]
33    GetTransaction(B256, Arc<eyre::Error>),
34    #[error("failed to process AnyRequest: {0}")]
35    AnyRequest(Arc<eyre::Error>),
36}
37
38impl DatabaseError {
39    fn get_rpc_error(&self) -> Option<&eyre::Error> {
40        match self {
41            Self::GetAccount(_, err) => Some(err),
42            Self::GetStorage(_, _, err) => Some(err),
43            Self::GetBlockHash(_, err) => Some(err),
44            Self::GetFullBlock(_, err) => Some(err),
45            Self::GetTransaction(_, err) => Some(err),
46            Self::AnyRequest(err) => Some(err),
47            // Enumerate explicitly to make sure errors are updated if a new one is added.
48            Self::MissingCode(_) | Self::Recv(_) | Self::Send(_) | Self::BlockNotFound(_) => None,
49        }
50    }
51
52    /// Whether the error is potentially caused by the user forking from an older block in a
53    /// non-archive node.
54    pub fn is_possibly_non_archive_node_error(&self) -> bool {
55        static GETH_MESSAGE: &str = "missing trie node";
56
57        self.get_rpc_error()
58            .map(|err| err.to_string().to_lowercase().contains(GETH_MESSAGE))
59            .unwrap_or(false)
60    }
61}
62
63impl<T> From<TrySendError<T>> for DatabaseError {
64    fn from(value: TrySendError<T>) -> Self {
65        value.into_send_error().into()
66    }
67}
68
69impl From<Infallible> for DatabaseError {
70    fn from(value: Infallible) -> Self {
71        match value {}
72    }
73}
74
75impl revm::database::DBErrorMarker for DatabaseError {}