1use std::fmt;
6
7use crate::constraint_system::{Composition, ConstraintKind, ConstraintSystem, ValueSegment};
8
9#[allow(missing_docs)] #[derive(Debug, thiserror::Error)]
12pub enum ConstraintSystemError {
13 #[error(
14 "the {segment:?} segment declares {len} values, over the maximum of {}",
15 ConstraintSystem::MAX_VALUES_PER_SEGMENT
16 )]
17 SegmentTooLarge { segment: ValueSegment, len: usize },
18 #[error("{constraint_kind} #{constraint_index} operand {operand_name} is malformed: {source}")]
19 ConstraintOperand {
20 constraint_kind: ConstraintKind,
21 constraint_index: usize,
22 operand_name: &'static str,
23 #[source]
24 source: OperandFault,
25 },
26 #[error("chip call #{call_index} has a malformed operand #{operand_index}: {source}")]
27 ChipCallOperand {
28 call_index: usize,
29 operand_index: usize,
30 #[source]
31 source: OperandFault,
32 },
33 #[error("{} calls chip {chip_id}, but the system has {n_chips} chips", ChipName(*chip_index))]
34 OutOfRangeChipId {
35 chip_index: Option<usize>,
36 chip_id: usize,
37 n_chips: usize,
38 },
39 #[error(
40 "{}'s call #{call_index} passes {arity} operands to chip {chip_id}, which has {n_inout} inout values",
41 ChipName(*chip_index)
42 )]
43 WrongCallArity {
44 chip_index: Option<usize>,
45 call_index: usize,
46 chip_id: usize,
47 arity: usize,
48 n_inout: usize,
49 },
50 #[error("chip #{chip_index} calls chip {callee}, which is not a later chip")]
51 CallOutOfOrder { chip_index: usize, callee: usize },
52 #[error(
53 "{}'s call #{call_index} names instance {first_instance}, but the call graph gives it {expected}",
54 ChipName(*chip_index)
55 )]
56 WrongCallInstance {
57 chip_index: Option<usize>,
58 call_index: usize,
59 first_instance: usize,
60 expected: usize,
61 },
62 #[error("chip #{chip_id} declares {declared} active instances, but {actual} calls claim it")]
63 WrongActiveInstanceCount {
64 chip_id: usize,
65 declared: usize,
66 actual: usize,
67 },
68 #[error("more invocations reach chip #{chip_id} than a usize can count")]
69 TooManyInstances { chip_id: usize },
70}
71
72#[derive(Debug, Clone, Copy, PartialEq, Eq)]
77pub struct ChipName(pub Option<usize>);
78
79impl fmt::Display for ChipName {
80 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
81 match self.0 {
82 Some(chip_index) => write!(f, "chip #{chip_index}"),
83 None => f.write_str("the main chip"),
84 }
85 }
86}
87
88#[allow(missing_docs)] #[derive(Debug, thiserror::Error)]
94pub enum OperandFault {
95 #[error("the shift is not canonical")]
96 NonCanonicalShift,
97 #[error("the shift amount n={shift_amount}>={max_amount}")]
98 ShiftAmountTooLarge {
99 shift_amount: usize,
100 max_amount: usize,
101 },
102 #[error("a lone shift sits in the outer slot; the canonical form places it inner")]
103 NonCanonicalShiftSequence,
104 #[error("a shift pair composes to {composition:?} rather than staying a pair")]
105 CollapsibleShiftSequence { composition: Composition },
106 #[error("it refers to a scratch value")]
107 ScratchValueIndex,
108 #[error("it refers to {segment:?} index {value_index} >= segment length {segment_len}")]
109 OutOfRangeValueIndex {
110 segment: ValueSegment,
111 value_index: u32,
112 segment_len: usize,
113 },
114}
115
116#[derive(Debug, thiserror::Error)]
121pub enum ConstraintViolation {
122 #[error("{val:016x} != 0")]
124 Zero {
125 val: u64,
127 },
128 #[error("({a:016x} & {b:016x}) ^ {c:016x} = {residue:016x} != 0")]
130 And {
131 a: u64,
133 b: u64,
135 c: u64,
137 residue: u64,
139 },
140 #[error("{a:016x} * {b:016x} = {expected_hi:016x}{expected_lo:016x}, got {hi:016x}{lo:016x}")]
142 Imul {
143 a: u64,
145 b: u64,
147 lo: u64,
149 hi: u64,
151 expected_lo: u64,
153 expected_hi: u64,
155 },
156 #[error("{a:032x} * {b:032x} = {expected:032x}, got {c:032x}")]
158 Bmul {
159 a: u128,
161 b: u128,
163 c: u128,
165 expected: u128,
167 },
168}
169
170impl ConstraintViolation {
171 pub const fn kind(&self) -> ConstraintKind {
176 match self {
177 Self::Zero { .. } => ConstraintKind::Zero,
178 Self::And { .. } => ConstraintKind::And,
179 Self::Imul { .. } => ConstraintKind::Imul,
180 Self::Bmul { .. } => ConstraintKind::Bmul,
181 }
182 }
183}
184
185#[derive(Debug, thiserror::Error)]
187pub enum VerificationError {
188 #[error(
193 "value {value_index} is {actual:016x}, but the system declares the constant {expected:016x}"
194 )]
195 ConstantMismatch {
196 value_index: u32,
198 expected: u64,
200 actual: u64,
202 },
203 #[error("{} #{constraint_index} is unsatisfied: {source}", source.kind())]
205 Unsatisfied {
206 constraint_index: usize,
208 source: ConstraintViolation,
210 },
211}
212
213struct CallerName(Option<(usize, usize)>);
218
219impl fmt::Display for CallerName {
220 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
221 match self.0 {
222 Some((chip_index, instance)) => write!(f, "chip #{chip_index} instance #{instance}"),
223 None => f.write_str("the main chip"),
224 }
225 }
226}
227
228#[allow(missing_docs)] #[derive(Debug, thiserror::Error)]
235pub enum VerificationM4Error {
236 #[error("the witness covers {n_witness_chips} chips, but the system has {n_chips}")]
237 WrongChipCount {
238 n_witness_chips: usize,
239 n_chips: usize,
240 },
241 #[error("the main chip is not satisfied: {0}")]
242 Main(#[from] VerificationError),
243 #[error("chip #{chip_id} instance #{instance} is not satisfied: {source}")]
244 ChipInstance {
245 chip_id: usize,
246 instance: usize,
247 #[source]
248 source: VerificationError,
249 },
250 #[error("chip #{chip_id} has {n_instances} instances, fewer than its {n_active} active ones")]
251 MissingInstances {
252 chip_id: usize,
253 n_instances: usize,
254 n_active: usize,
255 },
256 #[error(
257 "call #{call_index} of {} reaches chip #{chip_id} as invocation #{row}, passing {passed:016x} \
258 as inout value {word}, but the instance holds {served:016x}",
259 CallerName(*caller)
260 )]
261 CallMismatch {
262 chip_id: usize,
263 row: usize,
264 caller: Option<(usize, usize)>,
266 call_index: usize,
267 word: usize,
268 passed: u64,
269 served: u64,
270 },
271}