Skip to content

Commit

Permalink
feat: PG recursive verifier constructors based on stdlib inputs (#8052)
Browse files Browse the repository at this point in the history
Update the PG recursive verifier to take stdlib
accumulators/verification_keys and stdlib proofs as opposed to their
native counterparts. This work will allow for a connection to be made
between the proofs/vkeys used in noir protocol circuits and those used
in the backend. The workflow will be roughly 1) construct stdlib
vkey/proof from their known native counterparts, 2) use `assert_equal`
to connect the witnesses of these objects to those received in the
corresponding acir `RecursionConstraint`, and 3) run the recursive
verifier as usual.
  • Loading branch information
ledwards2225 authored Aug 20, 2024
1 parent 9227fa9 commit 4c568b0
Show file tree
Hide file tree
Showing 12 changed files with 84 additions and 28 deletions.
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ jobs:
- barretenberg/cpp/pil/**
- barretenberg/cpp/src/barretenberg/vm/**
- barretenberg/cpp/src/barretenberg/**/generated/*
- barretenberg/cpp/src/barretenberg/client_ivc.{hpp,cpp}
non-docs:
- '!(docs/**)'
non-misc-ci:
Expand Down
10 changes: 8 additions & 2 deletions barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,15 @@ void AztecIVC::complete_kernel_circuit_logic(ClientCircuit& circuit)
ASSERT(verification_queue.empty() || verification_queue.size() == 2);

for (auto& [proof, vkey] : verification_queue) {

// Construct stdlib accumulator, vkey and proof
auto stdlib_verifier_accum = std::make_shared<RecursiveVerifierInstance>(&circuit, verifier_accumulator);
auto stdlib_vkey = std::make_shared<RecursiveVerificationKey>(&circuit, vkey);
auto stdlib_proof = bb::convert_proof_to_witness(&circuit, proof);

// Perform folding recursive verification
FoldingRecursiveVerifier verifier{ &circuit, { verifier_accumulator, { vkey } } };
auto verifier_accum = verifier.verify_folding_proof(proof);
FoldingRecursiveVerifier verifier{ &circuit, stdlib_verifier_accum, { stdlib_vkey } };
auto verifier_accum = verifier.verify_folding_proof(stdlib_proof);
verifier_accumulator = std::make_shared<VerifierInstance>(verifier_accum->get_value());

// Perform databus commitment consistency checks and propagate return data commitments via public inputs
Expand Down
2 changes: 2 additions & 0 deletions barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ class AztecIVC {

using GURecursiveFlavor = MegaRecursiveFlavor_<bb::MegaCircuitBuilder>;
using RecursiveVerifierInstances = bb::stdlib::recursion::honk::RecursiveVerifierInstances_<GURecursiveFlavor, 2>;
using RecursiveVerifierInstance = RecursiveVerifierInstances::Instance;
using RecursiveVerificationKey = RecursiveVerifierInstances::VerificationKey;
using FoldingRecursiveVerifier =
bb::stdlib::recursion::honk::ProtoGalaxyRecursiveVerifier_<RecursiveVerifierInstances>;

Expand Down
10 changes: 8 additions & 2 deletions barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,14 @@ void ClientIVC::accumulate(ClientCircuit& circuit, const std::shared_ptr<Verific
// If a previous fold proof exists, add a recursive folding verification to the circuit
if (!fold_output.proof.empty()) {
BB_OP_COUNT_TIME_NAME("construct_circuits");
FoldingRecursiveVerifier verifier{ &circuit, { verifier_accumulator, { instance_vk } } };
auto verifier_accum = verifier.verify_folding_proof(fold_output.proof);

// Construct stdlib accumulator, vkey and proof
auto stdlib_verifier_accum = std::make_shared<RecursiveVerifierInstance>(&circuit, verifier_accumulator);
auto stdlib_instance_vk = std::make_shared<RecursiveVerificationKey>(&circuit, instance_vk);
auto stdlib_proof = bb::convert_proof_to_witness(&circuit, fold_output.proof);

FoldingRecursiveVerifier verifier{ &circuit, stdlib_verifier_accum, { stdlib_instance_vk } };
auto verifier_accum = verifier.verify_folding_proof(stdlib_proof);
verifier_accumulator = std::make_shared<VerifierInstance>(verifier_accum->get_value());
}

Expand Down
2 changes: 2 additions & 0 deletions barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ class ClientIVC {

using GURecursiveFlavor = MegaRecursiveFlavor_<bb::MegaCircuitBuilder>;
using RecursiveVerifierInstances = bb::stdlib::recursion::honk::RecursiveVerifierInstances_<GURecursiveFlavor, 2>;
using RecursiveVerifierInstance = RecursiveVerifierInstances::Instance;
using RecursiveVerificationKey = RecursiveVerifierInstances::VerificationKey;
using FoldingRecursiveVerifier =
bb::stdlib::recursion::honk::ProtoGalaxyRecursiveVerifier_<RecursiveVerifierInstances>;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,16 @@ namespace bb::stdlib::recursion::honk {
*/
void ClientIVCRecursiveVerifier::verify(const ClientIVC::Proof& proof)
{
// Construct stdlib accumulator, vkey and proof
auto stdlib_verifier_accum =
std::make_shared<RecursiveVerifierInstance>(builder.get(), verifier_input.fold_input.accumulator);
auto stdlib_instance_vk =
std::make_shared<RecursiveVerificationKey>(builder.get(), verifier_input.fold_input.instance_vks[0]);
auto stdlib_proof = bb::convert_proof_to_witness(builder.get(), proof.folding_proof);

// Perform recursive folding verification
FoldingVerifier folding_verifier{ builder.get(), verifier_input.fold_input };
auto recursive_verifier_accumulator = folding_verifier.verify_folding_proof(proof.folding_proof);
FoldingVerifier folding_verifier{ builder.get(), stdlib_verifier_accum, { stdlib_instance_vk } };
auto recursive_verifier_accumulator = folding_verifier.verify_folding_proof(stdlib_proof);
auto native_verifier_acc =
std::make_shared<FoldVerifierInput::Instance>(recursive_verifier_accumulator->get_value());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ class ClientIVCRecursiveVerifier {
using Builder = UltraCircuitBuilder; // The circuit will be an Ultra circuit
using RecursiveFlavor = MegaRecursiveFlavor_<Builder>; // The verifier algorithms are Mega
using RecursiveVerifierInstances = RecursiveVerifierInstances_<RecursiveFlavor, 2>;
using RecursiveVerifierInstance = RecursiveVerifierInstances::Instance;
using RecursiveVerificationKey = RecursiveVerifierInstances::VerificationKey;
using DeciderVerifier = DeciderRecursiveVerifier_<RecursiveFlavor>;
using FoldingVerifier = ProtoGalaxyRecursiveVerifier_<RecursiveVerifierInstances>;
using GoblinVerifier = GoblinRecursiveVerifier;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,12 +116,11 @@ template <class VerifierInstances> void ProtoGalaxyRecursiveVerifier_<VerifierIn

template <class VerifierInstances>
std::shared_ptr<typename VerifierInstances::Instance> ProtoGalaxyRecursiveVerifier_<
VerifierInstances>::verify_folding_proof(const HonkProof& proof)
VerifierInstances>::verify_folding_proof(const StdlibProof<Builder>& proof)
{
using Transcript = typename Flavor::Transcript;

StdlibProof<Builder> stdlib_proof = bb::convert_proof_to_witness(builder, proof);
transcript = std::make_shared<Transcript>(stdlib_proof);
transcript = std::make_shared<Transcript>(proof);
prepare_for_folding();

auto delta = transcript->template get_challenge<FF>("delta");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,11 @@ template <class VerifierInstances> class ProtoGalaxyRecursiveVerifier_ {
std::shared_ptr<Transcript> transcript;
VerifierInstances instances;

ProtoGalaxyRecursiveVerifier_(Builder* builder, const VerifierInput& input_data)
ProtoGalaxyRecursiveVerifier_(Builder* builder,
const std::shared_ptr<Instance>& accumulator,
const std::vector<std::shared_ptr<VerificationKey>>& instance_vks)
: builder(builder)
, instances(VerifierInstances(builder, input_data.accumulator, input_data.instance_vks)){};
, instances(VerifierInstances(builder, accumulator, instance_vks)){};

/**
* @brief Given a new round challenge δ for each iteration of the full ProtoGalaxy protocol, compute the vector
Expand Down Expand Up @@ -101,9 +103,9 @@ template <class VerifierInstances> class ProtoGalaxyRecursiveVerifier_ {
* @details In the recursive setting this function doesn't return anything because the equality checks performed by
* the recursive verifier, ensuring the folded ϕ*, e* and β* on the verifier side correspond to what has been sent
* by the prover, are expressed as constraints.
*
*/
std::shared_ptr<Instance> verify_folding_proof(const HonkProof&);
std::shared_ptr<Instance> verify_folding_proof(const StdlibProof<Builder>&);

/**
* @brief Evaluates the perturbator at a given scalar, in a sequential manner for the recursive setting.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ template <typename RecursiveFlavor> class ProtoGalaxyRecursiveTests : public tes
using OuterProverInstance = ProverInstance_<OuterFlavor>;

using RecursiveVerifierInstances = ::bb::stdlib::recursion::honk::RecursiveVerifierInstances_<RecursiveFlavor, 2>;
using RecursiveVerifierInstance = RecursiveVerifierInstances::Instance;
using RecursiveVerificationKey = RecursiveVerifierInstances::VerificationKey;
using FoldingRecursiveVerifier = ProtoGalaxyRecursiveVerifier_<RecursiveVerifierInstances>;
using DeciderRecursiveVerifier = DeciderRecursiveVerifier_<RecursiveFlavor>;
using InnerDeciderProver = DeciderProver_<InnerFlavor>;
Expand Down Expand Up @@ -193,9 +195,17 @@ template <typename RecursiveFlavor> class ProtoGalaxyRecursiveTests : public tes

// Create a recursive folding verifier circuit for the folding proof of the two instances
OuterBuilder folding_circuit;
auto verifier = FoldingRecursiveVerifier(&folding_circuit,
{ verifier_instance_1, { verifier_instance_2->verification_key } });
verifier.verify_folding_proof(folding_proof.proof);

auto recursive_verifier_instance_1 =
std::make_shared<RecursiveVerifierInstance>(&folding_circuit, verifier_instance_1);
auto recursive_verification_key_2 =
std::make_shared<RecursiveVerificationKey>(&folding_circuit, verifier_instance_2->verification_key);
StdlibProof<OuterBuilder> stdlib_proof = bb::convert_proof_to_witness(&folding_circuit, folding_proof.proof);

auto verifier = FoldingRecursiveVerifier{ &folding_circuit,
recursive_verifier_instance_1,
{ recursive_verification_key_2 } };
verifier.verify_folding_proof(stdlib_proof);
info("Folding Recursive Verifier: num gates = ", folding_circuit.num_gates);
EXPECT_EQ(folding_circuit.failed(), false) << folding_circuit.err();

Expand Down Expand Up @@ -257,9 +267,16 @@ template <typename RecursiveFlavor> class ProtoGalaxyRecursiveTests : public tes

// Create a recursive folding verifier circuit for the folding proof of the two instances
OuterBuilder folding_circuit;
auto verifier = FoldingRecursiveVerifier(&folding_circuit,
{ verifier_instance_1, { verifier_instance_2->verification_key } });
auto recursive_verifier_accumulator = verifier.verify_folding_proof(folding_proof.proof);
auto recursive_verifier_instance_1 =
std::make_shared<RecursiveVerifierInstance>(&folding_circuit, verifier_instance_1);
auto recursive_verification_key_2 =
std::make_shared<RecursiveVerificationKey>(&folding_circuit, verifier_instance_2->verification_key);
StdlibProof<OuterBuilder> stdlib_proof = bb::convert_proof_to_witness(&folding_circuit, folding_proof.proof);

auto verifier = FoldingRecursiveVerifier{ &folding_circuit,
recursive_verifier_instance_1,
{ recursive_verification_key_2 } };
auto recursive_verifier_accumulator = verifier.verify_folding_proof(stdlib_proof);
auto native_verifier_acc = std::make_shared<InnerVerifierInstance>(recursive_verifier_accumulator->get_value());
info("Folding Recursive Verifier: num gates = ", folding_circuit.num_gates);

Expand Down Expand Up @@ -356,9 +373,17 @@ template <typename RecursiveFlavor> class ProtoGalaxyRecursiveTests : public tes
// Create a recursive folding verifier circuit for the folding proof of the two instances with the untampered
// commitments
OuterBuilder folding_circuit;
FoldingRecursiveVerifier verifier{ &folding_circuit,
{ verifier_accumulator, { verifier_inst->verification_key } } };
auto recursive_verifier_acc = verifier.verify_folding_proof(folding_proof.proof);
auto recursive_verifier_instance_1 =
std::make_shared<RecursiveVerifierInstance>(&folding_circuit, verifier_accumulator);
auto recursive_verification_key_2 =
std::make_shared<RecursiveVerificationKey>(&folding_circuit, verifier_inst->verification_key);
StdlibProof<OuterBuilder> stdlib_proof = bb::convert_proof_to_witness(&folding_circuit, folding_proof.proof);

auto verifier = FoldingRecursiveVerifier{ &folding_circuit,
recursive_verifier_instance_1,
{ recursive_verification_key_2 } };
auto recursive_verifier_acc = verifier.verify_folding_proof(stdlib_proof);

// Validate that the target sum between prover and verifier is now different
EXPECT_FALSE(folding_proof.accumulator->target_sum == recursive_verifier_acc->target_sum.get_value());
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@ template <IsRecursiveFlavor Flavor_, size_t NUM_> struct RecursiveVerifierInstan
using Flavor = Flavor_;
using Builder = typename Flavor::CircuitBuilder;
using VerificationKey = typename Flavor::VerificationKey;
using NativeVerificationKey = typename Flavor::NativeVerificationKey;
using Instance = RecursiveVerifierInstance_<Flavor>;
using NativeInstance = bb::VerifierInstance_<typename Flavor::NativeFlavor>;
using ArrayType = std::array<std::shared_ptr<Instance>, NUM_>;

public:
Expand All @@ -23,13 +21,13 @@ template <IsRecursiveFlavor Flavor_, size_t NUM_> struct RecursiveVerifierInstan
Builder* builder;

RecursiveVerifierInstances_(Builder* builder,
const std::shared_ptr<NativeInstance>& accumulator,
const std::vector<std::shared_ptr<NativeVerificationKey>>& vks)
const std::shared_ptr<Instance>& accumulator,
const std::vector<std::shared_ptr<VerificationKey>>& vks)
: builder(builder)
{
ASSERT(vks.size() == NUM - 1);

_data[0] = std::make_shared<Instance>(builder, accumulator);
_data[0] = accumulator;

size_t idx = 1;
for (auto& vk : vks) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,15 @@ template <IsRecursiveFlavor Flavor> class RecursiveVerifierInstance_ {

RecursiveVerifierInstance_(Builder* builder)
: builder(builder){};

RecursiveVerifierInstance_(Builder* builder, std::shared_ptr<NativeVerificationKey> vk)
: builder(builder)
, verification_key(std::make_shared<VerificationKey>(builder, vk))
, verification_key(std::make_shared<VerificationKey>(builder, vk)){};

// Constructor from stdlib vkey
RecursiveVerifierInstance_(Builder* builder, std::shared_ptr<VerificationKey> vk)
: builder(builder)
, verification_key(vk)
{}

RecursiveVerifierInstance_(Builder* builder, const std::shared_ptr<VerifierInstance>& instance)
Expand Down

0 comments on commit 4c568b0

Please sign in to comment.