Skip to content

Commit 1fe63b2

Browse files
ludamadludamad0codyguntonledwards2225
authored
feat: goblin and eccvm bench (AztecProtocol#3606)
Benchmark ECCVM and Goblin. --------- Co-authored-by: ludamad <adam@aztecprotocol.com> Co-authored-by: codygunton <codygunton@gmail.com> Co-authored-by: ledwards2225 <l.edwards.d@gmail.com>
1 parent e893675 commit 1fe63b2

19 files changed

+309
-97
lines changed

barretenberg/cpp/CMakePresets.json

+5
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,11 @@
369369
"jobs": 0,
370370
"targets": ["barretenberg.wasm"]
371371
},
372+
{
373+
"name": "xray",
374+
"configurePreset": "xray",
375+
"inherits": "default"
376+
},
372377
{
373378
"name": "xray-verbose",
374379
"configurePreset": "xray-verbose",

barretenberg/cpp/src/barretenberg/benchmark/honk_bench/CMakeLists.txt

+4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# Each source represents a separate benchmark suite
22
set(BENCHMARK_SOURCES
33
standard_plonk.bench.cpp
4+
goblin.bench.cpp
5+
eccvm.bench.cpp
46
ultra_honk.bench.cpp
57
ultra_honk_rounds.bench.cpp
68
ultra_plonk.bench.cpp
@@ -10,9 +12,11 @@ set(BENCHMARK_SOURCES
1012
# Required libraries for benchmark suites
1113
set(LINKED_LIBRARIES
1214
ultra_honk
15+
eccvm
1316
stdlib_sha256
1417
stdlib_keccak
1518
stdlib_merkle_tree
19+
stdlib_recursion
1620
benchmark::benchmark
1721
)
1822

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
#include <benchmark/benchmark.h>
2+
3+
#include "barretenberg/benchmark/honk_bench/benchmark_utilities.hpp"
4+
#include "barretenberg/eccvm/eccvm_composer.hpp"
5+
#include "barretenberg/proof_system/circuit_builder/eccvm/eccvm_circuit_builder.hpp"
6+
7+
using namespace benchmark;
8+
using namespace proof_system;
9+
10+
using Flavor = honk::flavor::ECCVM;
11+
using Builder = ECCVMCircuitBuilder<Flavor>;
12+
using Composer = honk::ECCVMComposer;
13+
14+
namespace {
15+
16+
Builder generate_trace(size_t target_num_gates)
17+
{
18+
Builder builder;
19+
using G1 = typename Flavor::CycleGroup;
20+
using Fr = typename G1::Fr;
21+
22+
auto generators = G1::derive_generators("test generators", 2);
23+
24+
typename G1::element a = generators[0];
25+
typename G1::element b = generators[1];
26+
Fr x = Fr::random_element();
27+
Fr y = Fr::random_element();
28+
29+
typename G1::element expected_1 = (a * x) + a + a + (b * y) + (b * x) + (b * x);
30+
31+
// Each loop adds 163 gates. Note: builder.get_num_gates() is very expensive here (bug?) and it's actually painful
32+
// to use a `while` loop
33+
size_t num_iterations = target_num_gates / 163;
34+
for (size_t _ = 0; _ < num_iterations; _++) {
35+
builder.add_accumulate(a);
36+
builder.mul_accumulate(a, x);
37+
builder.mul_accumulate(b, x);
38+
builder.mul_accumulate(b, y);
39+
builder.add_accumulate(a);
40+
builder.mul_accumulate(b, x);
41+
builder.eq_and_reset(expected_1);
42+
}
43+
return builder;
44+
}
45+
46+
void eccvm_generate_prover(State& state) noexcept
47+
{
48+
barretenberg::srs::init_grumpkin_crs_factory("../srs_db/grumpkin");
49+
50+
size_t target_num_gates = 1 << static_cast<size_t>(state.range(0));
51+
for (auto _ : state) {
52+
Builder builder = generate_trace(target_num_gates);
53+
Composer composer;
54+
auto prover = composer.create_prover(builder);
55+
};
56+
}
57+
58+
void eccvm_prove(State& state) noexcept
59+
{
60+
barretenberg::srs::init_grumpkin_crs_factory("../srs_db/grumpkin");
61+
62+
size_t target_num_gates = 1 << static_cast<size_t>(state.range(0));
63+
Builder builder = generate_trace(target_num_gates);
64+
Composer composer;
65+
auto prover = composer.create_prover(builder);
66+
for (auto _ : state) {
67+
auto proof = prover.construct_proof();
68+
};
69+
}
70+
71+
BENCHMARK(eccvm_generate_prover)->Unit(kMillisecond)->DenseRange(10, 20);
72+
BENCHMARK(eccvm_prove)->Unit(kMillisecond)->DenseRange(10, 20);
73+
} // namespace
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
2+
#include <benchmark/benchmark.h>
3+
4+
#include "barretenberg/benchmark/honk_bench/benchmark_utilities.hpp"
5+
#include "barretenberg/goblin/goblin.hpp"
6+
#include "barretenberg/goblin/mock_circuits.hpp"
7+
#include "barretenberg/proof_system/circuit_builder/ultra_circuit_builder.hpp"
8+
#include "barretenberg/ultra_honk/ultra_composer.hpp"
9+
10+
using namespace benchmark;
11+
using namespace barretenberg;
12+
using namespace proof_system;
13+
14+
namespace {
15+
void goblin_full(State& state) noexcept
16+
{
17+
barretenberg::srs::init_crs_factory("../srs_db/ignition");
18+
barretenberg::srs::init_grumpkin_crs_factory("../srs_db/grumpkin");
19+
20+
Goblin goblin;
21+
22+
// Construct an initial circuit; its proof will be recursively verified by the first kernel
23+
GoblinUltraCircuitBuilder initial_circuit{ goblin.op_queue };
24+
GoblinMockCircuits::construct_simple_initial_circuit(initial_circuit);
25+
Goblin::AccumulationOutput kernel_input = goblin.accumulate(initial_circuit);
26+
27+
Goblin::Proof proof;
28+
for (auto _ : state) {
29+
// Construct a series of simple Goblin circuits; generate and verify their proofs
30+
size_t NUM_CIRCUITS = 1 << static_cast<size_t>(state.range(0));
31+
for (size_t circuit_idx = 0; circuit_idx < NUM_CIRCUITS; ++circuit_idx) {
32+
// Construct a circuit with logic resembling that of the "kernel circuit"
33+
GoblinUltraCircuitBuilder circuit_builder{ goblin.op_queue };
34+
GoblinMockCircuits::construct_mock_kernel_circuit(circuit_builder, kernel_input);
35+
36+
// Construct proof of the current kernel circuit to be recursively verified by the next one
37+
kernel_input = goblin.accumulate(circuit_builder);
38+
}
39+
40+
proof = goblin.prove();
41+
// Verify the final ultra proof
42+
}
43+
honk::GoblinUltraVerifier ultra_verifier{ kernel_input.verification_key };
44+
ultra_verifier.verify_proof(kernel_input.proof);
45+
// Verify the goblin proof (eccvm, translator, merge)
46+
goblin.verify(proof);
47+
}
48+
49+
void goblin_accumulate(State& state) noexcept
50+
{
51+
barretenberg::srs::init_crs_factory("../srs_db/ignition");
52+
barretenberg::srs::init_grumpkin_crs_factory("../srs_db/grumpkin");
53+
54+
Goblin goblin;
55+
56+
// Construct an initial circuit; its proof will be recursively verified by the first kernel
57+
GoblinUltraCircuitBuilder initial_circuit{ goblin.op_queue };
58+
GoblinMockCircuits::construct_simple_initial_circuit(initial_circuit);
59+
Goblin::AccumulationOutput kernel_input = goblin.accumulate(initial_circuit);
60+
61+
// Construct a series of simple Goblin circuits; generate and verify their proofs
62+
size_t NUM_CIRCUITS = 1 << static_cast<size_t>(state.range(0));
63+
for (auto _ : state) {
64+
for (size_t circuit_idx = 0; circuit_idx < NUM_CIRCUITS; ++circuit_idx) {
65+
// Construct a circuit with logic resembling that of the "kernel circuit"
66+
GoblinUltraCircuitBuilder circuit_builder{ goblin.op_queue };
67+
GoblinMockCircuits::construct_mock_kernel_circuit(circuit_builder, kernel_input);
68+
69+
// Construct proof of the current kernel circuit to be recursively verified by the next one
70+
kernel_input = goblin.accumulate(circuit_builder);
71+
}
72+
}
73+
}
74+
75+
void goblin_eccvm_prove(State& state) noexcept
76+
{
77+
barretenberg::srs::init_crs_factory("../srs_db/ignition");
78+
barretenberg::srs::init_grumpkin_crs_factory("../srs_db/grumpkin");
79+
80+
Goblin goblin;
81+
82+
// Construct an initial circuit; its proof will be recursively verified by the first kernel
83+
GoblinUltraCircuitBuilder initial_circuit{ goblin.op_queue };
84+
GoblinMockCircuits::construct_simple_initial_circuit(initial_circuit);
85+
Goblin::AccumulationOutput kernel_input = goblin.accumulate(initial_circuit);
86+
87+
// Construct a series of simple Goblin circuits; generate and verify their proofs
88+
size_t NUM_CIRCUITS = 1 << static_cast<size_t>(state.range(0));
89+
for (size_t circuit_idx = 0; circuit_idx < NUM_CIRCUITS; ++circuit_idx) {
90+
// Construct a circuit with logic resembling that of the "kernel circuit"
91+
GoblinUltraCircuitBuilder circuit_builder{ goblin.op_queue };
92+
GoblinMockCircuits::construct_mock_kernel_circuit(circuit_builder, kernel_input);
93+
94+
// Construct proof of the current kernel circuit to be recursively verified by the next one
95+
kernel_input = goblin.accumulate(circuit_builder);
96+
}
97+
98+
for (auto _ : state) {
99+
goblin.prove_eccvm();
100+
}
101+
}
102+
103+
void goblin_translator_prove(State& state) noexcept
104+
{
105+
barretenberg::srs::init_crs_factory("../srs_db/ignition");
106+
barretenberg::srs::init_grumpkin_crs_factory("../srs_db/grumpkin");
107+
108+
Goblin goblin;
109+
110+
// Construct an initial circuit; its proof will be recursively verified by the first kernel
111+
GoblinUltraCircuitBuilder initial_circuit{ goblin.op_queue };
112+
GoblinMockCircuits::construct_simple_initial_circuit(initial_circuit);
113+
Goblin::AccumulationOutput kernel_input = goblin.accumulate(initial_circuit);
114+
115+
// Construct a series of simple Goblin circuits; generate and verify their proofs
116+
size_t NUM_CIRCUITS = 1 << static_cast<size_t>(state.range(0));
117+
for (size_t circuit_idx = 0; circuit_idx < NUM_CIRCUITS; ++circuit_idx) {
118+
// Construct a circuit with logic resembling that of the "kernel circuit"
119+
GoblinUltraCircuitBuilder circuit_builder{ goblin.op_queue };
120+
GoblinMockCircuits::construct_mock_kernel_circuit(circuit_builder, kernel_input);
121+
122+
// Construct proof of the current kernel circuit to be recursively verified by the next one
123+
kernel_input = goblin.accumulate(circuit_builder);
124+
}
125+
126+
goblin.prove_eccvm();
127+
for (auto _ : state) {
128+
goblin.prove_translator();
129+
}
130+
}
131+
132+
} // namespace
133+
134+
BENCHMARK(goblin_full)->Unit(kMillisecond)->DenseRange(0, 7);
135+
BENCHMARK(goblin_accumulate)->Unit(kMillisecond)->DenseRange(0, 7);
136+
BENCHMARK(goblin_eccvm_prove)->Unit(kMillisecond)->DenseRange(0, 7);
137+
BENCHMARK(goblin_translator_prove)->Unit(kMillisecond)->DenseRange(0, 7);

barretenberg/cpp/src/barretenberg/dsl/acir_proofs/acir_composer.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "barretenberg/dsl/acir_format/acir_format.hpp"
55
#include "barretenberg/dsl/acir_format/recursion_constraint.hpp"
66
#include "barretenberg/dsl/types.hpp"
7+
#include "barretenberg/goblin/mock_circuits.hpp"
78
#include "barretenberg/plonk/proof_system/proving_key/proving_key.hpp"
89
#include "barretenberg/plonk/proof_system/proving_key/serialize.hpp"
910
#include "barretenberg/plonk/proof_system/verification_key/sol_gen.hpp"
@@ -101,7 +102,7 @@ void AcirComposer::create_goblin_circuit(acir_format::acir_format& constraint_sy
101102

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

107108
std::vector<uint8_t> AcirComposer::create_goblin_proof()

barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.hpp

+11-11
Original file line numberDiff line numberDiff line change
@@ -30,17 +30,17 @@ template <ECCVMFlavor Flavor> class ECCVMProver_ {
3030
const std::shared_ptr<PCSCommitmentKey>& commitment_key,
3131
const std::shared_ptr<Transcript>& transcript = std::make_shared<Transcript>());
3232

33-
void execute_preamble_round();
34-
void execute_wire_commitments_round();
35-
void execute_log_derivative_commitments_round();
36-
void execute_grand_product_computation_round();
37-
void execute_relation_check_rounds();
38-
void execute_univariatization_round();
39-
void execute_pcs_evaluation_round();
40-
void execute_shplonk_batched_quotient_round();
41-
void execute_shplonk_partial_evaluation_round();
42-
void execute_final_pcs_round();
43-
void execute_transcript_consistency_univariate_opening_round();
33+
BBERG_PROFILE void execute_preamble_round();
34+
BBERG_PROFILE void execute_wire_commitments_round();
35+
BBERG_PROFILE void execute_log_derivative_commitments_round();
36+
BBERG_PROFILE void execute_grand_product_computation_round();
37+
BBERG_PROFILE void execute_relation_check_rounds();
38+
BBERG_PROFILE void execute_univariatization_round();
39+
BBERG_PROFILE void execute_pcs_evaluation_round();
40+
BBERG_PROFILE void execute_shplonk_batched_quotient_round();
41+
BBERG_PROFILE void execute_shplonk_partial_evaluation_round();
42+
BBERG_PROFILE void execute_final_pcs_round();
43+
BBERG_PROFILE void execute_transcript_consistency_univariate_opening_round();
4444

4545
plonk::proof& export_proof();
4646
plonk::proof& construct_proof();

barretenberg/cpp/src/barretenberg/flavor/flavor.hpp

+3-5
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ class Ultra;
263263
class ECCVM;
264264
class GoblinUltra;
265265
template <typename BuilderType> class UltraRecursive_;
266-
template <typename BuilderType> class GoblinUltraRecursive_;
266+
class GoblinUltraRecursive;
267267
} // namespace proof_system::honk::flavor
268268

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

294294
template <typename T>
295295
concept IsGoblinFlavor = IsAnyOf<T, honk::flavor::GoblinUltra,
296-
honk::flavor::GoblinUltraRecursive_<UltraCircuitBuilder>,
297-
honk::flavor::GoblinUltraRecursive_<GoblinUltraCircuitBuilder>>;
296+
honk::flavor::GoblinUltraRecursive>;
298297

299298
template <typename T>
300299
concept IsRecursiveFlavor = IsAnyOf<T, honk::flavor::UltraRecursive_<UltraCircuitBuilder>,
301300
honk::flavor::UltraRecursive_<GoblinUltraCircuitBuilder>,
302-
honk::flavor::GoblinUltraRecursive_<UltraCircuitBuilder>,
303-
honk::flavor::GoblinUltraRecursive_<GoblinUltraCircuitBuilder>>;
301+
honk::flavor::GoblinUltraRecursive>;
304302

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

barretenberg/cpp/src/barretenberg/flavor/goblin_ultra_recursive.hpp

+6-8
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,14 @@ namespace proof_system::honk::flavor {
3838
*
3939
* @tparam BuilderType Determines the arithmetization of the verifier circuit defined based on this flavor.
4040
*/
41-
template <typename BuilderType> class GoblinUltraRecursive_ {
41+
class GoblinUltraRecursive {
4242
public:
43-
using CircuitBuilder = BuilderType; // Determines arithmetization of circuit instantiated with this flavor
43+
using CircuitBuilder = GoblinUltraCircuitBuilder;
4444
using Curve = plonk::stdlib::bn254<CircuitBuilder>;
45-
using GroupElement = typename Curve::Element;
46-
using Commitment = typename Curve::Element;
47-
using CommitmentHandle = typename Curve::Element;
48-
using FF = typename Curve::ScalarField;
45+
using GroupElement = Curve::Element;
46+
using FF = Curve::ScalarField;
47+
using Commitment = Curve::Element;
48+
using CommitmentHandle = Curve::Element;
4949
using NativeVerificationKey = flavor::GoblinUltra::VerificationKey;
5050

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

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

0 commit comments

Comments
 (0)