h33_substrate_verifier/error.rs
1//! Error type for the verifier.
2//!
3//! All fallible operations in this crate return [`VerifierError`]. The
4//! error variants are stable and semantic — calling code can match on
5//! them to drive UI, metrics, or retry logic.
6
7use alloc::string::String;
8use thiserror::Error;
9
10/// Every way verification can fail to *run*.
11///
12/// A successful [`verify_structural`](crate::verify::verify_structural)
13/// call still returns a [`VerificationResult`](crate::verify::VerificationResult)
14/// which itself may report failed checks — those are NOT
15/// [`VerifierError`]s. This type is reserved for inputs that are
16/// malformed to the point where no verdict can be produced.
17#[derive(Debug, Error)]
18#[non_exhaustive]
19pub enum VerifierError {
20 /// The `X-H33-Substrate` header was not 64 hex characters.
21 #[error("X-H33-Substrate header must be 64 hex characters (32 bytes), got {actual}")]
22 InvalidSubstrateHeaderLength {
23 /// Number of characters actually present in the header value.
24 actual: usize,
25 },
26
27 /// The `X-H33-Substrate` header contained invalid hex.
28 #[error("X-H33-Substrate header is not valid hex: {0}")]
29 InvalidSubstrateHeaderHex(String),
30
31 /// The `X-H33-Receipt` header was not 84 hex characters.
32 #[error("X-H33-Receipt header must be 84 hex characters (42 bytes), got {actual}")]
33 InvalidReceiptHeaderLength {
34 /// Number of characters actually present in the header value.
35 actual: usize,
36 },
37
38 /// The `X-H33-Receipt` header contained invalid hex.
39 #[error("X-H33-Receipt header is not valid hex: {0}")]
40 InvalidReceiptHeaderHex(String),
41
42 /// The decoded receipt bytes had an unexpected version byte.
43 ///
44 /// The expected version for this verifier build is
45 /// [`RECEIPT_VERSION`](crate::receipt::RECEIPT_VERSION).
46 #[error("CompactReceipt version byte is 0x{actual:02X}, expected 0x{expected:02X}")]
47 UnsupportedReceiptVersion {
48 /// The version byte the receipt actually carried.
49 actual: u8,
50 /// The version byte this verifier build understands.
51 expected: u8,
52 },
53
54 /// The decoded receipt bytes were not exactly 42 bytes.
55 #[error("CompactReceipt must decode to exactly {expected} bytes, got {actual}")]
56 InvalidReceiptSize {
57 /// Byte length the parser read.
58 actual: usize,
59 /// Byte length the spec requires.
60 expected: usize,
61 },
62
63 /// The receipt's algorithm flags byte had bits set that the verifier
64 /// does not recognize. This can happen when a newer server adds a
65 /// fourth signature family before the verifier crate catches up.
66 /// Not fatal — the recognized families still verify — but the
67 /// caller should know that the full algorithm set was not inspected.
68 #[error(
69 "CompactReceipt algorithm flags 0x{flags:02X} contain unrecognized bits; \
70 verifier only knows Dilithium (0x01), FALCON (0x02), SPHINCS+ (0x04)"
71 )]
72 UnknownAlgorithmBits {
73 /// The raw algorithm flags byte.
74 flags: u8,
75 },
76
77 /// The public-keys JSON document could not be parsed.
78 #[error("public keys JSON parse failed: {0}")]
79 PublicKeysParse(String),
80
81 /// A base64 value in the public-keys JSON could not be decoded.
82 #[error("public keys contained invalid base64 for field `{field}`: {detail}")]
83 PublicKeysBase64 {
84 /// The JSON field the bad base64 was in.
85 field: &'static str,
86 /// Human-readable decoder detail.
87 detail: String,
88 },
89
90 /// An unknown algorithm string appeared in `X-H33-Algorithms`. The
91 /// verifier recognizes exactly these identifiers:
92 ///
93 /// - `ML-DSA-65` (Dilithium, NIST FIPS 204)
94 /// - `FALCON-512`
95 /// - `SPHINCS+-SHA2-128f` (SLH-DSA, NIST FIPS 205)
96 #[error("unknown algorithm identifier in X-H33-Algorithms: `{0}`")]
97 UnknownAlgorithm(String),
98}
99
100#[cfg(feature = "std")]
101impl From<VerifierError> for std::io::Error {
102 fn from(e: VerifierError) -> Self {
103 Self::new(std::io::ErrorKind::InvalidData, e.to_string())
104 }
105}