FRI on coset

This commit is contained in:
wborgeaud 2021-04-30 15:07:54 +02:00
parent c464c038af
commit 0fa0942981
4 changed files with 80 additions and 5 deletions

View File

@ -98,6 +98,7 @@ fn fri_committed_trees<F: Field>(
let mut trees = Vec::new();
let mut shift = F::MULTIPLICATIVE_GROUP_GENERATOR;
let num_reductions = config.reduction_arity_bits.len();
for i in 0..num_reductions {
let arity = 1 << config.reduction_arity_bits[i];
@ -124,8 +125,9 @@ fn fri_committed_trees<F: Field>(
.map(|chunk| reduce_with_powers(chunk, beta))
.collect::<Vec<_>>(),
);
shift = shift.exp_u32(arity as u32);
// TODO: Is it faster to interpolate?
values = fft(coeffs.clone());
values = coeffs.clone().coset_fft(shift);
}
challenger.observe_elements(&coeffs.coeffs);
@ -315,7 +317,8 @@ fn fri_verifier_query_round<F: Field>(
let mut old_x_index = 0;
// `subgroup_x` is `subgroup[x_index]`, i.e., the actual field element in the domain.
let log_n = log2_strict(n);
let mut subgroup_x = F::primitive_root_of_unity(log_n).exp_usize(reverse_bits(x_index, log_n));
let mut subgroup_x = F::MULTIPLICATIVE_GROUP_GENERATOR
* F::primitive_root_of_unity(log_n).exp_usize(reverse_bits(x_index, log_n));
for (i, &arity_bits) in config.reduction_arity_bits.iter().enumerate() {
let arity = 1 << arity_bits;
let next_domain_size = domain_size >> arity_bits;
@ -397,8 +400,8 @@ mod tests {
type F = CrandallField;
let n = 1 << degree_log;
let evals = PolynomialValues::new((0..n).map(|_| F::rand()).collect());
let lde = evals.clone().lde(rate_bits);
let coeffs = PolynomialCoeffs::new((0..n).map(|_| F::rand()).collect()).lde(rate_bits);
let coset_lde = coeffs.clone().coset_fft(F::MULTIPLICATIVE_GROUP_GENERATOR);
let config = FriConfig {
num_query_rounds,
rate_bits,
@ -406,7 +409,7 @@ mod tests {
reduction_arity_bits,
};
let mut challenger = Challenger::new();
let proof = fri_proof(&ifft(lde.clone()), &lde, &mut challenger, &config);
let proof = fri_proof(&coeffs, &coset_lde, &mut challenger, &config);
let mut challenger = Challenger::new();
verify_fri_proof(degree_log, &proof, &mut challenger, &config)?;

View File

@ -0,0 +1,26 @@
use crate::field::field::Field;
use crate::merkle_tree::MerkleTree;
use crate::polynomial::polynomial::PolynomialValues;
use crate::util::transpose;
struct ListPolynomialCommitment<F: Field> {
pub lde_values: Vec<Vec<F>>,
pub rate_bits: usize,
pub merkle_tree: MerkleTree<F>,
}
impl<F: Field> ListPolynomialCommitment<F> {
pub fn new(values: Vec<PolynomialValues<F>>, rate_bits: usize) -> Self {
let lde_values = values
.into_iter()
.map(|p| p.lde(rate_bits).values)
.collect::<Vec<_>>();
let merkle_tree = MerkleTree::new(transpose(&lde_values), false);
Self {
lde_values,
rate_bits,
merkle_tree,
}
}
}

View File

@ -1,2 +1,3 @@
pub mod commitment;
pub(crate) mod division;
pub mod polynomial;

View File

@ -108,4 +108,49 @@ impl<F: Field> PolynomialCoeffs<F> {
.find(|&i| self.coeffs[i].is_nonzero())
.map_or(0, |i| i + 1)
}
pub fn fft(self) -> PolynomialValues<F> {
fft(self)
}
pub fn coset_fft(self, shift: F) -> PolynomialValues<F> {
let modified_poly: Self = shift
.powers()
.zip(self.coeffs)
.map(|(r, c)| r * c)
.collect::<Vec<_>>()
.into();
modified_poly.fft()
}
}
impl<F: Field> From<Vec<F>> for PolynomialCoeffs<F> {
fn from(coeffs: Vec<F>) -> Self {
Self::new(coeffs)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::field::crandall_field::CrandallField;
#[test]
fn test_coset_fft() {
type F = CrandallField;
let k = 8;
let n = 1 << k;
let poly = PolynomialCoeffs::new((0..n).map(|_| F::rand()).collect());
let shift = F::rand();
let coset_evals = poly.clone().coset_fft(shift).values;
let generator = F::primitive_root_of_unity(k);
let naive_coset_evals = F::cyclic_subgroup_coset_known_order(generator, shift, n)
.into_iter()
.map(|x| poly.eval(x))
.collect::<Vec<_>>();
assert_eq!(coset_evals, naive_coset_evals);
}
}