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

feat: IVC bench #4515

Merged
merged 32 commits into from
Feb 8, 2024
Merged
Show file tree
Hide file tree
Changes from 27 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
38a7327
gob recusion test with goblin.merge
ledwards2225 Feb 2, 2024
d5c3dbe
new folding test suite
ledwards2225 Feb 2, 2024
1b25736
Merge branch 'master' into lde/goblin_with_folding
ledwards2225 Feb 2, 2024
bb08bbe
Merge branch 'master' into lde/goblin_with_folding
ledwards2225 Feb 2, 2024
bb728f7
WiP; cant fold recursive folding verifier circuit
ledwards2225 Feb 2, 2024
81a5a93
Don't destroy shared_ptr; hack around different PI sizes.
codygunton Feb 5, 2024
668caca
Cleanup (Ultra already decided yeah?)
codygunton Feb 5, 2024
2be164d
Touch up example
codygunton Feb 5, 2024
ec5cf1f
Fix size printing
codygunton Feb 5, 2024
0b9e153
Move to new Bb module
codygunton Feb 5, 2024
7e1d64c
Use correct suite name
codygunton Feb 5, 2024
a67f8a2
Pseudocode
codygunton Feb 5, 2024
68f3e89
functionality in place; cleanup needed
ledwards2225 Feb 6, 2024
0690ac8
ivc prove and verify methods
ledwards2225 Feb 6, 2024
2a72e9e
Merge branch 'master' into lde/goblin_with_folding
ledwards2225 Feb 6, 2024
a69d34c
Cleanup and commenting
ledwards2225 Feb 7, 2024
600a17b
Merge branch 'master' into lde/goblin_with_folding
ledwards2225 Feb 7, 2024
416097a
verify final fold proof + typo
ledwards2225 Feb 7, 2024
cf24036
Merge branch 'master' into lde/goblin_with_folding
ledwards2225 Feb 7, 2024
f61b191
chaotic WiP
ledwards2225 Feb 7, 2024
54db43d
updates based on review
ledwards2225 Feb 7, 2024
56c02f0
Merge branch 'master' into lde/goblin_with_folding
ledwards2225 Feb 7, 2024
66a65fd
Merge branch 'lde/goblin_with_folding' into lde/ivc_bench
ledwards2225 Feb 7, 2024
af684ee
ivc bench is building
ledwards2225 Feb 7, 2024
57799db
Merge branch 'master' into lde/ivc_bench
ledwards2225 Feb 7, 2024
aa614d6
basic full ivc bench in place
ledwards2225 Feb 7, 2024
292543b
more benches plus pinning test
ledwards2225 Feb 8, 2024
42b3a04
kill prints
ledwards2225 Feb 8, 2024
b2587db
Merge branch 'master' into lde/ivc_bench
ledwards2225 Feb 8, 2024
0e404bc
cleanup
ledwards2225 Feb 8, 2024
93a2470
more cleanup
ledwards2225 Feb 8, 2024
91fbbfb
move folding kernel pinning to ivc
ledwards2225 Feb 8, 2024
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
11 changes: 6 additions & 5 deletions barretenberg/cpp/src/barretenberg/benchmark/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
add_subdirectory(basics_bench)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

added ivc_bench and alphabetized

