Skip to main content

akd/
errors.rs

1// Copyright (c) Meta Platforms, Inc. and affiliates.
2//
3// This source code is dual-licensed under either the MIT license found in the
4// LICENSE-MIT file in the root directory of this source tree or the Apache
5// License, Version 2.0 found in the LICENSE-APACHE file in the root directory
6// of this source tree. You may select, at your option, one of the above-listed licenses.
7
8//! Errors for various data structure operations.
9use core::fmt;
10
11use crate::node_label::NodeLabel;
12use crate::Direction;
13
14/// Symbolizes a AkdError, thrown by the akd.
15#[cfg_attr(test, derive(PartialEq, Eq))]
16#[derive(Debug)]
17pub enum AkdError {
18    /// Error propagation
19    TreeNode(TreeNodeError),
20    /// Error propagation
21    Directory(DirectoryError),
22    /// Error propagation
23    AzksErr(AzksError),
24    /// Vrf related error
25    Vrf(akd_core::ecvrf::VrfError),
26    /// Storage layer error thrown
27    Storage(StorageError),
28    /// Audit verification error thrown
29    AuditErr(AuditorError),
30    /// Parallelism/concurrency related errors
31    Parallelism(ParallelismError),
32    /// Test error
33    TestErr(String),
34}
35
36impl std::error::Error for AkdError {}
37
38impl From<TreeNodeError> for AkdError {
39    fn from(error: TreeNodeError) -> Self {
40        Self::TreeNode(error)
41    }
42}
43
44impl From<StorageError> for AkdError {
45    fn from(error: StorageError) -> Self {
46        Self::Storage(error)
47    }
48}
49
50impl From<DirectoryError> for AkdError {
51    fn from(error: DirectoryError) -> Self {
52        Self::Directory(error)
53    }
54}
55
56impl From<akd_core::ecvrf::VrfError> for AkdError {
57    fn from(error: akd_core::ecvrf::VrfError) -> Self {
58        Self::Vrf(error)
59    }
60}
61
62impl From<AzksError> for AkdError {
63    fn from(error: AzksError) -> Self {
64        Self::AzksErr(error)
65    }
66}
67
68impl From<AuditorError> for AkdError {
69    fn from(error: AuditorError) -> Self {
70        Self::AuditErr(error)
71    }
72}
73
74impl From<ParallelismError> for AkdError {
75    fn from(error: ParallelismError) -> Self {
76        Self::Parallelism(error)
77    }
78}
79
80impl From<akd_core::verify::VerificationError> for AkdError {
81    fn from(err: akd_core::verify::VerificationError) -> Self {
82        Self::Directory(err.into())
83    }
84}
85
86impl std::fmt::Display for AkdError {
87    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
88        match self {
89            AkdError::TreeNode(err) => {
90                writeln!(f, "AKD Tree Node Error: {err}")
91            }
92            AkdError::Directory(err) => {
93                writeln!(f, "AKD Directory Error: {err}")
94            }
95            AkdError::AzksErr(err) => {
96                writeln!(f, "AKD AZKS Error: {err}")
97            }
98            AkdError::Vrf(err) => {
99                writeln!(f, "AKD VRF Error: {err}")
100            }
101            AkdError::Storage(err) => {
102                writeln!(f, "AKD Storage Error: {err}")
103            }
104            AkdError::AuditErr(err) => {
105                writeln!(f, "AKD Auditor Error {err}")
106            }
107            AkdError::Parallelism(err) => {
108                writeln!(f, "AKD Parallelism Error: {err}")
109            }
110            AkdError::TestErr(err) => {
111                writeln!(f, "{err}")
112            }
113        }
114    }
115}
116
117/// Errors thrown by TreeNodes
118#[derive(Debug, Eq, PartialEq)]
119pub enum TreeNodeError {
120    /// At the moment the only supported dirs are 0, 1
121    InvalidDirection(Direction),
122    /// No direction provided for the node.
123    /// Second parameter is the label of the child attempted to be set
124    /// -- if there is one, otherwise it is None.
125    NoDirection(NodeLabel, Option<NodeLabel>),
126    /// The node didn't have a child in the given epoch
127    NoChildAtEpoch(u64, Direction),
128    /// The next epoch of this node's parent was invalid
129    ParentNextEpochInvalid(u64),
130    /// The hash of a parent was attempted to be updated, without setting the calling node as a child.
131    HashUpdateOrderInconsistent,
132    /// The node did not exist at epoch
133    NonexistentAtEpoch(NodeLabel, u64),
134    /// The state of a node did not exist at a given epoch
135    NoStateAtEpoch(NodeLabel, u64),
136    /// Failed to deserialize a digest
137    DigestDeserializationFailed(String),
138}
139
140impl std::error::Error for TreeNodeError {}
141
142impl fmt::Display for TreeNodeError {
143    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
144        match self {
145            Self::InvalidDirection(dir) => {
146                write!(
147                    f,
148                    "AKD is based on a binary tree. No child with a given direction: {dir:?}"
149                )
150            }
151            Self::NoDirection(node_label, child_label) => {
152                let mut to_print = format!("no direction provided for the node {node_label:?}");
153                // Add child info if given.
154                if let Some(child_label) = child_label {
155                    let child_str = format!(" and child {child_label:?}");
156                    to_print.push_str(&child_str);
157                }
158                write!(f, "{to_print}")
159            }
160            Self::NoChildAtEpoch(epoch, direction) => {
161                write!(f, "no node in direction {direction:?} at epoch {epoch}")
162            }
163            Self::ParentNextEpochInvalid(epoch) => {
164                write!(f, "Next epoch of parent is invalid, epoch = {epoch}")
165            }
166            Self::HashUpdateOrderInconsistent => {
167                write!(
168                    f,
169                    "Hash update in parent only allowed after node is inserted"
170                )
171            }
172            Self::NonexistentAtEpoch(label, epoch) => {
173                write!(
174                    f,
175                    "This node, labelled {label:?}, did not exist at epoch {epoch:?}."
176                )
177            }
178            Self::NoStateAtEpoch(label, epoch) => {
179                write!(
180                    f,
181                    "This node, labelled {label:?}, did not exist at epoch {epoch:?}."
182                )
183            }
184            Self::DigestDeserializationFailed(inner_error) => {
185                write!(f, "Encountered a serialization error {inner_error}")
186            }
187        }
188    }
189}
190
191/// An error thrown by the Azks data structure.
192#[cfg_attr(test, derive(PartialEq, Eq))]
193#[derive(Debug)]
194pub enum AzksError {
195    /// Membership proof did not verify
196    VerifyMembershipProof(String),
197    /// Append-only proof did not verify
198    VerifyAppendOnlyProof(String),
199    /// Thrown when a place where an epoch is needed wasn't provided one.
200    NoEpochGiven,
201}
202
203impl std::error::Error for AzksError {}
204
205impl fmt::Display for AzksError {
206    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
207        match self {
208            Self::VerifyMembershipProof(error_string) => {
209                write!(f, "{error_string}")
210            }
211            Self::VerifyAppendOnlyProof(error_string) => {
212                write!(f, "Append only proof did not verify: {error_string}")
213            }
214            Self::NoEpochGiven => {
215                write!(f, "An epoch was required but not supplied")
216            }
217        }
218    }
219}
220
221/// The errors thrown by various algorithms in [crate::directory::Directory]
222#[cfg_attr(test, derive(PartialEq, Eq))]
223#[derive(Debug)]
224pub enum DirectoryError {
225    /// A verification error occurred
226    Verification(akd_core::verify::VerificationError),
227    /// Tried to perform an operation on an invalid epoch or epoch range
228    InvalidEpoch(String),
229    /// AZKS not found in read-only directory mode
230    ReadOnlyDirectory(String),
231    /// Publish
232    Publish(String),
233    /// Detected an invalid version
234    InvalidVersion(String),
235}
236
237impl std::error::Error for DirectoryError {}
238
239impl fmt::Display for DirectoryError {
240    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
241        match self {
242            Self::Verification(err) => {
243                write!(f, "Verification failure {err}")
244            }
245            Self::InvalidEpoch(err_string) => {
246                write!(f, "Invalid epoch {err_string}")
247            }
248            Self::ReadOnlyDirectory(inner_message) => {
249                write!(f, "Directory in read-only mode: {inner_message}")
250            }
251            Self::Publish(inner_message) => {
252                write!(f, "Directory publish error: {inner_message}")
253            }
254            Self::InvalidVersion(inner_message) => {
255                write!(f, "Invalid version error: {inner_message}")
256            }
257        }
258    }
259}
260
261impl From<akd_core::verify::VerificationError> for DirectoryError {
262    fn from(err: akd_core::verify::VerificationError) -> Self {
263        Self::Verification(err)
264    }
265}
266
267/// Represents a storage-layer error
268#[cfg_attr(any(test, feature = "public_tests"), derive(PartialEq, Eq))]
269#[derive(Debug)]
270pub enum StorageError {
271    /// Data wasn't found in the storage layer
272    NotFound(String),
273    /// A transaction error
274    Transaction(String),
275    /// Some kind of storage connection error occurred
276    Connection(String),
277    /// Some other storage-layer error occurred
278    Other(String),
279}
280
281impl std::error::Error for StorageError {}
282
283impl fmt::Display for StorageError {
284    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
285        match self {
286            StorageError::Connection(inner) => {
287                write!(f, "Storage connection: {inner}")
288            }
289            StorageError::Transaction(inner) => {
290                write!(f, "Transaction: {inner}")
291            }
292            StorageError::NotFound(inner) => {
293                write!(f, "Data not found: {inner}")
294            }
295            StorageError::Other(inner) => {
296                write!(f, "Other storage error: {inner}")
297            }
298        }
299    }
300}
301
302/// The errors thrown by various algorithms in [crate::directory::Directory]
303#[cfg_attr(test, derive(PartialEq, Eq))]
304#[derive(Debug)]
305pub enum AuditorError {
306    /// A general auditor error
307    VerifyAuditProof(String),
308}
309
310impl std::error::Error for AuditorError {}
311
312impl fmt::Display for AuditorError {
313    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
314        match self {
315            Self::VerifyAuditProof(err_string) => {
316                write!(f, "Failed to verify audit {err_string}")
317            }
318        }
319    }
320}
321
322/// The errors thrown by parallel code
323#[cfg_attr(test, derive(PartialEq, Eq))]
324#[derive(Debug)]
325pub enum ParallelismError {
326    /// A tokio task join error
327    JoinErr(String),
328}
329
330impl std::error::Error for ParallelismError {}
331
332impl fmt::Display for ParallelismError {
333    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
334        match self {
335            Self::JoinErr(err_string) => {
336                write!(f, "Failed to join tokio task {err_string}")
337            }
338        }
339    }
340}