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_primitives_traits::{transaction::signed::RecoveryError, GotExpected};
7use reth_prune_types::PruneSegmentError;
8use reth_static_file_types::StaticFileSegment;
9use revm_database_interface::DBErrorMarker;
10
11pub type ProviderResult<Ok> = Result<Ok, ProviderError>;
13
14#[derive(Clone, Debug, thiserror::Error)]
16pub enum ProviderError {
17 #[error(transparent)]
19 Database(#[from] DatabaseError),
20 #[error(transparent)]
22 Pruning(#[from] PruneSegmentError),
23 #[error("{_0}")]
25 Rlp(alloy_rlp::Error),
26 #[error("trie witness error: {_0}")]
28 TrieWitnessError(String),
29 #[error("failed to recover sender for transaction")]
31 SenderRecoveryError,
32 #[error("block hash {_0} does not exist in Headers table")]
34 BlockHashNotFound(BlockHash),
35 #[error("block meta not found for block #{_0}")]
37 BlockBodyIndicesNotFound(BlockNumber),
38 #[error(
41 "storage change set for address {address} and key {storage_key} at block #{block_number} does not exist"
42 )]
43 StorageChangesetNotFound {
44 block_number: BlockNumber,
46 address: Address,
48 storage_key: Box<B256>,
52 },
53 #[error("account change set for address {address} at block #{block_number} does not exist")]
55 AccountChangesetNotFound {
56 block_number: BlockNumber,
58 address: Address,
60 },
61 #[error("total difficulty not found for block #{_0}")]
63 TotalDifficultyNotFound(BlockNumber),
64 #[error("no header found for {_0:?}")]
66 HeaderNotFound(BlockHashOrNumber),
67 #[error("no transaction found for {_0:?}")]
69 TransactionNotFound(HashOrNumber),
70 #[error("no receipt found for {_0:?}")]
72 ReceiptNotFound(HashOrNumber),
73 #[error("best block does not exist")]
75 BestBlockNotFound,
76 #[error("finalized block does not exist")]
78 FinalizedBlockNotFound,
79 #[error("safe block does not exist")]
81 SafeBlockNotFound,
82 #[error("unknown block {_0}")]
84 UnknownBlockHash(B256),
85 #[error("no state found for block {_0}")]
87 StateForHashNotFound(B256),
88 #[error("no state found for block number {_0}")]
90 StateForNumberNotFound(u64),
91 #[error("unable to find the block number for a given transaction index")]
93 BlockNumberForTransactionIndexNotFound,
94 #[error("merkle trie {_0}")]
96 StateRootMismatch(Box<RootMismatch>),
97 #[error("unwind merkle trie {_0}")]
99 UnwindStateRootMismatch(Box<RootMismatch>),
100 #[error("state at block #{_0} is pruned")]
102 StateAtBlockPruned(BlockNumber),
103 #[error("this provider does not support this request")]
105 UnsupportedProvider,
106 #[cfg(feature = "std")]
108 #[error("not able to find {_0} static file at {_1:?}")]
109 MissingStaticFilePath(StaticFileSegment, std::path::PathBuf),
110 #[error("not able to find {_0} static file for block number {_1}")]
112 MissingStaticFileBlock(StaticFileSegment, BlockNumber),
113 #[error("unable to find {_0} static file for transaction id {_1}")]
115 MissingStaticFileTx(StaticFileSegment, TxNumber),
116 #[error("unable to write block #{_1} to finalized static file {_0}")]
118 FinalizedStaticFile(StaticFileSegment, BlockNumber),
119 #[error("trying to append data to {_0} as block #{_1} but expected block #{_2}")]
121 UnexpectedStaticFileBlockNumber(StaticFileSegment, BlockNumber, BlockNumber),
122 #[error("trying to append row to {_0} at index #{_1} but expected index #{_2}")]
124 UnexpectedStaticFileTxNumber(StaticFileSegment, TxNumber, TxNumber),
125 #[error("cannot get a writer on a read-only environment.")]
127 ReadOnlyStaticFileAccess,
128 #[error("failed to initialize consistent view: {_0}")]
130 ConsistentView(Box<ConsistentViewError>),
131 #[error(transparent)]
133 UnifiedStorageWriterError(#[from] UnifiedStorageWriterError),
134 #[error("received invalid output from storage")]
136 InvalidStorageOutput,
137 #[error("missing trie updates for block {0}")]
139 MissingTrieUpdates(B256),
140 #[error(transparent)]
142 Other(#[from] AnyError),
143}
144
145impl ProviderError {
146 pub fn other<E>(error: E) -> Self
149 where
150 E: core::error::Error + Send + Sync + 'static,
151 {
152 Self::Other(AnyError::new(error))
153 }
154
155 pub fn as_other(&self) -> Option<&(dyn core::error::Error + Send + Sync + 'static)> {
157 match self {
158 Self::Other(err) => Some(err.as_error()),
159 _ => None,
160 }
161 }
162
163 pub fn downcast_other_ref<T: core::error::Error + 'static>(&self) -> Option<&T> {
167 let other = self.as_other()?;
168 other.downcast_ref()
169 }
170
171 pub fn is_other<T: core::error::Error + 'static>(&self) -> bool {
174 self.as_other().map(|err| err.is::<T>()).unwrap_or(false)
175 }
176}
177
178impl DBErrorMarker for ProviderError {}
179
180impl From<alloy_rlp::Error> for ProviderError {
181 fn from(error: alloy_rlp::Error) -> Self {
182 Self::Rlp(error)
183 }
184}
185
186impl From<RecoveryError> for ProviderError {
187 fn from(_: RecoveryError) -> Self {
188 Self::SenderRecoveryError
189 }
190}
191
192#[derive(Clone, Debug, PartialEq, Eq, Display)]
194#[display("root mismatch at #{block_number} ({block_hash}): {root}")]
195pub struct RootMismatch {
196 pub root: GotExpected<B256>,
198 pub block_number: BlockNumber,
200 pub block_hash: BlockHash,
202}
203
204#[derive(Debug, thiserror::Error)]
206#[error("{message}")]
207pub struct StaticFileWriterError {
208 pub message: String,
210}
211
212impl StaticFileWriterError {
213 pub fn new(message: impl Into<String>) -> Self {
215 Self { message: message.into() }
216 }
217}
218#[derive(Clone, Debug, PartialEq, Eq, Display)]
220pub enum ConsistentViewError {
221 #[display("node is syncing. best block: {best_block:?}")]
223 Syncing {
224 best_block: GotExpected<BlockNumber>,
226 },
227 #[display("inconsistent database state: {tip:?}")]
229 Inconsistent {
230 tip: GotExpected<Option<B256>>,
232 },
233 #[display("database view no longer contains block: {block:?}")]
235 Reorged {
236 block: B256,
238 },
239}
240
241impl From<ConsistentViewError> for ProviderError {
242 fn from(error: ConsistentViewError) -> Self {
243 Self::ConsistentView(Box::new(error))
244 }
245}
246
247#[cfg(test)]
248mod tests {
249 use super::*;
250
251 #[derive(thiserror::Error, Debug)]
252 #[error("E")]
253 struct E;
254
255 #[test]
256 fn other_err() {
257 let err = ProviderError::other(E);
258 assert!(err.is_other::<E>());
259 assert!(err.downcast_other_ref::<E>().is_some());
260 }
261}