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

refactor: No Translator composer #5202

Merged
merged 18 commits into from
Mar 19, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
6 changes: 5 additions & 1 deletion barretenberg/cpp/src/barretenberg/eccvm/eccvm_composer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,11 @@ std::shared_ptr<typename Flavor::ProvingKey> ECCVMComposer_<Flavor>::compute_pro
// Fix once we have a stable base to work off of
// enforce_nonzero_polynomial_selectors(circuit_constructor, proving_key.get());

compute_first_and_last_lagrange_polynomials<Flavor>(proving_key.get());
// First and last lagrange polynomials (in the full circuit size)
const auto [lagrange_first, lagrange_last] =
compute_first_and_last_lagrange_polynomials<FF>(proving_key->circuit_size);
proving_key->lagrange_first = lagrange_first;
proving_key->lagrange_last = lagrange_last;
{
const size_t n = proving_key->circuit_size;
typename Flavor::Polynomial lagrange_polynomial_second(n);
Expand Down
135 changes: 126 additions & 9 deletions barretenberg/cpp/src/barretenberg/flavor/goblin_translator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "barretenberg/ecc/curves/bn254/bn254.hpp"
#include "barretenberg/flavor/flavor.hpp"
#include "barretenberg/flavor/flavor_macros.hpp"
#include "barretenberg/honk/proof_system/permutation_library.hpp"
#include "barretenberg/polynomials/univariate.hpp"
#include "barretenberg/proof_system/arithmetization/arithmetization.hpp"
#include "barretenberg/proof_system/circuit_builder/goblin_translator_circuit_builder.hpp"
Expand Down Expand Up @@ -34,6 +35,8 @@ class GoblinTranslatorFlavor {
using Polynomial = bb::Polynomial<FF>;
using RelationSeparator = FF;

static constexpr size_t MINIMUM_MINI_CIRCUIT_SIZE = 2048;

// The size of the circuit which is filled with non-zero values for most polynomials. Most relations (everything
// except for Permutation and GenPermSort) can be evaluated just on the first chunk
// It is also the only parameter that can be changed without updating relations or structures in the flavor
Expand Down Expand Up @@ -125,6 +128,72 @@ class GoblinTranslatorFlavor {
auto get_selectors() { return RefArray<DataType, 0>{}; };
auto get_sigma_polynomials() { return RefArray<DataType, 0>{}; };
auto get_id_polynomials() { return RefArray<DataType, 0>{}; };

inline void compute_lagrange_polynomials(const CircuitBuilder& builder)
{
const size_t circuit_size = compute_dyadic_circuit_size(builder);
const size_t mini_circuit_dyadic_size = compute_mini_circuit_dyadic_size(builder);

Polynomial lagrange_polynomial_odd_in_minicircuit(circuit_size);
Polynomial lagrange_polynomial_even_in_minicircut(circuit_size);
Polynomial lagrange_polynomial_second(circuit_size);
Polynomial lagrange_polynomial_second_to_last_in_minicircuit(circuit_size);

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;
}
this->lagrange_odd_in_minicircuit = lagrange_polynomial_odd_in_minicircuit.share();
this->lagrange_even_in_minicircuit = lagrange_polynomial_even_in_minicircut.share();
lagrange_polynomial_second[1] = 1;
lagrange_polynomial_second_to_last_in_minicircuit[mini_circuit_dyadic_size - 2] = 1;
this->lagrange_second_to_last_in_minicircuit = lagrange_polynomial_second_to_last_in_minicircuit.share();
this->lagrange_second = lagrange_polynomial_second.share();
}

/**
* @brief Compute the extra numerator for Goblin range constraint argument
*
* @details Goblin proves that several polynomials contain only values in a certain range through 2 relations:
* 1) A grand product which ignores positions of elements (GoblinTranslatorPermutationRelation)
* 2) A relation enforcing a certain ordering on the elements of the given polynomial
* (GoblinTranslatorGenPermSortRelation)
*
* We take the values from 4 polynomials, and spread them into 5 polynomials + add all the steps from MAX_VALUE
* to 0. We order these polynomials and use them in the denominator of the grand product, at the same time
* checking that they go from MAX_VALUE to 0. To counteract the added steps we also generate an extra range
* constraint numerator, which contains 5 MAX_VALUE, 5 (MAX_VALUE-STEP),... values
*
*/
inline void compute_extra_range_constraint_numerator()
{
auto& extra_range_constraint_numerator = this->ordered_extra_range_constraints_numerator;

static constexpr uint32_t MAX_VALUE = (1 << MICRO_LIMB_BITS) - 1;

// Calculate how many elements there are in the sequence MAX_VALUE, MAX_VALUE - 3,...,0
size_t sorted_elements_count = (MAX_VALUE / SORT_STEP) + 1 + (MAX_VALUE % SORT_STEP == 0 ? 0 : 1);

// Check that we can fit every element in the polynomial
ASSERT((NUM_CONCATENATED_WIRES + 1) * sorted_elements_count < extra_range_constraint_numerator.size());

std::vector<size_t> sorted_elements(sorted_elements_count);

// Calculate the sequence in integers
sorted_elements[0] = MAX_VALUE;
for (size_t i = 1; i < sorted_elements_count; i++) {
sorted_elements[i] = (sorted_elements_count - 1 - i) * SORT_STEP;
}

// TODO(#756): can be parallelized further. This will use at most 5 threads
auto fill_with_shift = [&](size_t shift) {
for (size_t i = 0; i < sorted_elements_count; i++) {
extra_range_constraint_numerator[shift + i * (NUM_CONCATENATED_WIRES + 1)] = sorted_elements[i];
}
};
// Fill polynomials with a sequence, where each element is repeated NUM_CONCATENATED_WIRES+1 times
parallel_for(NUM_CONCATENATED_WIRES + 1, fill_with_shift);
}
};

template <typename DataType> class ConcatenatedRangeConstraints {
Expand Down Expand Up @@ -890,6 +959,28 @@ class GoblinTranslatorFlavor {
};

public:
static inline size_t compute_total_num_gates(const CircuitBuilder& builder)
{
return std::max(builder.num_gates, MINIMUM_MINI_CIRCUIT_SIZE);
}

static inline size_t compute_dyadic_circuit_size(const CircuitBuilder& builder)
{
const size_t total_num_gates = compute_total_num_gates(builder);

// Next power of 2
const size_t mini_circuit_dyadic_size = builder.get_circuit_subgroup_size(total_num_gates);

// The actual circuit size is several times bigger than the trace in the builder, because we use
// concatenation to bring the degree of relations down, while extending the length.
return mini_circuit_dyadic_size * CONCATENATION_GROUP_SIZE;
}

static inline size_t compute_mini_circuit_dyadic_size(const CircuitBuilder& builder)
{
return builder.get_circuit_subgroup_size(compute_total_num_gates(builder));
}

/**
* @brief The proving key is responsible for storing the polynomials used by the prover.
* @note TODO(Cody): Maybe multiple inheritance is the right thing here. In that case, nothing should eve
Expand All @@ -899,12 +990,33 @@ class GoblinTranslatorFlavor {
public:
BF batching_challenge_v = { 0 };
BF evaluation_input_x = { 0 };
ProvingKey() = default;

// Expose constructors on the base class
using Base = ProvingKey_<PrecomputedEntities<Polynomial>, WitnessEntities<Polynomial>, CommitmentKey>;
using Base::Base;

ProvingKey() = default;
ProvingKey(const CircuitBuilder& builder)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Core change: the keys and their constructors, partially defined in the flavors, are now fully defined there. This means it makes sense to move the auxiliary functions, constants etc into the flavors too.

: ProvingKey_<PrecomputedEntities<Polynomial>, WitnessEntities<Polynomial>, CommitmentKey>(
compute_dyadic_circuit_size(builder), 0)
, batching_challenge_v(builder.batching_challenge_v)
, evaluation_input_x(builder.evaluation_input_x)
{
// First and last lagrange polynomials (in the full circuit size)
const auto [lagrange_first, lagrange_last] =
compute_first_and_last_lagrange_polynomials<FF>(compute_dyadic_circuit_size(builder));
this->lagrange_first = lagrange_first;
this->lagrange_last = lagrange_last;

// 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
compute_lagrange_polynomials(builder);

// Compute the numerator for the permutation argument with several repetitions of steps bridging 0 and
// maximum range constraint
compute_extra_range_constraint_numerator();
}

// TODO(https://github.com/AztecProtocol/barretenberg/issues/810): get around this by properly having
// concatenated range be a concept outside of witnessentities
std::vector<std::string> get_labels()
Expand All @@ -917,13 +1029,6 @@ class GoblinTranslatorFlavor {
return concatenate(PrecomputedEntities<Polynomial>::get_all(),
WitnessEntities<Polynomial>::get_unshifted_wires());
}

ProvingKey(const size_t circuit_size)
: ProvingKey_<PrecomputedEntities<Polynomial>, WitnessEntities<Polynomial>, CommitmentKey>(circuit_size, 0)

, batching_challenge_v(0)
, evaluation_input_x(0)
{}
};

/**
Expand All @@ -934,8 +1039,20 @@ class GoblinTranslatorFlavor {
* resolve that, and split out separate PrecomputedPolynomials/Commitments data for clarity but also for
* portability of our circuits.
*/
using VerificationKey = VerificationKey_<PrecomputedEntities<Commitment>, VerifierCommitmentKey>;
class VerificationKey : public VerificationKey_<PrecomputedEntities<Commitment>, VerifierCommitmentKey> {
public:
std::vector<FF> public_inputs;

VerificationKey(const size_t circuit_size, const size_t num_public_inputs)
: VerificationKey_(circuit_size, num_public_inputs)
{}

template <typename ProvingKeyPtr>
VerificationKey(const ProvingKeyPtr& proving_key)
: VerificationKey_(proving_key)
, public_inputs(proving_key->public_inputs)
{}
};
/**
* @brief A field element for each entity of the flavor. These entities represent the prover polynomials
* evaluated at one point.
Expand Down
18 changes: 10 additions & 8 deletions barretenberg/cpp/src/barretenberg/goblin/goblin.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
#include "barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.hpp"
#include "barretenberg/proof_system/instance_inspector.hpp"
#include "barretenberg/stdlib/honk_recursion/verifier/merge_recursive_verifier.hpp"
#include "barretenberg/translator_vm/goblin_translator_composer.hpp"
#include "barretenberg/translator_vm/goblin_translator_prover.hpp"
#include "barretenberg/translator_vm/goblin_translator_verifier.hpp"
#include "barretenberg/ultra_honk/merge_prover.hpp"
#include "barretenberg/ultra_honk/merge_verifier.hpp"
#include "barretenberg/ultra_honk/ultra_prover.hpp"
Expand All @@ -32,7 +33,7 @@ class Goblin {
using ECCVMComposer = bb::ECCVMComposer;
using ECCVMProver = bb::ECCVMProver_<ECCVMFlavor>;
using TranslatorBuilder = bb::GoblinTranslatorCircuitBuilder;
using TranslatorComposer = bb::GoblinTranslatorComposer;
using TranslatorProver = bb::GoblinTranslatorProver;
using RecursiveMergeVerifier = bb::stdlib::recursion::goblin::MergeRecursiveVerifier_<GoblinUltraCircuitBuilder>;
using MergeProver = bb::MergeProver_<GoblinUltraFlavor>;
using MergeVerifier = bb::MergeVerifier_<GoblinUltraFlavor>;
Expand Down Expand Up @@ -82,9 +83,9 @@ class Goblin {
// TODO(https://github.com/AztecProtocol/barretenberg/issues/798) unique_ptr use is a hack
std::unique_ptr<ECCVMBuilder> eccvm_builder;
std::unique_ptr<TranslatorBuilder> translator_builder;
std::unique_ptr<TranslatorProver> translator_prover;
std::unique_ptr<ECCVMComposer> eccvm_composer;
std::unique_ptr<ECCVMProver> eccvm_prover;
std::unique_ptr<TranslatorComposer> translator_composer;

AccumulationOutput accumulator; // Used only for ACIR methods for now

Expand Down Expand Up @@ -173,9 +174,8 @@ class Goblin {
{
translator_builder = std::make_unique<TranslatorBuilder>(
eccvm_prover->translation_batching_challenge_v, eccvm_prover->evaluation_challenge_x, op_queue);
translator_composer = std::make_unique<TranslatorComposer>();
auto translator_prover = translator_composer->create_prover(*translator_builder, eccvm_prover->transcript);
goblin_proof.translator_proof = translator_prover.construct_proof();
translator_prover = std::make_unique<GoblinTranslatorProver>(*translator_builder, eccvm_prover->transcript);
goblin_proof.translator_proof = translator_prover->construct_proof();
};

/**
Expand Down Expand Up @@ -208,7 +208,8 @@ class Goblin {
auto eccvm_verifier = eccvm_composer->create_verifier(*eccvm_builder);
bool eccvm_verified = eccvm_verifier.verify_proof(proof.eccvm_proof);

auto translator_verifier = translator_composer->create_verifier(*translator_builder, eccvm_verifier.transcript);
GoblinTranslatorVerifier translator_verifier(translator_prover->key, eccvm_verifier.transcript);

bool accumulator_construction_verified = translator_verifier.verify_proof(proof.translator_proof);
// TODO(https://github.com/AztecProtocol/barretenberg/issues/799): Ensure translation_evaluations are passed
// correctly
Expand Down Expand Up @@ -294,7 +295,8 @@ class Goblin {
auto eccvm_verifier = eccvm_composer->create_verifier(*eccvm_builder);
bool eccvm_verified = eccvm_verifier.verify_proof(goblin_proof.eccvm_proof);

auto translator_verifier = translator_composer->create_verifier(*translator_builder, eccvm_verifier.transcript);
GoblinTranslatorVerifier translator_verifier(translator_prover->key, eccvm_verifier.transcript);

bool translation_accumulator_construction_verified =
translator_verifier.verify_proof(goblin_proof.translator_proof);
// TODO(https://github.com/AztecProtocol/barretenberg/issues/799): Ensure translation_evaluations are passed
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once
#include "barretenberg/common/ref_vector.hpp"
#include "barretenberg/polynomials/polynomial.hpp"
#include "barretenberg/relations/relation_parameters.hpp"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did you add this header?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I just double checked and it is needed. I guess it was an implicit dependency that was satisfied through one of the deleted files? This is defined in a header and the error happens when build relation_objects, so it's a little hard to tell the cause.

#include <typeinfo>

namespace bb {
Expand Down Expand Up @@ -353,86 +354,4 @@ void compute_goblin_translator_range_constraint_ordered_polynomials(StorageHandl
[](uint32_t in) { return FF(in); });
}

/**
* @brief Compute the extra numerator for Goblin range constraint argument
*
* @details Goblin proves that several polynomials contain only values in a certain range through 2 relations:
* 1) A grand product which ignores positions of elements (GoblinTranslatorPermutationRelation)
* 2) A relation enforcing a certain ordering on the elements of the given polynomial
* (GoblinTranslatorGenPermSortRelation)
*
* We take the values from 4 polynomials, and spread them into 5 polynomials + add all the steps from MAX_VALUE to 0. We
* order these polynomials and use them in the denominator of the grand product, at the same time checking that they go
* from MAX_VALUE to 0. To counteract the added steps we also generate an extra range constraint numerator, which
* 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, size_t dyadic_circuit_size)
{

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

auto& extra_range_constraint_numerator = proving_key->ordered_extra_range_constraints_numerator;

uint32_t MAX_VALUE = (1 << Flavor::MICRO_LIMB_BITS) - 1;

// Calculate how many elements there are in the sequence MAX_VALUE, MAX_VALUE - 3,...,0
size_t sorted_elements_count = (MAX_VALUE / sort_step) + 1 + (MAX_VALUE % sort_step == 0 ? 0 : 1);

// Check that we can fit every element in the polynomial
ASSERT((num_concatenated_wires + 1) * sorted_elements_count < full_circuit_size);

std::vector<size_t> sorted_elements(sorted_elements_count);

// Calculate the sequence in integers
sorted_elements[0] = MAX_VALUE;
for (size_t i = 1; i < sorted_elements_count; i++) {
sorted_elements[i] = (sorted_elements_count - 1 - i) * sort_step;
}

// TODO(#756): can be parallelized further. This will use at most 5 threads
auto fill_with_shift = [&](size_t shift) {
for (size_t i = 0; i < sorted_elements_count; i++) {
extra_range_constraint_numerator[shift + i * (num_concatenated_wires + 1)] = sorted_elements[i];
}
};
// Fill polynomials with a sequence, where each element is repeated num_concatenated_wires+1 times
parallel_for(num_concatenated_wires + 1, fill_with_shift);
}

/**
* @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, size_t mini_circuit_dyadic_size)

{
const size_t n = proving_key->circuit_size;
typename Flavor::Polynomial lagrange_polynomial_odd_in_minicircuit(n);
typename Flavor::Polynomial lagrange_polynomial_even_in_minicircut(n);
typename Flavor::Polynomial lagrange_polynomial_second(n);
typename Flavor::Polynomial lagrange_polynomial_second_to_last_in_minicircuit(n);

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[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();
}

} // namespace bb
Original file line number Diff line number Diff line change
Expand Up @@ -349,19 +349,16 @@ void compute_monomial_and_coset_fft_polynomials_from_lagrange(std::string label,

/**
* @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
*/
template <typename Flavor> inline void compute_first_and_last_lagrange_polynomials(const auto& proving_key)
template <typename FF>
inline std::tuple<Polynomial<FF>, Polynomial<FF>> compute_first_and_last_lagrange_polynomials(const size_t circuit_size)
{
const size_t n = proving_key->circuit_size;
typename Flavor::Polynomial lagrange_polynomial_0(n);
typename Flavor::Polynomial lagrange_polynomial_n_min_1(n);
Polynomial<FF> lagrange_polynomial_0(circuit_size);
Polynomial<FF> lagrange_polynomial_n_min_1(circuit_size);
lagrange_polynomial_0[0] = 1;
proving_key->lagrange_first = lagrange_polynomial_0.share();

lagrange_polynomial_n_min_1[n - 1] = 1;
proving_key->lagrange_last = lagrange_polynomial_n_min_1.share();
lagrange_polynomial_n_min_1[circuit_size - 1] = 1;
return std::make_tuple(lagrange_polynomial_0.share(), lagrange_polynomial_n_min_1.share());
}

/**
Expand Down
Loading
Loading