Add insert gadget to insert inferred leaf in FRI query rounds

This commit is contained in:
wborgeaud 2021-06-14 15:15:22 +02:00
parent fa229d9a27
commit cfa5807556
6 changed files with 86 additions and 19 deletions

View File

@ -1,22 +1,16 @@
use anyhow::{ensure, Result};
use itertools::izip;
use crate::circuit_builder::CircuitBuilder;
use crate::field::extension_field::target::{flatten_target, ExtensionTarget};
use crate::field::extension_field::{flatten, Extendable, FieldExtension, OEF};
use crate::field::extension_field::Extendable;
use crate::field::field::Field;
use crate::field::lagrange::{barycentric_weights, interpolant, interpolate};
use crate::fri::FriConfig;
use crate::hash::hash_n_to_1;
use crate::merkle_proofs::verify_merkle_proof;
use crate::plonk_challenger::{Challenger, RecursiveChallenger};
use crate::plonk_common::reduce_with_iter;
use crate::plonk_challenger::RecursiveChallenger;
use crate::proof::{
FriInitialTreeProof, FriInitialTreeProofTarget, FriProof, FriProofTarget, FriQueryRound,
FriQueryRoundTarget, Hash, HashTarget, OpeningSet, OpeningSetTarget,
FriInitialTreeProofTarget, FriProofTarget, FriQueryRoundTarget, HashTarget, OpeningSetTarget,
};
use crate::target::Target;
use crate::util::{log2_strict, reverse_bits, reverse_index_bits_in_place};
use crate::util::{log2_strict, reverse_index_bits_in_place};
impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
/// Computes P'(x^arity) from {P(x*g^i)}_(i=0..arity), where g is a `arity`-th root of unity
@ -180,7 +174,7 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
}
let denominator = self.sub_extension(subgroup_x, zeta);
let quotient = self.div_unsafe_extension(numerator, denominator);
let sum = self.add_extension(sum, quotient);
sum = self.add_extension(sum, quotient);
let evs = proof
.unsalted_evals(3, config)
@ -213,7 +207,7 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
let vanish_right = self.sub_extension(subgroup_x, zeta_right);
let denominator = self.mul_extension(vanish, vanish_right);
let quotient = self.div_unsafe_extension(numerator, denominator);
let sum = self.add_extension(sum, quotient);
sum = self.add_extension(sum, quotient);
let evs = proof
.unsalted_evals(2, config)
@ -245,7 +239,7 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
let vanish_frob = self.sub_extension(subgroup_x, zeta_frob);
let denominator = self.mul_extension(vanish, vanish_frob);
let quotient = self.div_unsafe_extension(numerator, denominator);
let sum = self.add_extension(sum, quotient);
sum = self.add_extension(sum, quotient);
sum
}
@ -285,7 +279,6 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
let mut subgroup_x = self.mul(g, phi);
for (i, &arity_bits) in config.reduction_arity_bits.iter().enumerate() {
let arity = 1 << arity_bits;
let next_domain_size = domain_size >> arity_bits;
let e_x = if i == 0 {
self.fri_combine_initial(
@ -309,8 +302,7 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
let mut evals = round_proof.steps[i].evals.clone();
// Insert P(y) into the evaluation vector, since it wasn't included by the prover.
let (low_x_index, high_x_index) = self.split_low_high(x_index, arity_bits);
// TODO: Uncomment this.
// evals.insert(x_index & (arity - 1), e_x);
evals = self.insert(low_x_index, e_x, evals);
evaluations.push(evals);
self.verify_merkle_proof(
flatten_target(&evaluations[i]),

29
src/gadgets/insert.rs Normal file
View File

@ -0,0 +1,29 @@
use crate::circuit_builder::CircuitBuilder;
use crate::field::extension_field::target::ExtensionTarget;
use crate::field::extension_field::Extendable;
use crate::target::Target;
use crate::util::log2_strict;
impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
/// Inserts a `Target` in a vector at a non-deterministic index. This is done by rotating to the
/// left, inserting at 0 and then rotating to the right.
/// Note: `index` is not range-checked.
pub fn insert(
&mut self,
index: Target,
element: ExtensionTarget<D>,
mut v: Vec<ExtensionTarget<D>>,
) -> Vec<ExtensionTarget<D>> {
let n = v.len();
debug_assert!(n.is_power_of_two());
let n_log = log2_strict(n);
v.push(self.zero_extension());
let mut v = self.rotate_left(index, &v, n_log);
v.insert(0, element);
v.pop().unwrap();
self.rotate_right(index, &v, n_log)
}
}

View File

@ -1,5 +1,6 @@
pub mod arithmetic;
pub mod hash;
pub mod insert;
pub mod interpolation;
pub mod polynomial;
pub mod range_check;

View File

@ -37,6 +37,22 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
res
}
pub fn rotate_right_fixed(
&mut self,
b: Target,
k: usize,
v: &[ExtensionTarget<D>],
len: usize,
) -> Vec<ExtensionTarget<D>> {
let mut res = Vec::new();
for i in 0..len {
res.push(self.select(b, v[(i - k) % len], v[i]));
}
res
}
/// Left-rotates an array by `num_rotation`. Assumes that `num_rotation` is range-checked to be
/// less than `len`.
/// Note: We assume `len` is less than 8 since we won't use any arity greater than 8 in FRI (maybe?).
@ -58,6 +74,24 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
v
}
pub fn rotate_right_from_bits(
&mut self,
num_rotation_bits: &[Target],
v: &[ExtensionTarget<D>],
len_log: usize,
) -> Vec<ExtensionTarget<D>> {
debug_assert_eq!(num_rotation_bits.len(), len_log);
let len = 1 << len_log;
debug_assert_eq!(v.len(), len);
let mut v = v.to_vec();
for i in 0..len_log {
v = self.rotate_right_fixed(num_rotation_bits[i], 1 << i, &v, len);
}
v
}
/// Left-rotates an array by `num_rotation`. Assumes that `num_rotation` is range-checked to be
/// less than `len`.
/// Note: We assume `len` is a power of two less than or equal to 8, since we won't use any
@ -74,6 +108,19 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
self.rotate_left_from_bits(&bits, v, len_log)
}
pub fn rotate_right(
&mut self,
num_rotation: Target,
v: &[ExtensionTarget<D>],
len_log: usize,
) -> Vec<ExtensionTarget<D>> {
let len = 1 << len_log;
debug_assert_eq!(v.len(), len);
let bits = self.split_le(num_rotation, len_log);
self.rotate_right_from_bits(&bits, v, len_log)
}
}
#[cfg(test)]

View File

@ -1,5 +1,4 @@
use crate::circuit_builder::CircuitBuilder;
use crate::circuit_data::CircuitConfig;
use crate::field::extension_field::target::ExtensionTarget;
use crate::field::extension_field::Extendable;
use crate::field::field::Field;
@ -8,7 +7,6 @@ use crate::generator::{SimpleGenerator, WitnessGenerator};
use crate::plonk_common::{reduce_with_powers, reduce_with_powers_recursive};
use crate::target::Target;
use crate::vars::{EvaluationTargets, EvaluationVars};
use crate::wire::Wire;
use crate::witness::PartialWitness;
use std::ops::Range;

View File

@ -5,7 +5,7 @@ use crate::gates::gate::{Gate, GateRef};
use crate::generator::WitnessGenerator;
use crate::vars::{EvaluationTargets, EvaluationVars};
/// A gate which takes a single constant parameter and outputs that value.
/// A gate which does nothing.
pub struct NoopGate;
impl NoopGate {