reth_storage_errors/
provider.rs1use crate::{any::AnyError, db::DatabaseError, writer::UnifiedStorageWriterError};
2use alloc::{boxed::Box, string::String};
3use alloy_eips::{BlockHashOrNumber, HashOrNumber};
4use alloy_primitives::{Address, BlockHash, BlockNumber, TxNumber, B256};
5use derive_more::Display;
6use reth_enclave::EnclaveError;
7use reth_primitives_traits::{transaction::signed::RecoveryError, GotExpected};
8use reth_prune_types::PruneSegmentError;
9use reth_static_file_types::StaticFileSegment;
10use revm_database_interface::DBErrorMarker;
11
12pub type ProviderResult<Ok> = Result<Ok, ProviderError>;
14
15#[derive(Clone, Debug, thiserror::Error)]
17pub enum ProviderError {
18 #[error(transparent)]
20 Database(#[from] DatabaseError),
21 #[error(transparent)]
23 Pruning(#[from] PruneSegmentError),
24 #[error("{_0}")]
26 Rlp(alloy_rlp::Error),
27 #[error("trie witness error: {_0}")]
29 TrieWitnessError(String),
30 #[error("failed to recover sender for transaction")]
32 SenderRecoveryError,
33 #[error("block hash {_0} does not exist in Headers table")]
35 BlockHashNotFound(BlockHash),
36 #[error("block meta not found for block #{_0}")]
38 BlockBodyIndicesNotFound(BlockNumber),
39 #[error(
42 "storage change set for address {address} and key {storage_key} at block #{block_number} does not exist"
43 )]
44 StorageChangesetNotFound {
45 block_number: BlockNumber,
47 address: Address,
49 storage_key: Box<B256>,
53 },
54 #[error("account change set for address {address} at block #{block_number} does not exist")]
56 AccountChangesetNotFound {
57 block_number: BlockNumber,
59 address: Address,
61 },
62 #[error("total difficulty not found for block #{_0}")]
64 TotalDifficultyNotFound(BlockNumber),
65 #[error("no header found for {_0:?}")]
67 HeaderNotFound(BlockHashOrNumber),
68 #[error("no transaction found for {_0:?}")]
70 TransactionNotFound(HashOrNumber),
71 #[error("no receipt found for {_0:?}")]
73 ReceiptNotFound(HashOrNumber),
74 #[error("best block does not exist")]
76 BestBlockNotFound,
77 #[error("finalized block does not exist")]
79 FinalizedBlockNotFound,
80 #[error("safe block does not exist")]
82 SafeBlockNotFound,
83 #[error("unknown block {_0}")]
85 UnknownBlockHash(B256),
86 #[error("no state found for block {_0}")]
88 StateForHashNotFound(B256),
89 #[error("no state found for block number {_0}")]
91 StateForNumberNotFound(u64),
92 #[error("unable to find the block number for a given transaction index")]
94 BlockNumberForTransactionIndexNotFound,
95 #[error("merkle trie {_0}")]
97 StateRootMismatch(Box<RootMismatch>),
98 #[error("unwind merkle trie {_0}")]
100 UnwindStateRootMismatch(Box<RootMismatch>),
101 #[error("state at block #{_0} is pruned")]
103 StateAtBlockPruned(BlockNumber),
104 #[error("this provider does not support this request")]
106 UnsupportedProvider,
107 #[cfg(feature = "std")]
109 #[error("not able to find {_0} static file at {_1:?}")]
110 MissingStaticFilePath(StaticFileSegment, std::path::PathBuf),
111 #[error("not able to find {_0} static file for block number {_1}")]
113 MissingStaticFileBlock(StaticFileSegment, BlockNumber),
114 #[error("unable to find {_0} static file for transaction id {_1}")]
116 MissingStaticFileTx(StaticFileSegment, TxNumber),
117 #[error("unable to write block #{_1} to finalized static file {_0}")]
119 FinalizedStaticFile(StaticFileSegment, BlockNumber),
120 #[error("trying to append data to {_0} as block #{_1} but expected block #{_2}")]
122 UnexpectedStaticFileBlockNumber(StaticFileSegment, BlockNumber, BlockNumber),
123 #[error("trying to append row to {_0} at index #{_1} but expected index #{_2}")]
125 UnexpectedStaticFileTxNumber(StaticFileSegment, TxNumber, TxNumber),
126 #[error("cannot get a writer on a read-only environment.")]
128 ReadOnlyStaticFileAccess,
129 #[error("failed to initialize consistent view: {_0}")]
131 ConsistentView(Box<ConsistentViewError>),
132 #[error(transparent)]
134 UnifiedStorageWriterError(#[from] UnifiedStorageWriterError),
135 #[error("received invalid output from storage")]
137 InvalidStorageOutput,
138 #[error("enclave error: {_0}")]
140 EnclaveError(EnclaveError),
141 #[error(transparent)]
143 Other(#[from] AnyError),
144}
145
146impl From<EnclaveError> for ProviderError {
147 fn from(err: EnclaveError) -> Self {
148 Self::EnclaveError(err)
149 }
150}
151
152impl ProviderError {
153 pub fn other<E>(error: E) -> Self
156 where
157 E: core::error::Error + Send + Sync + 'static,
158 {
159 Self::Other(AnyError::new(error))
160 }
161
162 pub fn as_other(&self) -> Option<&(dyn core::error::Error + Send + Sync + 'static)> {
164 match self {
165 Self::Other(err) => Some(err.as_error()),
166 _ => None,
167 }
168 }
169
170 pub fn downcast_other_ref<T: core::error::Error + 'static>(&self) -> Option<&T> {
174 let other = self.as_other()?;
175 other.downcast_ref()
176 }
177
178 pub fn is_other<T: core::error::Error + 'static>(&self) -> bool {
181 self.as_other().map(|err| err.is::<T>()).unwrap_or(false)
182 }
183}
184
185impl DBErrorMarker for ProviderError {}
186
187impl From<alloy_rlp::Error> for ProviderError {
188 fn from(error: alloy_rlp::Error) -> Self {
189 Self::Rlp(error)
190 }
191}
192
193impl From<RecoveryError> for ProviderError {
194 fn from(_: RecoveryError) -> Self {
195 Self::SenderRecoveryError
196 }
197}
198
199#[derive(Clone, Debug, PartialEq, Eq, Display)]
201#[display("root mismatch at #{block_number} ({block_hash}): {root}")]
202pub struct RootMismatch {
203 pub root: GotExpected<B256>,
205 pub block_number: BlockNumber,
207 pub block_hash: BlockHash,
209}
210
211#[derive(Debug, thiserror::Error)]
213#[error("{message}")]
214pub struct StaticFileWriterError {
215 pub message: String,
217}
218
219impl StaticFileWriterError {
220 pub fn new(message: impl Into<String>) -> Self {
222 Self { message: message.into() }
223 }
224}
225#[derive(Clone, Debug, PartialEq, Eq, Display)]
227pub enum ConsistentViewError {
228 #[display("node is syncing. best block: {best_block:?}")]
230 Syncing {
231 best_block: GotExpected<BlockNumber>,
233 },
234 #[display("inconsistent database state: {tip:?}")]
236 Inconsistent {
237 tip: GotExpected<Option<B256>>,
239 },
240 #[display("database view no longer contains block: {block:?}")]
242 Reorged {
243 block: B256,
245 },
246}
247
248impl From<ConsistentViewError> for ProviderError {
249 fn from(error: ConsistentViewError) -> Self {
250 Self::ConsistentView(Box::new(error))
251 }
252}
253
254#[cfg(test)]
255mod tests {
256 use super::*;
257
258 #[derive(thiserror::Error, Debug)]
259 #[error("E")]
260 struct E;
261
262 #[test]
263 fn other_err() {
264 let err = ProviderError::other(E);
265 assert!(err.is_other::<E>());
266 assert!(err.downcast_other_ref::<E>().is_some());
267 }
268}