1use crate::hash::Hash;
2use crate::utils;
3use anyhow::{Result, anyhow};
4use ff::{Field, PrimeField};
5use starkom_bluesky::Scalar;
6use starkom_poly;
7use std::marker::PhantomData;
8use std::sync::LazyLock;
9
10type Polynomial = starkom_poly::Polynomial<Scalar>;
11
12static LEAF_DST: LazyLock<Scalar> = LazyLock::new(|| utils::hash_to_scalar(b"starkom/fri/leaf"));
14
15static TREE_DST: LazyLock<Scalar> = LazyLock::new(|| utils::hash_to_scalar(b"starkom/fri/tree"));
17
18static FOLD_DST: LazyLock<Scalar> = LazyLock::new(|| utils::hash_to_scalar(b"starkom/fri/fold"));
20
21static GENERATOR_INV: LazyLock<Scalar> =
25 LazyLock::new(|| Scalar::MULTIPLICATIVE_GENERATOR.invert().unwrap());
26
27fn hash_leaf<H: Hash<Scalar>>(values: &[Scalar]) -> Scalar {
29 H::hash_many(
30 std::iter::once(*LEAF_DST)
31 .chain(std::iter::once(Scalar::from(values.len() as u64)))
32 .chain(values.iter().cloned())
33 .collect::<Vec<Scalar>>()
34 .as_slice(),
35 )
36}
37
38pub fn merklify<H: Hash<Scalar>>(mut values: &mut [Scalar], mut n: usize) {
58 assert!(n.is_power_of_two());
59 while n > 1 {
60 let m = n / 2;
61 for j in 0..m {
62 values[n + j] = H::hash_raw(*TREE_DST, values[j * 2], values[j * 2 + 1]);
63 }
64 values = &mut values[n..];
65 n = m;
66 }
67}
68
69#[derive(Debug, Clone, PartialEq, Eq)]
75pub struct Commitment {
76 roots: Vec<Scalar>,
80}
81
82impl Commitment {
83 pub fn len(&self) -> usize {
87 self.roots.len()
88 }
89
90 pub fn roots(&self) -> &[Scalar] {
94 self.roots.as_slice()
95 }
96
97 pub fn root(&self) -> Scalar {
100 *self.roots.first().unwrap()
101 }
102}
103
104#[derive(Debug, Clone, PartialEq, Eq)]
114pub struct LeafProof<H: Hash<Scalar>> {
115 leaf: Vec<Scalar>,
116 path: Vec<Scalar>,
117 _data: PhantomData<H>,
118}
119
120impl<H: Hash<Scalar>> LeafProof<H> {
121 pub fn leaf(&self) -> &[Scalar] {
123 self.leaf.as_slice()
124 }
125
126 pub fn check_leaf(&self, expected: &[Scalar]) -> Result<()> {
130 if expected.len() != self.leaf.len()
131 || self
132 .leaf
133 .iter()
134 .zip(expected.iter())
135 .any(|(&value1, &value2)| value1 != value2)
136 {
137 return Err(anyhow!("leaf value mismatch"));
138 }
139 Ok(())
140 }
141
142 pub fn len(&self) -> usize {
145 self.path.len()
146 }
147
148 pub fn verify(&self, mut index: usize, root_hash: Scalar) -> Result<()> {
150 let mut hash = hash_leaf::<H>(self.leaf.as_slice());
151 for sibling in &self.path {
152 hash = if index & 1 != 0 {
153 H::hash_raw(*TREE_DST, *sibling, hash)
154 } else {
155 H::hash_raw(*TREE_DST, hash, *sibling)
156 };
157 index >>= 1;
158 }
159 if index != 0 {
160 return Err(anyhow!("invalid index"));
161 }
162 if hash != root_hash {
163 return Err(anyhow!(
164 "root hash mismatch (got {}, want {})",
165 hash,
166 root_hash
167 ));
168 }
169 Ok(())
170 }
171
172 pub fn is_constant(&self) -> bool {
180 let mut hash = hash_leaf::<H>(self.leaf.as_slice());
181 for &sibling in &self.path {
182 if sibling != hash {
183 return false;
184 }
185 hash = H::hash_raw(*TREE_DST, hash, hash);
186 }
187 true
188 }
189}
190
191#[derive(Debug, Clone)]
198pub struct Tree<H: Hash<Scalar>> {
199 num_polys: usize,
201 leaves: Vec<Vec<Scalar>>,
203 hashes: Vec<Scalar>,
206 _data: PhantomData<H>,
207}
208
209impl<H: Hash<Scalar>> Tree<H> {
210 pub fn from_leaves(leaves: Vec<Vec<Scalar>>) -> Self {
221 let num_polys = leaves[0].len();
222 assert!(num_polys > 0);
223 let n = leaves.len();
224 assert!(n.is_power_of_two());
225 let mut hashes = vec![Scalar::ZERO; n * 2 - 1];
226 for i in 0..n {
227 let leaf = leaves[i].as_slice();
228 assert_eq!(leaf.len(), num_polys);
229 hashes[i] = hash_leaf::<H>(leaf);
230 }
231 merklify::<H>(hashes.as_mut_slice(), n);
232 Self {
233 num_polys,
234 leaves,
235 hashes,
236 _data: Default::default(),
237 }
238 }
239
240 pub fn new(values: Vec<Vec<Scalar>>) -> Self {
253 let k = values.len();
254 assert!(k > 0);
255 let n = values[0].len();
256 let leaves: Vec<Vec<Scalar>> = (0..n)
257 .map(|i| {
258 (0..k)
259 .map(|j| {
260 assert_eq!(n, values[j].len());
261 values[j][i]
262 })
263 .collect()
264 })
265 .collect();
266 Self::from_leaves(leaves)
267 }
268
269 pub fn num_polys(&self) -> usize {
273 self.num_polys
274 }
275
276 pub fn num_leaves(&self) -> usize {
279 self.leaves.len()
280 }
281
282 pub fn root_hash(&self) -> Scalar {
284 let n = self.leaves.len();
285 self.hashes[(n - 1) * 2]
286 }
287
288 pub fn leaf(&self, index: usize) -> &[Scalar] {
292 self.leaves[index].as_slice()
293 }
294
295 pub fn query(&self, mut index: usize) -> LeafProof<H> {
297 let mut n = self.leaves.len();
298 assert!(n.is_power_of_two());
299 assert!(index < n);
300 let leaf = self.leaves[index].clone();
301 let mut path = Vec::with_capacity(n.trailing_zeros() as usize);
302 let mut hashes = self.hashes.as_slice();
303 while n > 1 {
304 path.push(hashes[index ^ 1]);
305 hashes = &hashes[n..];
306 n /= 2;
307 index >>= 1;
308 }
309 LeafProof {
310 leaf,
311 path,
312 _data: Default::default(),
313 }
314 }
315
316 fn fold(&self) -> Self {
318 let n = self.leaves.len();
319 assert!(n.is_power_of_two());
320
321 let alpha = H::hash_raw(*FOLD_DST, self.hashes[(n - 1) * 2], Scalar::ZERO) * *GENERATOR_INV;
322
323 let k = n.trailing_zeros();
324 let omega_inv = Scalar::ROOT_OF_UNITY_INV.pow_vartime([1u64 << (Scalar::S - k), 0, 0, 0]);
325
326 let m = n / 2;
327 let mut omega_inv_i = Scalar::ONE;
328
329 let mut leaves = Vec::with_capacity(m);
330 for i in 0..m {
331 let pos = self.leaves[i].as_slice();
332 let neg = self.leaves[i + m].as_slice();
333 leaves.push(
334 pos.iter()
335 .cloned()
336 .zip(neg.iter().cloned())
337 .map(|(pos, neg)| {
338 (pos + neg + alpha * omega_inv_i * (pos - neg)) * Scalar::TWO_INV
339 })
340 .collect::<Vec<Scalar>>(),
341 );
342 omega_inv_i *= omega_inv;
343 }
344
345 Self::from_leaves(leaves)
346 }
347
348 fn fold_all(self, times: usize) -> Vec<Self> {
354 let mut trees = Vec::with_capacity(times + 1);
355 let mut tree = self;
356 for _ in 0..times {
357 let folded = tree.fold();
358 trees.push(tree);
359 tree = folded;
360 }
361 trees.push(tree);
362 trees
363 }
364}
365
366#[derive(Debug, Clone)]
367pub struct Query<H: Hash<Scalar>> {
368 n: usize,
370 index: usize,
372 folds: Vec<(LeafProof<H>, LeafProof<H>)>,
375 _data: PhantomData<H>,
376}
377
378impl<H: Hash<Scalar>> Query<H> {
379 pub fn indices(&self) -> (usize, usize) {
381 (self.index, (self.index + self.n / 2) % self.n)
382 }
383
384 pub fn x(&self) -> Scalar {
394 Polynomial::coset_element2(self.index, self.n)
395 }
396
397 pub fn values(&self) -> (&[Scalar], &[Scalar]) {
402 (self.folds[0].0.leaf(), self.folds[0].1.leaf())
403 }
404
405 pub fn len(&self) -> usize {
411 return self.folds.len();
412 }
413
414 pub fn verify(&self, commitment: &Commitment) -> Result<()> {
420 assert!(self.n.is_power_of_two());
421 assert!(self.index < self.n);
422 let k = self.n.trailing_zeros();
423
424 let folds = self.folds.as_slice();
425
426 let h = folds.len();
427 if h > k as usize + 1 {
428 return Err(anyhow!("invalid proof size"));
429 }
430 if commitment.len() != h {
431 return Err(anyhow!("wrong number of folding rounds"));
432 }
433
434 let mut m = self.n;
435 let mut index = self.index;
436 let mut pos = self.folds[0].0.leaf().to_vec();
437 let mut step = Scalar::ROOT_OF_UNITY_INV.pow_vartime([1u64 << (Scalar::S - k), 0, 0, 0]);
438
439 for r in 0..h {
440 let (left, right) = &folds[r];
441 let root_hash = commitment.roots()[r];
442 let alpha = H::hash_raw(*FOLD_DST, root_hash, Scalar::ZERO) * *GENERATOR_INV;
443 let neg = right.leaf();
444
445 if 1usize << left.len() != m {
446 return Err(anyhow!(
447 "invalid left-hand side Merkle proof height (got {}, want {})",
448 left.len(),
449 m.trailing_zeros()
450 ));
451 }
452 if 1usize << right.len() != m {
453 return Err(anyhow!(
454 "invalid right-hand side Merkle proof height (got {}, want {})",
455 right.len(),
456 m.trailing_zeros()
457 ));
458 }
459
460 left.check_leaf(pos.as_slice())?;
461 left.verify(index, root_hash)?;
462 right.verify((index + m / 2) % m, root_hash)?;
463
464 let omega_inv_i = step.pow_vartime([index as u64, 0, 0, 0]);
465 m /= 2;
466 index %= m;
467
468 for i in 0..pos.len() {
469 pos[i] =
470 (pos[i] + neg[i] + alpha * omega_inv_i * (pos[i] - neg[i])) * Scalar::TWO_INV;
471 }
472 step = step.square();
473 }
474
475 let (left, right) = folds.last().unwrap();
476 if !left.is_constant() || !right.is_constant() {
477 return Err(anyhow!("final folded polynomial is not constant"));
478 }
479
480 Ok(())
481 }
482}
483
484#[derive(Debug, Clone)]
491pub struct Prover<H: Hash<Scalar>> {
492 degree_bound: usize,
495 blowup_log2: usize,
497 trees: Vec<Tree<H>>,
501}
502
503impl<H: Hash<Scalar>> Prover<H> {
504 pub fn new(polynomials: Vec<Polynomial>, degree_bound: usize, blowup_log2: usize) -> Self {
505 assert!(degree_bound.is_power_of_two());
506 assert!(
507 polynomials
508 .iter()
509 .all(|polynomial| degree_bound >= polynomial.degree_bound())
510 );
511
512 let n = degree_bound << blowup_log2;
513 assert!(n as u64 <= 1u64 << Scalar::S);
514
515 let main_tree = Tree::<H>::new(
516 polynomials
517 .into_iter()
518 .map(|polynomial| polynomial.shifted_lde2(n))
519 .collect(),
520 );
521 let trees = main_tree.fold_all(degree_bound.trailing_zeros() as usize);
522
523 Self {
524 degree_bound,
525 blowup_log2,
526 trees,
527 }
528 }
529
530 pub fn degree_bound(&self) -> usize {
535 self.degree_bound
536 }
537
538 pub fn extended_domain_size(&self) -> usize {
540 self.degree_bound << self.blowup_log2
541 }
542
543 pub fn size(&self) -> usize {
545 self.degree_bound << self.blowup_log2
546 }
547
548 pub fn root_hash(&self) -> Scalar {
552 self.trees[0].root_hash()
553 }
554
555 pub fn commit(&self) -> Commitment {
557 Commitment {
558 roots: self.trees.iter().map(|tree| tree.root_hash()).collect(),
559 }
560 }
561
562 pub fn query(&self, index: usize) -> Query<H> {
567 let d = self.degree_bound;
568 assert!(d.is_power_of_two());
569
570 let n = self.degree_bound << self.blowup_log2;
571 assert!(index < n);
572
573 let mut m = n;
574 let mut i = index;
575 let mut folds = vec![];
576 for tree in &self.trees {
577 folds.push((tree.query(i), tree.query((i + m / 2) % m)));
578 m /= 2;
579 i %= m;
580 }
581
582 {
583 let (left, right) = folds.last().unwrap();
584 assert!(left.is_constant());
585 assert!(right.is_constant());
586 }
587
588 Query {
589 n,
590 index,
591 folds,
592 _data: Default::default(),
593 }
594 }
595}
596
597#[cfg(test)]
598mod tests {
599 use super::*;
600 use crate::hash;
601 use crate::utils::parse_scalar;
602
603 type Poseidon2Hash = hash::Poseidon2Hash<Scalar>;
604 type Sha2Hash = hash::Sha2Hash<Scalar>;
605
606 #[test]
607 fn test_merklify_one_sha2() {
608 let mut values = vec![12.into()];
609 merklify::<Sha2Hash>(&mut values, 1);
610 assert_eq!(values, vec![12.into()]);
611 }
612
613 #[test]
614 fn test_merklify_one_poseidon2() {
615 let mut values = vec![12.into()];
616 merklify::<Poseidon2Hash>(&mut values, 1);
617 assert_eq!(values, vec![12.into()]);
618 }
619
620 #[test]
621 fn test_merklify_two_sha2() {
622 let mut values = vec![34.into(), 56.into()];
623 values.resize(3, 0.into());
624 merklify::<Sha2Hash>(&mut values, 2);
625 assert_eq!(
626 values,
627 vec![
628 34.into(),
629 56.into(),
630 parse_scalar("0x4e92e96500d26aa6e159670815c01b01c89f3385627027e52b20c3be995d9cb4")
631 ]
632 );
633 }
634
635 #[test]
636 fn test_merklify_two_poseidon2() {
637 let mut values = vec![34.into(), 56.into()];
638 values.resize(3, 0.into());
639 merklify::<Poseidon2Hash>(&mut values, 2);
640 assert_eq!(
641 values,
642 vec![
643 34.into(),
644 56.into(),
645 parse_scalar("0x460d694c3fc49199a27c631df8a837d5b64566c40075981ff5cb0396cf52a80b")
646 ]
647 );
648 }
649
650 #[test]
651 fn test_merklify_four_sha2() {
652 let mut values = vec![78.into(), 90.into(), 12.into(), 34.into()];
653 values.resize(7, 0.into());
654 merklify::<Sha2Hash>(&mut values, 4);
655 assert_eq!(
656 values,
657 vec![
658 78.into(),
659 90.into(),
660 12.into(),
661 34.into(),
662 parse_scalar("0x4ba5bb5405a8d200b4c1b2fe1240daa6be892eb58048020e0a03f5fb6e009dec"),
663 parse_scalar("0x1f4cbe6657a61b9852cb8c219f5bf3a42d6404902560ef5dd14f91a414fff307"),
664 parse_scalar("0x58d1fe70cb37a8e745391c570e3cda9e0c24e74464fb5119a29d01f2b64af357"),
665 ]
666 );
667 }
668
669 #[test]
670 fn test_merklify_four_poseidon2() {
671 let mut values = vec![78.into(), 90.into(), 12.into(), 34.into()];
672 values.resize(7, 0.into());
673 merklify::<Poseidon2Hash>(&mut values, 4);
674 assert_eq!(
675 values,
676 vec![
677 78.into(),
678 90.into(),
679 12.into(),
680 34.into(),
681 parse_scalar("0x09c10aba0c59772b51adb65ac6780471b94bf18f63aa121901fb3a428f171064"),
682 parse_scalar("0x2786758795737449218651c7a13e09e40159eb361293bbd7526c26a110f4b733"),
683 parse_scalar("0x183ba165b9bd525fddf2be1420f9087f9ebfbf0bedbdb9e3bf4ec7a785325b13"),
684 ]
685 );
686 }
687
688 fn test_merkle_tree<H: Hash<Scalar>>(leaves: Vec<Vec<Scalar>>, expected_root_hash: Scalar) {
689 let tree = Tree::<H>::from_leaves(leaves.clone());
690 assert_eq!(tree.num_polys(), leaves[0].len());
691 assert_eq!(tree.num_leaves(), leaves.len());
692 assert_eq!(tree.root_hash(), expected_root_hash);
693 for i in 0..leaves.len() {
694 let leaf = &leaves[i];
695 let proof = tree.query(i);
696 assert!(proof.verify(i, expected_root_hash).is_ok());
697 assert_eq!(proof.leaf().len(), leaf.len());
698 assert!(
699 proof
700 .leaf()
701 .iter()
702 .zip(leaf.iter())
703 .all(|(&lhs, &rhs)| lhs == rhs)
704 );
705 }
706 }
707
708 #[test]
709 fn test_merkle_tree_one_leaf_1() {
710 test_merkle_tree::<Sha2Hash>(
711 vec![vec![12.into()]],
712 parse_scalar("0x563171d1d29fc71a8e64c1996982ba9391b948c0f8e53c06f49dd50a935195bd"),
713 );
714 test_merkle_tree::<Poseidon2Hash>(
715 vec![vec![12.into()]],
716 parse_scalar("0x2cdc51a32dac2ed86403822d494776d4512920a3790544b4be3ebf2cbde92171"),
717 );
718 }
719
720 #[test]
721 fn test_merkle_tree_one_leaf_2() {
722 test_merkle_tree::<Sha2Hash>(
723 vec![vec![34.into()]],
724 parse_scalar("0x0a6461fb4b46a4cbf7855d0f8b2221b476c8fa54d510d03c5e0f1b7add3720d6"),
725 );
726 test_merkle_tree::<Poseidon2Hash>(
727 vec![vec![34.into()]],
728 parse_scalar("0x7bd38f78c7b116426eb1c3ce88929882f997ba95fd38128105171586b32a8db0"),
729 );
730 }
731
732 #[test]
733 fn test_merkle_tree_one_leaf_two_polynomials_1() {
734 test_merkle_tree::<Sha2Hash>(
735 vec![vec![12.into(), 34.into()]],
736 parse_scalar("0x12bca773e3d548e97bc3c09698887d8aa79a2a224741aca93ac1f748bf9d0a76"),
737 );
738 test_merkle_tree::<Poseidon2Hash>(
739 vec![vec![12.into(), 34.into()]],
740 parse_scalar("0x7266dbf17f81908d1abfcc37f1ac92cbdbbc0ddf8ed65dd8c56c6a7d4d6d23cf"),
741 );
742 }
743
744 #[test]
745 fn test_merkle_tree_one_leaf_two_polynomials_2() {
746 test_merkle_tree::<Sha2Hash>(
747 vec![vec![34.into(), 12.into()]],
748 parse_scalar("0x54ee34331f32bd339abb4fc82eb2779e696b593bf4c186ca2e993eb0cd3711c3"),
749 );
750 test_merkle_tree::<Poseidon2Hash>(
751 vec![vec![34.into(), 12.into()]],
752 parse_scalar("0x2b81b71d5988e82d27fb48f0b4b2c8f8ff3ba99751f2449997d840d7518dc11b"),
753 );
754 }
755
756 #[test]
757 fn test_merkle_tree_one_leaf_three_polynomials_1() {
758 test_merkle_tree::<Sha2Hash>(
759 vec![vec![12.into(), 34.into(), 56.into()]],
760 parse_scalar("0x285ebc787db855722846ffd14565aa60215c39953648ea0555d493d6d998c634"),
761 );
762 test_merkle_tree::<Poseidon2Hash>(
763 vec![vec![12.into(), 34.into(), 56.into()]],
764 parse_scalar("0x0c3b7d987cb1e3d95e6e0f95fcc37f64ebe76006c7d060cc88d2f6e77ac8ee9c"),
765 );
766 }
767
768 #[test]
769 fn test_merkle_tree_one_leaf_three_polynomials_2() {
770 test_merkle_tree::<Sha2Hash>(
771 vec![vec![34.into(), 12.into(), 78.into()]],
772 parse_scalar("0x54b1edfda64b33dacfd52f04514907c6692cceb22c85737851b192e1b6fc230e"),
773 );
774 test_merkle_tree::<Poseidon2Hash>(
775 vec![vec![34.into(), 12.into(), 78.into()]],
776 parse_scalar("0x06e1ad1622dcc06212ca8b23ca3fd56cdc4d8b065d987412a9cb9fdf1d0e155d"),
777 );
778 }
779
780 #[test]
781 fn test_merkle_tree_two_leaves_1() {
782 test_merkle_tree::<Sha2Hash>(
783 vec![vec![12.into()], vec![34.into()]],
784 parse_scalar("0x20e65b4345db52cd8249ed9c1797f859c4f3dff7c5d9374eb4b89118cd39b643"),
785 );
786 test_merkle_tree::<Poseidon2Hash>(
787 vec![vec![12.into()], vec![34.into()]],
788 parse_scalar("0x2f0c2ee238a5c8f3f9380fa9cdd59d4c1774ef7659554bf37d2e40b1bfda0f3d"),
789 );
790 }
791
792 #[test]
793 fn test_merkle_tree_two_leaves_2() {
794 test_merkle_tree::<Sha2Hash>(
795 vec![vec![34.into()], vec![56.into()]],
796 parse_scalar("0x1cc4e046101296f69bed2fc83482ce4056cd50d36b18cb4b08920225144bcaa6"),
797 );
798 test_merkle_tree::<Poseidon2Hash>(
799 vec![vec![34.into()], vec![56.into()]],
800 parse_scalar("0x14ff951575b5892afaf39760090ee44f2de980a45528a69700570aa0321338ab"),
801 );
802 }
803
804 #[test]
805 fn test_merkle_tree_two_leaves_two_polynomials_1() {
806 test_merkle_tree::<Sha2Hash>(
807 vec![vec![12.into(), 34.into()], vec![56.into(), 78.into()]],
808 parse_scalar("0x65a2f27eccdf81249652273e3df595841ac0d7398b1a866fce9bd6fe3c891dbc"),
809 );
810 test_merkle_tree::<Poseidon2Hash>(
811 vec![vec![12.into(), 34.into()], vec![56.into(), 78.into()]],
812 parse_scalar("0x3233da25a14a69d02937ebb8f7ca4831e1aa53a069c14bdbddb138d0488b3827"),
813 );
814 }
815
816 #[test]
817 fn test_merkle_tree_two_leaves_two_polynomials_2() {
818 test_merkle_tree::<Sha2Hash>(
819 vec![vec![78.into(), 56.into()], vec![34.into(), 12.into()]],
820 parse_scalar("0x40383f40f001699d6bec77a7ef72289ed6461d28659b94c1156d3d8cad226141"),
821 );
822 test_merkle_tree::<Poseidon2Hash>(
823 vec![vec![78.into(), 56.into()], vec![34.into(), 12.into()]],
824 parse_scalar("0x73b93dac865870e7515af085294a34ebf1bb2f1d86faf619013a9855df6caebb"),
825 );
826 }
827
828 fn test_prover_impl<H: Hash<Scalar>>(
829 polynomials: Vec<Polynomial>,
830 degree_bound: usize,
831 blowup_log2: usize,
832 ) {
833 let prover = Prover::<H>::new(polynomials, degree_bound, blowup_log2);
834 assert_eq!(prover.degree_bound(), degree_bound);
835 let n = degree_bound << blowup_log2;
836 assert_eq!(prover.extended_domain_size(), n);
837 let commitment = prover.commit();
838 for i in 0..n {
839 let query = prover.query(i);
840 assert_eq!(query.indices(), (i, (i + n / 2) % n));
841 assert_eq!(query.len(), degree_bound.trailing_zeros() as usize + 1);
842 assert!(query.verify(&commitment).is_ok());
843 }
844 }
845
846 fn test_prover(polynomials: Vec<Polynomial>, degree_bound: usize) {
847 test_prover_impl::<Sha2Hash>(polynomials.clone(), degree_bound, 1);
848 test_prover_impl::<Poseidon2Hash>(polynomials.clone(), degree_bound, 1);
849 test_prover_impl::<Sha2Hash>(polynomials.clone(), degree_bound, 2);
850 test_prover_impl::<Poseidon2Hash>(polynomials.clone(), degree_bound, 2);
851 test_prover_impl::<Sha2Hash>(polynomials.clone(), degree_bound, 3);
852 test_prover_impl::<Poseidon2Hash>(polynomials.clone(), degree_bound, 3);
853 }
854
855 #[test]
856 fn test_one_constant_polynomial() {
857 test_prover(vec![Polynomial::with_coefficients(vec![12.into()])], 1);
858 test_prover(vec![Polynomial::with_coefficients(vec![34.into()])], 1);
859 }
860
861 #[test]
862 fn test_two_constant_polynomials() {
863 test_prover(
864 vec![
865 Polynomial::with_coefficients(vec![12.into()]),
866 Polynomial::with_coefficients(vec![34.into()]),
867 ],
868 1,
869 );
870 }
871
872 #[test]
873 fn test_three_constant_polynomials() {
874 test_prover(
875 vec![
876 Polynomial::with_coefficients(vec![34.into()]),
877 Polynomial::with_coefficients(vec![56.into()]),
878 Polynomial::with_coefficients(vec![78.into()]),
879 ],
880 1,
881 );
882 }
883
884 #[test]
885 fn test_one_polynomial_degree_one() {
886 test_prover(
887 vec![Polynomial::with_coefficients(vec![12.into(), 34.into()])],
888 2,
889 );
890 test_prover(
891 vec![Polynomial::with_coefficients(vec![56.into(), 78.into()])],
892 2,
893 );
894 }
895
896 #[test]
897 fn test_two_polynomials_degree_one() {
898 test_prover(
899 vec![
900 Polynomial::with_coefficients(vec![12.into(), 34.into()]),
901 Polynomial::with_coefficients(vec![56.into(), 78.into()]),
902 ],
903 2,
904 );
905 }
906
907 #[test]
908 fn test_three_polynomials_degree_one() {
909 test_prover(
910 vec![
911 Polynomial::with_coefficients(vec![34.into(), 56.into()]),
912 Polynomial::with_coefficients(vec![56.into(), 78.into()]),
913 Polynomial::with_coefficients(vec![78.into(), 90.into()]),
914 ],
915 2,
916 );
917 }
918
919 #[test]
920 fn test_one_polynomial_degree_three() {
921 test_prover(
922 vec![Polynomial::with_coefficients(vec![
923 12.into(),
924 34.into(),
925 56.into(),
926 78.into(),
927 ])],
928 4,
929 );
930 test_prover(
931 vec![Polynomial::with_coefficients(vec![
932 42.into(),
933 43.into(),
934 44.into(),
935 45.into(),
936 ])],
937 4,
938 );
939 }
940
941 #[test]
942 fn test_two_polynomials_degree_three() {
943 test_prover(
944 vec![
945 Polynomial::with_coefficients(vec![12.into(), 34.into(), 56.into(), 78.into()]),
946 Polynomial::with_coefficients(vec![42.into(), 43.into(), 44.into(), 45.into()]),
947 ],
948 4,
949 );
950 }
951
952 #[test]
953 fn test_three_polynomials_degree_three() {
954 test_prover(
955 vec![
956 Polynomial::with_coefficients(vec![42.into(), 43.into(), 44.into(), 45.into()]),
957 Polynomial::with_coefficients(vec![12.into(), 34.into(), 56.into(), 78.into()]),
958 Polynomial::with_coefficients(vec![34.into(), 56.into(), 78.into(), 90.into()]),
959 ],
960 4,
961 );
962 }
963}