arrabbiata/
challenge.rs

1use ark_ff::Zero;
2use core::{
3    fmt::{Display, Formatter, Result},
4    ops::{Index, IndexMut},
5};
6use kimchi::circuits::expr::AlphaChallengeTerm;
7use serde::{Deserialize, Serialize};
8use strum::EnumCount;
9use strum_macros::EnumCount as EnumCountMacro;
10
11#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize, EnumCountMacro)]
12pub enum ChallengeTerm {
13    /// Used to aggregate the constraints describing the relation. It is used to
14    /// enforce all constraints are satisfied at the same time.
15    /// Often noted `α`.
16    ConstraintCombiner,
17    /// Both challenges used in the permutation argument
18    Beta,
19    Gamma,
20    /// Used to homogenize the constraints and allow the protocol to fold two
21    /// instances of the same relation into a new one.
22    /// Often noted `u` in the paper mentioning "folding protocols".
23    ConstraintHomogeniser,
24    /// Used by the accumulation protocol (folding) to perform a random linear
25    /// transformation of the witnesses and the public values.
26    /// Often noted `r` in the paper mentioning "folding protocols".
27    RelationCombiner,
28}
29
30impl Display for ChallengeTerm {
31    fn fmt(&self, f: &mut Formatter) -> Result {
32        match self {
33            ChallengeTerm::ConstraintCombiner => write!(f, "alpha"),
34            ChallengeTerm::Beta => write!(f, "beta"),
35            ChallengeTerm::Gamma => write!(f, "gamma"),
36            ChallengeTerm::ConstraintHomogeniser => write!(f, "u"),
37            ChallengeTerm::RelationCombiner => write!(f, "r"),
38        }
39    }
40}
41
42pub struct Challenges<F> {
43    /// Used to aggregate the constraints describing the relation. It is used to
44    /// enforce all constraints are satisfied at the same time.
45    /// Often noted `α`.
46    pub constraint_combiner: F,
47
48    /// Both challenges used in the permutation argument.
49    pub beta: F,
50    pub gamma: F,
51
52    /// Used to homogenize the constraints and allow the protocol to fold two
53    /// instances of the same relation into a new one.
54    /// Often noted `u` in the paper mentioning "folding protocols".
55    pub constraint_homogeniser: F,
56
57    /// Used by the accumulation protocol (folding) to perform a random linear
58    /// transformation of the witnesses and the public values.
59    /// Often noted `r` in the paper mentioning "folding protocols".
60    pub relation_combiner: F,
61}
62
63impl<F> Index<usize> for Challenges<F> {
64    type Output = F;
65
66    fn index(&self, index: usize) -> &Self::Output {
67        if index == 0 {
68            &self.constraint_combiner
69        } else if index == 1 {
70            &self.beta
71        } else if index == 2 {
72            &self.gamma
73        } else if index == 3 {
74            &self.constraint_homogeniser
75        } else if index == 4 {
76            &self.relation_combiner
77        } else {
78            panic!(
79                "Index out of bounds, only {} are defined",
80                ChallengeTerm::COUNT
81            )
82        }
83    }
84}
85
86impl<F> IndexMut<usize> for Challenges<F> {
87    fn index_mut(&mut self, index: usize) -> &mut F {
88        if index == 0 {
89            &mut self.constraint_combiner
90        } else if index == 1 {
91            &mut self.beta
92        } else if index == 2 {
93            &mut self.gamma
94        } else if index == 3 {
95            &mut self.constraint_homogeniser
96        } else if index == 4 {
97            &mut self.relation_combiner
98        } else {
99            panic!(
100                "Index out of bounds, only {} are defined",
101                ChallengeTerm::COUNT
102            )
103        }
104    }
105}
106
107impl<F> IndexMut<ChallengeTerm> for Challenges<F> {
108    fn index_mut(&mut self, term: ChallengeTerm) -> &mut F {
109        match term {
110            ChallengeTerm::ConstraintCombiner => &mut self.constraint_combiner,
111            ChallengeTerm::Beta => &mut self.beta,
112            ChallengeTerm::Gamma => &mut self.gamma,
113            ChallengeTerm::ConstraintHomogeniser => &mut self.constraint_homogeniser,
114            ChallengeTerm::RelationCombiner => &mut self.relation_combiner,
115        }
116    }
117}
118
119impl<F: Zero> Default for Challenges<F> {
120    fn default() -> Self {
121        Self {
122            constraint_combiner: F::zero(),
123            beta: F::zero(),
124            gamma: F::zero(),
125            constraint_homogeniser: F::zero(),
126            relation_combiner: F::zero(),
127        }
128    }
129}
130
131impl<F> Index<ChallengeTerm> for Challenges<F> {
132    type Output = F;
133
134    fn index(&self, term: ChallengeTerm) -> &Self::Output {
135        match term {
136            ChallengeTerm::ConstraintCombiner => &self.constraint_combiner,
137            ChallengeTerm::Beta => &self.beta,
138            ChallengeTerm::Gamma => &self.gamma,
139            ChallengeTerm::ConstraintHomogeniser => &self.constraint_homogeniser,
140            ChallengeTerm::RelationCombiner => &self.relation_combiner,
141        }
142    }
143}
144
145impl<'a> AlphaChallengeTerm<'a> for ChallengeTerm {
146    const ALPHA: Self = Self::ConstraintCombiner;
147}