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}