add_subdirectory(decrypt_bench)
add_subdirectory(ipa_bench)
add_subdirectory(ivc_bench)
add_subdirectory(goblin_bench)
add_subdirectory(pippenger_bench)
add_subdirectory(plonk_bench)
add_subdirectory(ultra_bench)
add_subdirectory(goblin_bench)
add_subdirectory(basics_bench)
add_subdirectory(protogalaxy_bench)
add_subdirectory(relations_bench)
add_subdirectory(widgets_bench)
add_subdirectory(protogalaxy_bench)
add_subdirectory(ultra_bench)
add_subdirectory(widgets_bench)
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ class GoblinBench : public benchmark::Fixture {
// Construct and accumulate the mock kernel circuit
// Note: in first round, kernel_accum is empty since there is no previous kernel to recursively verify
GoblinUltraCircuitBuilder circuit_builder{ goblin.op_queue };
GoblinMockCircuits::construct_mock_kernel_circuit(circuit_builder, function_accum, kernel_accum);
GoblinMockCircuits::construct_mock_recursion_kernel_circuit(circuit_builder, function_accum, kernel_accum);
kernel_accum = goblin.accumulate(circuit_builder);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
barretenberg_module(ivc_bench client_ivc stdlib_recursion stdlib_sha256 stdlib_merkle_tree stdlib_primitives)
180 changes: 180 additions & 0 deletions barretenberg/cpp/src/barretenberg/benchmark/ivc_bench/ivc.bench.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@

#include <benchmark/benchmark.h>

#include "barretenberg/benchmark/ultra_bench/mock_proofs.hpp"
#include "barretenberg/client_ivc/client_ivc.hpp"
#include "barretenberg/common/op_count_google_bench.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 bb;

namespace {

/**
* @brief Benchmark suite for the aztec client PG-Goblin IVC scheme
*
*/
class IvcBench : public benchmark::Fixture {
public:
// Goblin::AccumulationOutput kernel_accum;
using Builder = GoblinUltraCircuitBuilder;

// Number of function circuits to accumulate(based on Zacs target numbers)
static constexpr size_t NUM_ITERATIONS_MEDIUM_COMPLEXITY = 6;

void SetUp([[maybe_unused]] const ::benchmark::State& state) override
{
bb::srs::init_crs_factory("../srs_db/ignition");
bb::srs::init_grumpkin_crs_factory("../srs_db/grumpkin");
}

/**
* @brief Perform a specified number of function circuit accumulation rounds
* @details Each round "accumulates" a mock function circuit and a mock kernel circuit. Each round thus consists of
* the generation of two circuits, two folding proofs and two Merge proofs. To match the sizes called out in the
* spec
* (https://github.com/AztecProtocol/aztec-packages/blob/master/yellow-paper/docs/cryptography/performance-targets.md)
* we set the size of the function circuit to be 2^17. The first one should be 2^19 but we can't currently support
* folding circuits of unequal size.
*
* @param state
*/
static void perform_ivc_accumulation_rounds(State& state, ClientIVC& ivc)
{
// Initialize IVC with function circuit
Builder function_circuit{ ivc.goblin.op_queue };
GoblinMockCircuits::construct_mock_function_circuit(function_circuit);
ivc.initialize(function_circuit);

// Accumulate kernel circuit (first kernel mocked as simple circuit since no folding proofs yet)
Builder kernel_circuit{ ivc.goblin.op_queue };
GoblinMockCircuits::construct_mock_function_circuit(kernel_circuit);
auto kernel_fold_proof = ivc.accumulate(kernel_circuit);

auto NUM_CIRCUITS = static_cast<size_t>(state.range(0));
NUM_CIRCUITS -= 1; // Subtract one to account for the "initialization" round above
for (size_t circuit_idx = 0; circuit_idx < NUM_CIRCUITS; ++circuit_idx) {

// Accumulate function circuit
Builder function_circuit{ ivc.goblin.op_queue };
GoblinMockCircuits::construct_mock_function_circuit(function_circuit);
auto function_fold_proof = ivc.accumulate(function_circuit);

// Accumulate kernel circuit
Builder kernel_circuit{ ivc.goblin.op_queue };
GoblinMockCircuits::construct_mock_folding_kernel(kernel_circuit, function_fold_proof, kernel_fold_proof);
auto kernel_fold_proof = ivc.accumulate(kernel_circuit);
}
}
};

/**
* @brief Benchmark the full PG-Goblin IVC protocol
*
*/
BENCHMARK_DEFINE_F(IvcBench, Full)(benchmark::State& state)
{
ClientIVC ivc;

for (auto _ : state) {
BB_REPORT_OP_COUNT_IN_BENCH(state);
// Perform a specified number of iterations of function/kernel accumulation
perform_ivc_accumulation_rounds(state, ivc);

// Construct IVC scheme proof (fold, decider, merge, eccvm, translator)
ivc.prove();
}
}

/**
* @brief Benchmark only the accumulation rounds
*
*/
BENCHMARK_DEFINE_F(IvcBench, Accumulate)(benchmark::State& state)
{
ClientIVC ivc;

// Perform a specified number of iterations of function/kernel accumulation
for (auto _ : state) {
perform_ivc_accumulation_rounds(state, ivc);
}
}

/**
* @brief Benchmark only the Decider component
*
*/
BENCHMARK_DEFINE_F(IvcBench, Decide)(benchmark::State& state)
{
ClientIVC ivc;

BB_REPORT_OP_COUNT_IN_BENCH(state);
// Perform a specified number of iterations of function/kernel accumulation
perform_ivc_accumulation_rounds(state, ivc);

// Construct eccvm proof, measure only translator proof construction
for (auto _ : state) {
ivc.decider_prove();
}
}

/**
* @brief Benchmark only the ECCVM component
*
*/
BENCHMARK_DEFINE_F(IvcBench, ECCVM)(benchmark::State& state)
{
ClientIVC ivc;

BB_REPORT_OP_COUNT_IN_BENCH(state);
// Perform a specified number of iterations of function/kernel accumulation
perform_ivc_accumulation_rounds(state, ivc);

// Construct and measure eccvm only
for (auto _ : state) {
ivc.goblin.prove_eccvm();
}
}

/**
* @brief Benchmark only the Translator component
*
*/
BENCHMARK_DEFINE_F(IvcBench, Translator)(benchmark::State& state)
{
ClientIVC ivc;

BB_REPORT_OP_COUNT_IN_BENCH(state);
// Perform a specified number of iterations of function/kernel accumulation
perform_ivc_accumulation_rounds(state, ivc);

// Construct eccvm proof, measure only translator proof construction
ivc.goblin.prove_eccvm();
for (auto _ : state) {
ivc.goblin.prove_translator();
}
}

#define ARGS \
Arg(IvcBench::NUM_ITERATIONS_MEDIUM_COMPLEXITY) \
->Arg(1 << 0) \
->Arg(1 << 1) \
->Arg(1 << 2) \
->Arg(1 << 3) \
->Arg(1 << 4) \
->Arg(1 << 5) \
->Arg(1 << 6)

BENCHMARK_REGISTER_F(IvcBench, Full)->Unit(benchmark::kMillisecond)->ARGS;
BENCHMARK_REGISTER_F(IvcBench, Accumulate)->Unit(benchmark::kMillisecond)->ARGS;
BENCHMARK_REGISTER_F(IvcBench, Decide)->Unit(benchmark::kMillisecond)->ARGS;
BENCHMARK_REGISTER_F(IvcBench, ECCVM)->Unit(benchmark::kMillisecond)->ARGS;
BENCHMARK_REGISTER_F(IvcBench, Translator)->Unit(benchmark::kMillisecond)->ARGS;

} // namespace

BENCHMARK_MAIN();
23 changes: 15 additions & 8 deletions barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ ClientIVC::FoldProof ClientIVC::accumulate(ClientCircuit& circuit)
goblin.merge(circuit); // Add recursive merge verifier and construct new merge proof
Composer composer;
auto instance = composer.create_instance(circuit);
info("accumulate: instance->instance_size", instance->proving_key->circuit_size);
std::vector<std::shared_ptr<Instance>> instances{ fold_output.accumulator, instance };
auto folding_prover = composer.create_folding_prover(instances);
fold_output = folding_prover.fold_instances();
Expand All @@ -46,14 +47,7 @@ ClientIVC::FoldProof ClientIVC::accumulate(ClientCircuit& circuit)
*/
ClientIVC::Proof ClientIVC::prove()
{
// Construct Goblin proof (merge, eccvm, translator)
auto goblin_proof = goblin.prove();

// Construct decider proof for the final accumulator
Composer composer;
auto decider_prover = composer.create_decider_prover(fold_output.accumulator);
auto decider_proof = decider_prover.construct_proof();
return { goblin_proof, fold_output.folding_data, decider_proof };
return { fold_output.folding_data, decider_prove(), goblin.prove() };
}

/**
Expand All @@ -76,4 +70,17 @@ bool ClientIVC::verify(Proof& proof)
bool decision = decider_verifier.verify_proof(proof.decider_proof);
return goblin_verified && folding_verified && decision;
}

/**
* @brief Internal method for constructing a decider proof
*
* @return HonkProof
*/
HonkProof ClientIVC::decider_prove() const
{
Composer composer;
auto decider_prover = composer.create_decider_prover(fold_output.accumulator);
return decider_prover.construct_proof();
}

} // namespace bb
4 changes: 3 additions & 1 deletion barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ class ClientIVC {

// A full proof for the IVC scheme
struct Proof {
Goblin::Proof goblin_proof;
FoldProof fold_proof; // final fold proof
HonkProof decider_proof;
Goblin::Proof goblin_proof;
};

private:
Expand All @@ -46,5 +46,7 @@ class ClientIVC {
Proof prove();

bool verify(Proof& proof);

HonkProof decider_prove() const;
};
} // namespace bb
2 changes: 1 addition & 1 deletion barretenberg/cpp/src/barretenberg/goblin/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
barretenberg_module(goblin stdlib_recursion ultra_honk eccvm translator_vm stdlib_sha256 stdlib_merkle_tree stdlib_primitives)
barretenberg_module(goblin stdlib_recursion ultra_honk eccvm translator_vm stdlib_sha256 stdlib_merkle_tree stdlib_primitives client_ivc)
Copy link
Contributor Author

