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: PG + Goblin #4399

Merged
merged 21 commits into from
Feb 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
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
3 changes: 1 addition & 2 deletions barretenberg/barretenberg.code-workspace
Original file line number Diff line number Diff line change
Expand Up @@ -152,8 +152,7 @@
},
"cmake.configureArgs": [
"--preset clang16",
"-G Ninja",
"-g"
Copy link
Contributor

Choose a reason for hiding this comment

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

This flag was preventing my CMakeTools from building... I guess removing it didn't give you problems?

"-G Ninja"
],
"cmake.useCMakePresets": "auto",
"editor.inlayHints.enabled": "offUnlessPressed",
Expand Down
1 change: 1 addition & 0 deletions barretenberg/cpp/scripts/bb-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ IMAGE_URI=$(calculate_image_uri $REPOSITORY)
retry docker pull $IMAGE_URI

TESTS=(
client_ivc_tests
commitment_schemes_tests
crypto_aes128_tests
crypto_blake2s_tests
Expand Down
1 change: 1 addition & 0 deletions barretenberg/cpp/src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ else()
endif()

add_subdirectory(barretenberg/bb)
add_subdirectory(barretenberg/client_ivc)
add_subdirectory(barretenberg/commitment_schemes)
add_subdirectory(barretenberg/common)
add_subdirectory(barretenberg/crypto)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
barretenberg_module(client_ivc goblin)
79 changes: 79 additions & 0 deletions barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
#include "barretenberg/client_ivc/client_ivc.hpp"

namespace bb {

ClientIVC::ClientIVC()
{
// TODO(https://github.com/AztecProtocol/barretenberg/issues/723):
GoblinMockCircuits::perform_op_queue_interactions_for_mock_first_circuit(goblin.op_queue);
}

/**
* @brief Initialize the IVC with a first circuit
* @details Initializes the accumulator and performs the initial goblin merge
*
* @param circuit
*/
void ClientIVC::initialize(ClientCircuit& circuit)
{
goblin.merge(circuit); // Construct new merge proof
Composer composer;
fold_output.accumulator = composer.create_instance(circuit);
}

/**
* @brief Accumulate a circuit into the IVC scheme
* @details Performs goblin merge, generates circuit instance, folds into accumulator and constructs a folding proof
*
* @param circuit Circuit to be accumulated/folded
* @return FoldProof
*/
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;
}

/**
* @brief Construct a proof for the IVC, which, if verified, fully establishes its correctness
*
* @return Proof
*/
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 };
}

/**
* @brief Verify a full proof of the IVC
*
* @param proof
* @return bool
*/
bool ClientIVC::verify(Proof& proof)
{
// 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);
// 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);
bool decision = decider_verifier.verify_proof(proof.decider_proof);
return goblin_verified && folding_verified && decision;
}
} // namespace bb
50 changes: 50 additions & 0 deletions barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#pragma once

#include "barretenberg/goblin/goblin.hpp"
#include "barretenberg/goblin/mock_circuits.hpp"
#include "barretenberg/ultra_honk/ultra_composer.hpp"

namespace bb {

/**
* @brief The IVC interface to be used by the aztec client for private function execution
* @details Combines Protogalaxy with Goblin to accumulate one circuit instance at a time with efficient EC group
* operations
*
*/
class ClientIVC {

public:
using Flavor = GoblinUltraFlavor;
using FF = Flavor::FF;
using FoldProof = std::vector<FF>;
using Accumulator = std::shared_ptr<ProverInstance_<Flavor>>;
using ClientCircuit = GoblinUltraCircuitBuilder; // can only be GoblinUltra

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

private:
using FoldingOutput = FoldingResult<Flavor>;
using Instance = ProverInstance_<GoblinUltraFlavor>;
using Composer = GoblinUltraComposer;

public:
Goblin goblin;
FoldingOutput fold_output;

ClientIVC();

void initialize(ClientCircuit& circuit);

FoldProof accumulate(ClientCircuit& circuit);

Proof prove();

bool verify(Proof& proof);
};
} // namespace bb
120 changes: 120 additions & 0 deletions barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
#include "barretenberg/client_ivc/client_ivc.hpp"
#include "barretenberg/goblin/goblin.hpp"
#include "barretenberg/goblin/mock_circuits.hpp"
#include "barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.hpp"
#include "barretenberg/proof_system/circuit_builder/ultra_circuit_builder.hpp"
#include "barretenberg/stdlib/recursion/honk/verifier/protogalaxy_recursive_verifier.hpp"
#include "barretenberg/ultra_honk/ultra_composer.hpp"

#include <gtest/gtest.h>
using namespace bb;

