From bb75e9d4d225b4ab03f0db3c5003bfd456b2aed8 Mon Sep 17 00:00:00 2001
From: "a.stevan" <antoine.stevan@isae-supaero.fr>
Date: Thu, 19 Sep 2024 17:18:10 +0200
Subject: [PATCH 1/5] add more information to some errors

---
 src/lib.rs | 25 +++++++++++++++++++++----
 1 file changed, 21 insertions(+), 4 deletions(-)

diff --git a/src/lib.rs b/src/lib.rs
index 17690c8..d8e2eb6 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -32,12 +32,18 @@ mod tests;
 pub enum VerifyError {
     BadFoldingFactor(usize),
     /// when $|D_i| \neq 2^\bullet$ or $|D_i| \leq k_i$
-    BadDomainSize(usize),
+    BadDomainSize {
+        size: usize,
+        degree_bound: Option<usize>,
+    },
     /// when $k_i \neq 2^\bullet$
     BadDegreeBound(usize),
     /// when $|D_i| \neq 0 \quad\text{mod}\quad N$ or $k_i \neq 0 \quad\text{mod}\quad N$
     DegreeTruncation {
         depth: usize,
+        size: usize,
+        degree_bound: usize,
+        folding_factor: usize,
     },
     /// one of the commitment layers did not verify
     CommitmentMismatch {
@@ -251,7 +257,10 @@ impl<F: FftField, H: Hasher> FriProof<F, H> {
         let () = AssertPowerOfTwo::<N>::OK;
 
         if !domain_size.is_power_of_two() || domain_size <= degree_bound {
-            return Err(VerifyError::BadDomainSize(domain_size));
+            return Err(VerifyError::BadDomainSize {
+                size: domain_size,
+                degree_bound: Some(degree_bound),
+            });
         }
         if !degree_bound.is_power_of_two() {
             return Err(VerifyError::BadDegreeBound(degree_bound));
@@ -260,7 +269,10 @@ impl<F: FftField, H: Hasher> FriProof<F, H> {
             return Err(VerifyError::BadFoldingFactor(N));
         };
         let Some(mut root) = F::get_root_of_unity(domain_size as u64) else {
-            return Err(VerifyError::BadDomainSize(domain_size));
+            return Err(VerifyError::BadDomainSize {
+                size: domain_size,
+                degree_bound: None,
+            });
         };
 
         // Preparation
@@ -317,7 +329,12 @@ impl<F: FftField, H: Hasher> FriProof<F, H> {
             }
 
             if domain_size % N != 0 || degree_bound % N != 0 {
-                return Err(VerifyError::DegreeTruncation { depth });
+                return Err(VerifyError::DegreeTruncation {
+                    depth,
+                    size: domain_size,
+                    degree_bound,
+                    folding_factor: N,
+                });
             }
             root = root.pow([N as u64]);
             domain_size /= N;
-- 
GitLab


From 5bcbc5752c0aea8e7bcbe2f841eb4a64066cb4d5 Mon Sep 17 00:00:00 2001
From: "a.stevan" <antoine.stevan@isae-supaero.fr>
Date: Fri, 20 Sep 2024 09:29:30 +0200
Subject: [PATCH 2/5] add asserts and doc to `to_polynomial` and
 `to_evaluations`

---
 src/utils.rs | 26 +++++++++++++++++++++-----
 1 file changed, 21 insertions(+), 5 deletions(-)

diff --git a/src/utils.rs b/src/utils.rs
index 4150646..f5b1dff 100644
--- a/src/utils.rs
+++ b/src/utils.rs
@@ -178,7 +178,9 @@ impl<H: Hasher> MerkleTreeExt for MerkleTree<H> {
 
 /// Converts `polynomial` from coefficient form to evaluations over roots of unity.
 ///
-/// `domain_size` must be a power of two and strictly greater than the degree of the polynomial.
+/// # Panics
+/// - `domain_size` must be a power of two
+/// - `domain_size` must be strictly greater than the degree of `polynomial`
 ///
 /// # Example
 /// ```
@@ -206,7 +208,14 @@ impl<H: Hasher> MerkleTreeExt for MerkleTree<H> {
 pub fn to_evaluations<F: FftField>(mut polynomial: Vec<F>, domain_size: usize) -> Vec<F> {
     debug_assert!(
         domain_size.is_power_of_two(),
-        "Domain size must be a power of two"
+        "Domain size must be a power of two, found {}",
+        domain_size,
+    );
+    debug_assert!(
+        domain_size > polynomial.len() - 1,
+        "Domain size must be strictly greater than the degree of the polynomial, found |D| = {} and deg(P) = {}",
+        domain_size,
+        polynomial.len() - 1,
     );
 
     let domain = GeneralEvaluationDomain::<F>::new(domain_size).unwrap();
@@ -217,13 +226,20 @@ pub fn to_evaluations<F: FftField>(mut polynomial: Vec<F>, domain_size: usize) -
 /// Interpolates the coefficient form from the evaluations over the roots of unity.
 /// This is the counterpart of [`to_evaluations`].
 ///
-/// `degree_bound` must be strictly greater than the degree of the polynomial. Otherwise, this
-/// may either panic or truncate higher degree coefficients.
+/// # Panics
+/// - the domain size, i.e. the number of `evaluations`, must be a power of two
+/// - `degree_bound` must be strictly greater than the degree of `polynomial`
+///
+/// > **Note**
+/// >
+/// > if the degree bound condition is not met, this function may either panic or
+/// > truncate higher degree coefficients.
 #[inline]
 pub fn to_polynomial<F: FftField>(mut evaluations: Vec<F>, degree_bound: usize) -> Vec<F> {
     debug_assert!(
         evaluations.len().is_power_of_two(),
-        "Domain size must be a power of two"
+        "Domain size must be a power of two, found {} evaluations",
+        evaluations.len(),
     );
 
     let domain = GeneralEvaluationDomain::<F>::new(evaluations.len()).unwrap();
-- 
GitLab


From 7d71a6465cbcb1488f1eb1ad1f3b17f6880067f4 Mon Sep 17 00:00:00 2001
From: "a.stevan" <antoine.stevan@isae-supaero.fr>
Date: Fri, 20 Sep 2024 09:41:14 +0200
Subject: [PATCH 3/5] complete doc of `rng`

---
 src/rng.rs | 19 +++++++++++++------
 1 file changed, 13 insertions(+), 6 deletions(-)

diff --git a/src/rng.rs b/src/rng.rs
index ef4923c..5891bc4 100644
--- a/src/rng.rs
+++ b/src/rng.rs
@@ -23,10 +23,15 @@ pub trait ReseedableRng {
 
     /// Draws a pseudo-random number from field `F`. This does not need to be overriden.
     ///
-    /// # Panics
-    /// This panics if this object is not able to draw a random value from this field.
+    /// > **Note**
+    /// >
+    /// > because converting a random sequence of bytes to an element of `F` might fail, e.g. if
+    /// > the underlying binary representation is bigger than the modulus of `F`, this function
+    /// > uses rejection sampling and might have to resample random bytes until they fit in `F`.
+    /// >
+    /// > however, because the size of `F` will likely be very large, the probability of
+    /// > [`draw_alpha`] getting stuck for a long time is very slim.
     fn draw_alpha<F: Field>(&mut self) -> F {
-        // This has never failed during tests, but this should be tested with other fields.
         loop {
             if let Some(alpha) = self.next_bytes(|bytes| F::from_random_bytes(bytes)) {
                 return alpha;
@@ -37,12 +42,14 @@ pub trait ReseedableRng {
     /// Draws a [`Vec`] of `count` positions, each of them being strictly less than `domain_size`.
     /// This does not need to be overriden.
     ///
-    /// `domain_size` must be a power of two; otherwise, the result is unspecified
-    /// (the implementation may either return incorrect positions or panic).
+    /// # Panics
+    /// - `domain_size` must be a power of two (otherwise, the result is unspecified and the
+    ///   implementation may either return incorrect positions or panic).
     fn draw_positions(&mut self, count: usize, domain_size: usize) -> Vec<usize> {
         debug_assert!(
             domain_size.is_power_of_two(),
-            "Domain size must be a power of two"
+            "Domain size must be a power of two, found {}",
+            domain_size,
         );
 
         let mask = domain_size - 1;
-- 
GitLab


From 44f700561d4fccf52b046dbe4bc9c1becee6ea9e Mon Sep 17 00:00:00 2001
From: "a.stevan" <antoine.stevan@isae-supaero.fr>
Date: Fri, 20 Sep 2024 09:55:24 +0200
Subject: [PATCH 4/5] fix doc typo

---
 src/rng.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/rng.rs b/src/rng.rs
index 5891bc4..45876c3 100644
--- a/src/rng.rs
+++ b/src/rng.rs
@@ -30,7 +30,7 @@ pub trait ReseedableRng {
     /// > uses rejection sampling and might have to resample random bytes until they fit in `F`.
     /// >
     /// > however, because the size of `F` will likely be very large, the probability of
-    /// > [`draw_alpha`] getting stuck for a long time is very slim.
+    /// > getting stuck for a long time is very slim.
     fn draw_alpha<F: Field>(&mut self) -> F {
         loop {
             if let Some(alpha) = self.next_bytes(|bytes| F::from_random_bytes(bytes)) {
-- 
GitLab


From c21fee4444728156fc575285bc3353b4fede3179 Mon Sep 17 00:00:00 2001
From: "a.stevan" <antoine.stevan@isae-supaero.fr>
Date: Fri, 20 Sep 2024 11:28:31 +0200
Subject: [PATCH 5/5] add missing panics doc

---
 src/commit.rs | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/commit.rs b/src/commit.rs
index 750f1de..7f46fa6 100644
--- a/src/commit.rs
+++ b/src/commit.rs
@@ -53,7 +53,8 @@ impl<const N: usize, F: FftField, H: Hasher> FriCommitments<N, F, H> {
     /// See [`crate::commit_polynomial`] for information about the other parameters.
     ///
     /// # Panics
-    /// This may either panic or have unspecified behaviour if `remainder_degree_plus_one` is inconsistent with
+    /// - `N` must be a power of 2
+    /// - This may either panic or have unspecified behaviour if `remainder_degree_plus_one` is inconsistent with
     /// the degree-bound of the polynomial and the folding factor, or if `F` does not contain a subgroup of size
     /// `evaluations.len()`.
     pub fn new<R>(
-- 
GitLab