Skip to content

Commit

Permalink
Adding ID and edge Lagrange polynomials to the proving key (#45)
Browse files Browse the repository at this point in the history
Added id and last and first lagrange polynomial to the proving key in honk
  • Loading branch information
Rumata888 authored and dbanks12 committed Jan 28, 2023
1 parent 872cce8 commit ecbc1b9
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -226,8 +226,11 @@ std::shared_ptr<waffle::proving_key> ComposerHelper<CircuitConstructor>::compute
ComposerHelper::compute_proving_key_base(circuit_constructor, waffle::ComposerType::STANDARD);

// Compute sigma polynomials (we should update that late)
// TODO: Update this
compute_standard_honk_sigma_permutations<3>(circuit_constructor, circuit_proving_key.get());
compute_standard_honk_sigma_permutations<CircuitConstructor::program_width>(circuit_constructor,
circuit_proving_key.get());
compute_standard_honk_id_polynomials<CircuitConstructor::program_width>(circuit_proving_key.get());

compute_first_and_last_lagrange_polynomials(circuit_proving_key.get());

return circuit_proving_key;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ void compute_wire_copy_cycles(CircuitConstructor& circuit_constructor, CycleColl
}

/**
* @brief Compute sigma permutations for standard honk.
* @brief Compute sigma permutations for standard honk and put them into polynomial cache
*
* @details These permutations don't involve sets. We only care about equating one witness value to another. The
* sequences don't use cosets unlike FFT-based Plonk, because there is no need for them. We simply use indices based on
Expand Down Expand Up @@ -175,4 +175,50 @@ void compute_standard_honk_sigma_permutations(CircuitConstructor& circuit_constr
}
}

/**
* @brief Compute standard honk id polynomials and put them into cache
*
* @details Honk permutations involve using id and sigma polynomials to generate variable cycles. This function
* generates the id polynomials and puts them into polynomial cache, so that they can be used by the prover.
*
* @tparam program_width The number of witness polynomials
* @param key Proving key where we will save the polynomials
*/
template <size_t program_width> void compute_standard_honk_id_polynomials(proving_key* key)
{
const size_t n = key->n;
// Fill id polynomials with default values
std::vector<barretenberg::polynomial> id_polynomials_lagrange;
for (uint64_t i = 0; i < program_width; ++i) {
// Construct permutation polynomials in lagrange base
std::string index = std::to_string(i + 1);
id_polynomials_lagrange.push_back(barretenberg::polynomial(key->n));
barretenberg::polynomial& id_polynomial_lagrange = id_polynomials_lagrange[i];
for (uint64_t j = 0; j < key->n; j++) {
id_polynomial_lagrange[j] = (i * n + j);
}
}
// Save to polynomial cache
for (size_t i = 0; i < program_width; i++) {
std::string index = std::to_string(i + 1);
key->polynomial_cache.put("id_" + index + "_lagrange", std::move(id_polynomials_lagrange[i]));
}
}

/**
* @brief Compute Lagrange Polynomials L_0 and L_{n-1} and put them in the polynomial cache
*
* @param key Proving key where we will save the polynomials
*/
inline void compute_first_and_last_lagrange_polynomials(proving_key* key)
{
const size_t n = key->n;
barretenberg::polynomial lagrange_polynomial_0(n, n);
barretenberg::polynomial lagrange_polynomial_n_min_1(n, n);
lagrange_polynomial_0[0] = 1;
lagrange_polynomial_n_min_1[n - 1] = 1;
key->polynomial_cache.put("L_first_lagrange", std::move(lagrange_polynomial_0));
key->polynomial_cache.put("L_last_lagrange", std::move(lagrange_polynomial_n_min_1));
}

} // namespace waffle
49 changes: 47 additions & 2 deletions cpp/src/aztec/honk/composer/standard_honk_composer.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ namespace test_standard_honk_composer {
* 2) That if the permutation argument is computed with witness values, the values from the identity permutation and
* sigma permutation are equal
*/
TEST(standard_honk_composer, test_sigma_correctness)
TEST(standard_honk_composer, test_sigma_and_id_correctness)
{
StandardHonkComposer composer = StandardHonkComposer();
fr a = fr::one();
Expand Down Expand Up @@ -90,17 +90,62 @@ TEST(standard_honk_composer, test_sigma_correctness)
std::string index = std::to_string(i + 1);
auto permutation_polynomial = proving_key->polynomial_cache.get("sigma_" + index + "_lagrange");
auto witness_polynomial = proving_key->polynomial_cache.get("w_" + index + "_lagrange");
auto id_polynomial = proving_key->polynomial_cache.get("id_" + index + "_lagrange");
// left = ∏ᵢ,ⱼ(ωᵢ,ⱼ + β⋅ind(i,j) + γ)
// right = ∏ᵢ,ⱼ(ωᵢ,ⱼ + β⋅σ(i,j) + γ)
for (size_t j = 0; j < proving_key->n; j++) {
auto current_witness = witness_polynomial[j];
left *= current_witness + beta * (i * (proving_key->n) + j) + gamma;
left *= current_witness + beta * id_polynomial[j] + gamma;
right *= current_witness + beta * permutation_polynomial[j] + gamma;
}
}
EXPECT_EQ(left, right);
}

/**
* @brief Check the correctness of lagrange polynomials generated during proving key computation
*
*/
TEST(standard_honk_composer, test_lagrange_polynomial_correctness)
{
// Create a composer and a dummy circuit with a few gates
waffle::StandardHonkComposer composer = waffle::StandardHonkComposer();
fr a = fr::one();
uint32_t a_idx = composer.add_variable(a);
fr b = fr::one();
fr c = a + b;
fr d = a + c;
uint32_t b_idx = composer.add_variable(b);
uint32_t c_idx = composer.add_variable(c);
uint32_t d_idx = composer.add_variable(d);
for (size_t i = 0; i < 16; i++) {
composer.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() });
composer.create_add_gate({ d_idx, c_idx, a_idx, fr::one(), fr::neg_one(), fr::neg_one(), fr::zero() });
}
// Generate proving key
auto proving_key = composer.compute_proving_key();
// Generate a random polynomial
barretenberg::polynomial random_polynomial = barretenberg::polynomial(proving_key->n, proving_key->n);
for (size_t i = 0; i < proving_key->n; i++) {
random_polynomial[i] = barretenberg::fr::random_element();
}
// Compute inner product of random polynomial and the first lagrange polynomial
barretenberg::polynomial first_lagrange_polynomial = proving_key->polynomial_cache.get("L_first_lagrange");
barretenberg::fr first_product(0);
for (size_t i = 0; i < proving_key->n; i++) {
first_product += random_polynomial[i] * first_lagrange_polynomial[i];
}
EXPECT_EQ(first_product, random_polynomial[0]);

// Compute inner product of random polynomial and the last lagrange polynomial
barretenberg::polynomial last_lagrange_polynomial = proving_key->polynomial_cache.get("L_last_lagrange");
barretenberg::fr last_product(0);
for (size_t i = 0; i < proving_key->n; i++) {
last_product += random_polynomial[i] * last_lagrange_polynomial[i];
}
EXPECT_EQ(last_product, random_polynomial[proving_key->n - 1]);
}

/**
* @brief Test that the assert_equal method in composer is working as intended
*
Expand Down

0 comments on commit ecbc1b9

Please sign in to comment.