Merge pull request #716 from mir-protocol/s/l1/l0

Change Lagrange polynomial notation
This commit is contained in:
wborgeaud 2022-09-13 12:57:20 +02:00 committed by GitHub
commit 8647f144b7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 49 additions and 49 deletions

View File

@ -181,8 +181,8 @@ fn verify_stark_proof_with_challenges_circuit<
let degree_bits = proof.recover_degree_bits(inner_config);
let zeta_pow_deg = builder.exp_power_of_2_extension(challenges.stark_zeta, degree_bits);
let z_h_zeta = builder.sub_extension(zeta_pow_deg, one);
let (l_1, l_last) =
eval_l_1_and_l_last_circuit(builder, degree_bits, challenges.stark_zeta, z_h_zeta);
let (l_0, l_last) =
eval_l_0_and_l_last_circuit(builder, degree_bits, challenges.stark_zeta, z_h_zeta);
let last =
builder.constant_extension(F::Extension::primitive_root_of_unity(degree_bits).inverse());
let z_last = builder.sub_extension(challenges.stark_zeta, last);
@ -191,7 +191,7 @@ fn verify_stark_proof_with_challenges_circuit<
builder.zero_extension(),
challenges.stark_alphas.clone(),
z_last,
l_1,
l_0,
l_last,
);
@ -254,7 +254,7 @@ fn verify_stark_proof_with_challenges_circuit<
);
}
fn eval_l_1_and_l_last_circuit<F: RichField + Extendable<D>, const D: usize>(
fn eval_l_0_and_l_last_circuit<F: RichField + Extendable<D>, const D: usize>(
builder: &mut CircuitBuilder<F, D>,
log_n: usize,
x: ExtensionTarget<D>,
@ -263,12 +263,12 @@ fn eval_l_1_and_l_last_circuit<F: RichField + Extendable<D>, const D: usize>(
let n = builder.constant_extension(F::Extension::from_canonical_usize(1 << log_n));
let g = builder.constant_extension(F::Extension::primitive_root_of_unity(log_n));
let one = builder.one_extension();
let l_1_deno = builder.mul_sub_extension(n, x, n);
let l_0_deno = builder.mul_sub_extension(n, x, n);
let l_last_deno = builder.mul_sub_extension(g, x, one);
let l_last_deno = builder.mul_extension(n, l_last_deno);
(
builder.div_extension(z_x, l_1_deno),
builder.div_extension(z_x, l_0_deno),
builder.div_extension(z_x, l_last_deno),
)
}

View File

@ -133,7 +133,7 @@ where
};
let degree_bits = proof.recover_degree_bits(config);
let (l_1, l_last) = eval_l_1_and_l_last(degree_bits, challenges.stark_zeta);
let (l_0, l_last) = eval_l_0_and_l_last(degree_bits, challenges.stark_zeta);
let last = F::primitive_root_of_unity(degree_bits).inverse();
let z_last = challenges.stark_zeta - last.into();
let mut consumer = ConstraintConsumer::<F::Extension>::new(
@ -143,7 +143,7 @@ where
.map(|&alpha| F::Extension::from_basefield(alpha))
.collect::<Vec<_>>(),
z_last,
l_1,
l_0,
l_last,
);
let num_permutation_zs = stark.num_permutation_batches(config);
@ -204,10 +204,10 @@ where
Ok(())
}
/// Evaluate the Lagrange polynomials `L_1` and `L_n` at a point `x`.
/// `L_1(x) = (x^n - 1)/(n * (x - 1))`
/// `L_n(x) = (x^n - 1)/(n * (g * x - 1))`, with `g` the first element of the subgroup.
fn eval_l_1_and_l_last<F: Field>(log_n: usize, x: F) -> (F, F) {
/// Evaluate the Lagrange polynomials `L_0` and `L_(n-1)` at a point `x`.
/// `L_0(x) = (x^n - 1)/(n * (x - 1))`
/// `L_(n-1)(x) = (x^n - 1)/(n * (g * x - 1))`, with `g` the first element of the subgroup.
fn eval_l_0_and_l_last<F: Field>(log_n: usize, x: F) -> (F, F) {
let n = F::from_canonical_usize(1 << log_n);
let g = F::primitive_root_of_unity(log_n);
let z_x = x.exp_power_of_2(log_n) - F::ONE;
@ -222,10 +222,10 @@ mod tests {
use plonky2::field::polynomial::PolynomialValues;
use plonky2::field::types::Field;
use crate::verifier::eval_l_1_and_l_last;
use crate::verifier::eval_l_0_and_l_last;
#[test]
fn test_eval_l_1_and_l_last() {
fn test_eval_l_0_and_l_last() {
type F = GoldilocksField;
let log_n = 5;
let n = 1 << log_n;
@ -234,7 +234,7 @@ mod tests {
let expected_l_first_x = PolynomialValues::selector(n, 0).ifft().eval(x);
let expected_l_last_x = PolynomialValues::selector(n, n - 1).ifft().eval(x);
let (l_first_x, l_last_x) = eval_l_1_and_l_last(log_n, x);
let (l_first_x, l_last_x) = eval_l_0_and_l_last(log_n, x);
assert_eq!(l_first_x, expected_l_first_x);
assert_eq!(l_last_x, expected_l_last_x);
}

View File

@ -51,8 +51,8 @@ impl<F: Field> ZeroPolyOnCoset<F> {
packed
}
/// Returns `L_1(x) = Z_H(x)/(n * (x - 1))` with `x = w^i`.
pub fn eval_l1(&self, i: usize, x: F) -> F {
/// Returns `L_0(x) = Z_H(x)/(n * (x - 1))` with `x = w^i`.
pub fn eval_l_0(&self, i: usize, x: F) -> F {
// Could also precompute the inverses using Montgomery.
self.eval(i) * (self.n * (x - F::ONE)).inverse()
}

View File

@ -64,31 +64,31 @@ pub(crate) fn eval_zero_poly<F: Field>(n: usize, x: F) -> F {
x.exp_u64(n as u64) - F::ONE
}
/// Evaluate the Lagrange basis `L_1` with `L_1(1) = 1`, and `L_1(x) = 0` for other members of an
/// Evaluate the Lagrange basis `L_0` with `L_0(1) = 1`, and `L_0(x) = 0` for other members of the
/// order `n` multiplicative subgroup.
pub(crate) fn eval_l_1<F: Field>(n: usize, x: F) -> F {
pub(crate) fn eval_l_0<F: Field>(n: usize, x: F) -> F {
if x.is_one() {
// The code below would divide by zero, since we have (x - 1) in both the numerator and
// denominator.
return F::ONE;
}
// L_1(x) = (x^n - 1) / (n * (x - 1))
// L_0(x) = (x^n - 1) / (n * (x - 1))
// = Z(x) / (n * (x - 1))
eval_zero_poly(n, x) / (F::from_canonical_usize(n) * (x - F::ONE))
}
/// Evaluates the Lagrange basis L_1(x), which has L_1(1) = 1 and vanishes at all other points in
/// Evaluates the Lagrange basis L_0(x), which has L_0(1) = 1 and vanishes at all other points in
/// the order-`n` subgroup.
///
/// Assumes `x != 1`; if `x` could be 1 then this is unsound.
pub(crate) fn eval_l_1_circuit<F: RichField + Extendable<D>, const D: usize>(
pub(crate) fn eval_l_0_circuit<F: RichField + Extendable<D>, const D: usize>(
builder: &mut CircuitBuilder<F, D>,
n: usize,
x: ExtensionTarget<D>,
x_pow_n: ExtensionTarget<D>,
) -> ExtensionTarget<D> {
// L_1(x) = (x^n - 1) / (n * (x - 1))
// L_0(x) = (x^n - 1) / (n * (x - 1))
// = Z(x) / (n * (x - 1))
let one = builder.one_extension();
let neg_one = builder.neg_one();

View File

@ -10,7 +10,7 @@ use crate::plonk::circuit_builder::CircuitBuilder;
use crate::plonk::circuit_data::CommonCircuitData;
use crate::plonk::config::GenericConfig;
use crate::plonk::plonk_common;
use crate::plonk::plonk_common::eval_l_1_circuit;
use crate::plonk::plonk_common::eval_l_0_circuit;
use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBaseBatch};
use crate::util::partial_products::{check_partial_products, check_partial_products_circuit};
use crate::util::reducing::ReducingFactorTarget;
@ -41,17 +41,17 @@ pub(crate) fn eval_vanishing_poly<
let constraint_terms = evaluate_gate_constraints(common_data, vars);
// The L_1(x) (Z(x) - 1) vanishing terms.
// The L_0(x) (Z(x) - 1) vanishing terms.
let mut vanishing_z_1_terms = Vec::new();
// The terms checking the partial products.
let mut vanishing_partial_products_terms = Vec::new();
let l1_x = plonk_common::eval_l_1(common_data.degree(), x);
let l_0_x = plonk_common::eval_l_0(common_data.degree(), x);
for i in 0..common_data.config.num_challenges {
let z_x = local_zs[i];
let z_gx = next_zs[i];
vanishing_z_1_terms.push(l1_x * (z_x - F::Extension::ONE));
vanishing_z_1_terms.push(l_0_x * (z_x - F::Extension::ONE));
let numerator_values = (0..common_data.config.num_routed_wires)
.map(|j| {
@ -135,7 +135,7 @@ pub(crate) fn eval_vanishing_poly_base_batch<
let mut numerator_values = Vec::with_capacity(num_routed_wires);
let mut denominator_values = Vec::with_capacity(num_routed_wires);
// The L_1(x) (Z(x) - 1) vanishing terms.
// The L_0(x) (Z(x) - 1) vanishing terms.
let mut vanishing_z_1_terms = Vec::with_capacity(num_challenges);
// The terms checking the partial products.
let mut vanishing_partial_products_terms = Vec::new();
@ -152,11 +152,11 @@ pub(crate) fn eval_vanishing_poly_base_batch<
let constraint_terms = PackedStridedView::new(&constraint_terms_batch, n, k);
let l1_x = z_h_on_coset.eval_l1(index, x);
let l_0_x = z_h_on_coset.eval_l_0(index, x);
for i in 0..num_challenges {
let z_x = local_zs[i];
let z_gx = next_zs[i];
vanishing_z_1_terms.push(l1_x * z_x.sub_one());
vanishing_z_1_terms.push(l_0_x * z_x.sub_one());
numerator_values.extend((0..num_routed_wires).map(|j| {
let wire_value = vars.local_wires[j];
@ -332,12 +332,12 @@ pub(crate) fn eval_vanishing_poly_circuit<
evaluate_gate_constraints_circuit(builder, common_data, vars,)
);
// The L_1(x) (Z(x) - 1) vanishing terms.
// The L_0(x) (Z(x) - 1) vanishing terms.
let mut vanishing_z_1_terms = Vec::new();
// The terms checking the partial products.
let mut vanishing_partial_products_terms = Vec::new();
let l1_x = eval_l_1_circuit(builder, common_data.degree(), x, x_pow_deg);
let l_0_x = eval_l_0_circuit(builder, common_data.degree(), x, x_pow_deg);
// Holds `k[i] * x`.
let mut s_ids = Vec::new();
@ -350,8 +350,8 @@ pub(crate) fn eval_vanishing_poly_circuit<
let z_x = local_zs[i];
let z_gx = next_zs[i];
// L_1(x) Z(x) = 0.
vanishing_z_1_terms.push(builder.mul_sub_extension(l1_x, z_x, l1_x));
// L_0(x) (Z(x) - 1) = 0.
vanishing_z_1_terms.push(builder.mul_sub_extension(l_0_x, z_x, l_0_x));
let mut numerator_values = Vec::new();
let mut denominator_values = Vec::new();

View File

@ -102,8 +102,8 @@ fn verify_stark_proof_with_challenges_circuit<
let zeta_pow_deg = builder.exp_power_of_2_extension(challenges.stark_zeta, degree_bits);
let z_h_zeta = builder.sub_extension(zeta_pow_deg, one);
let (l_1, l_last) =
eval_l_1_and_l_last_circuit(builder, degree_bits, challenges.stark_zeta, z_h_zeta);
let (l_0, l_last) =
eval_l_0_and_l_last_circuit(builder, degree_bits, challenges.stark_zeta, z_h_zeta);
let last =
builder.constant_extension(F::Extension::primitive_root_of_unity(degree_bits).inverse());
let z_last = builder.sub_extension(challenges.stark_zeta, last);
@ -112,7 +112,7 @@ fn verify_stark_proof_with_challenges_circuit<
builder.zero_extension(),
challenges.stark_alphas,
z_last,
l_1,
l_0,
l_last,
);
@ -170,7 +170,7 @@ fn verify_stark_proof_with_challenges_circuit<
);
}
fn eval_l_1_and_l_last_circuit<F: RichField + Extendable<D>, const D: usize>(
fn eval_l_0_and_l_last_circuit<F: RichField + Extendable<D>, const D: usize>(
builder: &mut CircuitBuilder<F, D>,
log_n: usize,
x: ExtensionTarget<D>,
@ -179,12 +179,12 @@ fn eval_l_1_and_l_last_circuit<F: RichField + Extendable<D>, const D: usize>(
let n = builder.constant_extension(F::Extension::from_canonical_usize(1 << log_n));
let g = builder.constant_extension(F::Extension::primitive_root_of_unity(log_n));
let one = builder.one_extension();
let l_1_deno = builder.mul_sub_extension(n, x, n);
let l_0_deno = builder.mul_sub_extension(n, x, n);
let l_last_deno = builder.mul_sub_extension(g, x, one);
let l_last_deno = builder.mul_extension(n, l_last_deno);
(
builder.div_extension(z_x, l_1_deno),
builder.div_extension(z_x, l_0_deno),
builder.div_extension(z_x, l_last_deno),
)
}

View File

@ -78,7 +78,7 @@ where
.unwrap(),
};
let (l_1, l_last) = eval_l_1_and_l_last(degree_bits, challenges.stark_zeta);
let (l_0, l_last) = eval_l_0_and_l_last(degree_bits, challenges.stark_zeta);
let last = F::primitive_root_of_unity(degree_bits).inverse();
let z_last = challenges.stark_zeta - last.into();
let mut consumer = ConstraintConsumer::<F::Extension>::new(
@ -88,7 +88,7 @@ where
.map(|&alpha| F::Extension::from_basefield(alpha))
.collect::<Vec<_>>(),
z_last,
l_1,
l_0,
l_last,
);
let permutation_data = stark.uses_permutation_args().then(|| PermutationCheckVars {
@ -144,10 +144,10 @@ where
Ok(())
}
/// Evaluate the Lagrange polynomials `L_1` and `L_n` at a point `x`.
/// `L_1(x) = (x^n - 1)/(n * (x - 1))`
/// `L_n(x) = (x^n - 1)/(n * (g * x - 1))`, with `g` the first element of the subgroup.
fn eval_l_1_and_l_last<F: Field>(log_n: usize, x: F) -> (F, F) {
/// Evaluate the Lagrange polynomials `L_0` and `L_(n-1)` at a point `x`.
/// `L_0(x) = (x^n - 1)/(n * (x - 1))`
/// `L_(n-1)(x) = (x^n - 1)/(n * (g * x - 1))`, with `g` the first element of the subgroup.
fn eval_l_0_and_l_last<F: Field>(log_n: usize, x: F) -> (F, F) {
let n = F::from_canonical_usize(1 << log_n);
let g = F::primitive_root_of_unity(log_n);
let z_x = x.exp_power_of_2(log_n) - F::ONE;
@ -189,10 +189,10 @@ mod tests {
use plonky2::field::polynomial::PolynomialValues;
use plonky2::field::types::Field;
use crate::verifier::eval_l_1_and_l_last;
use crate::verifier::eval_l_0_and_l_last;
#[test]
fn test_eval_l_1_and_l_last() {
fn test_eval_l_0_and_l_last() {
type F = GoldilocksField;
let log_n = 5;
let n = 1 << log_n;
@ -201,7 +201,7 @@ mod tests {
let expected_l_first_x = PolynomialValues::selector(n, 0).ifft().eval(x);
let expected_l_last_x = PolynomialValues::selector(n, n - 1).ifft().eval(x);
let (l_first_x, l_last_x) = eval_l_1_and_l_last(log_n, x);
let (l_first_x, l_last_x) = eval_l_0_and_l_last(log_n, x);
assert_eq!(l_first_x, expected_l_first_x);
assert_eq!(l_last_x, expected_l_last_x);
}