winter_fri/verifier/channel.rs
1// Copyright (c) Facebook, Inc. and its affiliates.
2//
3// This source code is licensed under the MIT license found in the
4// LICENSE file in the root directory of this source tree.
5
6use alloc::vec::Vec;
7use core::marker::PhantomData;
8
9use crypto::{ElementHasher, Hasher, VectorCommitment};
10use math::FieldElement;
11use utils::{group_slice_elements, DeserializationError};
12
13use crate::{FriProof, VerifierError};
14
15// VERIFIER CHANNEL TRAIT
16// ================================================================================================
17
18/// Defines an interface for a channel over which a verifier communicates with a prover.
19///
20/// This trait abstracts away implementation specifics of the [FriProof] struct. Thus, instead of
21/// dealing with FRI proofs directly, the verifier can read the data as if it was sent by the
22/// prover via an interactive channel.
23///
24/// Note: that reading removes the data from the channel. Thus, reading duplicated values from
25/// the channel should not be possible.
26pub trait VerifierChannel<E: FieldElement> {
27 /// Hash function used by the prover to commit to polynomial evaluations.
28 type Hasher: ElementHasher<BaseField = E::BaseField>;
29 /// Vector commitment used to commit to polynomial evaluations.
30 type VectorCommitment: VectorCommitment<Self::Hasher>;
31
32 // REQUIRED METHODS
33 // --------------------------------------------------------------------------------------------
34
35 /// Returns the number of partitions used during proof generation.
36 fn read_fri_num_partitions(&self) -> usize;
37
38 /// Reads and removes from the channel all FRI layer commitments sent by the prover.
39 ///
40 /// In the interactive version of the protocol, the prover sends layer commitments to the
41 /// verifier one-by-one, and the verifier responds with a value α drawn uniformly at random
42 /// from the entire field after each layer commitment is received. In the non-interactive
43 /// version, the verifier can read all layer commitments at once, and then generate α values
44 /// locally.
45 fn read_fri_layer_commitments(&mut self) -> Vec<<Self::Hasher as Hasher>::Digest>;
46
47 /// Reads and removes from the channel evaluations of the polynomial at the queried positions
48 /// for the next FRI layer.
49 ///
50 /// In the interactive version of the protocol, these evaluations are sent from the prover to
51 /// the verifier during the query phase of the FRI protocol.
52 ///
53 /// It is expected that layer queries and layer proofs at the same FRI layer are consistent.
54 /// That is, query values hash into the leaf nodes of corresponding vector commitment.
55 fn take_next_fri_layer_queries(&mut self) -> Vec<E>;
56
57 /// Reads and removes from the channel vector commitment opening proofs of queried evaluations
58 /// for the next FRI layer.
59 ///
60 /// In the interactive version of the protocol, these authentication paths are sent from the
61 /// prover to the verifier during the query phase of the FRI protocol.
62 ///
63 /// It is expected that layer proofs and layer queries at the same FRI layer are consistent.
64 /// That is, query values hash into the elements of the vector committed to using the specified
65 /// vector commitment scheme.
66 fn take_next_fri_layer_proof(
67 &mut self,
68 ) -> <Self::VectorCommitment as VectorCommitment<Self::Hasher>>::MultiProof;
69
70 /// Reads and removes the remainder polynomial from the channel.
71 fn take_fri_remainder(&mut self) -> Vec<E>;
72
73 // PROVIDED METHODS
74 // --------------------------------------------------------------------------------------------
75
76 /// Returns FRI query values at the specified positions from the current FRI layer and advances
77 /// layer pointer by one.
78 ///
79 /// This also checks if the values are valid against the provided FRI layer commitment.
80 ///
81 /// # Errors
82 /// Returns an error if query values did not match layer commitment.
83 fn read_layer_queries<const N: usize>(
84 &mut self,
85 positions: &[usize],
86 commitment: &<Self::Hasher as Hasher>::Digest,
87 ) -> Result<Vec<[E; N]>, VerifierError> {
88 let layer_proof = self.take_next_fri_layer_proof();
89 let layer_queries = self.take_next_fri_layer_queries();
90 // build the values (i.e., polynomial evaluations over a coset of a multiplicative subgroup
91 // of the current evaluation domain) corresponding to each leaf of the layer commitment
92 let leaf_values = group_slice_elements(&layer_queries);
93 // hash the aforementioned values to get the leaves to be verified against the previously
94 // received commitment
95 let hashed_values: Vec<<Self::Hasher as Hasher>::Digest> = leaf_values
96 .iter()
97 .map(|seg| <Self::Hasher as ElementHasher>::hash_elements(seg))
98 .collect();
99
100 <<Self as VerifierChannel<E>>::VectorCommitment as VectorCommitment<Self::Hasher>>::verify_many(
101 *commitment,
102 positions,
103 &hashed_values,
104 &layer_proof,
105 )
106 .map_err(|_| VerifierError::LayerCommitmentMismatch)?;
107
108 Ok(leaf_values.to_vec())
109 }
110
111 /// Returns FRI remainder polynomial read from this channel.
112 fn read_remainder(&mut self) -> Result<Vec<E>, VerifierError> {
113 let remainder = self.take_fri_remainder();
114
115 Ok(remainder)
116 }
117}
118
119// DEFAULT VERIFIER CHANNEL IMPLEMENTATION
120// ================================================================================================
121
122/// Provides a default implementation of the [VerifierChannel] trait.
123///
124/// Default verifier channel can be instantiated directly from a [FriProof] struct.
125///
126/// Though this implementation is primarily intended for testing purposes, it can be used in
127/// production use cases as well.
128pub struct DefaultVerifierChannel<
129 E: FieldElement,
130 H: ElementHasher<BaseField = E::BaseField>,
131 V: VectorCommitment<H>,
132> {
133 layer_commitments: Vec<H::Digest>,
134 layer_proofs: Vec<V::MultiProof>,
135 layer_queries: Vec<Vec<E>>,
136 remainder: Vec<E>,
137 num_partitions: usize,
138 _h: PhantomData<H>,
139}
140
141impl<E, H, V> DefaultVerifierChannel<E, H, V>
142where
143 E: FieldElement,
144 H: ElementHasher<BaseField = E::BaseField>,
145 V: VectorCommitment<H>,
146{
147 /// Builds a new verifier channel from the specified [FriProof].
148 ///
149 /// # Errors
150 /// Returns an error if the specified `proof` could not be parsed correctly.
151 pub fn new(
152 proof: FriProof,
153 layer_commitments: Vec<H::Digest>,
154 domain_size: usize,
155 folding_factor: usize,
156 ) -> Result<Self, DeserializationError> {
157 let num_partitions = proof.num_partitions();
158
159 let remainder = proof.parse_remainder()?;
160 let (layer_queries, layer_proofs) =
161 proof.parse_layers::<E, H, V>(domain_size, folding_factor)?;
162
163 Ok(DefaultVerifierChannel {
164 layer_commitments,
165 layer_proofs,
166 layer_queries,
167 remainder,
168 num_partitions,
169 _h: PhantomData,
170 })
171 }
172}
173
174impl<E, H, V> VerifierChannel<E> for DefaultVerifierChannel<E, H, V>
175where
176 E: FieldElement,
177 H: ElementHasher<BaseField = E::BaseField>,
178 V: VectorCommitment<H>,
179{
180 type Hasher = H;
181 type VectorCommitment = V;
182
183 fn read_fri_num_partitions(&self) -> usize {
184 self.num_partitions
185 }
186
187 fn read_fri_layer_commitments(&mut self) -> Vec<H::Digest> {
188 self.layer_commitments.drain(..).collect()
189 }
190
191 fn take_next_fri_layer_proof(&mut self) -> V::MultiProof {
192 self.layer_proofs.remove(0)
193 }
194
195 fn take_next_fri_layer_queries(&mut self) -> Vec<E> {
196 self.layer_queries.remove(0)
197 }
198
199 fn take_fri_remainder(&mut self) -> Vec<E> {
200 self.remainder.clone()
201 }
202}