Skip to content

Commit

Permalink
feat: goblin and eccvm bench (#3606)
Browse files Browse the repository at this point in the history
Benchmark ECCVM and Goblin.

---------

Co-authored-by: ludamad <[email protected]>
Co-authored-by: codygunton <[email protected]>
Co-authored-by: ledwards2225 <[email protected]>
  • Loading branch information
4 people authored Jan 4, 2024
1 parent e893675 commit 1fe63b2
Show file tree
Hide file tree
Showing 19 changed files with 309 additions and 97 deletions.
5 changes: 5 additions & 0 deletions barretenberg/cpp/CMakePresets.json
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,11 @@
"jobs": 0,
"targets": ["barretenberg.wasm"]
},
{
"name": "xray",
"configurePreset": "xray",
"inherits": "default"
},
{
"name": "xray-verbose",
"configurePreset": "xray-verbose",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Each source represents a separate benchmark suite
set(BENCHMARK_SOURCES
standard_plonk.bench.cpp
goblin.bench.cpp
eccvm.bench.cpp
ultra_honk.bench.cpp
ultra_honk_rounds.bench.cpp
ultra_plonk.bench.cpp
Expand All @@ -10,9 +12,11 @@ set(BENCHMARK_SOURCES
# Required libraries for benchmark suites
set(LINKED_LIBRARIES
ultra_honk
eccvm
stdlib_sha256
stdlib_keccak
stdlib_merkle_tree
stdlib_recursion
benchmark::benchmark
)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#include <benchmark/benchmark.h>

#include "barretenberg/benchmark/honk_bench/benchmark_utilities.hpp"
#include "barretenberg/eccvm/eccvm_composer.hpp"
#include "barretenberg/proof_system/circuit_builder/eccvm/eccvm_circuit_builder.hpp"

using namespace benchmark;
using namespace proof_system;

using Flavor = honk::flavor::ECCVM;
using Builder = ECCVMCircuitBuilder<Flavor>;
using Composer = honk::ECCVMComposer;

namespace {

Builder generate_trace(size_t target_num_gates)
{
Builder builder;
using G1 = typename Flavor::CycleGroup;
using Fr = typename G1::Fr;

auto generators = G1::derive_generators("test generators", 2);

typename G1::element a = generators[0];
typename G1::element b = generators[1];
Fr x = Fr::random_element();
Fr y = Fr::random_element();

typename G1::element expected_1 = (a * x) + a + a + (b * y) + (b * x) + (b * x);

// Each loop adds 163 gates. Note: builder.get_num_gates() is very expensive here (bug?) and it's actually painful
// to use a `while` loop
size_t num_iterations = target_num_gates / 163;
for (size_t _ = 0; _ < num_iterations; _++) {
builder.add_accumulate(a);
builder.mul_accumulate(a, x);
builder.mul_accumulate(b, x);
builder.mul_accumulate(b, y);
builder.add_accumulate(a);
builder.mul_accumulate(b, x);
builder.eq_and_reset(expected_1);
}
return builder;
}

void eccvm_generate_prover(State& state) noexcept
{
barretenberg::srs::init_grumpkin_crs_factory("../srs_db/grumpkin");

size_t target_num_gates = 1 << static_cast<size_t>(state.range(0));
for (auto _ : state) {
Builder builder = generate_trace(target_num_gates);
Composer composer;
auto prover = composer.create_prover(builder);
};
}

void eccvm_prove(State& state) noexcept
{
barretenberg::srs::init_grumpkin_crs_factory("../srs_db/grumpkin");

size_t target_num_gates = 1 << static_cast<size_t>(state.range(0));
Builder builder = generate_trace(target_num_gates);
Composer composer;
auto prover = composer.create_prover(builder);
for (auto _ : state) {
auto proof = prover.construct_proof();
};
}

BENCHMARK(eccvm_generate_prover)->Unit(kMillisecond)->DenseRange(10, 20);
BENCHMARK(eccvm_prove)->Unit(kMillisecond)->DenseRange(10, 20);
} // namespace
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@

#include <benchmark/benchmark.h>

#include "barretenberg/benchmark/honk_bench/benchmark_utilities.hpp"
#include "barretenberg/goblin/goblin.hpp"
#include "barretenberg/goblin/mock_circuits.hpp"
#include "barretenberg/proof_system/circuit_builder/ultra_circuit_builder.hpp"
#include "barretenberg/ultra_honk/ultra_composer.hpp"

using namespace benchmark;
using namespace barretenberg;
using namespace proof_system;

namespace {
void goblin_full(State& state) noexcept
{
barretenberg::srs::init_crs_factory("../srs_db/ignition");
barretenberg::srs::init_grumpkin_crs_factory("../srs_db/grumpkin");

Goblin goblin;

// Construct an initial circuit; its proof will be recursively verified by the first kernel
GoblinUltraCircuitBuilder initial_circuit{ goblin.op_queue };
GoblinMockCircuits::construct_simple_initial_circuit(initial_circuit);
Goblin::AccumulationOutput kernel_input = goblin.accumulate(initial_circuit);

Goblin::Proof proof;
for (auto _ : state) {
// Construct a series of simple Goblin circuits; generate and verify their proofs
size_t NUM_CIRCUITS = 1 << static_cast<size_t>(state.range(0));
for (size_t circuit_idx = 0; circuit_idx < NUM_CIRCUITS; ++circuit_idx) {
// Construct a circuit with logic resembling that of the "kernel circuit"
GoblinUltraCircuitBuilder circuit_builder{ goblin.op_queue };
GoblinMockCircuits::construct_mock_kernel_circuit(circuit_builder, kernel_input);

// Construct proof of the current kernel circuit to be recursively verified by the next one
kernel_input = goblin.accumulate(circuit_builder);
}

proof = goblin.prove();
// Verify the final ultra proof
}
honk::GoblinUltraVerifier ultra_verifier{ kernel_input.verification_key };
ultra_verifier.verify_proof(kernel_input.proof);
// Verify the goblin proof (eccvm, translator, merge)
goblin.verify(proof);
}

void goblin_accumulate(State& state) noexcept
{
barretenberg::srs::init_crs_factory("../srs_db/ignition");
barretenberg::srs::init_grumpkin_crs_factory("../srs_db/grumpkin");

Goblin goblin;

// Construct an initial circuit; its proof will be recursively verified by the first kernel
GoblinUltraCircuitBuilder initial_circuit{ goblin.op_queue };
GoblinMockCircuits::construct_simple_initial_circuit(initial_circuit);
Goblin::AccumulationOutput kernel_input = goblin.accumulate(initial_circuit);

// Construct a series of simple Goblin circuits; generate and verify their proofs
size_t NUM_CIRCUITS = 1 << static_cast<size_t>(state.range(0));
for (auto _ : state) {
for (size_t circuit_idx = 0; circuit_idx < NUM_CIRCUITS; ++circuit_idx) {
// Construct a circuit with logic resembling that of the "kernel circuit"
GoblinUltraCircuitBuilder circuit_builder{ goblin.op_queue };
GoblinMockCircuits::construct_mock_kernel_circuit(circuit_builder, kernel_input);

// Construct proof of the current kernel circuit to be recursively verified by the next one
kernel_input = goblin.accumulate(circuit_builder);
}
}
}

void goblin_eccvm_prove(State& state) noexcept
{
barretenberg::srs::init_crs_factory("../srs_db/ignition");
barretenberg::srs::init_grumpkin_crs_factory("../srs_db/grumpkin");

Goblin goblin;

// Construct an initial circuit; its proof will be recursively verified by the first kernel
GoblinUltraCircuitBuilder initial_circuit{ goblin.op_queue };
GoblinMockCircuits::construct_simple_initial_circuit(initial_circuit);
Goblin::AccumulationOutput kernel_input = goblin.accumulate(initial_circuit);

// Construct a series of simple Goblin circuits; generate and verify their proofs
size_t NUM_CIRCUITS = 1 << static_cast<size_t>(state.range(0));
for (size_t circuit_idx = 0; circuit_idx < NUM_CIRCUITS; ++circuit_idx) {
// Construct a circuit with logic resembling that of the "kernel circuit"
GoblinUltraCircuitBuilder circuit_builder{ goblin.op_queue };
GoblinMockCircuits::construct_mock_kernel_circuit(circuit_builder, kernel_input);

// Construct proof of the current kernel circuit to be recursively verified by the next one
kernel_input = goblin.accumulate(circuit_builder);
}

for (auto _ : state) {
goblin.prove_eccvm();
}
}

void goblin_translator_prove(State& state) noexcept
{
barretenberg::srs::init_crs_factory("../srs_db/ignition");
barretenberg::srs::init_grumpkin_crs_factory("../srs_db/grumpkin");

Goblin goblin;

// Construct an initial circuit; its proof will be recursively verified by the first kernel
GoblinUltraCircuitBuilder initial_circuit{ goblin.op_queue };
GoblinMockCircuits::construct_simple_initial_circuit(initial_circuit);
Goblin::AccumulationOutput kernel_input = goblin.accumulate(initial_circuit);

// Construct a series of simple Goblin circuits; generate and verify their proofs
size_t NUM_CIRCUITS = 1 << static_cast<size_t>(state.range(0));
for (size_t circuit_idx = 0; circuit_idx < NUM_CIRCUITS; ++circuit_idx) {
// Construct a circuit with logic resembling that of the "kernel circuit"
GoblinUltraCircuitBuilder circuit_builder{ goblin.op_queue };
GoblinMockCircuits::construct_mock_kernel_circuit(circuit_builder, kernel_input);

// Construct proof of the current kernel circuit to be recursively verified by the next one
kernel_input = goblin.accumulate(circuit_builder);
}

goblin.prove_eccvm();
for (auto _ : state) {
goblin.prove_translator();
}
}

} // namespace

BENCHMARK(goblin_full)->Unit(kMillisecond)->DenseRange(0, 7);
BENCHMARK(goblin_accumulate)->Unit(kMillisecond)->DenseRange(0, 7);
BENCHMARK(goblin_eccvm_prove)->Unit(kMillisecond)->DenseRange(0, 7);
BENCHMARK(goblin_translator_prove)->Unit(kMillisecond)->DenseRange(0, 7);
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "barretenberg/dsl/acir_format/acir_format.hpp"
#include "barretenberg/dsl/acir_format/recursion_constraint.hpp"
#include "barretenberg/dsl/types.hpp"
#include "barretenberg/goblin/mock_circuits.hpp"
#include "barretenberg/plonk/proof_system/proving_key/proving_key.hpp"
#include "barretenberg/plonk/proof_system/proving_key/serialize.hpp"
#include "barretenberg/plonk/proof_system/verification_key/sol_gen.hpp"
Expand Down Expand Up @@ -101,7 +102,7 @@ void AcirComposer::create_goblin_circuit(acir_format::acir_format& constraint_sy

// TODO(https://github.com/AztecProtocol/barretenberg/issues/817): Add some arbitrary op gates to ensure the
// associated polynomials are non-zero and to give ECCVM and Translator some ECC ops to process.
GoblinTestingUtils::construct_goblin_ecc_op_circuit(goblin_builder_);
GoblinMockCircuits::construct_goblin_ecc_op_circuit(goblin_builder_);
}

std::vector<uint8_t> AcirComposer::create_goblin_proof()
Expand Down
22 changes: 11 additions & 11 deletions barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,17 @@ template <ECCVMFlavor Flavor> class ECCVMProver_ {
const std::shared_ptr<PCSCommitmentKey>& commitment_key,
const std::shared_ptr<Transcript>& transcript = std::make_shared<Transcript>());

void execute_preamble_round();
void execute_wire_commitments_round();
void execute_log_derivative_commitments_round();
void execute_grand_product_computation_round();
void execute_relation_check_rounds();
void execute_univariatization_round();
void execute_pcs_evaluation_round();
void execute_shplonk_batched_quotient_round();
void execute_shplonk_partial_evaluation_round();
void execute_final_pcs_round();
void execute_transcript_consistency_univariate_opening_round();
BBERG_PROFILE void execute_preamble_round();
BBERG_PROFILE void execute_wire_commitments_round();
BBERG_PROFILE void execute_log_derivative_commitments_round();
BBERG_PROFILE void execute_grand_product_computation_round();
BBERG_PROFILE void execute_relation_check_rounds();
BBERG_PROFILE void execute_univariatization_round();
BBERG_PROFILE void execute_pcs_evaluation_round();
BBERG_PROFILE void execute_shplonk_batched_quotient_round();
BBERG_PROFILE void execute_shplonk_partial_evaluation_round();
BBERG_PROFILE void execute_final_pcs_round();
BBERG_PROFILE void execute_transcript_consistency_univariate_opening_round();

plonk::proof& export_proof();
plonk::proof& construct_proof();
Expand Down
8 changes: 3 additions & 5 deletions barretenberg/cpp/src/barretenberg/flavor/flavor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ class Ultra;
class ECCVM;
class GoblinUltra;
template <typename BuilderType> class UltraRecursive_;
template <typename BuilderType> class GoblinUltraRecursive_;
class GoblinUltraRecursive;
} // namespace proof_system::honk::flavor

// Forward declare plonk flavors
Expand Down Expand Up @@ -293,14 +293,12 @@ concept IsUltraFlavor = IsAnyOf<T, honk::flavor::Ultra, honk::flavor::GoblinUltr

template <typename T>
concept IsGoblinFlavor = IsAnyOf<T, honk::flavor::GoblinUltra,
honk::flavor::GoblinUltraRecursive_<UltraCircuitBuilder>,
honk::flavor::GoblinUltraRecursive_<GoblinUltraCircuitBuilder>>;
honk::flavor::GoblinUltraRecursive>;

template <typename T>
concept IsRecursiveFlavor = IsAnyOf<T, honk::flavor::UltraRecursive_<UltraCircuitBuilder>,
honk::flavor::UltraRecursive_<GoblinUltraCircuitBuilder>,
honk::flavor::GoblinUltraRecursive_<UltraCircuitBuilder>,
honk::flavor::GoblinUltraRecursive_<GoblinUltraCircuitBuilder>>;
honk::flavor::GoblinUltraRecursive>;

template <typename T> concept IsGrumpkinFlavor = IsAnyOf<T, honk::flavor::ECCVM>;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,14 @@ namespace proof_system::honk::flavor {
*
* @tparam BuilderType Determines the arithmetization of the verifier circuit defined based on this flavor.
*/
template <typename BuilderType> class GoblinUltraRecursive_ {
class GoblinUltraRecursive {
public:
using CircuitBuilder = BuilderType; // Determines arithmetization of circuit instantiated with this flavor
using CircuitBuilder = GoblinUltraCircuitBuilder;
using Curve = plonk::stdlib::bn254<CircuitBuilder>;
using GroupElement = typename Curve::Element;
using Commitment = typename Curve::Element;
using CommitmentHandle = typename Curve::Element;
using FF = typename Curve::ScalarField;
using GroupElement = Curve::Element;
using FF = Curve::ScalarField;
using Commitment = Curve::Element;
using CommitmentHandle = Curve::Element;
using NativeVerificationKey = flavor::GoblinUltra::VerificationKey;

// Note(luke): Eventually this may not be needed at all
Expand Down Expand Up @@ -78,7 +78,6 @@ template <typename BuilderType> class GoblinUltraRecursive_ {
using SumcheckTupleOfTuplesOfUnivariates = decltype(create_sumcheck_tuple_of_tuples_of_univariates<Relations>());
using TupleOfArraysOfValues = decltype(create_tuple_of_arrays_of_values<Relations>());

public:
/**
* @brief A field element for each entity of the flavor. These entities represent the prover polynomials evaluated
* at one point.
Expand All @@ -87,7 +86,6 @@ template <typename BuilderType> class GoblinUltraRecursive_ {
public:
using Base = GoblinUltra::AllEntities<FF>;
using Base::Base;
AllValues(std::array<FF, NUM_ALL_ENTITIES> _data_in) { this->_data = _data_in; }
};
/**
* @brief The verification key is responsible for storing the the commitments to the precomputed (non-witnessk)
Expand Down
Loading

0 comments on commit 1fe63b2

Please sign in to comment.