Skip to main content

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}