Skip to main content

bc_envelope/base/
error.rs

1use bc_components::Error as ComponentsError;
2use thiserror::Error;
3
4/// Error types returned when operating on Gordian Envelopes.
5///
6/// These errors capture various conditions that can occur when working with
7/// envelopes, including structure validation, operation constraints, and
8/// extension-specific errors.
9///
10/// The errors are organized by category, reflecting the base envelope
11/// specification and various extensions defined in the Gordian Envelope
12/// Internet Draft and Blockchain Commons Research (BCR) documents.
13#[derive(Debug, Error)]
14pub enum Error {
15    //
16    // Base Specification
17    /// Returned when attempting to compress or encrypt an envelope that has
18    /// already been elided.
19    ///
20    /// This error occurs because an elided envelope only contains a digest
21    /// reference and no longer has a subject that can be compressed or
22    /// encrypted.
23    #[error("envelope was elided, so it cannot be compressed or encrypted")]
24    AlreadyElided,
25
26    /// Returned when attempting to retrieve an assertion by predicate, but
27    /// multiple matching assertions exist.
28    ///
29    /// For queries that expect a single result (like `object_for_predicate`),
30    /// having multiple matching assertions is ambiguous and requires more
31    /// specific targeting.
32    #[error("more than one assertion matches the predicate")]
33    AmbiguousPredicate,
34
35    /// Returned when a digest validation fails.
36    ///
37    /// This can occur when unwrapping an envelope, verifying signatures, or
38    /// other operations that rely on the integrity of envelope digests.
39    #[error("digest did not match")]
40    InvalidDigest,
41
42    /// Returned when an envelope's format is invalid.
43    ///
44    /// This typically occurs during parsing or decoding of an envelope from
45    /// CBOR.
46    #[error("invalid format")]
47    InvalidFormat,
48
49    /// Returned when a digest is expected but not found.
50    ///
51    /// This can occur when working with envelope structures that require digest
52    /// information, such as when working with elided envelopes.
53    #[error("a digest was expected but not found")]
54    MissingDigest,
55
56    /// Returned when attempting to retrieve an assertion by predicate, but no
57    /// matching assertion exists.
58    ///
59    /// This error occurs with functions like `object_for_predicate` when the
60    /// specified predicate doesn't match any assertion in the envelope.
61    #[error("no assertion matches the predicate")]
62    NonexistentPredicate,
63
64    /// Returned when attempting to unwrap an envelope that wasn't wrapped.
65    ///
66    /// This error occurs when calling `Envelope::try_unwrap` on an
67    /// envelope that doesn't have the wrapped format.
68    #[error("cannot unwrap an envelope that was not wrapped")]
69    NotWrapped,
70
71    /// Returned when expecting an envelope's subject to be a leaf, but it
72    /// isn't.
73    ///
74    /// This error occurs when calling methods that require access to a leaf
75    /// value but the envelope's subject is an assertion, node, or elided.
76    #[error("the envelope's subject is not a leaf")]
77    NotLeaf,
78
79    /// Returned when expecting an envelope's subject to be an assertion, but it
80    /// isn't.
81    ///
82    /// This error occurs when calling methods that require an assertion
83    /// structure but the envelope's subject has a different format.
84    #[error("the envelope's subject is not an assertion")]
85    NotAssertion,
86
87    /// Returned
88    #[error("assertion must be a map with exactly one element")]
89    InvalidAssertion,
90
91    //
92    // Attachments Extension
93    /// Returned when an attachment's format is invalid.
94    ///
95    /// This error occurs when an envelope contains an attachment with an
96    /// invalid structure according to the Envelope Attachment specification
97    /// (BCR-2023-006).
98    #[cfg(feature = "attachment")]
99    #[error("invalid attachment")]
100    InvalidAttachment,
101
102    /// Returned when an attachment is requested but does not exist.
103    ///
104    /// This error occurs when attempting to retrieve an attachment by ID that
105    /// doesn't exist in the envelope.
106    #[cfg(feature = "attachment")]
107    #[error("nonexistent attachment")]
108    NonexistentAttachment,
109
110    /// Returned when multiple attachments match a single query.
111    ///
112    /// This error occurs when multiple attachments have the same ID, making
113    /// it ambiguous which attachment should be returned.
114    #[cfg(feature = "attachment")]
115    #[error("abiguous attachment")]
116    AmbiguousAttachment,
117
118    //
119    // Edges Extension
120    /// Returned when an edge is missing the required `'isA'` assertion.
121    #[cfg(feature = "edge")]
122    #[error("edge missing 'isA' assertion")]
123    EdgeMissingIsA,
124
125    /// Returned when an edge is missing the required `'source'` assertion.
126    #[cfg(feature = "edge")]
127    #[error("edge missing 'source' assertion")]
128    EdgeMissingSource,
129
130    /// Returned when an edge is missing the required `'target'` assertion.
131    #[cfg(feature = "edge")]
132    #[error("edge missing 'target' assertion")]
133    EdgeMissingTarget,
134
135    /// Returned when an edge has duplicate `'isA'` assertions.
136    #[cfg(feature = "edge")]
137    #[error("edge has duplicate 'isA' assertions")]
138    EdgeDuplicateIsA,
139
140    /// Returned when an edge has duplicate `'source'` assertions.
141    #[cfg(feature = "edge")]
142    #[error("edge has duplicate 'source' assertions")]
143    EdgeDuplicateSource,
144
145    /// Returned when an edge has duplicate `'target'` assertions.
146    #[cfg(feature = "edge")]
147    #[error("edge has duplicate 'target' assertions")]
148    EdgeDuplicateTarget,
149
150    /// Returned when an edge has an assertion that is not one of the
151    /// three required predicates (`'isA'`, `'source'`, `'target'`).
152    #[cfg(feature = "edge")]
153    #[error("edge has unexpected assertion")]
154    EdgeUnexpectedAssertion,
155
156    /// Returned when an edge is requested but does not exist.
157    #[cfg(feature = "edge")]
158    #[error("nonexistent edge")]
159    NonexistentEdge,
160
161    /// Returned when multiple edges match a single query.
162    #[cfg(feature = "edge")]
163    #[error("ambiguous edge")]
164    AmbiguousEdge,
165
166    //
167    // Compression Extension
168    /// Returned when attempting to compress an envelope that is already
169    /// compressed.
170    ///
171    /// This error occurs when calling compression functions on an envelope that
172    /// already has compressed content, as defined in BCR-2023-005.
173    #[cfg(feature = "compress")]
174    #[error("envelope was already compressed")]
175    AlreadyCompressed,
176
177    /// Returned when attempting to decompress an envelope that is not
178    /// compressed.
179    ///
180    /// This error occurs when calling decompression functions on an envelope
181    /// that doesn't contain compressed content.
182    #[cfg(feature = "compress")]
183    #[error("cannot decompress an envelope that was not compressed")]
184    NotCompressed,
185
186    //
187    // Symmetric Encryption Extension
188    /// Returned when attempting to encrypt an envelope that is already
189    /// encrypted or compressed.
190    ///
191    /// This error occurs to prevent multiple layers of encryption or encryption
192    /// of compressed data, which could reduce security, as defined in
193    /// BCR-2023-004.
194    #[cfg(feature = "encrypt")]
195    #[error(
196        "envelope was already encrypted or compressed, so it cannot be encrypted"
197    )]
198    AlreadyEncrypted,
199
200    /// Returned when attempting to decrypt an envelope that is not encrypted.
201    ///
202    /// This error occurs when calling decryption functions on an envelope that
203    /// doesn't contain encrypted content.
204    #[cfg(feature = "encrypt")]
205    #[error("cannot decrypt an envelope that was not encrypted")]
206    NotEncrypted,
207
208    //
209    // Known Values Extension
210    /// Returned when expecting an envelope's subject to be a known value, but
211    /// it isn't.
212    ///
213    /// This error occurs when calling methods that require a known value (as
214    /// defined in BCR-2023-003) but the envelope's subject is a different
215    /// type.
216    #[cfg(feature = "known_value")]
217    #[error("the envelope's subject is not a known value")]
218    NotKnownValue,
219
220    //
221    // Public Key Encryption Extension
222    /// Returned when attempting to decrypt an envelope with a recipient that
223    /// doesn't match.
224    ///
225    /// This error occurs when trying to use a private key to decrypt an
226    /// envelope that wasn't encrypted for the corresponding public key.
227    #[cfg(feature = "recipient")]
228    #[error("unknown recipient")]
229    UnknownRecipient,
230
231    //
232    // Encrypted Key Extension
233    /// Returned when attempting to decrypt an envelope with a secret that
234    /// doesn't match.
235    ///
236    /// This error occurs when trying to use a secret that does not correspond
237    /// to the expected recipient, preventing successful decryption.
238    #[cfg(feature = "secret")]
239    #[error("secret not found")]
240    UnknownSecret,
241
242    //
243    // Public Key Signing Extension
244    /// Returned when a signature verification fails.
245    ///
246    /// This error occurs when a signature does not validate against its
247    /// purported public key.
248    #[cfg(feature = "signature")]
249    #[error("could not verify a signature")]
250    UnverifiedSignature,
251
252    /// Returned when the outer signature object type is not `Signature`.
253    #[cfg(feature = "signature")]
254    #[error("unexpected outer signature object type")]
255    InvalidOuterSignatureType,
256
257    /// Returned when the inner signature object type is not `Signature`.
258    #[cfg(feature = "signature")]
259    #[error("unexpected inner signature object type")]
260    InvalidInnerSignatureType,
261
262    /// Returned when the inner signature is not made with the same key as the
263    /// outer signature.
264    #[cfg(feature = "signature")]
265    #[error("inner signature not made with same key as outer signature")]
266    UnverifiedInnerSignature,
267
268    /// Returned when the signature object is not a `Signature`.
269    #[cfg(feature = "signature")]
270    #[error("unexpected signature object type")]
271    InvalidSignatureType,
272
273    //
274    // SSKR Extension
275    /// Returned when SSKR shares are invalid or insufficient for
276    /// reconstruction.
277    ///
278    /// This error occurs when attempting to join SSKR shares that are
279    /// malformed, from different splits, or insufficient to meet the
280    /// recovery threshold.
281    #[cfg(feature = "sskr")]
282    #[error("invalid SSKR shares")]
283    InvalidShares,
284
285    //
286    // Types Extension
287    /// Returned when an envelope contains an invalid type.
288    ///
289    /// This error occurs when an envelope's type information doesn't match
290    /// the expected format or value.
291    #[cfg(feature = "types")]
292    #[error("invalid type")]
293    InvalidType,
294
295    /// Returned when an envelope contains ambiguous type information.
296    ///
297    /// This error occurs when multiple type assertions exist that conflict
298    /// with each other or create ambiguity about the envelope's type.
299    #[cfg(feature = "types")]
300    #[error("ambiguous type")]
301    AmbiguousType,
302
303    /// Returned when the subject of the envelope is not the unit value.
304    #[cfg(feature = "known_value")]
305    #[error("the subject of the envelope is not the unit value")]
306    SubjectNotUnit,
307
308    //
309    // Expressions Extension
310    /// Returned when a response envelope has an unexpected ID.
311    ///
312    /// This error occurs when processing a response envelope and the ID doesn't
313    /// match the expected request ID, as defined in BCR-2023-012.
314    #[cfg(feature = "expression")]
315    #[error("unexpected response ID")]
316    UnexpectedResponseID,
317
318    /// Returned when a response envelope is invalid.
319    #[cfg(feature = "expression")]
320    #[error("invalid response")]
321    InvalidResponse,
322
323    /// SSKR error
324    #[cfg(feature = "sskr")]
325    #[error("sskr error: {0}")]
326    SSKR(#[from] bc_components::SSKRError),
327
328    /// dcbor error
329    #[error("dcbor error: {0}")]
330    Cbor(#[from] dcbor::Error),
331
332    /// Components error
333    #[error("components error: {0}")]
334    Components(#[from] ComponentsError),
335
336    /// General error
337    #[error("general error: {0}")]
338    General(String),
339}
340
341impl Error {
342    pub fn msg(msg: impl Into<String>) -> Self { Error::General(msg.into()) }
343}
344
345impl From<Error> for dcbor::Error {
346    fn from(error: Error) -> dcbor::Error {
347        match error {
348            Error::Cbor(err) => err,
349            _ => dcbor::Error::Custom(error.to_string()),
350        }
351    }
352}
353
354pub type Result<T> = std::result::Result<T, Error>;