class ClientIVCTests : public ::testing::Test {
protected:
static void SetUpTestSuite()
{
srs::init_crs_factory("../srs_db/ignition");
srs::init_grumpkin_crs_factory("../srs_db/grumpkin");
}

using Flavor = ClientIVC::Flavor;
using FF = typename Flavor::FF;
using Builder = ClientIVC::ClientCircuit;
using Composer = GoblinUltraComposer;
using Accumulator = ClientIVC::Accumulator;
using FoldProof = ClientIVC::FoldProof;

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

/**
* @brief Construct mock circuit with arithmetic gates and goblin ops
* @details Currently default sized to 2^16 to match kernel. (Note: op gates will bump size to next power of 2)
*
*/
static Builder create_mock_circuit(ClientIVC& ivc, size_t num_gates = 1 << 15)
{
Builder circuit{ ivc.goblin.op_queue };
GoblinMockCircuits::construct_arithmetic_circuit(circuit, num_gates);
GoblinMockCircuits::construct_goblin_ecc_op_circuit(circuit);
return circuit;
}

/**
* @brief Construct mock kernel consisting of two recursive folding verifiers
*
* @param builder
* @param fctn_fold_proof
* @param kernel_fold_proof
*/
static void construct_mock_folding_kernel(Builder& builder,
FoldProof& fctn_fold_proof,
FoldProof& kernel_fold_proof)
{
FoldingRecursiveVerifier verifier_1{ &builder };
verifier_1.verify_folding_proof(fctn_fold_proof);

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

/**
* @brief Perform native fold verification and run decider prover/verifier
*
*/
static void EXPECT_FOLDING_AND_DECIDING_VERIFIED(const Accumulator& accumulator, const FoldProof& fold_proof)
{
// Verify fold proof
Composer composer;
auto folding_verifier = composer.create_folding_verifier();
bool folding_verified = folding_verifier.verify_folding_proof(fold_proof);
EXPECT_TRUE(folding_verified);

// Run decider
auto decider_prover = composer.create_decider_prover(accumulator);
auto decider_verifier = composer.create_decider_verifier(accumulator);
auto decider_proof = decider_prover.construct_proof();
bool decision = decider_verifier.verify_proof(decider_proof);
EXPECT_TRUE(decision);
}
};

/**
* @brief A full Goblin test using PG that mimicks the basic aztec client architecture
*
*/
TEST_F(ClientIVCTests, Full)
{
ClientIVC ivc;

// Initialize IVC with function circuit
Builder function_circuit = create_mock_circuit(ivc);
ivc.initialize(function_circuit);

// Accumulate kernel circuit (first kernel mocked as simple circuit since no folding proofs yet)
Builder kernel_circuit = create_mock_circuit(ivc);
FoldProof kernel_fold_proof = ivc.accumulate(kernel_circuit);
EXPECT_FOLDING_AND_DECIDING_VERIFIED(ivc.fold_output.accumulator, kernel_fold_proof);

size_t NUM_CIRCUITS = 1;
for (size_t circuit_idx = 0; circuit_idx < NUM_CIRCUITS; ++circuit_idx) {
// Accumulate function circuit
Builder function_circuit = create_mock_circuit(ivc);
FoldProof function_fold_proof = ivc.accumulate(function_circuit);
EXPECT_FOLDING_AND_DECIDING_VERIFIED(ivc.fold_output.accumulator, function_fold_proof);

// Accumulate kernel circuit
Builder kernel_circuit{ ivc.goblin.op_queue };
construct_mock_folding_kernel(kernel_circuit, function_fold_proof, kernel_fold_proof);
FoldProof kernel_fold_proof = ivc.accumulate(kernel_circuit);
EXPECT_FOLDING_AND_DECIDING_VERIFIED(ivc.fold_output.accumulator, kernel_fold_proof);
}

// Constuct four proofs: merge, eccvm, translator, decider
auto proof = ivc.prove();

// Verify all four proofs
EXPECT_TRUE(ivc.verify(proof));
}

This file was deleted.

25 changes: 25 additions & 0 deletions barretenberg/cpp/src/barretenberg/goblin/goblin.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,31 @@ class Goblin {
return { ultra_proof, instance->verification_key };
};

/**
* @brief Add a recursive merge verifier to input circuit and construct a merge proof for the updated op queue
* @details When this method is used, the "prover" functionality of the IVC scheme must be performed explicitly, but
* this method has to be called first so that the recursive merge verifier can be "appended" to the circuit being
* accumulated
*
* @param circuit_builder
*/
void merge(GoblinUltraCircuitBuilder& circuit_builder)
{
// Complete the circuit logic by recursively verifying previous merge proof if it exists
if (merge_proof_exists) {
RecursiveMergeVerifier merge_verifier{ &circuit_builder };
[[maybe_unused]] auto pairing_points = merge_verifier.verify_proof(merge_proof);
}

// Construct and store the merge proof to be recursively verified on the next call to accumulate
MergeProver merge_prover{ op_queue };
merge_proof = merge_prover.construct_proof();

if (!merge_proof_exists) {
merge_proof_exists = true;
}
};

/**
* @brief Construct an ECCVM proof and the translation polynomial evaluations
*
Expand Down
Loading
Loading