1use std::fmt;
2
3#[derive(Debug, Clone, PartialEq, Eq)]
5pub enum GenerationError {
6 InvalidGenerator {
8 generator: i64,
9 reason: &'static str,
10 },
11 DuplicateGenerator { generator: i64 },
13 InvalidSplitPrime { split_prime: i64 },
15 PrimeNotSplit { split_prime: i64, generator: i64 },
17 InvalidFieldElementDimension { expected: usize, actual: usize },
19 InvalidSearchParameter {
21 parameter: &'static str,
22 reason: &'static str,
23 },
24 PrimeElementNotFound { prime: i64, max_exponent: usize },
26 MissingImaginaryGenerator,
28 InsufficientPoints { requested: usize, found: usize },
30}
31
32impl fmt::Display for GenerationError {
33 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
34 match self {
35 GenerationError::InvalidGenerator { generator, reason } => {
36 write!(f, "invalid generator {generator}: {reason}")
37 }
38 GenerationError::DuplicateGenerator { generator } => {
39 write!(f, "duplicate generator {generator}")
40 }
41 GenerationError::InvalidSplitPrime { split_prime } => {
42 write!(f, "split prime {split_prime} is not an odd prime")
43 }
44 GenerationError::PrimeNotSplit {
45 split_prime,
46 generator,
47 } => write!(
48 f,
49 "prime {split_prime} is not split by generator {generator}"
50 ),
51 GenerationError::InvalidFieldElementDimension { expected, actual } => write!(
52 f,
53 "field element has {actual} coefficients, but field degree is {expected}"
54 ),
55 GenerationError::InvalidSearchParameter { parameter, reason } => {
56 write!(f, "invalid search parameter {parameter}: {reason}")
57 }
58 GenerationError::PrimeElementNotFound {
59 prime,
60 max_exponent,
61 } => write!(
62 f,
63 "could not find a suitable prime element theta for p = {prime} up to exponent {max_exponent}"
64 ),
65 GenerationError::MissingImaginaryGenerator => write!(
66 f,
67 "field is missing the imaginary generator -1 required by the construction"
68 ),
69 GenerationError::InsufficientPoints { requested, found } => write!(
70 f,
71 "could not generate enough points: requested {requested}, found {found}"
72 ),
73 }
74 }
75}
76
77impl std::error::Error for GenerationError {}
78
79#[derive(Debug, Clone, PartialEq, Eq)]
81pub enum VerificationError {
82 PointCountMismatch { expected: usize, actual: usize },
84 EdgeIndexOutOfBounds {
86 edge: (usize, usize),
87 point_count: usize,
88 },
89 SelfEdge { index: usize },
91 EdgeSetMismatch {
93 expected: Vec<(usize, usize)>,
94 actual: Vec<(usize, usize)>,
95 },
96 PointMismatch { index: usize },
98 QuantizedProjectionMismatch {
100 index: usize,
101 expected: [i64; 2],
102 actual: [i64; 2],
103 },
104 AlgebraicKeyDimensionMismatch { expected: usize, actual: usize },
106 InvalidAlgebraicKeyDenominator { denominator: i64 },
108 TranslationNotNormOne { index: usize },
110 CandidateOutsideWindow {
112 index: usize,
113 radius: String,
114 max_embedding_norm: String,
115 },
116 ProjectionMismatch { index: usize },
118 CandidatePathMismatch { index: usize },
120 CandidatePathTranslationOutOfBounds {
122 candidate_index: usize,
123 translation_index: usize,
124 translation_count: usize,
125 },
126 EdgeProvenanceMismatch { edge_index: usize },
128 InvalidConstruction { reason: String },
130 CertificateSchemaMismatch { reason: String },
132}
133
134impl fmt::Display for VerificationError {
135 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
136 match self {
137 VerificationError::PointCountMismatch { expected, actual } => write!(
138 f,
139 "certificate has {actual} points, but expected {expected}"
140 ),
141 VerificationError::EdgeIndexOutOfBounds { edge, point_count } => write!(
142 f,
143 "certificate edge ({}, {}) is outside point count {point_count}",
144 edge.0, edge.1
145 ),
146 VerificationError::SelfEdge { index } => {
147 write!(f, "certificate contains self-edge at point {index}")
148 }
149 VerificationError::EdgeSetMismatch { expected, actual } => write!(
150 f,
151 "certificate edge set mismatch: expected {} edges, got {}",
152 expected.len(),
153 actual.len()
154 ),
155 VerificationError::PointMismatch { index } => {
156 write!(f, "certificate point {index} does not match construction")
157 }
158 VerificationError::QuantizedProjectionMismatch {
159 index,
160 expected,
161 actual,
162 } => write!(
163 f,
164 "projection key {index} mismatch: expected {:?}, got {:?}",
165 expected, actual
166 ),
167 VerificationError::AlgebraicKeyDimensionMismatch { expected, actual } => write!(
168 f,
169 "algebraic key has {actual} coefficients, but field degree is {expected}"
170 ),
171 VerificationError::InvalidAlgebraicKeyDenominator { denominator } => write!(
172 f,
173 "algebraic key denominator must be positive, got {denominator}"
174 ),
175 VerificationError::TranslationNotNormOne { index } => {
176 write!(f, "translation {index} is not certified as norm-one")
177 }
178 VerificationError::CandidateOutsideWindow {
179 index,
180 radius,
181 max_embedding_norm,
182 } => write!(
183 f,
184 "candidate {index} is outside polydisk radius {radius}; max embedding norm is {max_embedding_norm}"
185 ),
186 VerificationError::ProjectionMismatch { index } => {
187 write!(f, "projection {index} does not match algebraic candidate")
188 }
189 VerificationError::CandidatePathMismatch { index } => {
190 write!(f, "candidate path {index} does not replay to stored key")
191 }
192 VerificationError::CandidatePathTranslationOutOfBounds {
193 candidate_index,
194 translation_index,
195 translation_count,
196 } => write!(
197 f,
198 "candidate {candidate_index} path references translation {translation_index}, but only {translation_count} translations exist"
199 ),
200 VerificationError::EdgeProvenanceMismatch { edge_index } => {
201 write!(
202 f,
203 "construction edge {edge_index} is not explained by its translation provenance"
204 )
205 }
206 VerificationError::InvalidConstruction { reason } => {
207 write!(f, "invalid certificate construction: {reason}")
208 }
209 VerificationError::CertificateSchemaMismatch { reason } => {
210 write!(f, "certificate schema mismatch: {reason}")
211 }
212 }
213 }
214}
215
216impl std::error::Error for VerificationError {}