reth_storage_errors/
provider.rs1use crate::{any::AnyError, db::DatabaseError};
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("no header found for {_0:?}")]
63 HeaderNotFound(BlockHashOrNumber),
64 #[error("no transaction found for {_0:?}")]
66 TransactionNotFound(HashOrNumber),
67 #[error("no receipt found for {_0:?}")]
69 ReceiptNotFound(HashOrNumber),
70 #[error("best block does not exist")]
72 BestBlockNotFound,
73 #[error("finalized block does not exist")]
75 FinalizedBlockNotFound,
76 #[error("safe block does not exist")]
78 SafeBlockNotFound,
79 #[error("unknown block {_0}")]
81 UnknownBlockHash(B256),
82 #[error("no state found for block {_0}")]
84 StateForHashNotFound(B256),
85 #[error("no state found for block number {_0}")]
87 StateForNumberNotFound(u64),
88 #[error("unable to find the block number for a given transaction index")]
90 BlockNumberForTransactionIndexNotFound,
91 #[error("merkle trie {_0}")]
93 StateRootMismatch(Box<RootMismatch>),
94 #[error("unwind merkle trie {_0}")]
96 UnwindStateRootMismatch(Box<RootMismatch>),
97 #[error("state at block #{_0} is pruned")]
99 StateAtBlockPruned(BlockNumber),
100 #[error("this provider does not support this request")]
102 UnsupportedProvider,
103 #[cfg(feature = "std")]
105 #[error("not able to find {_0} static file at {_1:?}")]
106 MissingStaticFileSegmentPath(StaticFileSegment, std::path::PathBuf),
107 #[cfg(feature = "std")]
109 #[error("not able to find static file at {_0:?}")]
110 MissingStaticFilePath(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("received invalid output from storage")]
134 InvalidStorageOutput,
135 #[error("missing trie updates for block {0}")]
137 MissingTrieUpdates(B256),
138 #[error("insufficient changesets to revert to block #{requested}. Available changeset range: {available:?}")]
140 InsufficientChangesets {
141 requested: BlockNumber,
143 available: core::ops::RangeInclusive<BlockNumber>,
145 },
146 #[error(transparent)]
148 Other(#[from] AnyError),
149}
150
151impl ProviderError {
152 pub fn other<E>(error: E) -> Self
155 where
156 E: core::error::Error + Send + Sync + 'static,
157 {
158 Self::Other(AnyError::new(error))
159 }
160
161 pub fn as_other(&self) -> Option<&(dyn core::error::Error + Send + Sync + 'static)> {
163 match self {
164 Self::Other(err) => Some(err.as_error()),
165 _ => None,
166 }
167 }
168
169 pub fn downcast_other_ref<T: core::error::Error + 'static>(&self) -> Option<&T> {
173 let other = self.as_other()?;
174 other.downcast_ref()
175 }
176
177 pub fn is_other<T: core::error::Error + 'static>(&self) -> bool {
180 self.as_other().map(|err| err.is::<T>()).unwrap_or(false)
181 }
182}
183
184impl DBErrorMarker for ProviderError {}
185
186impl From<alloy_rlp::Error> for ProviderError {
187 fn from(error: alloy_rlp::Error) -> Self {
188 Self::Rlp(error)
189 }
190}
191
192impl From<RecoveryError> for ProviderError {
193 fn from(_: RecoveryError) -> Self {
194 Self::SenderRecoveryError
195 }
196}
197
198#[derive(Clone, Debug, PartialEq, Eq, Display)]
200#[display("root mismatch at #{block_number} ({block_hash}): {root}")]
201pub struct RootMismatch {
202 pub root: GotExpected<B256>,
204 pub block_number: BlockNumber,
206 pub block_hash: BlockHash,
208}
209
210#[derive(Debug, thiserror::Error)]
212#[error("{message}")]
213pub struct StaticFileWriterError {
214 pub message: String,
216}
217
218impl StaticFileWriterError {
219 pub fn new(message: impl Into<String>) -> Self {
221 Self { message: message.into() }
222 }
223}
224#[derive(Clone, Debug, PartialEq, Eq, Display)]
226pub enum ConsistentViewError {
227 #[display("node is syncing. best block: {best_block:?}")]
229 Syncing {
230 best_block: GotExpected<BlockNumber>,
232 },
233 #[display("inconsistent database state: {tip:?}")]
235 Inconsistent {
236 tip: GotExpected<Option<B256>>,
238 },
239 #[display("database view no longer contains block: {block:?}")]
241 Reorged {
242 block: B256,
244 },
245}
246
247impl From<ConsistentViewError> for ProviderError {
248 fn from(error: ConsistentViewError) -> Self {
249 Self::ConsistentView(Box::new(error))
250 }
251}
252
253#[cfg(test)]
254mod tests {
255 use super::*;
256
257 #[derive(thiserror::Error, Debug)]
258 #[error("E")]
259 struct E;
260
261 #[test]
262 fn other_err() {
263 let err = ProviderError::other(E);
264 assert!(err.is_other::<E>());
265 assert!(err.downcast_other_ref::<E>().is_some());
266 }
267}