halo2_axiom/plonk/permutation/
verifier.rs
1use ff::{Field, PrimeField};
2use std::iter;
3
4use super::super::{circuit::Any, ChallengeBeta, ChallengeGamma, ChallengeX};
5use super::{Argument, VerifyingKey};
6use crate::{
7 arithmetic::CurveAffine,
8 plonk::{self, Error},
9 poly::{commitment::MSM, Rotation, VerifierQuery},
10 transcript::{EncodedChallenge, TranscriptRead},
11};
12
13pub struct Committed<C: CurveAffine> {
14 permutation_product_commitments: Vec<C>,
15}
16
17pub struct EvaluatedSet<C: CurveAffine> {
18 permutation_product_commitment: C,
19 permutation_product_eval: C::Scalar,
20 permutation_product_next_eval: C::Scalar,
21 permutation_product_last_eval: Option<C::Scalar>,
22}
23
24pub struct CommonEvaluated<C: CurveAffine> {
25 permutation_evals: Vec<C::Scalar>,
26}
27
28pub struct Evaluated<C: CurveAffine> {
29 sets: Vec<EvaluatedSet<C>>,
30}
31
32impl Argument {
33 pub(crate) fn read_product_commitments<
34 C: CurveAffine,
35 E: EncodedChallenge<C>,
36 T: TranscriptRead<C, E>,
37 >(
38 &self,
39 vk: &plonk::VerifyingKey<C>,
40 transcript: &mut T,
41 ) -> Result<Committed<C>, Error> {
42 let chunk_len = vk.cs_degree - 2;
43
44 let permutation_product_commitments = self
45 .columns
46 .chunks(chunk_len)
47 .map(|_| transcript.read_point())
48 .collect::<Result<Vec<_>, _>>()?;
49
50 Ok(Committed {
51 permutation_product_commitments,
52 })
53 }
54}
55
56impl<C: CurveAffine> VerifyingKey<C> {
57 pub(in crate::plonk) fn evaluate<E: EncodedChallenge<C>, T: TranscriptRead<C, E>>(
58 &self,
59 transcript: &mut T,
60 ) -> Result<CommonEvaluated<C>, Error> {
61 let permutation_evals = self
62 .commitments
63 .iter()
64 .map(|_| transcript.read_scalar())
65 .collect::<Result<Vec<_>, _>>()?;
66
67 Ok(CommonEvaluated { permutation_evals })
68 }
69}
70
71impl<C: CurveAffine> Committed<C> {
72 pub(crate) fn evaluate<E: EncodedChallenge<C>, T: TranscriptRead<C, E>>(
73 self,
74 transcript: &mut T,
75 ) -> Result<Evaluated<C>, Error> {
76 let mut sets = vec![];
77
78 let mut iter = self.permutation_product_commitments.into_iter();
79
80 while let Some(permutation_product_commitment) = iter.next() {
81 let permutation_product_eval = transcript.read_scalar()?;
82 let permutation_product_next_eval = transcript.read_scalar()?;
83 let permutation_product_last_eval = if iter.len() > 0 {
84 Some(transcript.read_scalar()?)
85 } else {
86 None
87 };
88
89 sets.push(EvaluatedSet {
90 permutation_product_commitment,
91 permutation_product_eval,
92 permutation_product_next_eval,
93 permutation_product_last_eval,
94 });
95 }
96
97 Ok(Evaluated { sets })
98 }
99}
100
101impl<C: CurveAffine> Evaluated<C> {
102 #[allow(clippy::too_many_arguments)]
103 pub(in crate::plonk) fn expressions<'a>(
104 &'a self,
105 vk: &'a plonk::VerifyingKey<C>,
106 p: &'a Argument,
107 common: &'a CommonEvaluated<C>,
108 advice_evals: &'a [C::Scalar],
109 fixed_evals: &'a [C::Scalar],
110 instance_evals: &'a [C::Scalar],
111 l_0: C::Scalar,
112 l_last: C::Scalar,
113 l_blind: C::Scalar,
114 beta: ChallengeBeta<C>,
115 gamma: ChallengeGamma<C>,
116 x: ChallengeX<C>,
117 ) -> impl Iterator<Item = C::Scalar> + 'a {
118 let chunk_len = vk.cs_degree - 2;
119 iter::empty()
120 .chain(
123 self.sets
124 .first()
125 .map(|first_set| l_0 * &(C::Scalar::ONE - &first_set.permutation_product_eval)),
126 )
127 .chain(self.sets.last().map(|last_set| {
130 (last_set.permutation_product_eval.square() - &last_set.permutation_product_eval)
131 * &l_last
132 }))
133 .chain(
136 self.sets
137 .iter()
138 .skip(1)
139 .zip(self.sets.iter())
140 .map(|(set, last_set)| {
141 (
142 set.permutation_product_eval,
143 last_set.permutation_product_last_eval.unwrap(),
144 )
145 })
146 .map(move |(set, prev_last)| (set - &prev_last) * &l_0),
147 )
148 .chain(
154 self.sets
155 .iter()
156 .zip(p.columns.chunks(chunk_len))
157 .zip(common.permutation_evals.chunks(chunk_len))
158 .enumerate()
159 .map(move |(chunk_index, ((set, columns), permutation_evals))| {
160 let mut left = set.permutation_product_next_eval;
161 for (eval, permutation_eval) in columns
162 .iter()
163 .map(|&column| match column.column_type() {
164 Any::Advice(_) => {
165 advice_evals[vk.cs.get_any_query_index(column, Rotation::cur())]
166 }
167 Any::Fixed => {
168 fixed_evals[vk.cs.get_any_query_index(column, Rotation::cur())]
169 }
170 Any::Instance => {
171 instance_evals
172 [vk.cs.get_any_query_index(column, Rotation::cur())]
173 }
174 })
175 .zip(permutation_evals.iter())
176 {
177 left *= &(eval + &(*beta * permutation_eval) + &*gamma);
178 }
179
180 let mut right = set.permutation_product_eval;
181 let mut current_delta = (*beta * &*x)
182 * &(<C::Scalar as PrimeField>::DELTA
183 .pow_vartime([(chunk_index * chunk_len) as u64]));
184 for eval in columns.iter().map(|&column| match column.column_type() {
185 Any::Advice(_) => {
186 advice_evals[vk.cs.get_any_query_index(column, Rotation::cur())]
187 }
188 Any::Fixed => {
189 fixed_evals[vk.cs.get_any_query_index(column, Rotation::cur())]
190 }
191 Any::Instance => {
192 instance_evals[vk.cs.get_any_query_index(column, Rotation::cur())]
193 }
194 }) {
195 right *= &(eval + ¤t_delta + &*gamma);
196 current_delta *= &C::Scalar::DELTA;
197 }
198
199 (left - &right) * (C::Scalar::ONE - &(l_last + &l_blind))
200 }),
201 )
202 }
203
204 pub(in crate::plonk) fn queries<'r, M: MSM<C> + 'r>(
205 &'r self,
206 vk: &'r plonk::VerifyingKey<C>,
207 x: ChallengeX<C>,
208 ) -> impl Iterator<Item = VerifierQuery<'r, C, M>> + Clone {
209 let blinding_factors = vk.cs.blinding_factors();
210 let x_next = vk.domain.rotate_omega(*x, Rotation::next());
211 let x_last = vk
212 .domain
213 .rotate_omega(*x, Rotation(-((blinding_factors + 1) as i32)));
214
215 iter::empty()
216 .chain(self.sets.iter().flat_map(move |set| {
217 iter::empty()
218 .chain(Some(VerifierQuery::new_commitment(
221 &set.permutation_product_commitment,
222 *x,
223 set.permutation_product_eval,
224 )))
225 .chain(Some(VerifierQuery::new_commitment(
226 &set.permutation_product_commitment,
227 x_next,
228 set.permutation_product_next_eval,
229 )))
230 }))
231 .chain(self.sets.iter().rev().skip(1).flat_map(move |set| {
233 Some(VerifierQuery::new_commitment(
234 &set.permutation_product_commitment,
235 x_last,
236 set.permutation_product_last_eval.unwrap(),
237 ))
238 }))
239 }
240}
241
242impl<C: CurveAffine> CommonEvaluated<C> {
243 pub(in crate::plonk) fn queries<'r, M: MSM<C> + 'r>(
244 &'r self,
245 vkey: &'r VerifyingKey<C>,
246 x: ChallengeX<C>,
247 ) -> impl Iterator<Item = VerifierQuery<'r, C, M>> + Clone {
248 vkey.commitments
250 .iter()
251 .zip(self.permutation_evals.iter())
252 .map(move |(commitment, &eval)| VerifierQuery::new_commitment(commitment, *x, eval))
253 }
254}