Skip to main content

reth_execution_errors/
trie.rs

1//! Errors when computing the state root.
2
3use alloc::{boxed::Box, string::ToString};
4use alloy_primitives::{Bytes, B256};
5use nybbles::Nibbles;
6use reth_storage_errors::{db::DatabaseError, provider::ProviderError};
7use thiserror::Error;
8
9/// State root errors.
10#[derive(Error, Clone, Debug)]
11pub enum StateRootError {
12    /// Internal database error.
13    #[error(transparent)]
14    Database(#[from] DatabaseError),
15    /// Storage root error.
16    #[error(transparent)]
17    StorageRootError(#[from] StorageRootError),
18    /// Provider error when loading prefix sets
19    #[error(transparent)]
20    PrefixSetLoadError(#[from] ProviderError),
21}
22
23impl From<StateRootError> for ProviderError {
24    fn from(value: StateRootError) -> Self {
25        match value {
26            StateRootError::Database(err) |
27            StateRootError::StorageRootError(StorageRootError::Database(err)) => {
28                Self::Database(err)
29            }
30            StateRootError::PrefixSetLoadError(err) => err,
31        }
32    }
33}
34
35/// Storage root error.
36#[derive(Error, Clone, Debug)]
37pub enum StorageRootError {
38    /// Internal database error.
39    #[error(transparent)]
40    Database(#[from] DatabaseError),
41}
42
43impl From<StorageRootError> for DatabaseError {
44    fn from(err: StorageRootError) -> Self {
45        match err {
46            StorageRootError::Database(err) => err,
47        }
48    }
49}
50
51/// State proof errors.
52#[derive(Error, Clone, Debug)]
53pub enum StateProofError {
54    /// Internal database error.
55    #[error(transparent)]
56    Database(#[from] DatabaseError),
57    /// RLP decoding error.
58    #[error(transparent)]
59    Rlp(#[from] alloy_rlp::Error),
60    /// Trie inconsistency detected during proof calculation.
61    ///
62    /// This occurs when cached trie nodes disagree with the leaf data, causing
63    /// proof calculation to be unable to make forward progress.
64    #[error("trie inconsistency: {0}")]
65    TrieInconsistency(alloc::string::String),
66}
67
68impl From<StateProofError> for ProviderError {
69    fn from(value: StateProofError) -> Self {
70        match value {
71            StateProofError::Database(error) => Self::Database(error),
72            StateProofError::Rlp(error) => Self::Rlp(error),
73            StateProofError::TrieInconsistency(msg) => Self::Database(DatabaseError::Other(msg)),
74        }
75    }
76}
77
78/// Result type with [`SparseStateTrieError`] as error.
79pub type SparseStateTrieResult<Ok> = Result<Ok, SparseStateTrieError>;
80
81/// Error encountered in `SparseStateTrie`.
82#[derive(Error, Debug)]
83#[error(transparent)]
84pub struct SparseStateTrieError(#[from] Box<SparseStateTrieErrorKind>);
85
86impl<T: Into<SparseStateTrieErrorKind>> From<T> for SparseStateTrieError {
87    #[cold]
88    fn from(value: T) -> Self {
89        Self(Box::new(value.into()))
90    }
91}
92
93impl From<SparseTrieError> for SparseStateTrieErrorKind {
94    #[cold]
95    fn from(value: SparseTrieError) -> Self {
96        Self::Sparse(*value.0)
97    }
98}
99
100impl SparseStateTrieError {
101    /// Returns the error kind.
102    pub const fn kind(&self) -> &SparseStateTrieErrorKind {
103        &self.0
104    }
105
106    /// Consumes the error and returns the error kind.
107    pub fn into_kind(self) -> SparseStateTrieErrorKind {
108        *self.0
109    }
110}
111
112/// Error encountered in `SparseStateTrie`.
113#[derive(Error, Debug)]
114pub enum SparseStateTrieErrorKind {
115    /// Encountered invalid root node.
116    #[error("invalid root node at {path:?}: {node:?}")]
117    InvalidRootNode {
118        /// Path to first proof node.
119        path: Nibbles,
120        /// Encoded first proof node.
121        node: Bytes,
122    },
123    /// Storage sparse trie error.
124    #[error("error in storage trie for address {0:?}: {1:?}")]
125    SparseStorageTrie(B256, SparseTrieErrorKind),
126    /// Sparse trie error.
127    #[error(transparent)]
128    Sparse(#[from] SparseTrieErrorKind),
129    /// RLP error.
130    #[error(transparent)]
131    Rlp(#[from] alloy_rlp::Error),
132}
133
134/// Result type with [`SparseTrieError`] as error.
135pub type SparseTrieResult<Ok> = Result<Ok, SparseTrieError>;
136
137/// Error encountered in `SparseTrie`.
138#[derive(Error, Debug)]
139#[error(transparent)]
140pub struct SparseTrieError(#[from] Box<SparseTrieErrorKind>);
141
142impl<T: Into<SparseTrieErrorKind>> From<T> for SparseTrieError {
143    #[cold]
144    fn from(value: T) -> Self {
145        Self(Box::new(value.into()))
146    }
147}
148
149impl SparseTrieError {
150    /// Returns the error kind.
151    pub const fn kind(&self) -> &SparseTrieErrorKind {
152        &self.0
153    }
154
155    /// Consumes the error and returns the error kind.
156    pub fn into_kind(self) -> SparseTrieErrorKind {
157        *self.0
158    }
159}
160
161/// [`SparseTrieError`] kind.
162#[derive(Error, Debug)]
163pub enum SparseTrieErrorKind {
164    /// Sparse trie is still blind. Thrown on attempt to update it.
165    #[error("sparse trie is blind")]
166    Blind,
167    /// Encountered blinded node on update.
168    #[error("attempted to update blind node at {path:?}: {hash}")]
169    BlindedNode {
170        /// Blind node path.
171        path: Nibbles,
172        /// Node hash
173        hash: B256,
174    },
175    /// Encountered unexpected node at path when revealing.
176    #[error("encountered an invalid node at path {path:?} when revealing: {node:?}")]
177    Reveal {
178        /// Path to the node.
179        path: Nibbles,
180        /// Node that was at the path when revealing.
181        node: Box<dyn core::fmt::Debug + Send + Sync>,
182    },
183    /// RLP error.
184    #[error(transparent)]
185    Rlp(#[from] alloy_rlp::Error),
186    /// Node not found in provider during revealing.
187    #[error("node {path:?} not found in provider during revealing")]
188    NodeNotFoundInProvider {
189        /// Path to the missing node.
190        path: Nibbles,
191    },
192    /// Other.
193    #[error(transparent)]
194    Other(#[from] Box<dyn core::error::Error + Send + Sync>),
195}
196
197/// Trie witness errors.
198#[derive(Error, Debug)]
199pub enum TrieWitnessError {
200    /// Error gather proofs.
201    #[error(transparent)]
202    Proof(#[from] StateProofError),
203    /// RLP decoding error.
204    #[error(transparent)]
205    Rlp(#[from] alloy_rlp::Error),
206    /// Sparse state trie error.
207    #[error(transparent)]
208    Sparse(#[from] SparseStateTrieError),
209    /// Missing account.
210    #[error("missing account {_0}")]
211    MissingAccount(B256),
212}
213
214impl From<SparseStateTrieErrorKind> for TrieWitnessError {
215    fn from(error: SparseStateTrieErrorKind) -> Self {
216        Self::Sparse(error.into())
217    }
218}
219
220impl From<TrieWitnessError> for ProviderError {
221    fn from(error: TrieWitnessError) -> Self {
222        Self::TrieWitnessError(error.to_string())
223    }
224}