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: use new IVC scheme #8480

Merged
merged 23 commits into from
Sep 17, 2024
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
379b8b0
introduce auto verify mode, basic ClientIvc tests pass using AztecIvc
ledwards2225 Sep 10, 2024
2045e41
all ClientIvc tests pass with auto AztecIvc swapped in
ledwards2225 Sep 10, 2024
5c5160f
client ivc integration tests passes with aztec ivc
ledwards2225 Sep 11, 2024
dbc37ff
pub inputs hack
ledwards2225 Sep 12, 2024
4878db2
cleanup and trigger e2e on aztec ivc changes
ledwards2225 Sep 12, 2024
6cd39f9
fixx gcc
ledwards2225 Sep 12, 2024
2a24811
update fold basic prgram to have even num circuits
ledwards2225 Sep 16, 2024
d0e9a58
Merge branch 'master' into lde/integrate_new_ivc
ledwards2225 Sep 16, 2024
b48bb6e
bump grump in main ts
ledwards2225 Sep 16, 2024
b547310
remove old client ivc
ledwards2225 Sep 16, 2024
c6b99ae
fix bb method type in ivc integration tests
ledwards2225 Sep 16, 2024
8f413e0
ensure even number of circuits in ts integration test
ledwards2225 Sep 16, 2024
7526125
smaller test case in ivc recursion tests
ledwards2225 Sep 16, 2024
5bc512d
fix yarn formatter
ledwards2225 Sep 16, 2024
29bb769
rename bench
ledwards2225 Sep 16, 2024
b48c3a6
try to fix linker for bench
ledwards2225 Sep 16, 2024
f5d5c6f
Merge branch 'master' into lde/integrate_new_ivc
ledwards2225 Sep 16, 2024
d50f435
fix pinning and update bench name
ledwards2225 Sep 16, 2024
3cb8e05
Merge branch 'master' into lde/integrate_new_ivc
ledwards2225 Sep 16, 2024
ba053f4
rename AztecIVC to ClientIVC
ledwards2225 Sep 17, 2024
331a2c8
complete all renaming
ledwards2225 Sep 17, 2024
8dc7768
comments etc
ledwards2225 Sep 17, 2024
9742c6e
Merge branch 'master' into lde/integrate_new_ivc
ledwards2225 Sep 17, 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
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ jobs:
- barretenberg/cpp/pil/**
- barretenberg/cpp/src/barretenberg/vm/**
- barretenberg/cpp/src/barretenberg/**/generated/*
- barretenberg/cpp/src/barretenberg/client_ivc.{hpp,cpp}
- barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc.{hpp,cpp}
non-docs:
- '!(docs/**)'
non-misc-ci:
Expand Down
2 changes: 1 addition & 1 deletion barretenberg/cpp/bootstrap.sh
Original file line number Diff line number Diff line change
Expand Up @@ -118,5 +118,5 @@ if [ ! -d ./srs_db/grumpkin ]; then
# The Grumpkin SRS is generated manually at the moment, only up to a large enough size for tests
# If tests require more points, the parameter can be increased here. Note: IPA requires
# dyadic_circuit_size + 1 points so in general this number will be a power of two plus 1
cd ./build && cmake --build . --parallel --target grumpkin_srs_gen && ./bin/grumpkin_srs_gen 8193
cd ./build && cmake --build . --parallel --target grumpkin_srs_gen && ./bin/grumpkin_srs_gen 32769
Copy link
Contributor Author

Choose a reason for hiding this comment

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

this has been too low for our tests for a long time - unrelated to this PR

fi
2 changes: 0 additions & 2 deletions barretenberg/cpp/src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ endif()
add_subdirectory(barretenberg/aztec_ivc)
add_subdirectory(barretenberg/bb)
add_subdirectory(barretenberg/circuit_checker)
add_subdirectory(barretenberg/client_ivc)
add_subdirectory(barretenberg/commitment_schemes)
add_subdirectory(barretenberg/commitment_schemes_recursion)
add_subdirectory(barretenberg/common)
Expand Down Expand Up @@ -115,7 +114,6 @@ set(BARRETENBERG_TARGET_OBJECTS
$<TARGET_OBJECTS:aztec_ivc_objects>
$<TARGET_OBJECTS:commitment_schemes_objects>
$<TARGET_OBJECTS:common_objects>
$<TARGET_OBJECTS:client_ivc_objects>
$<TARGET_OBJECTS:crypto_aes128_objects>
$<TARGET_OBJECTS:crypto_blake2s_objects>
$<TARGET_OBJECTS:crypto_blake3s_objects>
Expand Down
39 changes: 38 additions & 1 deletion barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,12 @@ void AztecIVC::complete_kernel_circuit_logic(ClientCircuit& circuit)
*/
void AztecIVC::accumulate(ClientCircuit& circuit, const std::shared_ptr<VerificationKey>& precomputed_vk)
{
is_kernel = !is_kernel; // toggle on each call (every even circuit is a kernel)

if (auto_verify_mode && is_kernel) {
complete_kernel_circuit_logic(circuit);
}

// Construct merge proof for the present circuit and add to merge verification queue
MergeProof merge_proof = goblin.prove_merge(circuit);
merge_verification_queue.emplace_back(merge_proof);
Expand Down Expand Up @@ -264,9 +270,40 @@ bool AztecIVC::prove_and_verify()
{
auto proof = prove();

ASSERT(verification_queue.size() == 1); // ensure only a single fold proof remains in the queue
auto verifier_inst = std::make_shared<DeciderVerificationKey>(this->verification_queue[0].honk_verification_key);
return verify(proof, { this->verifier_accumulator, verifier_inst });
}

/**
* @brief Given a set of circuits, compute the verification keys that will be required by the IVC scheme
* @details The verification keys computed here are in general not the same as the verification keys for the
* raw input circuits because recursive verifier circuits (merge and/or folding) may be appended to the incoming
* circuits as part accumulation.
* @note This method exists for convenience and is not not meant to be used in practice for IVC. Given a set of
* circuits, it could be run once and for all to compute then save the required VKs. It also provides a convenient
* (albeit innefficient) way of separating out the cost of computing VKs from a benchmark.
*
* @param circuits A copy of the circuits to be accumulated (passing by reference would alter the original circuits)
* @return std::vector<std::shared_ptr<AztecIVC::VerificationKey>>
*/
std::vector<std::shared_ptr<AztecIVC::VerificationKey>> AztecIVC::precompute_folding_verification_keys(
std::vector<ClientCircuit> circuits)
{
std::vector<std::shared_ptr<VerificationKey>> vkeys;

for (auto& circuit : circuits) {
accumulate(circuit);
vkeys.emplace_back(honk_vk);
}

// Reset the scheme so it can be reused for actual accumulation, maintaining the trace structure setting as is
TraceStructure structure = trace_structure;
bool auto_verify = auto_verify_mode;
*this = AztecIVC();
this->trace_structure = structure;
this->auto_verify_mode = auto_verify;

return vkeys;
}

} // namespace bb
7 changes: 7 additions & 0 deletions barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,10 @@ class AztecIVC {
// A flag indicating whether or not to construct a structured trace in the DeciderProvingKey
TraceStructure trace_structure = TraceStructure::NONE;

// Setting auto_verify_mode = true will cause kernel completion logic to be added to kernels automatically
bool auto_verify_mode = false;
bool is_kernel = true;

bool initialized = false; // Is the IVC accumulator initialized

void instantiate_stdlib_verification_queue(
Expand Down Expand Up @@ -141,5 +145,8 @@ class AztecIVC {
bool prove_and_verify();

HonkProof decider_prove() const;

std::vector<std::shared_ptr<VerificationKey>> precompute_folding_verification_keys(
std::vector<ClientCircuit> circuits);
};
} // namespace bb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#include "barretenberg/client_ivc/client_ivc.hpp"
#include "barretenberg/aztec_ivc/aztec_ivc.hpp"
#include "barretenberg/goblin/goblin.hpp"
#include "barretenberg/goblin/mock_circuits.hpp"
#include "barretenberg/stdlib_circuit_builders/mega_circuit_builder.hpp"
Expand All @@ -8,58 +8,43 @@

using namespace bb;

class ClientIVCTests : public ::testing::Test {
class AztecIVCAutoVerifyTests : 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 Flavor = AztecIVC::Flavor;
using FF = typename Flavor::FF;
using VerificationKey = Flavor::VerificationKey;
using Builder = ClientIVC::ClientCircuit;
using DeciderProvingKey = ClientIVC::DeciderProvingKey;
using DeciderVerificationKey = ClientIVC::DeciderVerificationKey;
using FoldProof = ClientIVC::FoldProof;
using DeciderProver = ClientIVC::DeciderProver;
using DeciderVerifier = ClientIVC::DeciderVerifier;
using Builder = AztecIVC::ClientCircuit;
using DeciderProvingKey = AztecIVC::DeciderProvingKey;
using DeciderVerificationKey = AztecIVC::DeciderVerificationKey;
using FoldProof = AztecIVC::FoldProof;
using DeciderProver = AztecIVC::DeciderProver;
using DeciderVerifier = AztecIVC::DeciderVerifier;
using DeciderProvingKeys = DeciderProvingKeys_<Flavor>;
using FoldingProver = ProtogalaxyProver_<DeciderProvingKeys>;
using DeciderVerificationKeys = DeciderVerificationKeys_<Flavor>;
using FoldingVerifier = ProtogalaxyVerifier_<DeciderVerificationKeys>;

/**
* @brief Prove and verify the IVC scheme
* @details Constructs four proofs: merge, eccvm, translator, decider; Verifies these four plus the final folding
* proof constructed on the last accumulation round
*
*/
static bool prove_and_verify(ClientIVC& ivc)
{
ZoneScopedN("ClientIVC::prove_and_verify");
auto proof = ivc.prove();

auto verifier_inst = std::make_shared<DeciderVerificationKey>(ivc.decider_vk);
return ivc.verify(proof, { ivc.verifier_accumulator, verifier_inst });
}

/**
* @brief Construct mock circuit with arithmetic gates and goblin ops
* @details Currently default sized to 2^16 to match kernel. (Note: dummy op gates added to avoid non-zero
* polynomials will bump size to next power of 2)
*
*/
static Builder create_mock_circuit(ClientIVC& ivc, size_t log2_num_gates = 16)
static Builder create_mock_circuit(AztecIVC& ivc, size_t log2_num_gates = 16)
{
Builder circuit{ ivc.goblin.op_queue };
MockCircuits::construct_arithmetic_circuit(circuit, log2_num_gates);

// TODO(https://github.com/AztecProtocol/barretenberg/issues/911): We require goblin ops to be added to the
// function circuit because we cannot support zero commtiments. While the builder handles this at
// finalisation stage via the add_gates_to_ensure_all_polys_are_non_zero function for other MegaHonk
// circuits (where we don't explicitly need to add goblin ops), in ClientIVC merge proving happens prior to
// circuits (where we don't explicitly need to add goblin ops), in AztecIVC merge proving happens prior to
// folding where the absense of goblin ecc ops will result in zero commitments.
MockCircuits::construct_goblin_ecc_op_circuit(circuit);
return circuit;
Expand All @@ -70,9 +55,10 @@ class ClientIVCTests : public ::testing::Test {
* @brief A simple-as-possible test demonstrating IVC for two mock circuits
*
*/
TEST_F(ClientIVCTests, Basic)
TEST_F(AztecIVCAutoVerifyTests, Basic)
{
ClientIVC ivc;
AztecIVC ivc;
ivc.auto_verify_mode = true;

{
// Initialize the IVC with an arbitrary circuit
Expand All @@ -86,64 +72,20 @@ TEST_F(ClientIVCTests, Basic)
ivc.accumulate(circuit_1);
}

EXPECT_TRUE(prove_and_verify(ivc));
};

/**
* @brief A simple test demonstrating IVC for three mock circuits which does more logic than just two circuits.
*
*/
TEST_F(ClientIVCTests, BasicThree)
{
ClientIVC ivc;

for (size_t idx = 0; idx < 3; ++idx) {
Builder circuit = create_mock_circuit(ivc);
ivc.accumulate(circuit);
}

EXPECT_TRUE(prove_and_verify(ivc));
};

/**
* @brief Check that the IVC fails if an intermediate fold proof is invalid
*
*/
TEST_F(ClientIVCTests, BasicFailure)
{
ClientIVC ivc;

// Initialize the IVC with an arbitrary circuit
Builder circuit_0 = create_mock_circuit(ivc);
ivc.accumulate(circuit_0);

// Create another circuit and accumulate
Builder circuit_1 = create_mock_circuit(ivc);
ivc.accumulate(circuit_1);

// Tamper with the fold proof just created in the last accumulation step
for (auto& val : ivc.fold_output.proof) {
if (val > 0) { // tamper by finding the first non-zero value and incrementing it by 1
val += 1;
break;
}
}
// Accumulate another circuit; this involves recursive folding verification of the bad proof which throws an error
// because of circuit sizes don't match.
Builder circuit_2 = create_mock_circuit(ivc);
EXPECT_ANY_THROW(ivc.accumulate(circuit_2));
EXPECT_TRUE(ivc.prove_and_verify());
};

/**
* @brief Prove and verify accumulation of an arbitrary set of circuits
*
*/
TEST_F(ClientIVCTests, BasicLarge)
TEST_F(AztecIVCAutoVerifyTests, BasicLarge)
{
ClientIVC ivc;
AztecIVC ivc;
ivc.auto_verify_mode = true;

// Construct a set of arbitrary circuits
size_t NUM_CIRCUITS = 5;
size_t NUM_CIRCUITS = 6;
std::vector<Builder> circuits;
for (size_t idx = 0; idx < NUM_CIRCUITS; ++idx) {
circuits.emplace_back(create_mock_circuit(ivc));
Expand All @@ -154,41 +96,45 @@ TEST_F(ClientIVCTests, BasicLarge)
ivc.accumulate(circuit);
}

EXPECT_TRUE(prove_and_verify(ivc));
EXPECT_TRUE(ivc.prove_and_verify());
};

/**
* @brief Using a structured trace allows for the accumulation of circuits of varying size
*
*/
TEST_F(ClientIVCTests, BasicStructured)
TEST_F(AztecIVCAutoVerifyTests, BasicStructured)
{
ClientIVC ivc;
AztecIVC ivc;
ivc.auto_verify_mode = true;
ivc.trace_structure = TraceStructure::SMALL_TEST;

// Construct some circuits of varying size
Builder circuit_0 = create_mock_circuit(ivc, /*log2_num_gates=*/5);
Builder circuit_1 = create_mock_circuit(ivc, /*log2_num_gates=*/8);
Builder circuit_2 = create_mock_circuit(ivc, /*log2_num_gates=*/11);
Builder circuit_3 = create_mock_circuit(ivc, /*log2_num_gates=*/11);

// The circuits can be accumulated as normal due to the structured trace
ivc.accumulate(circuit_0);
ivc.accumulate(circuit_1);
ivc.accumulate(circuit_2);
ivc.accumulate(circuit_3);

EXPECT_TRUE(prove_and_verify(ivc));
EXPECT_TRUE(ivc.prove_and_verify());
};

/**
* @brief Prove and verify accumulation of an arbitrary set of circuits using precomputed verification keys
*
*/
TEST_F(ClientIVCTests, PrecomputedVerificationKeys)
TEST_F(AztecIVCAutoVerifyTests, PrecomputedVerificationKeys)
{
ClientIVC ivc;
AztecIVC ivc;
ivc.auto_verify_mode = true;

// Construct a set of arbitrary circuits
size_t NUM_CIRCUITS = 3;
size_t NUM_CIRCUITS = 4;
std::vector<Builder> circuits;
for (size_t idx = 0; idx < NUM_CIRCUITS; ++idx) {
circuits.emplace_back(create_mock_circuit(ivc));
Expand All @@ -202,20 +148,21 @@ TEST_F(ClientIVCTests, PrecomputedVerificationKeys)
ivc.accumulate(circuit, precomputed_vk);
}

EXPECT_TRUE(prove_and_verify(ivc));
EXPECT_TRUE(ivc.prove_and_verify());
};

/**
* @brief Perform accumulation with a structured trace and precomputed verification keys
*
*/
TEST_F(ClientIVCTests, StructuredPrecomputedVKs)
TEST_F(AztecIVCAutoVerifyTests, StructuredPrecomputedVKs)
{
ClientIVC ivc;
AztecIVC ivc;
ivc.auto_verify_mode = true;
ivc.trace_structure = TraceStructure::SMALL_TEST;

// Construct a set of arbitrary circuits
size_t NUM_CIRCUITS = 3;
size_t NUM_CIRCUITS = 4;
std::vector<Builder> circuits;
for (size_t idx = 0; idx < NUM_CIRCUITS; ++idx) {
circuits.emplace_back(create_mock_circuit(ivc, /*log2_num_gates=*/5));
Expand All @@ -229,5 +176,5 @@ TEST_F(ClientIVCTests, StructuredPrecomputedVKs)
ivc.accumulate(circuit, precomputed_vk);
}

EXPECT_TRUE(prove_and_verify(ivc));
EXPECT_TRUE(ivc.prove_and_verify());
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#include "barretenberg/aztec_ivc/aztec_ivc.hpp"
#include "barretenberg/goblin/mock_circuits.hpp"
#include "barretenberg/stdlib_circuit_builders/mega_circuit_builder.hpp"

#include <gtest/gtest.h>

using namespace bb;

/**
* @brief For benchmarking, we want to be sure that our mocking functions create circuits of a known size. We control
* this, to the degree that matters for proof construction time, using these "pinning tests" that fix values.
*
*/
class MockKernelTest : public ::testing::Test {
public:
using Builder = MegaCircuitBuilder;

protected:
static void SetUpTestSuite() { srs::init_crs_factory("../srs_db/ignition"); }
};

// TEST_F(MockKernelTest, PinFoldingKernelSizes)
// {
// ClientIVC ivc;

// // Construct two function circuits and a kernel circuit
// Builder circuit_1{ ivc.goblin.op_queue };
// Builder circuit_2{ ivc.goblin.op_queue };
// Builder kernel_circuit{ ivc.goblin.op_queue };

// GoblinMockCircuits::construct_mock_function_circuit(circuit_1);
// GoblinMockCircuits::construct_mock_function_circuit(circuit_2);
// GoblinMockCircuits::construct_mock_folding_kernel(kernel_circuit);

// // Accumulate all three; The kernel will contain a single recursive folding verifier
// ivc.accumulate(circuit_1);
// ivc.accumulate(circuit_2);
// ivc.accumulate(kernel_circuit);

// EXPECT_EQ(ivc.fold_output.accumulator->proving_key.log_circuit_size, 17);
// }
Loading
Loading