Skip to content

Commit

Permalink
refactor: No Translator composer (#5202)
Browse files Browse the repository at this point in the history
Get rid of the Translator composer. The eventual goal will be a a
uniform interface across all proving systems (prover, verifier, keys all
constructed in the same way, also sharing more code).
  • Loading branch information
codygunton authored Mar 19, 2024
1 parent 21356e6 commit c8897ca
Show file tree
Hide file tree
Showing 16 changed files with 361 additions and 529 deletions.
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)
: 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"
#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

0 comments on commit c8897ca

Please sign in to comment.