Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Release the size of goblin translator #4259

Merged
merged 5 commits into from
Jan 30, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,10 @@ template <typename Flavor, typename StorageHandle> void compute_concatenated_pol
// Resulting concatenated polynomials
auto targets = proving_key->get_concatenated_constraints();

// Targets have to be full-sized polynomials. We can compute the mini circuit size from them by dividing by
// concatenation index
const size_t MINI_CIRCUIT_SIZE = targets[0].size() / Flavor::CONCATENATION_INDEX;
ASSERT(MINI_CIRCUIT_SIZE * Flavor::CONCATENATION_INDEX == targets[0].size());
// A function that produces 1 concatenated polynomial
// TODO(#756): This can be rewritten to use more cores. Currently uses at maximum the number of concatenated
// polynomials (4 in Goblin Translator)
Expand All @@ -201,8 +205,8 @@ template <typename Flavor, typename StorageHandle> void compute_concatenated_pol
for (size_t j = 0; j < my_group.size(); j++) {
auto starting_write_offset = current_target.begin();
auto finishing_read_offset = my_group[j].begin();
std::advance(starting_write_offset, j * Flavor::MINI_CIRCUIT_SIZE);
std::advance(finishing_read_offset, Flavor::MINI_CIRCUIT_SIZE);
std::advance(starting_write_offset, j * MINI_CIRCUIT_SIZE);
std::advance(finishing_read_offset, MINI_CIRCUIT_SIZE);
// Copy into appropriate position in the concatenated polynomial
std::copy(my_group[j].begin(), finishing_read_offset, starting_write_offset);
}
Expand Down Expand Up @@ -233,16 +237,17 @@ template <typename Flavor, typename StorageHandle> void compute_concatenated_pol
* @param proving_key
*/
template <typename Flavor, typename StorageHandle>
void compute_goblin_translator_range_constraint_ordered_polynomials(StorageHandle* proving_key)
void compute_goblin_translator_range_constraint_ordered_polynomials(StorageHandle* proving_key,
size_t mini_circuit_dyadic_size)
{

using FF = typename Flavor::FF;

// Get constants
constexpr auto sort_step = Flavor::SORT_STEP;
constexpr auto num_concatenated_wires = Flavor::NUM_CONCATENATED_WIRES;
constexpr auto full_circuit_size = Flavor::FULL_CIRCUIT_SIZE;
constexpr auto mini_circuit_size = Flavor::MINI_CIRCUIT_SIZE;
const auto mini_circuit_size = mini_circuit_dyadic_size;
const auto full_circuit_size = mini_circuit_dyadic_size * Flavor::CONCATENATION_INDEX;

// The value we have to end polynomials with
constexpr uint32_t max_value = (1 << Flavor::MICRO_LIMB_BITS) - 1;
Expand All @@ -251,7 +256,7 @@ void compute_goblin_translator_range_constraint_ordered_polynomials(StorageHandl
constexpr size_t sorted_elements_count = (max_value / sort_step) + 1 + (max_value % sort_step == 0 ? 0 : 1);

// Check if we can construct these polynomials
static_assert((num_concatenated_wires + 1) * sorted_elements_count < full_circuit_size);
ASSERT((num_concatenated_wires + 1) * sorted_elements_count < full_circuit_size);

// First use integers (easier to sort)
std::vector<size_t> sorted_elements(sorted_elements_count);
Expand All @@ -278,7 +283,7 @@ void compute_goblin_translator_range_constraint_ordered_polynomials(StorageHandl
// Get the group and the main target vector
auto my_group = concatenation_groups[i];
auto& current_vector = ordered_vectors_uint[i];
current_vector.resize(Flavor::FULL_CIRCUIT_SIZE);
current_vector.resize(full_circuit_size);

// Calculate how much space there is for values from the original polynomials
auto free_space_before_runway = full_circuit_size - sorted_elements_count;
Expand Down Expand Up @@ -362,12 +367,14 @@ void compute_goblin_translator_range_constraint_ordered_polynomials(StorageHandl
* contains 5 MAX_VALUE, 5 (MAX_VALUE-STEP),... values
*
* @param key Proving key where we will save the polynomials
* @param dyadic_circuit_size The full size of the circuit
*/
template <typename Flavor> inline void compute_extra_range_constraint_numerator(auto proving_key)
template <typename Flavor>
inline void compute_extra_range_constraint_numerator(auto proving_key, size_t dyadic_circuit_size)
{

// Get the full goblin circuits size (this is the length of concatenated range constraint polynomials)
auto full_circuit_size = Flavor::FULL_CIRCUIT_SIZE;
auto full_circuit_size = dyadic_circuit_size;
auto sort_step = Flavor::SORT_STEP;
auto num_concatenated_wires = Flavor::NUM_CONCATENATED_WIRES;

Expand Down Expand Up @@ -403,8 +410,10 @@ template <typename Flavor> inline void compute_extra_range_constraint_numerator(
* @brief Compute odd and even largrange polynomials (up to mini_circuit length) and put them in the polynomial cache
*
* @param key Proving key where we will save the polynomials
* @param mini_circuit_dyadic_size The size of the part of the circuit where the computation of translated value happens
*/
template <typename Flavor> inline void compute_lagrange_polynomials_for_goblin_translator(auto proving_key)
template <typename Flavor>
inline void compute_lagrange_polynomials_for_goblin_translator(auto proving_key, size_t mini_circuit_dyadic_size)

{
const size_t n = proving_key->circuit_size;
Expand All @@ -413,15 +422,15 @@ template <typename Flavor> inline void compute_lagrange_polynomials_for_goblin_t
typename Flavor::Polynomial lagrange_polynomial_second(n);
typename Flavor::Polynomial lagrange_polynomial_second_to_last_in_minicircuit(n);

for (size_t i = 1; i < Flavor::MINI_CIRCUIT_SIZE - 1; i += 2) {
for (size_t i = 1; i < mini_circuit_dyadic_size - 1; i += 2) {
lagrange_polynomial_odd_in_minicircuit[i] = 1;
lagrange_polynomial_even_in_minicircut[i + 1] = 1;
}
proving_key->lagrange_odd_in_minicircuit = lagrange_polynomial_odd_in_minicircuit.share();

proving_key->lagrange_even_in_minicircuit = lagrange_polynomial_even_in_minicircut.share();
lagrange_polynomial_second[1] = 1;
lagrange_polynomial_second_to_last_in_minicircuit[Flavor::MINI_CIRCUIT_SIZE - 2] = 1;
lagrange_polynomial_second_to_last_in_minicircuit[mini_circuit_dyadic_size - 2] = 1;
proving_key->lagrange_second_to_last_in_minicircuit = lagrange_polynomial_second_to_last_in_minicircuit.share();
proving_key->lagrange_second = lagrange_polynomial_second.share();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ class GoblinTranslatorCircuitBuilder : public CircuitBuilderBase<bb::fr> {

};

// Basic goblin translator has the minicircuit size of 2048, so optimize for that case
// Basic goblin translator has the minimum minicircuit size of 16384, so optimize for that case
// For context, minicircuit is the part of the final polynomials fed into the proving system, where we have all the
// arithmetic logic. However, the full circuit is several times larger (we use a trick to bring down the degree of
// the permutation argument)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,7 @@ using Transcript = typename Flavor::Transcript;

void GoblinTranslatorComposer::compute_circuit_size_parameters(CircuitBuilder& circuit_builder)
{
const size_t num_gates = circuit_builder.num_gates;

// number of populated rows in the execution trace
size_t num_rows_populated_in_execution_trace = num_gates;

// Goblin translator circuits always have a predefined size and are structured as a VM (no concept of selectors)
ASSERT(MINI_CIRCUIT_SIZE >= num_rows_populated_in_execution_trace);

total_num_gates = std::max(MINI_CIRCUIT_SIZE, num_rows_populated_in_execution_trace);
total_num_gates = std::max(circuit_builder.num_gates, MINIMUM_MINI_CIRCUIT_SIZE);

// Next power of 2
mini_circuit_dyadic_size = circuit_builder.get_circuit_subgroup_size(total_num_gates);
Expand Down Expand Up @@ -189,7 +181,7 @@ void GoblinTranslatorComposer::compute_witness(CircuitBuilder& circuit_builder)
// We also contruct ordered polynomials, which have the same values as concatenated ones + enough values to bridge
// the range from 0 to maximum range defined by the range constraint.
bb::honk::permutation_library::compute_goblin_translator_range_constraint_ordered_polynomials<Flavor>(
proving_key.get());
proving_key.get(), mini_circuit_dyadic_size);

computed_witness = true;
}
Expand Down Expand Up @@ -273,11 +265,13 @@ std::shared_ptr<typename Flavor::ProvingKey> GoblinTranslatorComposer::compute_p

// Compute polynomials with odd and even indices set to 1 up to the minicircuit margin + lagrange polynomials at
// second and second to last indices in the minicircuit
bb::honk::permutation_library::compute_lagrange_polynomials_for_goblin_translator<Flavor>(proving_key.get());
bb::honk::permutation_library::compute_lagrange_polynomials_for_goblin_translator<Flavor>(proving_key.get(),
mini_circuit_dyadic_size);

// Compute the numerator for the permutation argument with several repetitions of steps bridging 0 and maximum range
// constraint
bb::honk::permutation_library::compute_extra_range_constraint_numerator<Flavor>(proving_key.get());
bb::honk::permutation_library::compute_extra_range_constraint_numerator<Flavor>(proving_key.get(),
dyadic_circuit_size);

return proving_key;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,11 @@ class GoblinTranslatorComposer {
using VerifierCommitmentKey = typename Flavor::VerifierCommitmentKey;
using Polynomial = typename Flavor::Polynomial;
using Transcript = BaseTranscript;
static constexpr size_t MINI_CIRCUIT_SIZE = Flavor::MINI_CIRCUIT_SIZE;

static constexpr std::string_view NAME_STRING = "GoblinTranslator";
static constexpr size_t NUM_WIRES = CircuitBuilder::NUM_WIRES;
// The minimum size of the mini-circuit (or sorted constraints won't work)
static constexpr size_t MINIMUM_MINI_CIRCUIT_SIZE = 2048;
std::shared_ptr<ProvingKey> proving_key;
std::shared_ptr<VerificationKey> verification_key;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,6 @@ class GoblinTranslatorProver {
using Curve = typename Flavor::Curve;
using Transcript = typename Flavor::Transcript;

static size_t constexpr MINI_CIRCUIT_SIZE = Flavor::MINI_CIRCUIT_SIZE;
static size_t constexpr FULL_CIRCUIT_SIZE = Flavor::FULL_CIRCUIT_SIZE;

public:
explicit GoblinTranslatorProver(const std::shared_ptr<ProvingKey>& input_key,
const std::shared_ptr<CommitmentKey>& commitment_key,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,8 @@ TEST_F(RelationCorrectnessTests, GoblinTranslatorPermutationRelationCorrectness)
using Polynomial = bb::Polynomial<FF>;
using namespace bb::honk::permutation_library;
auto& engine = numeric::get_debug_randomness();
auto circuit_size = Flavor::MINI_CIRCUIT_SIZE * Flavor::CONCATENATION_INDEX;
const size_t mini_circuit_size = 2048;
auto full_circuit_size = mini_circuit_size * Flavor::CONCATENATION_INDEX;

// We only need gamma, because permutationr elation only uses gamma
FF gamma = FF::random_element();
Expand All @@ -391,16 +392,16 @@ TEST_F(RelationCorrectnessTests, GoblinTranslatorPermutationRelationCorrectness)
// Create storage for polynomials
ProverPolynomials prover_polynomials;
for (Polynomial& prover_poly : prover_polynomials.get_all()) {
prover_poly = Polynomial{ circuit_size };
prover_poly = Polynomial{ full_circuit_size };
}

// Fill in lagrange polynomials used in the permutation relation
prover_polynomials.lagrange_first[0] = 1;
prover_polynomials.lagrange_last[circuit_size - 1] = 1;
prover_polynomials.lagrange_last[full_circuit_size - 1] = 1;

// Put random values in all the non-concatenated constraint polynomials used to range constrain the values
auto fill_polynomial_with_random_14_bit_values = [&](auto& polynomial) {
for (size_t i = 0; i < Flavor::MINI_CIRCUIT_SIZE; i++) {
for (size_t i = 0; i < mini_circuit_size; i++) {
polynomial[i] = engine.get_random_uint16() & ((1 << Flavor::MICRO_LIMB_BITS) - 1);
}
};
Expand Down Expand Up @@ -470,23 +471,23 @@ TEST_F(RelationCorrectnessTests, GoblinTranslatorPermutationRelationCorrectness)
fill_polynomial_with_random_14_bit_values(prover_polynomials.relation_wide_limbs_range_constraint_3);

// Compute ordered range constraint polynomials that go in the denominator of the grand product polynomial
compute_goblin_translator_range_constraint_ordered_polynomials<Flavor>(&prover_polynomials);
compute_goblin_translator_range_constraint_ordered_polynomials<Flavor>(&prover_polynomials, mini_circuit_size);

// Compute the fixed numerator (part of verification key)
compute_extra_range_constraint_numerator<Flavor>(&prover_polynomials);
compute_extra_range_constraint_numerator<Flavor>(&prover_polynomials, full_circuit_size);

// Compute concatenated polynomials (4 polynomials produced from other constraint polynomials by concatenation)
compute_concatenated_polynomials<Flavor>(&prover_polynomials);

// Compute the grand product polynomial
grand_product_library::compute_grand_product<Flavor, bb::GoblinTranslatorPermutationRelation<FF>>(
circuit_size, prover_polynomials, params);
full_circuit_size, prover_polynomials, params);
prover_polynomials.z_perm_shift = prover_polynomials.z_perm.shifted();

using Relations = typename Flavor::Relations;

// Check that permutation relation is satisfied across each row of the prover polynomials
check_relation<Flavor, std::tuple_element_t<0, Relations>>(circuit_size, prover_polynomials, params);
check_relation<Flavor, std::tuple_element_t<0, Relations>>(full_circuit_size, prover_polynomials, params);
}

TEST_F(RelationCorrectnessTests, GoblinTranslatorGenPermSortRelationCorrectness)
Expand All @@ -496,8 +497,8 @@ TEST_F(RelationCorrectnessTests, GoblinTranslatorGenPermSortRelationCorrectness)
using ProverPolynomials = typename Flavor::ProverPolynomials;
using Polynomial = bb::Polynomial<FF>;
auto& engine = numeric::get_debug_randomness();

const auto circuit_size = Flavor::FULL_CIRCUIT_SIZE;
const size_t mini_circuit_size = 2048;
const auto circuit_size = Flavor::CONCATENATION_INDEX * mini_circuit_size;
const auto sort_step = Flavor::SORT_STEP;
const auto max_value = (1 << Flavor::MICRO_LIMB_BITS) - 1;

Expand Down Expand Up @@ -579,8 +580,8 @@ TEST_F(RelationCorrectnessTests, GoblinTranslatorExtraRelationsCorrectness)

auto& engine = numeric::get_debug_randomness();

auto circuit_size = Flavor::FULL_CIRCUIT_SIZE;
auto mini_circuit_size = Flavor::MINI_CIRCUIT_SIZE;
const size_t mini_circuit_size = 2048;
const auto circuit_size = Flavor::CONCATENATION_INDEX * mini_circuit_size;

// We only use accumulated_result from relation parameters in this relation
RelationParameters<FF> params;
Expand Down Expand Up @@ -681,7 +682,8 @@ TEST_F(RelationCorrectnessTests, GoblinTranslatorDecompositionRelationCorrectnes
using Polynomial = bb::Polynomial<FF>;
auto& engine = numeric::get_debug_randomness();

auto circuit_size = Flavor::FULL_CIRCUIT_SIZE;
constexpr size_t mini_circuit_size = 2048;
const auto circuit_size = Flavor::CONCATENATION_INDEX * mini_circuit_size;

// Decomposition relation doesn't use any relation parameters
RelationParameters<FF> params;
Expand Down Expand Up @@ -723,7 +725,7 @@ TEST_F(RelationCorrectnessTests, GoblinTranslatorDecompositionRelationCorrectnes
}

// Fill in lagrange odd polynomial (the only non-witness one we are using)
for (size_t i = 1; i < Flavor::MINI_CIRCUIT_SIZE - 1; i += 2) {
for (size_t i = 1; i < mini_circuit_size - 1; i += 2) {
prover_polynomials.lagrange_odd_in_minicircuit[i] = 1;
}

Expand Down Expand Up @@ -811,7 +813,7 @@ TEST_F(RelationCorrectnessTests, GoblinTranslatorDecompositionRelationCorrectnes
};

// Put random values in all the non-concatenated constraint polynomials used to range constrain the values
for (size_t i = 1; i < Flavor::MINI_CIRCUIT_SIZE - 1; i += 2) {
for (size_t i = 1; i < mini_circuit_size - 1; i += 2) {
// P.x
prover_polynomials.x_lo_y_hi[i] = FF(engine.get_random_uint256() & ((uint256_t(1) << LOW_WIDE_LIMB_WIDTH) - 1));
prover_polynomials.x_hi_z_1[i] = FF(engine.get_random_uint256() & ((uint256_t(1) << HIGH_WIDE_LIMB_WIDTH) - 1));
Expand Down Expand Up @@ -1055,15 +1057,15 @@ TEST_F(RelationCorrectnessTests, GoblinTranslatorNonNativeRelationCorrectness)
using Polynomial = bb::Polynomial<FF>;

constexpr size_t NUM_LIMB_BITS = Flavor::NUM_LIMB_BITS;
constexpr auto circuit_size = Flavor::FULL_CIRCUIT_SIZE;
constexpr auto mini_circuit_size = Flavor::MINI_CIRCUIT_SIZE;
constexpr auto mini_circuit_size = 2048;
constexpr auto circuit_size = Flavor::CONCATENATION_INDEX * mini_circuit_size;

auto& engine = numeric::get_debug_randomness();

auto op_queue = std::make_shared<bb::ECCOpQueue>();

// Generate random EccOpQueue actions
for (size_t i = 0; i < ((Flavor::MINI_CIRCUIT_SIZE >> 1) - 1); i++) {
for (size_t i = 0; i < ((mini_circuit_size >> 1) - 1); i++) {
switch (engine.get_random_uint8() & 3) {
case 0:
op_queue->empty_row();
Expand Down
Loading