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: Remove VK computation Pg prover flow; improve benchmark to reflect possible optimization #4639

Merged
merged 32 commits into from
Feb 29, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
eebe885
moved to new branch
maramihali Feb 16, 2024
30f9b9e
works
maramihali Feb 16, 2024
bbaacad
aaaaaaaaaaaaa
maramihali Feb 16, 2024
b5b77f4
bench work
maramihali Feb 16, 2024
7e09c8b
cleaning up
maramihali Feb 19, 2024
2188c57
Merge branch 'master' into mm/pg-refactor-new
maramihali Feb 19, 2024
ffaddfc
cleanup
maramihali Feb 19, 2024
ec36ede
more cleanup
maramihali Feb 20, 2024
f97dd1e
more cleanup
maramihali Feb 20, 2024
f1934c1
Merge branch 'mm/pg-refactor-new' of github.com:AztecProtocol/aztec-p…
maramihali Feb 20, 2024
5a75ea3
Merge branch 'master' into mm/pg-refactor-new
maramihali Feb 20, 2024
c587218
typos + make gcc pass
maramihali Feb 20, 2024
cb57dad
stuff
maramihali Feb 20, 2024
58b61b8
Merge branch 'master' into mm/pg-refactor-new
maramihali Feb 21, 2024
f1f7127
make sure we fold as many function circuits as expected, not one more
maramihali Feb 22, 2024
a89ebd0
Merge branch 'master' into mm/pg-refactor-new
maramihali Feb 22, 2024
0388795
additional op count timing
ludamad Feb 22, 2024
02bc325
Merge branch 'master' into mm/pg-refactor-new
maramihali Feb 22, 2024
0e78233
Merge branch 'feat/op-count-time-ivc-bench' into mm/pg-refactor-new
ludamad Feb 22, 2024
8b52cc0
Merge remote-tracking branch 'origin/mm/pg-refactor-new' into mm/pg-r…
ludamad Feb 22, 2024
f6378f3
Merge github.com:AztecProtocol/aztec-packages into mm/pg-refactor-new
maramihali Feb 22, 2024
6a339fe
Merge branch 'mm/pg-refactor-new' of github.com:AztecProtocol/aztec-p…
maramihali Feb 22, 2024
de842c4
Merge branch 'master' into mm/pg-refactor-new
maramihali Feb 23, 2024
26118e6
Merge remote-tracking branch 'origin/master' into mm/pg-refactor-new
codygunton Feb 23, 2024
b80d8f6
Merge branch 'mm/pg-refactor-new' of github.com:AztecProtocol/aztec-p…
maramihali Feb 26, 2024
30d92bc
Merge branch 'master' into mm/pg-refactor-new
maramihali Feb 26, 2024
53affad
respond to review
maramihali Feb 28, 2024
64ea544
Merge branch 'master' into mm/pg-refactor-new
maramihali Feb 28, 2024
4e40628
more refactoring based to PR reviews
maramihali Feb 28, 2024
9261e38
Merge branch 'master' into mm/pg-refactor-new
maramihali Feb 29, 2024
94ed534
address more pr comments
maramihali Feb 29, 2024
940f842
Merge branch 'master' into mm/pg-refactor-new
maramihali Feb 29, 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
47 changes: 30 additions & 17 deletions barretenberg/cpp/src/barretenberg/benchmark/ivc_bench/ivc.bench.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ namespace {
class IvcBench : public benchmark::Fixture {
public:
using Builder = GoblinUltraCircuitBuilder;
using FoldOutput = GoblinMockCircuits::FoldOutput;

// Number of function circuits to accumulate(based on Zacs target numbers)
static constexpr size_t NUM_ITERATIONS_MEDIUM_COMPLEXITY = 6;
Expand All @@ -33,39 +34,51 @@ class IvcBench : public benchmark::Fixture {

/**
* @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
* @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
* 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.
*
*/
static void perform_ivc_accumulation_rounds(State& state, ClientIVC& ivc)
{
// Initialize IVC with function circuit
Builder function_circuit{ ivc.goblin.op_queue };
GoblinUltraCircuitBuilder initial_function_circuit{ ivc.goblin.op_queue };
GoblinMockCircuits::construct_mock_function_circuit(initial_function_circuit);
ivc.initialize(initial_function_circuit);
auto kernel_acc = std::make_shared<ClientIVC::VerifierInstance>();
kernel_acc->verification_key = ivc.vks[0];

GoblinUltraCircuitBuilder function_circuit{ ivc.goblin.op_queue };
GoblinMockCircuits::construct_mock_function_circuit(function_circuit);
ivc.initialize(function_circuit);
auto function_fold_proof = ivc.accumulate(function_circuit);
FoldOutput function_fold_output = { function_fold_proof, ivc.vks[1] };

// 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);
kernel_acc =
GoblinMockCircuits::construct_mock_folding_kernel(kernel_circuit, function_fold_output, {}, kernel_acc);
auto kernel_fold_proof = ivc.accumulate(kernel_circuit);

FoldOutput kernel_fold_output = { kernel_fold_proof, ivc.vks[2] };
auto NUM_CIRCUITS = static_cast<size_t>(state.range(0));
NUM_CIRCUITS -= 1; // Subtract one to account for the "initialization" round above
// Subtract one to account for the "initialization" round above
NUM_CIRCUITS -= 1;
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);
function_fold_output = { function_fold_proof, ivc.vks[1] };

// 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);
kernel_acc = GoblinMockCircuits::construct_mock_folding_kernel(
kernel_circuit, function_fold_output, kernel_fold_output, kernel_acc);

kernel_fold_proof = ivc.accumulate(kernel_circuit);
kernel_fold_output = { kernel_fold_proof, ivc.vks[3] };
}
}
};
Expand All @@ -77,7 +90,7 @@ class IvcBench : public benchmark::Fixture {
BENCHMARK_DEFINE_F(IvcBench, Full)(benchmark::State& state)
{
ClientIVC ivc;

ivc.precompute_folding_verification_keys();
for (auto _ : state) {
BB_REPORT_OP_COUNT_IN_BENCH(state);
// Perform a specified number of iterations of function/kernel accumulation
Expand All @@ -95,7 +108,7 @@ BENCHMARK_DEFINE_F(IvcBench, Full)(benchmark::State& state)
BENCHMARK_DEFINE_F(IvcBench, Accumulate)(benchmark::State& state)
{
ClientIVC ivc;

ivc.precompute_folding_verification_keys();
// Perform a specified number of iterations of function/kernel accumulation
for (auto _ : state) {
perform_ivc_accumulation_rounds(state, ivc);
Expand All @@ -109,7 +122,7 @@ BENCHMARK_DEFINE_F(IvcBench, Accumulate)(benchmark::State& state)
BENCHMARK_DEFINE_F(IvcBench, Decide)(benchmark::State& state)
{
ClientIVC ivc;

ivc.precompute_folding_verification_keys();
BB_REPORT_OP_COUNT_IN_BENCH(state);
// Perform a specified number of iterations of function/kernel accumulation
perform_ivc_accumulation_rounds(state, ivc);
Expand All @@ -127,7 +140,7 @@ BENCHMARK_DEFINE_F(IvcBench, Decide)(benchmark::State& state)
BENCHMARK_DEFINE_F(IvcBench, ECCVM)(benchmark::State& state)
{
ClientIVC ivc;

ivc.precompute_folding_verification_keys();
BB_REPORT_OP_COUNT_IN_BENCH(state);
// Perform a specified number of iterations of function/kernel accumulation
perform_ivc_accumulation_rounds(state, ivc);
Expand All @@ -145,7 +158,7 @@ BENCHMARK_DEFINE_F(IvcBench, ECCVM)(benchmark::State& state)
BENCHMARK_DEFINE_F(IvcBench, Translator)(benchmark::State& state)
{
ClientIVC ivc;

ivc.precompute_folding_verification_keys();
BB_REPORT_OP_COUNT_IN_BENCH(state);
// Perform a specified number of iterations of function/kernel accumulation
perform_ivc_accumulation_rounds(state, ivc);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ template <typename Composer> void fold_one(State& state) noexcept
static_assert(std::same_as<Flavor, UltraFlavor>);
bb::mock_proofs::generate_basic_arithmetic_circuit(builder, log2_num_gates);
}
return composer.create_instance(builder);
return composer.create_prover_instance(builder);
};

std::shared_ptr<Instance> instance_1 = construct_instance();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,41 +12,41 @@ template <typename Composer>
void _bench_round(::benchmark::State& state,
void (*F)(ProtoGalaxyProver_<ProverInstances_<typename Composer::Flavor, 2>>&))
{
using Flavor = typename Composer::Flavor;
using Instance = ProverInstance_<Flavor>;
using Builder = typename Flavor::CircuitBuilder;

bb::srs::init_crs_factory("../srs_db/ignition");
auto log2_num_gates = static_cast<size_t>(state.range(0));
auto composer = Composer();

const auto construct_instance = [&]() {
Builder builder;
if constexpr (std::same_as<Flavor, GoblinUltraFlavor>) {
GoblinMockCircuits::construct_arithmetic_circuit(builder, log2_num_gates);
} else {
static_assert(std::same_as<Flavor, UltraFlavor>);
bb::mock_proofs::generate_basic_arithmetic_circuit(builder, log2_num_gates);
}
return composer.create_instance(builder);
};

std::shared_ptr<Instance> instance_1 = construct_instance();
std::shared_ptr<Instance> instance_2 = construct_instance();

auto folding_prover = composer.create_folding_prover({ instance_1, instance_2 });

// prepare the prover state
folding_prover.state.accumulator = instance_1;
folding_prover.state.deltas.resize(log2_num_gates);
std::fill_n(folding_prover.state.deltas.begin(), log2_num_gates, 0);
folding_prover.state.perturbator = Flavor::Polynomial::random(1 << log2_num_gates);
folding_prover.transcript = Flavor::Transcript::prover_init_empty();
folding_prover.preparation_round();

for (auto _ : state) {
F(folding_prover);
}
// using Flavor = typename Composer::Flavor;
// using Instance = ProverInstance_<Flavor>;
// using Builder = typename Flavor::CircuitBuilder;
static_cast<void>(state);
static_cast<void>(F);
// bb::srs::init_crs_factory("../srs_db/ignition");
// auto log2_num_gates = static_cast<size_t>(state.range(0));
// auto composer = Composer();

// const auto construct_instance = [&]() {
// Builder builder;
// if constexpr (std::same_as<Flavor, GoblinUltraFlavor>) {
// GoblinMockCircuits::construct_arithmetic_circuit(builder, log2_num_gates);
// } else {
// static_assert(std::same_as<Flavor, UltraFlavor>);
// bb::mock_proofs::generate_basic_arithmetic_circuit(builder, log2_num_gates);
// }
// return composer.create_prover_instance(builder);
// };

// std::shared_ptr<Instance> instance_1 = construct_instance();
// std::shared_ptr<Instance> instance_2 = construct_instance();

// auto folding_prover = composer.create_folding_prover({ instance_1, instance_2 });

// // prepare the prover state
// folding_prover.state.accumulator = instance_1;
// folding_prover.state.deltas.resize(log2_num_gates);
// std::fill_n(folding_prover.state.deltas.begin(), log2_num_gates, 0);
// folding_prover.state.perturbator = Flavor::Polynomial::random(1 << log2_num_gates);
// folding_prover.transcript = Flavor::Transcript::prover_init_empty();
// folding_prover.preparation_round();

// for (auto _ : state) {
// F(folding_prover);
}

void bench_round_ultra(::benchmark::State& state, void (*F)(ProtoGalaxyProver_<ProverInstances_<UltraFlavor, 2>>&))
Expand All @@ -60,23 +60,25 @@ void bench_round_goblin_ultra(::benchmark::State& state,
_bench_round<GoblinUltraComposer>(state, F);
}

BENCHMARK_CAPTURE(bench_round_ultra, preparation, [](auto& prover) { prover.preparation_round(); })
-> DenseRange(14, 20) -> Unit(kMillisecond);
BENCHMARK_CAPTURE(bench_round_ultra, perturbator, [](auto& prover) { prover.perturbator_round(); })
-> DenseRange(14, 20) -> Unit(kMillisecond);
BENCHMARK_CAPTURE(bench_round_ultra, combiner_quotient, [](auto& prover) { prover.combiner_quotient_round(); })
-> DenseRange(14, 20) -> Unit(kMillisecond);
BENCHMARK_CAPTURE(bench_round_ultra, accumulator_update, [](auto& prover) { prover.accumulator_update_round(); })
-> DenseRange(14, 20) -> Unit(kMillisecond);

BENCHMARK_CAPTURE(bench_round_goblin_ultra, preparation, [](auto& prover) { prover.preparation_round(); })
-> DenseRange(14, 20) -> Unit(kMillisecond);
BENCHMARK_CAPTURE(bench_round_goblin_ultra, perturbator, [](auto& prover) { prover.perturbator_round(); })
-> DenseRange(14, 20) -> Unit(kMillisecond);
BENCHMARK_CAPTURE(bench_round_goblin_ultra, combiner_quotient, [](auto& prover) { prover.combiner_quotient_round(); })
-> DenseRange(14, 20) -> Unit(kMillisecond);
BENCHMARK_CAPTURE(bench_round_goblin_ultra, accumulator_update, [](auto& prover) { prover.accumulator_update_round(); })
-> DenseRange(14, 20) -> Unit(kMillisecond);
// BENCHMARK_CAPTURE(bench_round_ultra, preparation, [](auto& prover) { prover.preparation_round(); })
// -> DenseRange(14, 20) -> Unit(kMillisecond);
// BENCHMARK_CAPTURE(bench_round_ultra, perturbator, [](auto& prover) { prover.perturbator_round(); })
// -> DenseRange(14, 20) -> Unit(kMillisecond);
// BENCHMARK_CAPTURE(bench_round_ultra, combiner_quotient, [](auto& prover) { prover.combiner_quotient_round(); })
// -> DenseRange(14, 20) -> Unit(kMillisecond);
// BENCHMARK_CAPTURE(bench_round_ultra, accumulator_update, [](auto& prover) { prover.accumulator_update_round(); })
// -> DenseRange(14, 20) -> Unit(kMillisecond);

// BENCHMARK_CAPTURE(bench_round_goblin_ultra, preparation, [](auto& prover) { prover.preparation_round(); })
// -> DenseRange(14, 20) -> Unit(kMillisecond);
// BENCHMARK_CAPTURE(bench_round_goblin_ultra, perturbator, [](auto& prover) { prover.perturbator_round(); })
// -> DenseRange(14, 20) -> Unit(kMillisecond);
// BENCHMARK_CAPTURE(bench_round_goblin_ultra, combiner_quotient, [](auto& prover) { prover.combiner_quotient_round();
// })
// -> DenseRange(14, 20) -> Unit(kMillisecond);
// BENCHMARK_CAPTURE(bench_round_goblin_ultra, accumulator_update, [](auto& prover) { prover.accumulator_update_round();
// })
// -> DenseRange(14, 20) -> Unit(kMillisecond);

} // namespace bb

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ inline UltraProver get_prover(UltraComposer& composer,
{
UltraComposer::CircuitBuilder builder;
test_circuit_function(builder, num_iterations);
std::shared_ptr<UltraComposer::Instance> instance = composer.create_instance(builder);
std::shared_ptr<UltraComposer::ProverInstance> instance = composer.create_prover_instance(builder);
return composer.create_prover(instance);
}

Expand All @@ -64,7 +64,7 @@ inline GoblinUltraProver get_prover(GoblinUltraComposer& composer,
{
GoblinUltraComposer::CircuitBuilder builder;
test_circuit_function(builder, num_iterations);
std::shared_ptr<GoblinUltraComposer::Instance> instance = composer.create_instance(builder);
std::shared_ptr<GoblinUltraComposer::ProverInstance> instance = composer.create_prover_instance(builder);
return composer.create_prover(instance);
}

Expand Down
77 changes: 64 additions & 13 deletions barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ void ClientIVC::initialize(ClientCircuit& circuit)
{
goblin.merge(circuit); // Construct new merge proof
Composer composer;
fold_output.accumulator = composer.create_instance(circuit);
prover_fold_output.accumulator = composer.create_prover_instance(circuit);
}

/**
Expand All @@ -32,11 +32,10 @@ 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);
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();
return fold_output.folding_data;
prover_instance = composer.create_prover_instance(circuit);
auto folding_prover = composer.create_folding_prover({ prover_fold_output.accumulator, prover_instance });
prover_fold_output = folding_prover.fold_instances();
return prover_fold_output.folding_data;
}

/**
Expand All @@ -46,7 +45,7 @@ ClientIVC::FoldProof ClientIVC::accumulate(ClientCircuit& circuit)
*/
ClientIVC::Proof ClientIVC::prove()
{
return { fold_output.folding_data, decider_prove(), goblin.prove() };
return { prover_fold_output.folding_data, decider_prove(), goblin.prove() };
}

/**
Expand All @@ -55,19 +54,19 @@ ClientIVC::Proof ClientIVC::prove()
* @param proof
* @return bool
*/
bool ClientIVC::verify(Proof& proof)
bool ClientIVC::verify(Proof& proof, const std::vector<ClientIVC::VerifierAccumulator>& verifier_instances)
{
// Goblin verification (merge, eccvm, translator)
bool goblin_verified = goblin.verify(proof.goblin_proof);

// Decider verification
Composer composer;
auto folding_verifier = composer.create_folding_verifier();
bool folding_verified = folding_verifier.verify_folding_proof(proof.fold_proof);
auto folding_verifier = composer.create_folding_verifier({ verifier_instances[0], verifier_instances[1] });
auto verifier_accumulator = folding_verifier.verify_folding_proof(proof.fold_proof);
// NOTE: Use of member accumulator here will go away with removal of vkey from ProverInstance
auto decider_verifier = composer.create_decider_verifier(fold_output.accumulator);
auto decider_verifier = composer.create_decider_verifier(verifier_accumulator);
bool decision = decider_verifier.verify_proof(proof.decider_proof);
return goblin_verified && folding_verified && decision;
return goblin_verified && decision;
}

/**
Expand All @@ -78,8 +77,60 @@ bool ClientIVC::verify(Proof& proof)
HonkProof ClientIVC::decider_prove() const
{
Composer composer;
auto decider_prover = composer.create_decider_prover(fold_output.accumulator);
auto decider_prover = composer.create_decider_prover(prover_fold_output.accumulator);
return decider_prover.construct_proof();
}

/**
* @brief Precompute the array of verification keys by simulating folding. There will be 4 different verification keys.
*
*/
void ClientIVC::precompute_folding_verification_keys()
{
Composer composer;

// Accumulate three circuits to generate two folding proofs for input to folding kernel
ClientCircuit circuit_1{ goblin.op_queue };
GoblinMockCircuits::construct_mock_function_circuit(circuit_1);

initialize(circuit_1);

composer.compute_commitment_key(prover_fold_output.accumulator->instance_size);

vks[0] = composer.compute_verification_key(prover_fold_output.accumulator);
auto verifier_acc = std::make_shared<VerifierInstance>();
verifier_acc->verification_key = vks[0];

ClientCircuit circuit_2{ goblin.op_queue };
GoblinMockCircuits::construct_mock_function_circuit(circuit_2);
auto fold_proof_1 = accumulate(circuit_2);
vks[1] = composer.compute_verification_key(prover_instance);

FoldOutput kernel_accum;
// Construct kernel circuit
ClientCircuit kernel_circuit{ goblin.op_queue };
auto new_acc =
GoblinMockCircuits::construct_mock_folding_kernel(kernel_circuit, { fold_proof_1, vks[1] }, {}, verifier_acc);
auto fold_proof_3 = accumulate(kernel_circuit);
vks[2] = composer.compute_verification_key(prover_instance); // first iteration of a kernel is smaller

ClientCircuit circuit_4{ goblin.op_queue };
GoblinMockCircuits::construct_mock_function_circuit(circuit_4);
auto fold_proof_4 = accumulate(circuit_4);

ClientCircuit new_kernel_circuit = GoblinUltraCircuitBuilder{ goblin.op_queue };
auto new_new_acc = GoblinMockCircuits::construct_mock_folding_kernel(
new_kernel_circuit, { fold_proof_4, vks[1] }, { fold_proof_3, vks[2] }, new_acc);

auto fold_proof_5 = accumulate(new_kernel_circuit);

vks[3] = composer.compute_verification_key(prover_instance);
auto kernel_inst = std::make_shared<VerifierInstance>();
kernel_inst->verification_key = vks[3];

goblin.op_queue = std::make_shared<Goblin::OpQueue>();
goblin.merge_proof_exists = false;
GoblinMockCircuits::perform_op_queue_interactions_for_mock_first_circuit(goblin.op_queue);
}

} // namespace bb
Loading
Loading