p3_sumcheck/error.rs
1use thiserror::Error;
2
3/// Errors from sumcheck protocol verification.
4#[derive(Error, Debug, PartialEq, Eq)]
5pub enum SumcheckError {
6 /// The proof contains a different number of rounds than expected.
7 #[error("Sumcheck round count mismatch: expected {expected}, got {actual}")]
8 RoundCountMismatch {
9 /// Round count the configuration fixes.
10 expected: usize,
11 /// Round count the proof carries.
12 actual: usize,
13 },
14
15 /// The proof is missing sumcheck data when rounds > 0.
16 #[error("Missing sumcheck data for {expected_rounds} expected rounds")]
17 MissingSumcheckData {
18 /// Round count the configuration fixes.
19 expected_rounds: usize,
20 },
21
22 /// Proof-of-work witness verification failed.
23 #[error("Sumcheck round {round}: pow witness does not meet {difficulty} bits")]
24 InvalidPowWitness {
25 /// Round whose challenge the rejected grinding step guards.
26 round: usize,
27 /// Difficulty in bits that the step requires.
28 difficulty: usize,
29 },
30
31 /// Grinding is enabled but a round carries no witness to replay its step with.
32 #[error("Sumcheck round {round}: missing the pow witness for {difficulty} bits")]
33 MissingPowWitness {
34 /// Round whose challenge the absent grinding step guards.
35 round: usize,
36 /// Difficulty in bits that the step requires.
37 difficulty: usize,
38 },
39
40 /// The witness count is not the one the difficulty fixes.
41 ///
42 /// Zero difficulty admits no witnesses, and a positive one admits exactly one per round.
43 #[error("Sumcheck PoW witness count mismatch: expected {expected}, got {actual}")]
44 PowWitnessCountMismatch {
45 /// Witness count the configuration fixes.
46 expected: usize,
47 /// Witness count the proof carries.
48 actual: usize,
49 },
50
51 /// HVZK sumcheck: a per-round wire payload had the wrong number of field elements.
52 ///
53 /// Each round carries `max(ell_zk, 3) - 1` of them.
54 ///
55 /// The linear coefficient is the one left off, per Lemma 6.4 and paper ยง6.
56 #[error("HVZK round {round}: wire size mismatch, expected {expected}, got {actual}")]
57 WireSizeMismatch {
58 /// Round index where the mismatch was found, counted from zero.
59 round: usize,
60 /// Element count the configuration fixes.
61 expected: usize,
62 /// Element count the proof carries.
63 actual: usize,
64 },
65
66 /// HVZK sumcheck: the base field has characteristic two.
67 ///
68 /// Lemma 6.4 inverts the endpoint identity, which divides by two.
69 #[error("HVZK sumcheck: Lemma 6.4 requires char(F) != 2")]
70 EvenCharacteristic,
71
72 /// HVZK sumcheck: the mask code message is too short to hide a round.
73 ///
74 /// A mask of degree `ell_zk - 1` must cover the degree-2 plain piece.
75 #[error("HVZK sumcheck: mask message length {ell_zk} is below the required 3")]
76 MaskTooShort {
77 /// Mask code message length the configuration fixes.
78 ell_zk: usize,
79 },
80
81 /// HVZK sumcheck: a masked batch was configured with no rounds.
82 ///
83 /// Such a batch commits no mask and reduces no claim.
84 #[error("HVZK sumcheck: a masked batch must run at least one round")]
85 NoRounds,
86
87 /// An opening claim's evaluations do not match the requested column shape.
88 ///
89 /// The evaluations come from the proof, so a malformed proof must be
90 /// rejected here rather than aborting the verifier.
91 #[error(
92 "Opening shape mismatch for table {table_idx}: requested {expected_current} current and {expected_next} next, got {actual_current} current and {actual_next} next"
93 )]
94 OpeningShapeMismatch {
95 /// Table whose opening claim was rejected.
96 table_idx: usize,
97 /// Current-column count the request fixes.
98 expected_current: usize,
99 /// Next-column count the request fixes.
100 expected_next: usize,
101 /// Current-column count the claim carries.
102 actual_current: usize,
103 /// Next-column count the claim carries.
104 actual_next: usize,
105 },
106}