@ledwards2225 ledwards2225 Feb 8, 2024

Choose a reason for hiding this comment

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

Needing to add client_ivc to the goblin module is is again a symptom of having mock_circuits within goblin. There's a good bit of related restructuring to do here so I'd like to do a follow on to move things around.

Copy link
Contributor

Choose a reason for hiding this comment

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

This introduces a circular dependency. Can you just do the reorg now?

Copy link
Contributor

Choose a reason for hiding this comment

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

I don't understand why this is needed here. What's defined (not declared, but defined) in client_ivc but needed in goblin?

46 changes: 42 additions & 4 deletions barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "barretenberg/stdlib/merkle_tree/merkle_tree.hpp"
#include "barretenberg/stdlib/primitives/curves/secp256k1.hpp"
#include "barretenberg/stdlib/primitives/packed_byte_array/packed_byte_array.hpp"
#include "barretenberg/stdlib/recursion/honk/verifier/protogalaxy_recursive_verifier.hpp"
#include "barretenberg/stdlib/recursion/honk/verifier/ultra_recursive_verifier.hpp"

namespace bb {
Expand All @@ -31,6 +32,11 @@ class GoblinMockCircuits {
using KernelInput = Goblin::AccumulationOutput;
static constexpr size_t NUM_OP_QUEUE_COLUMNS = Flavor::NUM_WIRES;

using GURecursiveFlavor = GoblinUltraRecursiveFlavor_<GoblinUltraBuilder>;
using RecursiveVerifierInstances = ::bb::VerifierInstances_<GURecursiveFlavor, 2>;
using FoldingRecursiveVerifier =
bb::stdlib::recursion::honk::ProtoGalaxyRecursiveVerifier_<RecursiveVerifierInstances>;

/**
* @brief Populate a builder with a specified number of arithmetic gates; includes a PI
*
Expand Down Expand Up @@ -164,7 +170,7 @@ class GoblinMockCircuits {
}

/**
* @brief Construct a size 2^17 mock kernel circuit for benchmarking
* @brief Construct a size 2^17 mock kernel circuit based on vanilla recursion for benchmarking
* @details This circuit contains (1) some arbitrary operations representing general kernel logic, (2) recursive
* verification of a function circuit proof, and optionally (3) recursive verification of a previous kernel circuit
* proof. The arbitrary kernel logic is structured to bring the final dyadic circuit size of the kernel to 2^17.
Expand All @@ -174,9 +180,9 @@ class GoblinMockCircuits {
* @param function_accum {proof, vkey} for function circuit to be recursively verified
* @param prev_kernel_accum {proof, vkey} for previous kernel circuit to be recursively verified
*/
static void construct_mock_kernel_circuit(GoblinUltraBuilder& builder,
const KernelInput& function_accum,
const KernelInput& prev_kernel_accum)
static void construct_mock_recursion_kernel_circuit(GoblinUltraBuilder& builder,
const KernelInput& function_accum,
const KernelInput& prev_kernel_accum)
{
// Add operations representing general kernel logic e.g. state updates. Note: these are structured to make the
// kernel "full" within the dyadic size 2^17 (130914 gates)
Expand All @@ -198,6 +204,38 @@ class GoblinMockCircuits {
}
}

/**
* @brief Construct a mock kernel circuit based on folding
* @details This circuit contains (1) some arbitrary operations representing general kernel logic, (2) recursive
* folding verification of a function circuit folding proof, and optionally (3) recursive folding verification of a
* previous kernel circuit folding proof. The arbitrary kernel logic is structured to bring the final dyadic circuit
* size of the kernel to 2^17.
*
* TODO(https://github.com/AztecProtocol/barretenberg/issues/801): Pairing point aggregation not implemented
* @param builder
* @param function_accum {proof, vkey} for function circuit to be recursively verified
* @param prev_kernel_accum {proof, vkey} for previous kernel circuit to be recursively verified
*/
static void construct_mock_folding_kernel(GoblinUltraBuilder& builder,
const std::vector<FF>& function_fold_proof,
const std::vector<FF>& kernel_fold_proof)
{
// Add operations representing general kernel logic e.g. state updates. Note: these are structured to make the
// kernel "full" within the dyadic size 2^17 (130914 gates)
const size_t NUM_MERKLE_CHECKS = 20;
const size_t NUM_ECDSA_VERIFICATIONS = 1;
const size_t NUM_SHA_HASHES = 1;
stdlib::generate_merkle_membership_test_circuit(builder, NUM_MERKLE_CHECKS);
stdlib::generate_ecdsa_verification_test_circuit(builder, NUM_ECDSA_VERIFICATIONS);
stdlib::generate_sha256_test_circuit(builder, NUM_SHA_HASHES);

FoldingRecursiveVerifier verifier_1{ &builder };
verifier_1.verify_folding_proof(function_fold_proof);

FoldingRecursiveVerifier verifier_2{ &builder };
verifier_2.verify_folding_proof(kernel_fold_proof);
}

/**
* @brief A minimal version of the mock kernel (recursive verifiers only) for faster testing
*
Expand Down
Loading
Loading