casper_types/digest/
error.rs

1//! Errors in constructing and validating indexed Merkle proofs, chunks with indexed Merkle proofs.
2
3use alloc::string::String;
4use core::fmt::{self, Display, Formatter};
5#[cfg(feature = "std")]
6use std::error::Error as StdError;
7
8use super::{ChunkWithProof, Digest};
9use crate::bytesrepr;
10
11/// Possible hashing errors.
12#[derive(Debug)]
13#[non_exhaustive]
14pub enum Error {
15    /// The digest length was an incorrect size.
16    IncorrectDigestLength(usize),
17    /// There was a decoding error.
18    Base16DecodeError(base16::DecodeError),
19}
20
21impl Display for Error {
22    fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
23        match self {
24            Error::IncorrectDigestLength(length) => {
25                write!(
26                    formatter,
27                    "incorrect digest length {}, expected length {}.",
28                    length,
29                    Digest::LENGTH
30                )
31            }
32            Error::Base16DecodeError(error) => {
33                write!(formatter, "base16 decode error: {}", error)
34            }
35        }
36    }
37}
38
39#[cfg(feature = "std")]
40impl StdError for Error {
41    fn source(&self) -> Option<&(dyn StdError + 'static)> {
42        match self {
43            Error::IncorrectDigestLength(_) => None,
44            Error::Base16DecodeError(error) => Some(error),
45        }
46    }
47}
48
49/// Error validating a Merkle proof of a chunk.
50#[derive(Debug, PartialEq, Eq)]
51#[non_exhaustive]
52pub enum MerkleVerificationError {
53    /// Index out of bounds.
54    IndexOutOfBounds {
55        /// Count.
56        count: u64,
57        /// Index.
58        index: u64,
59    },
60
61    /// Unexpected proof length.
62    UnexpectedProofLength {
63        /// Count.
64        count: u64,
65        /// Index.
66        index: u64,
67        /// Expected proof length.
68        expected_proof_length: u8,
69        /// Actual proof length.
70        actual_proof_length: usize,
71    },
72}
73
74impl Display for MerkleVerificationError {
75    fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
76        match self {
77            MerkleVerificationError::IndexOutOfBounds { count, index } => {
78                write!(
79                    formatter,
80                    "index out of bounds - count: {}, index: {}",
81                    count, index
82                )
83            }
84            MerkleVerificationError::UnexpectedProofLength {
85                count,
86                index,
87                expected_proof_length,
88                actual_proof_length,
89            } => {
90                write!(
91                    formatter,
92                    "unexpected proof length - count: {}, index: {}, expected length: {}, actual \
93                    length: {}",
94                    count, index, expected_proof_length, actual_proof_length
95                )
96            }
97        }
98    }
99}
100
101#[cfg(feature = "std")]
102impl StdError for MerkleVerificationError {}
103
104/// Error validating a chunk with proof.
105#[derive(Debug)]
106#[non_exhaustive]
107pub enum ChunkWithProofVerificationError {
108    /// Indexed Merkle proof verification error.
109    MerkleVerificationError(MerkleVerificationError),
110
111    /// Empty Merkle proof for trie with chunk.
112    ChunkWithProofHasEmptyMerkleProof {
113        /// Chunk with empty Merkle proof.
114        chunk_with_proof: ChunkWithProof,
115    },
116    /// Unexpected Merkle root hash.
117    UnexpectedRootHash,
118    /// Bytesrepr error.
119    Bytesrepr(bytesrepr::Error),
120
121    /// First digest in indexed Merkle proof did not match hash of chunk.
122    FirstDigestInMerkleProofDidNotMatchHashOfChunk {
123        /// First digest in indexed Merkle proof.
124        first_digest_in_indexed_merkle_proof: Digest,
125        /// Hash of chunk.
126        hash_of_chunk: Digest,
127    },
128}
129
130impl Display for ChunkWithProofVerificationError {
131    fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
132        match self {
133            ChunkWithProofVerificationError::MerkleVerificationError(error) => {
134                write!(formatter, "{}", error)
135            }
136            ChunkWithProofVerificationError::ChunkWithProofHasEmptyMerkleProof {
137                chunk_with_proof,
138            } => {
139                write!(
140                    formatter,
141                    "chunk with proof has empty merkle proof: {:?}",
142                    chunk_with_proof
143                )
144            }
145            ChunkWithProofVerificationError::UnexpectedRootHash => {
146                write!(formatter, "merkle proof has an unexpected root hash")
147            }
148            ChunkWithProofVerificationError::Bytesrepr(error) => {
149                write!(
150                    formatter,
151                    "bytesrepr error computing chunkable hash: {}",
152                    error
153                )
154            }
155            ChunkWithProofVerificationError::FirstDigestInMerkleProofDidNotMatchHashOfChunk {
156                first_digest_in_indexed_merkle_proof,
157                hash_of_chunk,
158            } => {
159                write!(
160                    formatter,
161                    "first digest in merkle proof did not match hash of chunk - first digest: \
162                    {:?}, hash of chunk: {:?}",
163                    first_digest_in_indexed_merkle_proof, hash_of_chunk
164                )
165            }
166        }
167    }
168}
169
170impl From<MerkleVerificationError> for ChunkWithProofVerificationError {
171    fn from(error: MerkleVerificationError) -> Self {
172        ChunkWithProofVerificationError::MerkleVerificationError(error)
173    }
174}
175
176#[cfg(feature = "std")]
177impl StdError for ChunkWithProofVerificationError {
178    fn source(&self) -> Option<&(dyn StdError + 'static)> {
179        match self {
180            ChunkWithProofVerificationError::MerkleVerificationError(error) => Some(error),
181            ChunkWithProofVerificationError::Bytesrepr(error) => Some(error),
182            ChunkWithProofVerificationError::ChunkWithProofHasEmptyMerkleProof { .. }
183            | ChunkWithProofVerificationError::UnexpectedRootHash
184            | ChunkWithProofVerificationError::FirstDigestInMerkleProofDidNotMatchHashOfChunk {
185                ..
186            } => None,
187        }
188    }
189}
190
191/// Error during the construction of a Merkle proof.
192#[derive(Debug, Eq, PartialEq, Clone)]
193#[non_exhaustive]
194pub enum MerkleConstructionError {
195    /// Chunk index was out of bounds.
196    IndexOutOfBounds {
197        /// Total chunks count.
198        count: u64,
199        /// Requested index.
200        index: u64,
201    },
202    /// Too many Merkle tree leaves.
203    TooManyLeaves {
204        /// Total chunks count.
205        count: String,
206    },
207}
208
209impl Display for MerkleConstructionError {
210    fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
211        match self {
212            MerkleConstructionError::IndexOutOfBounds { count, index } => {
213                write!(
214                    formatter,
215                    "could not construct merkle proof - index out of bounds - count: {}, index: {}",
216                    count, index
217                )
218            }
219            MerkleConstructionError::TooManyLeaves { count } => {
220                write!(
221                    formatter,
222                    "could not construct merkle proof - too many leaves - count: {}, max: {} \
223                    (u64::MAX)",
224                    count,
225                    u64::MAX
226                )
227            }
228        }
229    }
230}
231
232#[cfg(feature = "std")]
233impl StdError for MerkleConstructionError {}