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