mithril_stm/circuits/halo2/
errors.rs

1use midnight_proofs::plonk::Error as PlonkError;
2use thiserror::Error;
3
4use crate::StmError;
5
6/// Circuit-scoped errors for Halo2 STM validation and execution.
7#[cfg_attr(not(test), allow(dead_code))]
8#[derive(Debug, Error, Clone, PartialEq, Eq)]
9pub enum StmCircuitError {
10    /// Invalid relation parameters: quorum must be strictly lower than number of lotteries.
11    #[error(
12        "Circuit::validate_parameters failed: quorum ({quorum}) must be lower than num_lotteries ({num_lotteries})"
13    )]
14    InvalidCircuitParameters { quorum: u32, num_lotteries: u32 },
15
16    /// Witness vector length does not match the configured quorum.
17    #[error(
18        "Circuit::validate_witness_length failed: expected quorum {expected_quorum}, got {actual}"
19    )]
20    WitnessLengthMismatch { expected_quorum: u32, actual: u32 },
21
22    /// Witness lottery index does not fit in the circuit's 32-bit constraint representation.
23    #[error(
24        "Circuit::validate_lottery_index failed: index ({index}) exceeds max supported ({max_supported})"
25    )]
26    LotteryIndexTooLarge { index: u64, max_supported: u64 },
27
28    /// Witness lottery index is not a valid in-circuit lottery slot.
29    #[error(
30        "Circuit::validate_lottery_index failed: index ({index}) must be lower than num_lotteries ({num_lotteries})"
31    )]
32    LotteryIndexOutOfBounds { index: u64, num_lotteries: u32 },
33
34    /// Merkle sibling path length does not match the configured Merkle depth.
35    #[error(
36        "Circuit::validate_merkle_sibling_length failed: expected depth {expected_depth}, got {actual}"
37    )]
38    MerkleSiblingLengthMismatch { expected_depth: u32, actual: u32 },
39
40    /// Merkle position path length does not match the configured Merkle depth.
41    #[error(
42        "Circuit::validate_merkle_position_length failed: expected depth {expected_depth}, got {actual}"
43    )]
44    MerklePositionLengthMismatch { expected_depth: u32, actual: u32 },
45
46    /// Failed to parse the prime field modulus while splitting field limbs.
47    #[error("Field modulus parse failed")]
48    FieldModulusParseFailed,
49
50    /// Failed to convert a reduced integer into a prime field element.
51    #[error("Field element conversion failed")]
52    FieldElementConversionFailed,
53
54    /// Bit decomposition range is invalid for the selected prime field.
55    #[error("Invalid bit decomposition range ({num_bits}) for field size ({field_bits})")]
56    InvalidBitDecompositionRange { num_bits: u32, field_bits: u32 },
57
58    /// Merkle tree depth does not fit fixture sizing constraints.
59    #[error("Invalid merkle tree depth ({depth})")]
60    InvalidMerkleTreeDepth { depth: u32 },
61
62    /// Selected leaf index is out of bounds for the current tree.
63    #[error("Invalid selected leaf index ({index}) for {num_leaves} leaves")]
64    InvalidSelectedLeafIndex { index: u32, num_leaves: u32 },
65
66    /// Empty lottery indices were provided where at least one is required.
67    #[error("Empty indices")]
68    EmptyIndices,
69
70    /// Witness must contain at least two entries.
71    #[error("Witness too short (got {actual}, expected at least 2)")]
72    WitnessTooShort { actual: u32 },
73
74    /// No distinct witness entries were found.
75    #[error("No distinct witness entries")]
76    NoDistinctWitnessEntries,
77
78    /// Tried to build a witness from an empty signer set.
79    #[error("Empty signer leaves")]
80    EmptySignerLeaves,
81
82    /// Signer leaf index is out of bounds.
83    #[error("Invalid signer leaf index ({index}) for {num_signers} signers")]
84    InvalidSignerFixtureIndex { index: u32, num_signers: u32 },
85
86    /// Failed to decode challenge bytes into a base field element.
87    #[error("Invalid challenge bytes")]
88    InvalidChallengeBytes,
89
90    /// Challenge bytes decode but do not match native challenge value.
91    #[error("Challenge endianness mismatch")]
92    ChallengeEndiannessMismatch,
93
94    /// Merkle root digest has an invalid byte length.
95    #[error("Invalid merkle root digest length ({actual})")]
96    InvalidMerkleRootDigestLength { actual: u32 },
97
98    /// Merkle root digest is not a canonical base field element encoding.
99    #[error("Non-canonical merkle root digest")]
100    NonCanonicalMerkleRootDigest,
101
102    /// STM Merkle-path verification failed for selected leaf.
103    #[error("Merkle path verification failed")]
104    MerklePathVerificationFailed,
105
106    /// Failed to create the local assets directory for persisted circuit params.
107    #[error("Failed to create params assets directory")]
108    ParamsAssetsDirCreate,
109
110    /// In-memory circuit key cache lock is poisoned.
111    #[error("Circuit keys cache lock poisoned ({operation})")]
112    CircuitKeysCacheLockPoisoned { operation: &'static str },
113
114    /// Signature generation failed while preparing witness.
115    #[error("Signature generation failed")]
116    SignatureGenerationFailed,
117
118    /// Signature verification failed while preparing witness.
119    #[error("Signature verification failed")]
120    SignatureVerificationFailed,
121
122    /// Proof was generated but rejected by the verifier.
123    #[error("Proof verification rejected")]
124    VerificationRejected,
125}
126
127/// Convert STM-layer errors to Midnight synthesis errors at relation boundaries.
128pub(crate) fn to_synthesis_error(error: StmError) -> PlonkError {
129    let error = match error.downcast::<PlonkError>() {
130        Ok(plonk_error) => return plonk_error,
131        Err(error) => error,
132    };
133
134    let error = match error.downcast::<StmCircuitError>() {
135        Ok(stm_error) => return PlonkError::Synthesis(stm_error.to_string()),
136        Err(error) => error,
137    };
138
139    PlonkError::Synthesis(error.to_string())
140}