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>;