Skip to content

Commit

Permalink
Remove all top level declarations (#1512)
Browse files Browse the repository at this point in the history
Includes #1511, but also removes the declarations of the challenges in
the `permutation` and `lookup` modules.

With these changes, we never declare a column or challenge outside a
machine namespace. This greatly simplifies #1470.

---------

Co-authored-by: schaeff <thibaut@schaeff.fr>
Co-authored-by: chriseth <chris@ethereum.org>
  • Loading branch information
3 people committed Jul 2, 2024
1 parent 72b4d73 commit f0af0c1
Show file tree
Hide file tree
Showing 11 changed files with 68 additions and 62 deletions.
2 changes: 1 addition & 1 deletion pipeline/tests/powdr_std.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ fn permutation_via_challenges_bn() {
}

#[test]
#[should_panic = "Error reducing expression to constraint:\nExpression: std::protocols::permutation::permutation([main.z], main.permutation_constraint)\nError: FailedAssertion(\"The Goldilocks field is too small and needs to move to the extension field. Pass two accumulators instead!\")"]
#[should_panic = "Error reducing expression to constraint:\nExpression: std::protocols::permutation::permutation(main.is_first, [main.z], main.alpha, main.beta, main.permutation_constraint)\nError: FailedAssertion(\"The Goldilocks field is too small and needs to move to the extension field. Pass two accumulators instead!\""]
fn permutation_via_challenges_gl() {
let f = "std/permutation_via_challenges.asm";
Pipeline::<GoldilocksField>::default()
Expand Down
1 change: 1 addition & 0 deletions std/mod.asm
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ mod prelude;
mod protocols;
mod prover;
mod utils;
mod well_known;
28 changes: 5 additions & 23 deletions std/protocols/lookup.asm
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use std::prover::challenge;
use std::array::fold;
use std::utils::unwrap_or_else;
use std::array::len;
Expand All @@ -18,16 +17,6 @@ use std::math::fp2::eval_ext;
use std::math::fp2::from_base;
use std::math::fp2::constrain_eq_ext;


let is_first: col = |i| if i == 0 { 1 } else { 0 };

// challenges to be used in polynomial evaluation and folding different columns
let alpha1: expr = challenge(0, 1);
let alpha2: expr = challenge(0, 2);

let beta1: expr = challenge(0, 3);
let beta2: expr = challenge(0, 4);

let unpack_lookup_constraint: Constr -> (expr, expr[], expr, expr[]) = |lookup_constraint| match lookup_constraint {
Constr::Lookup((lhs_selector, rhs_selector), values) => (
unwrap_or_else(lhs_selector, || 1),
Expand All @@ -54,16 +43,8 @@ let<T: Add + Mul + FromLiteral> compress_expression_array: T[], Fp2<T> -> Fp2<T>
);

// Compute z' = z + 1/(beta-a_i) * lhs_selector - m_i/(beta-b_i) * rhs_selector, using extension field arithmetic
let compute_next_z: Fp2<expr>, Constr, expr -> fe[] = query |acc, lookup_constraint, multiplicities| {
let compute_next_z: Fp2<expr>, Fp2<expr>, Fp2<expr>, Constr, expr -> fe[] = query |acc, alpha, beta, lookup_constraint, multiplicities| {
let (lhs_selector, lhs, rhs_selector, rhs) = unpack_lookup_constraint(lookup_constraint);
let alpha = if len(lhs) > 1 {
Fp2::Fp2(alpha1, alpha2)
} else {
// The optimizer will have removed alpha, but the compression function
// still accesses it (to multiply by 0 in this case)
from_base(0)
};
let beta = Fp2::Fp2(beta1, beta2);

let lhs_denom = sub_ext(beta, compress_expression_array(lhs, alpha));
let rhs_denom = sub_ext(beta, compress_expression_array(rhs, alpha));
Expand All @@ -88,11 +69,14 @@ let compute_next_z: Fp2<expr>, Constr, expr -> fe[] = query |acc, lookup_constra

// Adds constraints that enforce that rhs is the lookup for lhs
// Arguments:
// - is_first: A column that is 1 for the first row and 0 for the rest
// - alpha: A challenge used to compress the LHS and RHS values
// - beta: A challenge used to update the accumulator
// - acc: A phase-2 witness column to be used as the accumulator. If 2 are provided, computations
// are done on the F_{p^2} extension field.
// - lookup_constraint: The lookup constraint
// - multiplicities: The multiplicities which shows how many times each RHS value appears in the LHS
let lookup: expr[], Constr, expr -> Constr[] = |acc, lookup_constraint, multiplicities| {
let lookup: expr, expr[], Fp2<expr>, Fp2<expr>, Constr, expr -> Constr[] = |is_first, acc, alpha, beta, lookup_constraint, multiplicities| {

let (lhs_selector, lhs, rhs_selector, rhs) = unpack_lookup_constraint(lookup_constraint);

Expand All @@ -113,8 +97,6 @@ let lookup: expr[], Constr, expr -> Constr[] = |acc, lookup_constraint, multipli
// in which case the operations below effectively only operate on the first component.
let fp2_from_array = |arr| if with_extension { Fp2::Fp2(arr[0], arr[1]) } else { from_base(arr[0]) };
let acc_ext = fp2_from_array(acc);
let alpha = fp2_from_array([alpha1, alpha2]);
let beta = fp2_from_array([beta1, beta2]);

let lhs_denom = sub_ext(beta, compress_expression_array(lhs, alpha));
let rhs_denom = sub_ext(beta, compress_expression_array(rhs, alpha));
Expand Down
32 changes: 3 additions & 29 deletions std/protocols/permutation.asm
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use std::prover::challenge;
use std::array::fold;
use std::array::map;
use std::utils::unwrap_or_else;
Expand All @@ -18,20 +17,6 @@ use std::math::fp2::eval_ext;
use std::math::fp2::from_base;
use std::math::fp2::constrain_eq_ext;

let is_first: col = |i| if i == 0 { 1 } else { 0 };

/// Get two phase-2 challenges to use in all permutation arguments.
/// Note that this assumes that globally no other challenge of these IDs is used,
/// and that challenges for multiple permutation arguments are re-used.
/// We declare two components for each challenge here, in case we need to operate
/// on the extension field. If we don't, we won't end up needing it and the optimizer
/// will remove it.
let alpha1: expr = challenge(0, 1);
let alpha2: expr = challenge(0, 2);

let beta1: expr = challenge(0, 3);
let beta2: expr = challenge(0, 4);

let unpack_permutation_constraint: Constr -> (expr, expr[], expr, expr[]) = |permutation_constraint| match permutation_constraint {
Constr::Permutation((lhs_selector, rhs_selector), values) => (
unwrap_or_else(lhs_selector, || 1),
Expand Down Expand Up @@ -65,18 +50,9 @@ let<T: Add + Mul + Sub + FromLiteral> selected_or_one: T, Fp2<T> -> Fp2<T> = |se
/// the provided permutation constraint).
/// This is intended to be used as a hint in the extension field case; for the base case
/// automatic witgen is smart enough to figure out the value of the accumulator.
let compute_next_z: Fp2<expr>, Constr -> fe[] = query |acc, permutation_constraint| {
let compute_next_z: Fp2<expr>, Fp2<expr>, Fp2<expr>, Constr -> fe[] = query |acc, alpha, beta, permutation_constraint| {

let (lhs_selector, lhs, rhs_selector, rhs) = unpack_permutation_constraint(permutation_constraint);

let alpha = if len(lhs) > 1 {
Fp2::Fp2(alpha1, alpha2)
} else {
// The optimizer will have removed alpha, but the compression function
// still accesses it (to multiply by 0 in this case)
from_base(0)
};
let beta = Fp2::Fp2(beta1, beta2);

let lhs_folded = selected_or_one(lhs_selector, sub_ext(beta, compress_expression_array(lhs, alpha)));
let rhs_folded = selected_or_one(rhs_selector, sub_ext(beta, compress_expression_array(rhs, alpha)));
Expand Down Expand Up @@ -117,7 +93,7 @@ let compute_next_z: Fp2<expr>, Constr -> fe[] = query |acc, permutation_constrai
/// the wrapping behavior: The first accumulator is constrained to be 1, and the last
/// accumulator is the same as the first one, because of wrapping.
/// For small fields, this computation should happen in the extension field.
let permutation: expr[], Constr -> Constr[] = |acc, permutation_constraint| {
let permutation: expr, expr[], Fp2<expr>, Fp2<expr>, Constr -> Constr[] = |is_first, acc, alpha, beta, permutation_constraint| {

let (lhs_selector, lhs, rhs_selector, rhs) = unpack_permutation_constraint(permutation_constraint);

Expand All @@ -131,14 +107,12 @@ let permutation: expr[], Constr -> Constr[] = |acc, permutation_constraint| {
let _ = if !with_extension {
assert(!needs_extension(), || "The Goldilocks field is too small and needs to move to the extension field. Pass two accumulators instead!")
} else { () };

// On the extension field, we'll need two field elements to represent the challenge.
// If we don't need an extension field, we can simply set the second component to 0,
// in which case the operations below effectively only operate on the first component.
let fp2_from_array = |arr| if with_extension { Fp2::Fp2(arr[0], arr[1]) } else { from_base(arr[0]) };
let acc_ext = fp2_from_array(acc);
let alpha = fp2_from_array([alpha1, alpha2]);
let beta = fp2_from_array([beta1, beta2]);

// If the selector is 1, contribute a factor of `beta - compress_expression_array(lhs)` to accumulator.
// If the selector is 0, contribute a factor of 1 to the accumulator.
Expand Down
1 change: 1 addition & 0 deletions std/well_known.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
let is_first: int -> int = |i| if i == 0 { 1 } else { 0 };
2 changes: 1 addition & 1 deletion test_data/asm/second_phase_hint.asm
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::prover::eval;
use std::prover::challenge;

machine Main with degree: 8 {
col fixed is_first = [1] + [0]*;
let is_first: col = std::well_known::is_first;

let count;

Expand Down
9 changes: 8 additions & 1 deletion test_data/std/lookup_via_challenges.asm
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
use std::prover::Query;
use std::convert::fe;
use std::protocols::lookup::lookup;
use std::math::fp2::from_base;
use std::prover::challenge;

machine Main with degree: 8 {

let alpha = from_base(challenge(0, 1));
let beta = from_base(challenge(0, 2));

col fixed random_six = [1, 1, 1, 0, 1, 1, 1, 0];
col fixed first_seven = [1, 1, 1, 1, 1, 1, 1, 0];

Expand All @@ -22,6 +28,7 @@ machine Main with degree: 8 {
// TODO: Functions currently cannot add witness columns at later stages,
// so we have to manually create it here and pass it to permutation().
col witness stage(1) z;
lookup([z], lookup_constraint, m);
let is_first: col = std::well_known::is_first;
lookup(is_first, [z], alpha, beta, lookup_constraint, m);

}
15 changes: 13 additions & 2 deletions test_data/std/lookup_via_challenges_ext.asm
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,17 @@ use std::convert::fe;
use std::protocols::lookup::lookup;
use std::protocols::lookup::compute_next_z;
use std::math::fp2::Fp2;
use std::prover::challenge;

machine Main with degree: 8 {

let alpha1: expr = challenge(0, 1);
let alpha2: expr = challenge(0, 2);
let beta1: expr = challenge(0, 3);
let beta2: expr = challenge(0, 4);
let alpha = Fp2::Fp2(alpha1, alpha2);
let beta = Fp2::Fp2(beta1, beta2);

col fixed a_sel = [0, 1, 1, 1, 0, 1, 0, 0];
col fixed b_sel = [1, 1, 0, 1, 1, 1, 1, 0];

Expand All @@ -25,11 +34,13 @@ machine Main with degree: 8 {
// so we have to manually create it here and pass it to lookup().
col witness stage(1) z1;
col witness stage(1) z2;
let z = Fp2::Fp2(z1, z2);

lookup([z1, z2], lookup_constraint, m);
let is_first: col = std::well_known::is_first;
lookup(is_first, [z1, z2], alpha, beta, lookup_constraint, m);

// TODO: Helper columns, because we can't access the previous row in hints
let hint = query |i| Query::Hint(compute_next_z(Fp2::Fp2(z1, z2), lookup_constraint, m)[i]);
let hint = query |i| Query::Hint(compute_next_z(z, alpha, beta, lookup_constraint, m)[i]);
col witness stage(1) z1_next(i) query hint(0);
col witness stage(1) z2_next(i) query hint(1);

Expand Down
16 changes: 14 additions & 2 deletions test_data/std/lookup_via_challenges_ext_simple.asm
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,18 @@ use std::convert::fe;
use std::protocols::lookup::lookup;
use std::protocols::lookup::compute_next_z;
use std::math::fp2::Fp2;
use std::prover::challenge;

machine Main with degree: 8 {

// We don't need an alpha here, because we only "fold" one element.
// Therefore, the optimizer will remove it, but the hint still accesses it...
let alpha = Fp2::Fp2(0, 0);

let beta1: expr = challenge(0, 3);
let beta2: expr = challenge(0, 4);
let beta = Fp2::Fp2(beta1, beta2);

col fixed a = [1, 1, 4, 1, 1, 2, 1, 1];
col witness b(i) query Query::Hint(fe(i+1));
col fixed m = [6, 1, 0, 1, 0, 0, 0, 0];
Expand All @@ -18,11 +28,13 @@ machine Main with degree: 8 {
// so we have to manually create it here and pass it to lookup().
col witness stage(1) z1;
col witness stage(1) z2;
let z = Fp2::Fp2(z1, z2);

lookup([z1, z2], lookup_constraint, m);
let is_first: col = std::well_known::is_first;
lookup(is_first, [z1, z2], alpha, beta, lookup_constraint, m);

// TODO: Helper columns, because we can't access the previous row in hints
let hint = query |i| Query::Hint(compute_next_z(Fp2::Fp2(z1, z2), lookup_constraint, m)[i]);
let hint = query |i| Query::Hint(compute_next_z(z, alpha, beta, lookup_constraint, m)[i]);
col witness stage(1) z1_next(i) query hint(0);
col witness stage(1) z2_next(i) query hint(1);

Expand Down
9 changes: 8 additions & 1 deletion test_data/std/permutation_via_challenges.asm
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
use std::prover::Query;
use std::convert::fe;
use std::protocols::permutation::permutation;
use std::math::fp2::from_base;
use std::prover::challenge;

machine Main with degree: 8 {

let alpha = from_base(challenge(0, 1));
let beta = from_base(challenge(0, 2));

col fixed first_four = [1, 1, 1, 1, 0, 0, 0, 0];

// Two pairs of witness columns, claimed to be permutations of one another
Expand All @@ -20,6 +26,7 @@ machine Main with degree: 8 {
// TODO: Functions currently cannot add witness columns at later stages,
// so we have to manually create it here and pass it to permutation().
col witness stage(1) z;
permutation([z], permutation_constraint);
let is_first: col = std::well_known::is_first;
permutation(is_first, [z], alpha, beta, permutation_constraint);

}
15 changes: 13 additions & 2 deletions test_data/std/permutation_via_challenges_ext.asm
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,17 @@ use std::convert::fe;
use std::protocols::permutation::permutation;
use std::protocols::permutation::compute_next_z;
use std::math::fp2::Fp2;
use std::prover::challenge;

machine Main with degree: 8 {

let alpha1: expr = challenge(0, 1);
let alpha2: expr = challenge(0, 2);
let beta1: expr = challenge(0, 3);
let beta2: expr = challenge(0, 4);
let alpha = Fp2::Fp2(alpha1, alpha2);
let beta = Fp2::Fp2(beta1, beta2);

col fixed first_four = [1, 1, 1, 1, 0, 0, 0, 0];

// Two pairs of witness columns, claimed to be permutations of one another
Expand All @@ -23,10 +32,12 @@ machine Main with degree: 8 {
// so we have to manually create it here and pass it to permutation().
col witness stage(1) z1;
col witness stage(1) z2;
permutation([z1, z2], permutation_constraint);
let z = Fp2::Fp2(z1, z2);
let is_first: col = std::well_known::is_first;
permutation(is_first, [z1, z2], alpha, beta, permutation_constraint);

// TODO: Helper columns, because we can't access the previous row in hints
let hint = query |i| Query::Hint(compute_next_z(Fp2::Fp2(z1, z2), permutation_constraint)[i]);
let hint = query |i| Query::Hint(compute_next_z(z, alpha, beta, permutation_constraint)[i]);
col witness stage(1) z1_next(i) query hint(0);
col witness stage(1) z2_next(i) query hint(1);

Expand Down

0 comments on commit f0af0c1

Please sign in to comment.