p3_binary_pcs/whir/error.rs
1//! Why a binary WHIR commitment, schedule or opening was refused.
2
3use p3_sumcheck::ring_switch::bits::{BitRingSwitchError, BitRingSwitchProofError};
4use p3_whir::{VerifierError, WhirConfigError};
5use thiserror::Error;
6
7use crate::packing::PackError;
8
9/// Why a Boolean commitment or opening was refused.
10#[derive(Debug, Error)]
11#[non_exhaustive]
12pub enum BooleanWhirError {
13 /// The witness is narrower than the coordinates one element absorbs.
14 #[error("a bit witness of {actual} variables cannot absorb {needed} into one element")]
15 WitnessTooNarrow {
16 /// Coordinates one element absorbs.
17 needed: usize,
18 /// Variables the witness has.
19 actual: usize,
20 },
21
22 /// The schedule does not commit the elements the packing holds.
23 #[error("the schedule commits {actual} variables, the packing holds {expected}")]
24 ConfigArity {
25 /// Variables the packing holds.
26 expected: usize,
27 /// Variables the schedule commits.
28 actual: usize,
29 },
30
31 /// The witness does not cover the committed hypercube.
32 #[error("the packed witness has {actual} variables, expected {expected}")]
33 WitnessArity {
34 /// Variables the commitment holds.
35 expected: usize,
36 /// Variables the witness packs to.
37 actual: usize,
38 },
39
40 /// No opening point was supplied, so there is nothing to prove.
41 #[error("an opening needs at least one point")]
42 NoPoints,
43
44 /// The claim counts on the two sides of an opening disagree.
45 #[error("{expected} points against {values} values and {reductions} reductions")]
46 ClaimCount {
47 /// Points supplied.
48 expected: usize,
49 /// Values supplied.
50 values: usize,
51 /// Reductions the proof carries.
52 reductions: usize,
53 },
54
55 /// The opening point does not name the committed function's variables.
56 #[error("the opening point names {actual} variables, expected {expected}")]
57 PointArity {
58 /// Variables the committed function has.
59 expected: usize,
60 /// Variables the point names.
61 actual: usize,
62 },
63
64 /// An opening asks for no reading at all.
65 #[error("opening {index} asks for no reading")]
66 NoReading {
67 /// Position of the opening.
68 index: usize,
69 },
70
71 /// An opening steps within more rows than the witness has.
72 #[error("opening {index} steps within {row_variables} rows of {num_variables} variables")]
73 RowVariables {
74 /// Position of the opening.
75 index: usize,
76 /// Trailing coordinates the successor view steps within.
77 row_variables: usize,
78 /// Variables the witness has.
79 num_variables: usize,
80 },
81
82 /// A reading is present where its opening asks for none, or missing where it asks for one.
83 #[error("the readings of opening {index} do not match what it asks for")]
84 ReadingShape {
85 /// Position of the opening.
86 index: usize,
87 },
88
89 /// The bits do not reinterpret as whole elements of the alphabet.
90 #[error(transparent)]
91 Packing(PackError),
92
93 /// A reduction could not be set up for its opening.
94 #[error(transparent)]
95 Reduction(BitRingSwitchError),
96
97 /// A reduction proof was rejected.
98 #[error(transparent)]
99 ReductionProof(BitRingSwitchProofError),
100
101 /// The proximity argument refused to commit or to open.
102 #[error(transparent)]
103 Commit(WhirConfigError),
104
105 /// The proximity opening was rejected.
106 #[error(transparent)]
107 Opening(VerifierError),
108
109 /// A surviving claim was not closed by the value the commitment opened.
110 #[error("a surviving claim does not match the opened value")]
111 SurvivingClaim,
112}
113
114/// Why a schedule or a proof was refused by the ceiling.
115#[derive(Clone, Copy, Debug, Error, PartialEq, Eq)]
116#[non_exhaustive]
117pub enum BudgetError {
118 /// The verifier would open more positions than the ceiling allows.
119 #[error("{actual} opened positions exceed the budget of {budget}")]
120 Queries {
121 /// Positions the schedule opens.
122 actual: usize,
123 /// Positions the ceiling allows.
124 budget: usize,
125 },
126
127 /// The proof is larger than the ceiling allows.
128 #[error("{actual} proof bytes exceed the budget of {budget}")]
129 Bytes {
130 /// Bytes the proof occupies.
131 actual: usize,
132 /// Bytes the ceiling allows.
133 budget: usize,
134 },
135
136 /// The schedule demands more grinding than the ceiling allows.
137 #[error("{actual} grinding bits exceed the budget of {budget}")]
138 Grinding {
139 /// Bits the schedule demands.
140 actual: usize,
141 /// Bits the ceiling allows.
142 budget: usize,
143 },
144}
145
146/// Why a profile could not be turned into a schedule.
147#[derive(Debug, Error)]
148#[non_exhaustive]
149pub enum ProfileError {
150 /// The derivation refused the profile.
151 #[error(transparent)]
152 Schedule(WhirConfigError),
153
154 /// The analysis demands more grinding than one witness of the alphabet can carry.
155 #[error("the schedule needs {required} grinding bits, one witness allows {ceiling}")]
156 Grinding {
157 /// Bits the analysis demands.
158 required: usize,
159 /// Bits one witness carries.
160 ceiling: usize,
161 },
162
163 /// The derived schedule opens no position, so nothing ties a codeword to the commitment.
164 ///
165 /// Queries are the only part of the run that tests proximity.
166 ///
167 /// A schedule opening none of them accepts any codeword, whatever the level reported.
168 ///
169 /// That is what crediting grinding with the whole target derives to.
170 ///
171 /// The protocol level is a saturating difference.
172 ///
173 /// So the credit is whole whenever the budget reaches the target, not only at zero.
174 ///
175 /// The floor lives in the schedule itself, so every constructor meets it.
176 #[error("the derived schedule opens no position, so it accepts any codeword")]
177 ZeroQueries,
178}