This commit is contained in:
Robin Salen 2023-05-05 08:04:01 +02:00
parent c0fc349c58
commit 4351237160
No known key found for this signature in database
GPG Key ID: FB87BACFB3CB2007
5 changed files with 45 additions and 52 deletions

View File

@ -62,16 +62,16 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
}
/// Adds a lookup (input, output) pair to the stored lookups. Takes a `Target` input and returns a `Target` output.
pub fn add_lookup_from_index(&mut self, looking_input: Target, lut_index: usize) -> Target {
pub fn add_lookup_from_index(&mut self, looking_in: Target, lut_index: usize) -> Target {
assert!(
lut_index < self.get_luts_length(),
"lut number {} not in luts (length = {})",
lut_index,
self.get_luts_length()
);
let looking_output = self.add_virtual_target();
self.update_lookups(looking_input, looking_output, lut_index);
looking_output
let looking_out = self.add_virtual_target();
self.update_lookups(looking_in, looking_out, lut_index);
looking_out
}
/// We call this function at the end of circuit building right before the PI gate to add all `LookupTableGate` and `LookupGate`.
@ -91,13 +91,13 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
let lookups = self.get_lut_lookups(lut_index).to_owned();
for (looking_inp, looking_out) in lookups {
for (looking_in, looking_out) in lookups {
let gate = LookupGate::new_from_table(&self.config, lut.clone());
let (gate, i) =
self.find_slot(gate, &[F::from_canonical_usize(lut_index)], &[]);
let gate_inp = Target::wire(gate, LookupGate::wire_ith_looking_inp(i));
let gate_in = Target::wire(gate, LookupGate::wire_ith_looking_inp(i));
let gate_out = Target::wire(gate, LookupGate::wire_ith_looking_out(i));
self.connect(gate_inp, looking_inp);
self.connect(gate_in, looking_in);
self.connect(gate_out, looking_out);
}

View File

@ -53,11 +53,15 @@ use crate::util::timing::TimingTree;
use crate::util::{log2_ceil, log2_strict, transpose, transpose_poly_values};
/// Number of random coins needed for lookups (for each challenge).
/// A coin is a randomly sampled extension field element from the verifier,
/// consisting internally of `CircuitConfig::num_challenges` field elements.
pub const NUM_COINS_LOOKUP: usize = 4;
/// Enum listing the different types of lookup challenges. `ChallengeA` is used for the linear combination of input and output pairs in Sum and LDC.
/// Enum listing the different types of lookup challenges.
/// `ChallengeA` is used for the linear combination of input and output pairs in Sum and LDC.
/// `ChallengeB` is used for the linear combination of input and output pairs in the polynomial RE.
/// `ChallengeAlpha` is used for the running sums: 1/(alpha - combo_i). `ChallengeDelta` is a challenge on which to evaluate the interpolated LUT function.
/// `ChallengeAlpha` is used for the running sums: 1/(alpha - combo_i).
/// `ChallengeDelta` is a challenge on which to evaluate the interpolated LUT function.
pub enum LookupChallenges {
ChallengeA = 0,
ChallengeB = 1,
@ -65,7 +69,10 @@ pub enum LookupChallenges {
ChallengeDelta = 3,
}
/// Structure containing, for each lookup table, the indices of the last lookup row, the last lookup table row and the first lookup table row. Since the rows are in reverse order in the trace, they actually correspond, respectively, to: the indices of the first `LookupGate`, the first `LookupTableGate` and the last `LookupTableGate`.
/// Structure containing, for each lookup table, the indices of the last lookup row,
/// the last lookup table row and the first lookup table row. Since the rows are in
/// reverse order in the trace, they actually correspond, respectively, to: the indices
/// of the first `LookupGate`, the first `LookupTableGate` and the last `LookupTableGate`.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct LookupWire {
/// Index of the last lookup row (i.e. the first `LookupGate`).
@ -118,7 +125,7 @@ pub struct CircuitBuilder<F: RichField + Extendable<D>, const D: usize> {
/// List of constant generators used to fill the constant wires.
constant_generators: Vec<ConstantGenerator<F>>,
/// Rows for each LUT: LookupWire contains: first `LookupTableGate`, first `LookupGate`, last `LookupGate`.
/// Rows for each LUT: LookupWire contains: first `LookupGate`, first `LookupTableGate`, last `LookupTableGate`.
lookup_rows: Vec<LookupWire>,
/// For each LUT index, vector of `(looking_in, looking_out)` pairs.
@ -226,19 +233,14 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
}
/// Adds a looking (input, output) pair to the corresponding LUT.
pub fn update_lookups(
&mut self,
looking_inp: Target,
looking_output: Target,
lut_index: usize,
) {
pub fn update_lookups(&mut self, looking_in: Target, looking_out: Target, lut_index: usize) {
assert!(
lut_index < self.lut_to_lookups.len(),
"The LUT with index {} has not been created. The last LUT is at index {}",
lut_index,
self.lut_to_lookups.len() - 1
);
self.lut_to_lookups[lut_index].push((looking_inp, looking_output));
self.lut_to_lookups[lut_index].push((looking_in, looking_out));
}
pub fn num_luts(&mut self) -> usize {
@ -585,6 +587,12 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
/// Returns the LUT at index `idx`.
pub fn get_lut(&self, idx: usize) -> Arc<Vec<(u16, u16)>> {
assert!(
idx < self.luts.len(),
"index idx: {} greater than the total number of created LUTS: {}",
idx,
self.luts.len()
);
self.luts[idx].clone()
}
@ -593,9 +601,7 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
where
T: Copy,
{
(0..inputs.len())
.map(|i| (inputs[i], f(inputs[i])))
.collect()
inputs.iter().map(|&input| (input, f(input))).collect()
}
/// Given a function `f: fn(u16) -> u16`, adds a LUT to the circuit builder.
@ -1070,7 +1076,7 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
num_partial_products(self.config.num_routed_wires, quotient_degree_factor);
let lookup_degree = self.config.max_quotient_degree_factor - 1;
let num_lookup_polys = if self.luts.is_empty() {
let num_lookup_polys = if num_luts == 0 {
0
} else {
// There is 1 RE polynomial and multiple Sum/LDC polynomials.

View File

@ -583,25 +583,14 @@ impl<F: RichField + Extendable<D>, const D: usize> CommonCircuitData<F, D> {
}
fn fri_all_polys(&self) -> Vec<FriPolynomialInfo> {
let has_lookup = self.num_lookup_polys != 0;
if has_lookup {
[
self.fri_preprocessed_polys(),
self.fri_wire_polys(),
self.fri_zs_partial_products_polys(),
self.fri_quotient_polys(),
self.fri_lookup_polys(),
]
.concat()
} else {
[
self.fri_preprocessed_polys(),
self.fri_wire_polys(),
self.fri_zs_partial_products_polys(),
self.fri_quotient_polys(),
]
.concat()
}
[
self.fri_preprocessed_polys(),
self.fri_wire_polys(),
self.fri_zs_partial_products_polys(),
self.fri_quotient_polys(),
self.fri_lookup_polys(),
]
.concat()
}
}

View File

@ -509,10 +509,10 @@ fn compute_lookup_polys<
// Get looking combos.
let looking_combos: Vec<F> = (0..num_lu_slots)
.map(|s| {
let looking_inp = witness.get_wire(row, LookupGate::wire_ith_looking_inp(s));
let looking_in = witness.get_wire(row, LookupGate::wire_ith_looking_inp(s));
let looking_out = witness.get_wire(row, LookupGate::wire_ith_looking_out(s));
looking_inp + deltas[LookupChallenges::ChallengeA as usize] * looking_out
looking_in + deltas[LookupChallenges::ChallengeA as usize] * looking_out
})
.collect();
// Get (alpha - combo).

View File

@ -43,9 +43,7 @@ pub(crate) fn get_lut_poly<F: RichField + Extendable<D>, const D: usize>(
+ b * F::from_canonical_u16(common_data.luts[lut_index][i].1),
);
}
for _ in n..degree {
coeffs.push(F::ZERO);
}
coeffs.append(&mut vec![F::ZERO; degree - n]);
coeffs.reverse();
PolynomialCoeffs::new(coeffs)
}
@ -360,13 +358,15 @@ pub fn check_lookup_constraints<F: RichField + Extendable<D>, const D: usize>(
let z_x_lookup_sldcs = &local_lookup_zs[1..num_sldc_polys + 1];
let z_gx_lookup_sldcs = &next_lookup_zs[1..num_sldc_polys + 1];
let delta_challenge_a = F::Extension::from(deltas[LookupChallenges::ChallengeA as usize]);
let delta_challenge_b = F::Extension::from(deltas[LookupChallenges::ChallengeB as usize]);
// Compute all current looked and looking combos, i.e. the combos we need for the SLDC polynomials.
let current_looked_combos: Vec<F::Extension> = (0..num_lut_slots)
.map(|s| {
let input_wire = vars.local_wires[LookupTableGate::wire_ith_looked_inp(s)];
let output_wire = vars.local_wires[LookupTableGate::wire_ith_looked_out(s)];
input_wire
+ F::Extension::from(deltas[LookupChallenges::ChallengeA as usize]) * output_wire
input_wire + delta_challenge_a * output_wire
})
.collect();
@ -374,8 +374,7 @@ pub fn check_lookup_constraints<F: RichField + Extendable<D>, const D: usize>(
.map(|s| {
let input_wire = vars.local_wires[LookupGate::wire_ith_looking_inp(s)];
let output_wire = vars.local_wires[LookupGate::wire_ith_looking_out(s)];
input_wire
+ F::Extension::from(deltas[LookupChallenges::ChallengeA as usize]) * output_wire
input_wire + delta_challenge_a * output_wire
})
.collect();
@ -384,8 +383,7 @@ pub fn check_lookup_constraints<F: RichField + Extendable<D>, const D: usize>(
.map(|s| {
let input_wire = vars.local_wires[LookupTableGate::wire_ith_looked_inp(s)];
let output_wire = vars.local_wires[LookupTableGate::wire_ith_looked_out(s)];
input_wire
+ F::Extension::from(deltas[LookupChallenges::ChallengeB as usize]) * output_wire
input_wire + delta_challenge_b * output_wire
})
.collect();