Skip to content

Commit

Permalink
general cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
ledwards2225 committed Mar 28, 2023
1 parent d8b04bf commit c6ced55
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 109 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
#include "barretenberg/honk/sumcheck/relations/grand_product_computation_relation.hpp"
#include "barretenberg/honk/sumcheck/relations/grand_product_initialization_relation.hpp"
#include "barretenberg/honk/utils/public_inputs.hpp"
// #include "barretenberg/honk/proof_system/prover_library.hpp"

#include <gtest/gtest.h>

Expand Down
1 change: 0 additions & 1 deletion cpp/src/barretenberg/honk/proof_system/prover.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ template <typename settings> class Prover {

std::vector<barretenberg::polynomial> wire_polynomials;
barretenberg::polynomial z_permutation;
barretenberg::polynomial z_lookup;

std::shared_ptr<bonk::proving_key> key;

Expand Down
154 changes: 94 additions & 60 deletions cpp/src/barretenberg/honk/proof_system/prover_library.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "prover_library.hpp"
#include "barretenberg/plonk/proof_system/types/prover_settings.hpp"
#include <span>

namespace honk::prover_library {
Expand Down Expand Up @@ -114,10 +115,75 @@ Polynomial compute_permutation_grand_product(std::shared_ptr<bonk::proving_key>&
return z_perm;
}

template <size_t program_width>
/**
* @brief Compute the lookup grand product polynomial Z_lookup(X).
*
* @details The lookup grand product polynomial Z_lookup is of the form
*
* ∏(1 + β) ⋅ ∏(q_lookup*f_k + γ) ⋅ ∏(t_k + βt_{k+1} + γ(1 + β))
* Z_lookup(X_j) = -----------------------------------------------------------------
* ∏(s_k + βs_{k+1} + γ(1 + β))
*
* where ∏ := ∏_{k<j}. This polynomial is constructed in evaluation form over the course
* of three steps:
*
* Step 1) Compute polynomials f, t and s and incorporate them into terms that are ultimately needed
* to construct the grand product polynomial Z_lookup(X):
* Note 1: In what follows, 't' is associated with table values (and is not to be confused with the
* quotient polynomial, also refered to as 't' elsewhere). Polynomial 's' is the sorted concatenation
* of the witnesses and the table values.
* Note 2: Evaluation at Xω is indicated explicitly, e.g. 'p(Xω)'; evaluation at X is simply omitted, e.g. 'p'
*
* 1a. Compute f, then set accumulators[0] = (q_lookup*f + γ), where
*
* f = (w_1 + q_2*w_1(Xω)) + η(w_2 + q_m*w_2(Xω)) + η²(w_3 + q_c*w_3(Xω)) + η³q_index.
* Note that q_2, q_m, and q_c are just the selectors from Standard Plonk that have been repurposed
* in the context of the plookup gate to represent 'shift' values. For example, setting each of the
* q_* in f to 2^8 facilitates operations on 32-bit values via four operations on 8-bit values. See
* Ultra documentation for details.
*
* 1b. Compute t, then set accumulators[1] = (t + βt(Xω) + γ(1 + β)), where t = t_1 + ηt_2 + η²t_3 + η³t_4
*
* 1c. Set accumulators[2] = (1 + β)
*
* 1d. Compute s, then set accumulators[3] = (s + βs(Xω) + γ(1 + β)), where s = s_1 + ηs_2 + η²s_3 + η³s_4
*
* Step 2) Compute the constituent product components of Z_lookup(X).
* Let ∏ := Prod_{k<j}. Let f_k, t_k and s_k now represent the k'th component of the polynomials f,t and s
* defined above. We compute the following four product polynomials needed to construct the grand product
* Z_lookup(X).
* 1. accumulators[0][j] = ∏ (q_lookup*f_k + γ)
* 2. accumulators[1][j] = ∏ (t_k + βt_{k+1} + γ(1 + β))
* 3. accumulators[2][j] = ∏ (1 + β)
* 4. accumulators[3][j] = ∏ (s_k + βs_{k+1} + γ(1 + β))
*
* Step 3) Combine the accumulator product elements to construct Z_lookup(X).
*
* ∏ (1 + β) ⋅ ∏ (q_lookup*f_k + γ) ⋅ ∏ (t_k + βt_{k+1} + γ(1 + β))
* Z_lookup(g^j) = --------------------------------------------------------------------------
* ∏ (s_k + βs_{k+1} + γ(1 + β))
*
* Note: Montgomery batch inversion is used to efficiently compute the coefficients of Z_lookup
* rather than peforming n individual inversions. I.e. we first compute the double product P_n:
*
* P_n := ∏_{j<n} ∏_{k<j} S_k, where S_k = (s_k + βs_{k+1} + γ(1 + β))
*
* and then compute the inverse on P_n. Then we work back to front to obtain terms of the form
* 1/∏_{k<i} S_i that appear in Z_lookup, using the fact that P_i/P_{i+1} = 1/∏_{k<i} S_i. (Note
* that once we have 1/P_n, we can compute 1/P_{n-1} as (1/P_n) * ∏_{k<n} S_i, and
* so on).
*
* @param key proving key
* @param wire_polynomials
* @param sorted_list_accumulator
* @param eta
* @param beta
* @param gamma
* @return Polynomial
*/
Polynomial compute_lookup_grand_product(std::shared_ptr<bonk::proving_key>& key,
std::vector<Polynomial>& wire_polynomials,
Polynomial& s_lagrange,
Polynomial& sorted_list_accumulator,
Fr eta,
Fr beta,
Fr gamma)
Expand All @@ -128,14 +194,15 @@ Polynomial compute_lookup_grand_product(std::shared_ptr<bonk::proving_key>& key,
const size_t circuit_size = key->circuit_size;

// Allocate 4 length n 'accumulator' polynomials. accumulators[0] will be used to construct
// z_lookup (lagrange base) in place.
// z_lookup in place.
// Note: The magic number 4 here comes from the structure of the grand product and is not related to the program
// width.
std::array<Polynomial, 4> accumulators;
for (size_t i = 0; i < 4; ++i) {
accumulators[i] = Polynomial{ key->circuit_size };
}

// Obtain column step size values that have been stored in repurposed selctors
std::span<const Fr> column_1_step_size = key->polynomial_store.get("q_2_lagrange");
std::span<const Fr> column_2_step_size = key->polynomial_store.get("q_m_lagrange");
std::span<const Fr> column_3_step_size = key->polynomial_store.get("q_c_lagrange");
Expand All @@ -146,6 +213,7 @@ Polynomial compute_lookup_grand_product(std::shared_ptr<bonk::proving_key>& key,
wires[i] = wire_polynomials[i];
}

// Note: the number of table polys is related to program width but '4' is the only value supported
std::array<std::span<const Fr>, 4> tables{
key->polynomial_store.get("table_value_1_lagrange"),
key->polynomial_store.get("table_value_2_lagrange"),
Expand All @@ -159,31 +227,11 @@ Polynomial compute_lookup_grand_product(std::shared_ptr<bonk::proving_key>& key,
const Fr beta_constant = beta + Fr(1); // (1 + β)
const Fr gamma_beta_constant = gamma * beta_constant; // γ(1 + β)

// Step 1: Compute polynomials f, t and s and incorporate them into terms that are ultimately needed
// to construct the grand product polynomial Z_lookup(X):
// Note 1: In what follows, 't' is associated with table values (and is not to be confused with the
// quotient polynomial, also refered to as 't' elsewhere). Polynomial 's' is the sorted concatenation
// of the witnesses and the table values.
// Note 2: Evaluation at Xω is indicated explicitly, e.g. 'p(Xω)'; evaluation at X is simply omitted, e.g. 'p'
//
// 1a. Compute f, then set accumulators[0] = (q_lookup*f + γ), where
//
// f = (w_1 + q_2*w_1(Xω)) + η(w_2 + q_m*w_2(Xω)) + η²(w_3 + q_c*w_3(Xω)) + η³q_index.
// Note that q_2, q_m, and q_c are just the selectors from Standard Plonk that have been repurposed
// in the context of the plookup gate to represent 'shift' values. For example, setting each of the
// q_* in f to 2^8 facilitates operations on 32-bit values via four operations on 8-bit values. See
// Ultra documentation for details.
//
// 1b. Compute t, then set accumulators[1] = (t + βt(Xω) + γ(1 + β)), where t = t_1 + ηt_2 + η²t_3 + η³t_4
//
// 1c. Set accumulators[2] = (1 + β)
//
// 1d. Compute s, then set accumulators[3] = (s + βs(Xω) + γ(1 + β)), where s = s_1 + ηs_2 + η²s_3 + η³s_4
//

Fr T0;
// Step (1)

Fr T0; // intermediate value for various calculations below
// Note: block_mask is used for efficient modulus, i.e. i % N := i & (N-1), for N = 2^k
const size_t block_mask = key->small_domain.size - 1;
const size_t block_mask = circuit_size - 1;
// Initialize 't(X)' to be used in an expression of the form t(X) + β*t(Xω)
Fr next_table = tables[0][0] + tables[1][0] * eta + tables[2][0] * eta_sqr + tables[3][0] * eta_cube;

Expand Down Expand Up @@ -224,46 +272,22 @@ Polynomial compute_lookup_grand_product(std::shared_ptr<bonk::proving_key>& key,
accumulators[2][i] = beta_constant;

// Set i'th element of polynomial (s + βs(Xω) + γ(1 + β))
accumulators[3][i] = s_lagrange[(i + 1) & block_mask];
accumulators[3][i] = sorted_list_accumulator[(i + 1) & block_mask];
accumulators[3][i] *= beta;
accumulators[3][i] += s_lagrange[i];
accumulators[3][i] += sorted_list_accumulator[i];
accumulators[3][i] += gamma_beta_constant;
}

// Step 2: Compute the constituent product components of Z_lookup(X).
// Let ∏ := Prod_{k<j}. Let f_k, t_k and s_k now represent the k'th component of the polynomials f,t and s
// defined above. We compute the following four product polynomials needed to construct the grand product
// Z_lookup(X).
// 1. accumulators[0][j] = ∏ (q_lookup*f_k + γ)
// 2. accumulators[1][j] = ∏ (t_k + βt_{k+1} + γ(1 + β))
// 3. accumulators[2][j] = ∏ (1 + β)
// 4. accumulators[3][j] = ∏ (s_k + βs_{k+1} + γ(1 + β))
// Step (2)

// Note: This is a small multithreading bottleneck, as we have only 4 parallelizable processes.
for (auto& accum : accumulators) {
for (size_t i = 0; i < circuit_size - 1; ++i) {
accum[i + 1] *= accum[i];
}
}

// Step 3: Combine the accumulator product elements to construct Z_lookup(X).
//
// ∏ (1 + β) ⋅ ∏ (q_lookup*f_k + γ) ⋅ ∏ (t_k + βt_{k+1} + γ(1 + β))
// Z_lookup(g^j) = --------------------------------------------------------------------------
// ∏ (s_k + βs_{k+1} + γ(1 + β))
//
// Note: Montgomery batch inversion is used to efficiently compute the coefficients of Z_lookup
// rather than peforming n individual inversions. I.e. we first compute the double product P_n:
//
// P_n := ∏_{j<n} ∏_{k<j} S_k, where S_k = (s_k + βs_{k+1} + γ(1 + β))
//
// and then compute the inverse on P_n. Then we work back to front to obtain terms of the form
// 1/∏_{k<i} S_i that appear in Z_lookup, using the fact that P_i/P_{i+1} = 1/∏_{k<i} S_i. (Note
// that once we have 1/P_n, we can compute 1/P_{n-1} as (1/P_n) * ∏_{k<n} S_i, and
// so on).

// Compute Z_lookup using Montgomery batch inversion
// Note: This loop sets the values of z_lookup[i] for i = 1,...,(n-1), (Recall accumulators[0][i] = z_lookup[i +
// 1])
// Step (3)

// Compute <Z_lookup numerator> * ∏_{j<i}∏_{k<j}S_k
Fr inversion_accumulator = Fr::one();
Expand All @@ -279,7 +303,6 @@ Polynomial compute_lookup_grand_product(std::shared_ptr<bonk::proving_key>& key,
// ∏_{k<i}S_k
for (size_t i = circuit_size - 2; i != std::numeric_limits<size_t>::max(); --i) {
// N.B. accumulators[0][i] = z_lookup[i + 1]
// We can avoid fully reducing z_lookup[i + 1] as the inverse fft will take care of that for us
accumulators[0][i] *= inversion_accumulator;
inversion_accumulator *= accumulators[3][i];
}
Expand All @@ -293,6 +316,17 @@ Polynomial compute_lookup_grand_product(std::shared_ptr<bonk::proving_key>& key,
return z_lookup;
}

/**
* @brief Construct sorted list accumulator polynomial 's'.
*
* @details Compute s = s_1 + η*s_2 + η²*s_3 + η³*s_4 (via Horner) where s_i are the
* sorted concatenated witness/table polynomials
*
* @param key proving key
* @param sorted_list_polynomials sorted concatenated witness/table polynomials
* @param eta random challenge
* @return Polynomial
*/
Polynomial compute_sorted_list_accumulator(std::shared_ptr<bonk::proving_key>& key,
std::vector<Polynomial>& sorted_list_polynomials,
Fr eta)
Expand All @@ -304,7 +338,7 @@ Polynomial compute_sorted_list_accumulator(std::shared_ptr<bonk::proving_key>& k
std::span<const Fr> s_3 = sorted_list_polynomials[2];
std::span<const Fr> s_4 = sorted_list_polynomials[3];

// Construct s = s_1 + η*s_2 + η²*s_3 + η³*s_4 via Horner, i.e. s = s_1 + η(s_2 + η(s_3 + η*s_4))
// Construct s via Horner, i.e. s = s_1 + η(s_2 + η(s_3 + η*s_4))
for (size_t i = 0; i < circuit_size; ++i) {
Fr T0 = s_4[i];
T0 *= eta;
Expand All @@ -320,7 +354,7 @@ Polynomial compute_sorted_list_accumulator(std::shared_ptr<bonk::proving_key>& k

template Polynomial compute_permutation_grand_product<plonk::standard_settings::program_width>(
std::shared_ptr<bonk::proving_key>&, std::vector<Polynomial>&, Fr, Fr);
template Polynomial compute_lookup_grand_product<plonk::standard_settings::program_width>(
std::shared_ptr<bonk::proving_key>&, std::vector<Polynomial>&, Polynomial&, Fr, Fr, Fr);
template Polynomial compute_permutation_grand_product<plonk::ultra_settings::program_width>(
std::shared_ptr<bonk::proving_key>&, std::vector<Polynomial>&, Fr, Fr);

} // namespace honk::prover_library
3 changes: 1 addition & 2 deletions cpp/src/barretenberg/honk/proof_system/prover_library.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,9 @@ Polynomial compute_permutation_grand_product(std::shared_ptr<bonk::proving_key>&
Fr beta,
Fr gamma);

template <size_t program_width>
Polynomial compute_lookup_grand_product(std::shared_ptr<bonk::proving_key>& key,
std::vector<Polynomial>& wire_polynomials,
Polynomial& s_lagrange,
Polynomial& sorted_list_accumulator,
Fr eta,
Fr beta,
Fr gamma);
Expand Down
Loading

0 comments on commit c6ced55

Please # to comment.