Skip to content

Commit

Permalink
chore: address various comments
Browse files Browse the repository at this point in the history
  • Loading branch information
Al-Kindi-0 committed Jul 2, 2024
1 parent aec071f commit 4ed37ae
Show file tree
Hide file tree
Showing 17 changed files with 131 additions and 87 deletions.
19 changes: 10 additions & 9 deletions air/src/proof/queries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ impl Queries {
/// * `domain_size` is not a power of two.
/// * `num_queries` is zero.
/// * `values_per_query` is zero.
pub fn parse<H, E, V>(
pub fn parse<E, H, V>(
self,
domain_size: usize,
num_queries: usize,
Expand Down Expand Up @@ -116,10 +116,13 @@ impl Queries {
let opening_proof = <V::MultiProof as Deserializable>::read_from(&mut reader)?;

// check that the opening proof matches the domain length
assert_eq!(
<V as VectorCommitment<H>>::get_multiproof_domain_len(&opening_proof),
domain_size
);
if <V as VectorCommitment<H>>::get_multiproof_domain_len(&opening_proof) != domain_size {
return Err(DeserializationError::InvalidValue(format!(
"expected a domain of size {} but was {}",
domain_size,
<V as VectorCommitment<H>>::get_multiproof_domain_len(&opening_proof),
)));
}

if reader.has_more_bytes() {
return Err(DeserializationError::UnconsumedBytes);
Expand Down Expand Up @@ -155,12 +158,10 @@ impl Deserializable for Queries {
/// Returns an error of a valid query struct could not be read from the specified source.
fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
// read values
let num_value_bytes = source.read_u32()?;
let values = source.read_vec(num_value_bytes as usize)?;
let values = Vec::<_>::read_from(source)?;

// read paths
let num_paths_bytes = source.read_u32()?;
let paths = source.read_vec(num_paths_bytes as usize)?;
let paths = Vec::<_>::read_from(source)?;

Ok(Queries { opening_proof: paths, values })
}
Expand Down
15 changes: 11 additions & 4 deletions crypto/src/commitment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,16 @@ use crate::Hasher;
/// This is a cryptographic primitive allowing one to commit, using a commitment string `com`, to
/// a vector of values (v_0, ..., v_{n-1}) such that one can later reveal the value at the i-th
/// position.
///
/// This is achieved by providing the value `v_i` together with a proof `proof_i` such that anyone
/// posessing `com` can be convinced, with high confidence, that the claim is true.
///
/// Vector commitment schemes usually have some batching properties in the sense that opening
/// proofs for a number of `(i, v_i)` can be batched together into one batch opening proof in order
/// to optimize both the proof size as well as the verification time.
///
/// The current implementation restricts both of the commitment string as well as the leaf values
/// to be `H::Digest` where `H` is a type parameter such that `H: Hasher`.
pub trait VectorCommitment<H: Hasher>: Sized {
/// Options defining the VC i.e., public parameters.
type Options: Default;
Expand All @@ -41,21 +45,24 @@ pub trait VectorCommitment<H: Hasher>: Sized {
/// options.
fn with_options(items: Vec<H::Digest>, options: Self::Options) -> Result<Self, Self::Error>;

/// Returns the commitment string to the commited values.
/// Returns the commitment string to the committed values.
fn commitment(&self) -> H::Digest;

/// Returns the length of the vector commited to for `Self::Proof`.
/// Returns the length of the vector committed to for `Self`.
fn get_domain_len(&self) -> usize;

/// Returns the length of the vector committed to for `Self::Proof`.
fn get_proof_domain_len(proof: &Self::Proof) -> usize;

/// Returns the length of the vector commited to for `Self::MultiProof`.
/// Returns the length of the vector committed to for `Self::MultiProof`.
fn get_multiproof_domain_len(proof: &Self::MultiProof) -> usize;

/// Opens the value at a given index and provides a proof for the correctness of claimed value.
fn open(&self, index: usize) -> Result<(H::Digest, Self::Proof), Self::Error>;

#[allow(clippy::type_complexity)]
/// Opens the values at a given index set and provides a proof for the correctness of claimed
/// values.
#[allow(clippy::type_complexity)]
fn open_many(
&self,
indexes: &[usize],
Expand Down
4 changes: 4 additions & 0 deletions crypto/src/merkle/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,10 @@ impl<H: Hasher> VectorCommitment<H> for MerkleTree<H> {
*self.root()
}

fn get_domain_len(&self) -> usize {
1 << self.depth()
}

fn get_proof_domain_len(proof: &Self::Proof) -> usize {
1 << proof.len()
}
Expand Down
18 changes: 14 additions & 4 deletions fri/src/proof.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ impl FriProof {
/// * This proof is not consistent with the specified `domain_size` and `folding_factor`.
/// * Any of the layers could not be parsed successfully.
#[allow(clippy::type_complexity)]
pub fn parse_layers<H, E, V>(
pub fn parse_layers<E, H, V>(
self,
mut domain_size: usize,
folding_factor: usize,
Expand All @@ -146,9 +146,19 @@ impl FriProof {
// parse all layers
for (i, layer) in self.layers.into_iter().enumerate() {
domain_size /= folding_factor;
let (qv, op) = layer.parse::<H, _, V>(folding_factor).map_err(|err| {
let (qv, op) = layer.parse::<_, H, V>(folding_factor).map_err(|err| {
DeserializationError::InvalidValue(format!("failed to parse FRI layer {i}: {err}"))
})?;

// check that the opening proof matches the domain length
if <V as VectorCommitment<H>>::get_multiproof_domain_len(&op) != domain_size {
return Err(DeserializationError::InvalidValue(format!(
"expected a domain of size {} but was {}",
domain_size,
<V as VectorCommitment<H>>::get_multiproof_domain_len(&op),
)));
}

layer_proofs.push(op);
layer_queries.push(qv);
}
Expand Down Expand Up @@ -241,7 +251,7 @@ impl FriProofLayer {
///
/// # Panics
/// Panics if `query_values` is an empty slice.
pub(crate) fn new<E: FieldElement, H: Hasher, const N: usize, V: VectorCommitment<H>>(
pub(crate) fn new<E: FieldElement, H: Hasher, V: VectorCommitment<H>, const N: usize>(
query_values: Vec<[E; N]>,
proof: <V as VectorCommitment<H>>::MultiProof,
) -> Self {
Expand Down Expand Up @@ -277,7 +287,7 @@ impl FriProofLayer {
/// * This layer does not contain at least one query.
/// * Parsing of any of the query values or the corresponding batch opening proof fails.
/// * Not all bytes have been consumed while parsing this layer.
pub fn parse<H, E, V>(
pub fn parse<E, H, V>(
self,
folding_factor: usize,
) -> Result<(Vec<E>, <V as VectorCommitment<H>>::MultiProof), DeserializationError>
Expand Down
8 changes: 4 additions & 4 deletions fri/src/prover/channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use math::FieldElement;
/// In the interactive version of the protocol, the verifier chooses α uniformly at random from
/// the entire field. In the non-interactive version, the α is drawn pseudo-randomly based on the
/// commitments the prover has written into the channel up to this point.
pub trait ProverChannel<E: FieldElement, H: Hasher> {
pub trait ProverChannel<E: FieldElement> {
/// Hash function used by the prover to commit to polynomial evaluations.
type Hasher: ElementHasher<BaseField = E::BaseField>;

Expand All @@ -31,10 +31,10 @@ pub trait ProverChannel<E: FieldElement, H: Hasher> {
/// evaluations of a polynomial at a given layer. The vector commitment is built by
/// first transposing evaluations into a two-dimensional matrix where each row contains
/// values needed to compute a single value of the next FRI layer, and then computing
/// the hash of each row to get one entry of the vector being commited to. Thus, the number
/// the hash of each row to get one entry of the vector being committed to. Thus, the number
/// of elements grouped into a single leaf is equal to the `folding_factor` used for FRI layer
/// construction.
fn commit_fri_layer(&mut self, layer_root: H::Digest);
fn commit_fri_layer(&mut self, layer_root: <Self::Hasher as Hasher>::Digest);

/// Returns a random α drawn uniformly at random from the entire field.
///
Expand Down Expand Up @@ -116,7 +116,7 @@ where
}
}

impl<E, H, R> ProverChannel<E, H> for DefaultProverChannel<E, H, R>
impl<E, H, R> ProverChannel<E> for DefaultProverChannel<E, H, R>
where
E: FieldElement,
H: ElementHasher<BaseField = E::BaseField>,
Expand Down
15 changes: 6 additions & 9 deletions fri/src/prover/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,9 @@ mod tests;
///
/// The prover is parametrized with the following types:
///
/// * `B` specifies the base field of the STARK protocol.
/// * `E` specifies the field in which the FRI protocol is executed. This can be the same as the
/// base field `B`, but it can also be an extension of the base field in cases when the base
/// field is too small to provide desired security level for the FRI protocol.
/// * `E` specifies the field in which the FRI protocol is executed.
/// * `C` specifies the type used to simulate prover-verifier interaction.
/// * `H` specifies the hash function used to build for each layer the vector of values commited to
/// * `H` specifies the hash function used to build for each layer the vector of values committed to
/// using the specified vector commitment scheme. The same hash function must be used in
/// the prover channel to generate pseudo random values.
/// * `V` specifies the vector commitment scheme used in order to commit to each layer.
Expand Down Expand Up @@ -98,7 +95,7 @@ mod tests;
pub struct FriProver<E, C, H, V>
where
E: FieldElement,
C: ProverChannel<E, H, Hasher = H>,
C: ProverChannel<E, Hasher = H>,
H: ElementHasher<BaseField = E::BaseField>,
V: VectorCommitment<H>,
{
Expand All @@ -122,7 +119,7 @@ struct FriRemainder<E: FieldElement>(Vec<E>);
impl<E, C, H, V> FriProver<E, C, H, V>
where
E: FieldElement,
C: ProverChannel<E, H, Hasher = H>,
C: ProverChannel<E, Hasher = H>,
H: ElementHasher<BaseField = E::BaseField>,
V: VectorCommitment<H>,
{
Expand Down Expand Up @@ -308,12 +305,12 @@ fn query_layer<E: FieldElement, H: Hasher, V: VectorCommitment<H>, const N: usiz
for &position in positions.iter() {
queried_values.push(evaluations[position]);
}
FriProofLayer::new::<_, _, N, V>(queried_values, proof.1)
FriProofLayer::new::<_, _, V, N>(queried_values, proof.1)
}

/// Hashes each of the arrays in the provided slice and returns a vector commitment to resulting
/// hashes.
pub fn build_layer_commitment<H, E, V, const N: usize>(
pub fn build_layer_commitment<E, H, V, const N: usize>(
values: &[[E; N]],
) -> Result<V, <V as VectorCommitment<H>>::Error>
where
Expand Down
2 changes: 1 addition & 1 deletion fri/src/prover/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ fn fri_prove_verify(
let mut prover = FriProver::<_, _, _, MerkleTree<Blake3>>::new(options.clone());
prover.build_layers(&mut channel, evaluations.clone());
let positions = channel.draw_query_positions(0);
let proof = prover.build_proof(&positions); // assert_eq!(1, 0 );
let proof = prover.build_proof(&positions);

// make sure the proof can be verified
let commitments = channel.layer_commitments().to_vec();
Expand Down
2 changes: 1 addition & 1 deletion fri/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ pub fn map_positions_to_indexes(
folding_factor: usize,
num_partitions: usize,
) -> Vec<usize> {
// if there was only 1 partition, order of elements in the commitment tree
// if there was only 1 partition, order of elements in the vector commitment
// is the same as the order of elements in the evaluation domain
if num_partitions == 1 {
return positions.to_vec();
Expand Down
9 changes: 7 additions & 2 deletions fri/src/verifier/channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ use crate::{FriProof, VerifierError};
pub trait VerifierChannel<E: FieldElement> {
/// Hash function used by the prover to commit to polynomial evaluations.
type Hasher: ElementHasher<BaseField = E::BaseField>;
/// Vector commitment used to commit to polynomial evaluations.
type VectorCommitment: VectorCommitment<Self::Hasher>;

// REQUIRED METHODS
Expand Down Expand Up @@ -60,7 +61,7 @@ pub trait VerifierChannel<E: FieldElement> {
/// 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 elements of the vector commited to using the specified
/// That is, query values hash into the elements of the vector committed to using the specified
/// vector commitment scheme.
fn take_next_fri_layer_proof(
&mut self,
Expand All @@ -86,7 +87,11 @@ pub trait VerifierChannel<E: FieldElement> {
) -> Result<Vec<[E; N]>, VerifierError> {
let layer_proof = self.take_next_fri_layer_proof();
let layer_queries = self.take_next_fri_layer_queries();
// build the values (i.e., polynomial evaluations over a coset of a multiplicative subgroup
// of the current evaluation domain) corresponding to each leaf of the layer commitment
let leaf_values = group_slice_elements(&layer_queries);
// hash the aforementioned values to get the leaves to be verified against the previously
// received commitment
let hashed_values: Vec<<Self::Hasher as Hasher>::Digest> = leaf_values
.iter()
.map(|seg| <Self::Hasher as ElementHasher>::hash_elements(seg))
Expand Down Expand Up @@ -153,7 +158,7 @@ where

let remainder = proof.parse_remainder()?;
let (layer_queries, layer_proofs) =
proof.parse_layers::<H, E, V>(domain_size, folding_factor)?;
proof.parse_layers::<E, H, V>(domain_size, folding_factor)?;

Ok(DefaultVerifierChannel {
layer_commitments,
Expand Down
2 changes: 1 addition & 1 deletion prover/src/channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ where
// FRI PROVER CHANNEL IMPLEMENTATION
// ================================================================================================

impl<'a, A, E, H, R, V> fri::ProverChannel<E, H> for ProverChannel<'a, A, E, H, R, V>
impl<'a, A, E, H, R, V> fri::ProverChannel<E> for ProverChannel<'a, A, E, H, R, V>
where
A: Air,
E: FieldElement<BaseField = A::BaseField>,
Expand Down
14 changes: 12 additions & 2 deletions prover/src/constraints/commitment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,22 @@ pub struct ConstraintCommitment<
_h: PhantomData<H>,
}

impl<E: FieldElement, H: ElementHasher<BaseField = E::BaseField>, V: VectorCommitment<H>>
ConstraintCommitment<E, H, V>
impl<E, H, V> ConstraintCommitment<E, H, V>
where
E: FieldElement,
H: ElementHasher<BaseField = E::BaseField>,
V: VectorCommitment<H>,
{
/// Creates a new constraint evaluation commitment from the provided composition polynomial
/// evaluations and the corresponding vector commitment.
pub fn new(evaluations: RowMatrix<E>, commitment: V) -> ConstraintCommitment<E, H, V> {
assert_eq!(
evaluations.num_rows(),
commitment.get_domain_len(),
"number of rows in constraint evaluation matrix must be the same as the size
of the vector commitment domain"
);

ConstraintCommitment {
evaluations,
vector_commitment: commitment,
Expand Down
2 changes: 1 addition & 1 deletion prover/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -549,7 +549,7 @@ pub trait Prover {
// finally, build constraint evaluation commitment
let constraint_commitment = info_span!(
"compute_constraint_evaluation_commitment",
tree_depth = domain_size.ilog2()
log_domain_size = domain_size.ilog2()
)
.in_scope(|| {
let commitment = composed_evaluations.commit_to_rows::<Self::HashFn, Self::VC>();
Expand Down
4 changes: 2 additions & 2 deletions prover/src/matrix/col_matrix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ impl<E: FieldElement> ColMatrix<E> {
///
/// The commitment is built as follows:
/// * Each row of the matrix is hashed into a single digest of the specified hash function.
/// * The resulting vector of digests is commited to using the specified vector commitment
/// * The resulting vector of digests is committed to using the specified vector commitment
/// scheme.
/// * The resulting commitment is returned as the commitment to the entire matrix.
pub fn commit_to_rows<H, V>(&self) -> V
Expand All @@ -282,7 +282,7 @@ impl<E: FieldElement> ColMatrix<E> {
}
);

V::new(row_hashes).unwrap()
V::new(row_hashes).expect("failed to construct trace vector commitment")
}

// CONVERSIONS
Expand Down
2 changes: 1 addition & 1 deletion prover/src/matrix/row_matrix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ impl<E: FieldElement> RowMatrix<E> {
);

// build the vector commitment to the hashed rows
V::new(row_hashes).unwrap()
V::new(row_hashes).expect("failed to construct trace vector commitment")
}
}

Expand Down
Loading

0 comments on commit 4ed37ae

Please sign in to comment.