mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-10 09:43:09 +00:00
Blinding parameter can be set differently for each Merkle tree in a FRI proof.
This commit is contained in:
parent
ed805453c3
commit
ce0507ba12
@ -8,6 +8,7 @@ use plonky2::fri::FriConfig;
|
||||
use plonky2::gates::constant::ConstantGate;
|
||||
use plonky2::gates::gmimc::GMiMCGate;
|
||||
use plonky2::hash::GMIMC_ROUNDS;
|
||||
use plonky2::prover::PLONK_BLINDING;
|
||||
use plonky2::witness::PartialWitness;
|
||||
|
||||
fn main() {
|
||||
@ -40,7 +41,7 @@ fn bench_prove<F: Field>() {
|
||||
rate_bits: 3,
|
||||
reduction_arity_bits: vec![1],
|
||||
num_query_rounds: 1,
|
||||
blinding: true,
|
||||
blinding: PLONK_BLINDING.to_vec(),
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@ -274,14 +274,16 @@ impl<F: Field> CircuitBuilder<F> {
|
||||
let constant_vecs = self.constant_polys();
|
||||
let constants_commitment = ListPolynomialCommitment::new(
|
||||
constant_vecs.into_iter().map(|v| v.ifft()).collect(),
|
||||
&self.config.fri_config,
|
||||
self.config.fri_config.rate_bits,
|
||||
false,
|
||||
);
|
||||
|
||||
let k_is = get_unique_coset_shifts(degree, self.config.num_routed_wires);
|
||||
let sigma_vecs = self.sigma_vecs(&k_is);
|
||||
let sigmas_commitment = ListPolynomialCommitment::new(
|
||||
sigma_vecs.into_iter().map(|v| v.ifft()).collect(),
|
||||
&self.config.fri_config,
|
||||
self.config.fri_config.rate_bits,
|
||||
false,
|
||||
);
|
||||
|
||||
let constants_root = constants_commitment.merkle_tree.root;
|
||||
|
||||
@ -35,7 +35,7 @@ impl Default for CircuitConfig {
|
||||
rate_bits: 1,
|
||||
reduction_arity_bits: vec![1],
|
||||
num_query_rounds: 1,
|
||||
blinding: true,
|
||||
blinding: vec![true],
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@ -20,8 +20,9 @@ pub struct FriConfig {
|
||||
/// Number of query rounds to perform.
|
||||
pub num_query_rounds: usize,
|
||||
|
||||
/// True if the last element of the Merkle trees' leaf vectors is a blinding element.
|
||||
pub blinding: bool,
|
||||
/// Vector of the same length as the number of initial Merkle trees.
|
||||
/// `blinding[i]==true` iff the i-th tree is salted.
|
||||
pub blinding: Vec<bool>,
|
||||
}
|
||||
|
||||
fn fri_delta(rate_log: usize, conjecture: bool) -> f64 {
|
||||
@ -79,7 +80,7 @@ mod tests {
|
||||
rate_bits,
|
||||
proof_of_work_bits: 2,
|
||||
reduction_arity_bits,
|
||||
blinding: false,
|
||||
blinding: vec![false],
|
||||
};
|
||||
let tree = {
|
||||
let mut leaves = coset_lde
|
||||
|
||||
@ -149,7 +149,8 @@ fn fri_combine_initial<F: Field>(
|
||||
let e = proof
|
||||
.evals_proofs
|
||||
.iter()
|
||||
.flat_map(|(v, _)| &v[..v.len() - if config.blinding { SALT_SIZE } else { 0 }])
|
||||
.enumerate()
|
||||
.flat_map(|(i, (v, _))| &v[..v.len() - if config.blinding[i] { SALT_SIZE } else { 0 }])
|
||||
.rev()
|
||||
.fold(F::ZERO, |acc, &e| alpha * acc + e);
|
||||
let numerator = e - interpolant.eval(subgroup_x);
|
||||
|
||||
@ -15,27 +15,28 @@ pub const SALT_SIZE: usize = 2;
|
||||
|
||||
pub struct ListPolynomialCommitment<F: Field> {
|
||||
pub polynomials: Vec<PolynomialCoeffs<F>>,
|
||||
pub fri_config: FriConfig,
|
||||
pub merkle_tree: MerkleTree<F>,
|
||||
pub degree: usize,
|
||||
pub rate_bits: usize,
|
||||
pub blinding: bool,
|
||||
}
|
||||
|
||||
impl<F: Field> ListPolynomialCommitment<F> {
|
||||
pub fn new(polynomials: Vec<PolynomialCoeffs<F>>, fri_config: &FriConfig) -> Self {
|
||||
pub fn new(polynomials: Vec<PolynomialCoeffs<F>>, rate_bits: usize, blinding: bool) -> Self {
|
||||
let degree = polynomials[0].len();
|
||||
let lde_values = polynomials
|
||||
.par_iter()
|
||||
.map(|p| {
|
||||
assert_eq!(p.len(), degree, "Polynomial degree invalid.");
|
||||
p.clone()
|
||||
.lde(fri_config.rate_bits)
|
||||
.lde(rate_bits)
|
||||
.coset_fft(F::MULTIPLICATIVE_GROUP_GENERATOR)
|
||||
.values
|
||||
})
|
||||
.chain(if fri_config.blinding {
|
||||
.chain(if blinding {
|
||||
// If blinding, salt with two random elements to each leaf vector.
|
||||
(0..SALT_SIZE)
|
||||
.map(|_| F::rand_vec(degree << fri_config.rate_bits))
|
||||
.map(|_| F::rand_vec(degree << rate_bits))
|
||||
.collect()
|
||||
} else {
|
||||
Vec::new()
|
||||
@ -48,22 +49,27 @@ impl<F: Field> ListPolynomialCommitment<F> {
|
||||
|
||||
Self {
|
||||
polynomials,
|
||||
fri_config: fri_config.clone(),
|
||||
merkle_tree,
|
||||
degree,
|
||||
rate_bits,
|
||||
blinding,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn leaf(&self, index: usize) -> &[F] {
|
||||
let leaf = &self.merkle_tree.leaves[index];
|
||||
&leaf[0..leaf.len() - if self.fri_config.blinding { 2 } else { 0 }]
|
||||
&leaf[0..leaf.len() - if self.blinding { SALT_SIZE } else { 0 }]
|
||||
}
|
||||
|
||||
pub fn open(
|
||||
&self,
|
||||
points: &[F],
|
||||
challenger: &mut Challenger<F>,
|
||||
config: &FriConfig,
|
||||
) -> (OpeningProof<F>, Vec<Vec<F>>) {
|
||||
assert_eq!(self.rate_bits, config.rate_bits);
|
||||
assert_eq!(config.blinding.len(), 1);
|
||||
assert_eq!(self.blinding, config.blinding[0]);
|
||||
for p in points {
|
||||
assert_ne!(
|
||||
p.exp_usize(self.degree),
|
||||
@ -102,7 +108,7 @@ impl<F: Field> ListPolynomialCommitment<F> {
|
||||
|
||||
let quotient = Self::compute_quotient(points, &composition_evals, &composition_poly);
|
||||
|
||||
let lde_quotient = PolynomialCoeffs::from(quotient.clone()).lde(self.fri_config.rate_bits);
|
||||
let lde_quotient = PolynomialCoeffs::from(quotient.clone()).lde(self.rate_bits);
|
||||
let lde_quotient_values = lde_quotient
|
||||
.clone()
|
||||
.coset_fft(F::MULTIPLICATIVE_GROUP_GENERATOR);
|
||||
@ -112,7 +118,7 @@ impl<F: Field> ListPolynomialCommitment<F> {
|
||||
&lde_quotient,
|
||||
&lde_quotient_values,
|
||||
challenger,
|
||||
&self.fri_config,
|
||||
&config,
|
||||
);
|
||||
|
||||
(
|
||||
@ -128,17 +134,21 @@ impl<F: Field> ListPolynomialCommitment<F> {
|
||||
commitments: &[&Self],
|
||||
points: &[F],
|
||||
challenger: &mut Challenger<F>,
|
||||
config: &FriConfig,
|
||||
) -> (OpeningProof<F>, Vec<Vec<Vec<F>>>) {
|
||||
let degree = commitments[0].degree;
|
||||
assert!(
|
||||
commitments.iter().all(|c| c.degree == degree),
|
||||
"Trying to open polynomial commitments of different degrees."
|
||||
);
|
||||
let fri_config = &commitments[0].fri_config;
|
||||
assert!(
|
||||
commitments.iter().all(|c| &c.fri_config == fri_config),
|
||||
"Trying to open polynomial commitments with different config."
|
||||
);
|
||||
assert_eq!(config.blinding.len(), commitments.len());
|
||||
for (i, commitment) in commitments.iter().enumerate() {
|
||||
assert_eq!(commitment.rate_bits, config.rate_bits, "Invalid rate.");
|
||||
assert_eq!(
|
||||
commitment.blinding, config.blinding[i],
|
||||
"Invalid blinding paramater."
|
||||
);
|
||||
assert_eq!(
|
||||
commitment.degree, degree,
|
||||
"Trying to open polynomial commitments of different degrees."
|
||||
);
|
||||
}
|
||||
for p in points {
|
||||
assert_ne!(
|
||||
p.exp_usize(degree),
|
||||
@ -184,7 +194,7 @@ impl<F: Field> ListPolynomialCommitment<F> {
|
||||
|
||||
let quotient = Self::compute_quotient(points, &composition_evals, &composition_poly);
|
||||
|
||||
let lde_quotient = PolynomialCoeffs::from(quotient.clone()).lde(fri_config.rate_bits);
|
||||
let lde_quotient = PolynomialCoeffs::from(quotient.clone()).lde(config.rate_bits);
|
||||
let lde_quotient_values = lde_quotient
|
||||
.clone()
|
||||
.coset_fft(F::MULTIPLICATIVE_GROUP_GENERATOR);
|
||||
@ -197,7 +207,7 @@ impl<F: Field> ListPolynomialCommitment<F> {
|
||||
&lde_quotient,
|
||||
&lde_quotient_values,
|
||||
challenger,
|
||||
&fri_config,
|
||||
&config,
|
||||
);
|
||||
|
||||
(
|
||||
@ -213,8 +223,9 @@ impl<F: Field> ListPolynomialCommitment<F> {
|
||||
commitments: &[&Self; 5],
|
||||
points: &[F],
|
||||
challenger: &mut Challenger<F>,
|
||||
config: &FriConfig,
|
||||
) -> (OpeningProof<F>, Vec<OpeningSet<F>>) {
|
||||
let (op, mut evaluations) = Self::batch_open(commitments, points, challenger);
|
||||
let (op, mut evaluations) = Self::batch_open(commitments, points, challenger, config);
|
||||
let opening_sets = evaluations
|
||||
.par_iter_mut()
|
||||
.map(|evals| {
|
||||
@ -343,12 +354,12 @@ mod tests {
|
||||
rate_bits: 2,
|
||||
reduction_arity_bits: vec![3, 2, 1, 2],
|
||||
num_query_rounds: 3,
|
||||
blinding: false,
|
||||
blinding: vec![false],
|
||||
};
|
||||
let (polys, points) = gen_random_test_case::<F>(k, degree_log, num_points);
|
||||
|
||||
let lpc = ListPolynomialCommitment::new(polys, &fri_config);
|
||||
let (proof, evaluations) = lpc.open(&points, &mut Challenger::new());
|
||||
let lpc = ListPolynomialCommitment::new(polys, fri_config.rate_bits, false);
|
||||
let (proof, evaluations) = lpc.open(&points, &mut Challenger::new(), &fri_config);
|
||||
proof.verify(
|
||||
&points,
|
||||
&evaluations.into_iter().map(|e| vec![e]).collect::<Vec<_>>(),
|
||||
@ -370,12 +381,12 @@ mod tests {
|
||||
rate_bits: 2,
|
||||
reduction_arity_bits: vec![3, 2, 1, 2],
|
||||
num_query_rounds: 3,
|
||||
blinding: true,
|
||||
blinding: vec![true],
|
||||
};
|
||||
let (polys, points) = gen_random_test_case::<F>(k, degree_log, num_points);
|
||||
|
||||
let lpc = ListPolynomialCommitment::new(polys, &fri_config);
|
||||
let (proof, evaluations) = lpc.open(&points, &mut Challenger::new());
|
||||
let lpc = ListPolynomialCommitment::new(polys, fri_config.rate_bits, true);
|
||||
let (proof, evaluations) = lpc.open(&points, &mut Challenger::new(), &fri_config);
|
||||
proof.verify(
|
||||
&points,
|
||||
&evaluations.into_iter().map(|e| vec![e]).collect::<Vec<_>>(),
|
||||
@ -399,20 +410,21 @@ mod tests {
|
||||
rate_bits: 2,
|
||||
reduction_arity_bits: vec![2, 3, 1, 2],
|
||||
num_query_rounds: 3,
|
||||
blinding: false,
|
||||
blinding: vec![false, false, false],
|
||||
};
|
||||
let (polys0, _) = gen_random_test_case::<F>(k0, degree_log, num_points);
|
||||
let (polys1, _) = gen_random_test_case::<F>(k0, degree_log, num_points);
|
||||
let (polys2, points) = gen_random_test_case::<F>(k0, degree_log, num_points);
|
||||
|
||||
let lpc0 = ListPolynomialCommitment::new(polys0, &fri_config);
|
||||
let lpc1 = ListPolynomialCommitment::new(polys1, &fri_config);
|
||||
let lpc2 = ListPolynomialCommitment::new(polys2, &fri_config);
|
||||
let lpc0 = ListPolynomialCommitment::new(polys0, fri_config.rate_bits, false);
|
||||
let lpc1 = ListPolynomialCommitment::new(polys1, fri_config.rate_bits, false);
|
||||
let lpc2 = ListPolynomialCommitment::new(polys2, fri_config.rate_bits, false);
|
||||
|
||||
let (proof, evaluations) = ListPolynomialCommitment::batch_open(
|
||||
&[&lpc0, &lpc1, &lpc2],
|
||||
&points,
|
||||
&mut Challenger::new(),
|
||||
&fri_config,
|
||||
);
|
||||
proof.verify(
|
||||
&points,
|
||||
@ -441,20 +453,21 @@ mod tests {
|
||||
rate_bits: 2,
|
||||
reduction_arity_bits: vec![2, 3, 1, 2],
|
||||
num_query_rounds: 3,
|
||||
blinding: true,
|
||||
blinding: vec![true, false, true],
|
||||
};
|
||||
let (polys0, _) = gen_random_test_case::<F>(k0, degree_log, num_points);
|
||||
let (polys1, _) = gen_random_test_case::<F>(k0, degree_log, num_points);
|
||||
let (polys2, points) = gen_random_test_case::<F>(k0, degree_log, num_points);
|
||||
|
||||
let lpc0 = ListPolynomialCommitment::new(polys0, &fri_config);
|
||||
let lpc1 = ListPolynomialCommitment::new(polys1, &fri_config);
|
||||
let lpc2 = ListPolynomialCommitment::new(polys2, &fri_config);
|
||||
let lpc0 = ListPolynomialCommitment::new(polys0, fri_config.rate_bits, true);
|
||||
let lpc1 = ListPolynomialCommitment::new(polys1, fri_config.rate_bits, false);
|
||||
let lpc2 = ListPolynomialCommitment::new(polys2, fri_config.rate_bits, true);
|
||||
|
||||
let (proof, evaluations) = ListPolynomialCommitment::batch_open(
|
||||
&[&lpc0, &lpc1, &lpc2],
|
||||
&points,
|
||||
&mut Challenger::new(),
|
||||
&fri_config,
|
||||
);
|
||||
proof.verify(
|
||||
&points,
|
||||
|
||||
@ -26,6 +26,10 @@ macro_rules! timed {
|
||||
res
|
||||
}};
|
||||
}
|
||||
|
||||
/// Corresponds to constants - sigmas - wires - zs - quotient — polynomial commitments.
|
||||
pub const PLONK_BLINDING: [bool; 5] = [false, false, true, true, true];
|
||||
|
||||
pub(crate) fn prove<F: Field>(
|
||||
prover_data: &ProverOnlyCircuitData<F>,
|
||||
common_data: &CommonCircuitData<F>,
|
||||
@ -59,7 +63,7 @@ pub(crate) fn prove<F: Field>(
|
||||
// TODO: Could try parallelizing the transpose, or not doing it explicitly, instead having
|
||||
// merkle_root_bit_rev_order do it implicitly.
|
||||
let wires_commitment = timed!(
|
||||
ListPolynomialCommitment::new(wires_polynomials, &fri_config),
|
||||
ListPolynomialCommitment::new(wires_polynomials, fri_config.rate_bits, true),
|
||||
"to compute wires commitment"
|
||||
);
|
||||
|
||||
@ -75,7 +79,7 @@ pub(crate) fn prove<F: Field>(
|
||||
let plonk_z_vecs = timed!(compute_zs(&common_data), "to compute Z's");
|
||||
|
||||
let plonk_zs_commitment = timed!(
|
||||
ListPolynomialCommitment::new(plonk_z_vecs, &fri_config),
|
||||
ListPolynomialCommitment::new(plonk_z_vecs, fri_config.rate_bits, true),
|
||||
"to commit to Z's"
|
||||
);
|
||||
|
||||
@ -107,7 +111,7 @@ pub(crate) fn prove<F: Field>(
|
||||
let quotient_poly_coeff_chunks = quotient_poly_coeff.chunks(degree);
|
||||
all_quotient_poly_chunks.extend(quotient_poly_coeff_chunks);
|
||||
}
|
||||
ListPolynomialCommitment::new(all_quotient_poly_chunks, &fri_config)
|
||||
ListPolynomialCommitment::new(all_quotient_poly_chunks, fri_config.rate_bits, true)
|
||||
},
|
||||
"to compute quotient polys and commit to them"
|
||||
);
|
||||
@ -129,6 +133,7 @@ pub(crate) fn prove<F: Field>(
|
||||
],
|
||||
&zetas,
|
||||
&mut challenger,
|
||||
&common_data.config.fri_config
|
||||
),
|
||||
"to compute opening proofs"
|
||||
);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user