Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 barretenberg/cpp/src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ add_subdirectory(barretenberg/eccvm)
add_subdirectory(barretenberg/env)
add_subdirectory(barretenberg/examples)
add_subdirectory(barretenberg/flavor)
add_subdirectory(barretenberg/grumpkin_srs_gen)
add_subdirectory(barretenberg/goblin)
add_subdirectory(barretenberg/grumpkin_srs_gen)
add_subdirectory(barretenberg/honk)
add_subdirectory(barretenberg/join_split_example)
add_subdirectory(barretenberg/numeric)
Expand Down
11 changes: 5 additions & 6 deletions barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,16 +81,15 @@ template <typename Curve> class KZG {
auto quotient_commitment = verifier_transcript->template receive_from_prover<Commitment>("KZG:W");

GroupElement P_0;
// Note: In the recursive setting, we only add the contribution if it is not the point at infinity (i.e. if the
// evaluation is not equal to zero).
if constexpr (Curve::is_stdlib_type) {
auto builder = verifier_transcript->builder;
auto one = Fr(builder, 1);
std::vector<GroupElement> commitments = { claim.commitment, quotient_commitment };
std::vector<Fr> scalars = { one, claim.opening_pair.challenge };
std::vector<GroupElement> commitments = { claim.commitment,
quotient_commitment,
GroupElement::one(builder) };
std::vector<Fr> scalars = { one, claim.opening_pair.challenge, -claim.opening_pair.evaluation };
P_0 = GroupElement::batch_mul(commitments, scalars);
// Note: This implementation assumes the evaluation is zero (as is the case for shplonk).
ASSERT(claim.opening_pair.evaluation.get_value() == 0);

} else {
P_0 = claim.commitment;
P_0 += quotient_commitment * claim.opening_pair.challenge;
Expand Down
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 ultra_honk eccvm translator_vm transcript)
barretenberg_module(goblin stdlib_recursion ultra_honk eccvm translator_vm)
Copy link
Contributor Author

@ledwards2225 ledwards2225 Dec 6, 2023

Choose a reason for hiding this comment

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

Since recursion is now baked into Goblin, this simpler version of the test doesn't really make sense anymore. It wasn't adding much anyway

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,6 @@ class GoblinRecursionTests : public ::testing::Test {

using Curve = curve::BN254;
using FF = Curve::ScalarField;
using Fbase = Curve::BaseField;
using Point = Curve::AffineElement;
using CommitmentKey = pcs::CommitmentKey<Curve>;
using OpQueue = proof_system::ECCOpQueue;
using GoblinUltraBuilder = proof_system::GoblinUltraCircuitBuilder;
using ECCVMFlavor = flavor::ECCVM;
using ECCVMBuilder = proof_system::ECCVMCircuitBuilder<ECCVMFlavor>;
Expand All @@ -36,11 +32,11 @@ class GoblinRecursionTests : public ::testing::Test {
using TranslatorBuilder = proof_system::GoblinTranslatorCircuitBuilder;
using TranslatorComposer = GoblinTranslatorComposer;
using TranslatorConsistencyData = barretenberg::TranslationEvaluations;
using Proof = proof_system::plonk::proof;
using NativeVerificationKey = flavor::GoblinUltra::VerificationKey;
using RecursiveFlavor = flavor::GoblinUltraRecursive_<GoblinUltraBuilder>;
using RecursiveVerifier = proof_system::plonk::stdlib::recursion::honk::UltraRecursiveVerifier_<RecursiveFlavor>;
using Goblin = barretenberg::Goblin;
using KernelInput = Goblin::AccumulationOutput;
using UltraVerifier = UltraVerifier_<flavor::GoblinUltra>;

/**
* @brief Construct a mock kernel circuit
Expand All @@ -58,8 +54,11 @@ class GoblinRecursionTests : public ::testing::Test {
// Execute recursive aggregation of previous kernel proof
RecursiveVerifier verifier{ &builder, kernel_input.verification_key };
// TODO(https://github.com/AztecProtocol/barretenberg/issues/801): Aggregation
auto pairing_points = verifier.verify_proof(kernel_input.proof); // app function proof
pairing_points = verifier.verify_proof(kernel_input.proof); // previous kernel proof
auto pairing_points = verifier.verify_proof(kernel_input.proof); // previous kernel proof
// TODO(https://github.com/AztecProtocol/barretenberg/issues/803): Mock app circuit. In the absence of a mocked
// app circuit proof, we simply perform another recursive verification for the previous kernel proof to
// approximate the work done for the app proof.
pairing_points = verifier.verify_proof(kernel_input.proof);
}
};

Expand All @@ -69,11 +68,12 @@ class GoblinRecursionTests : public ::testing::Test {
*/
TEST_F(GoblinRecursionTests, Pseudo)
{
barretenberg::Goblin goblin;
Goblin goblin;

// Construct an initial circuit; its proof will be recursively verified by the first kernel
GoblinUltraBuilder initial_circuit{ goblin.op_queue };
GoblinTestingUtils::construct_simple_initial_circuit(initial_circuit);

KernelInput kernel_input = goblin.accumulate(initial_circuit);

// Construct a series of simple Goblin circuits; generate and verify their proofs
Expand All @@ -88,8 +88,12 @@ TEST_F(GoblinRecursionTests, Pseudo)
}

Goblin::Proof proof = goblin.prove();
// Verify the final ultra proof
UltraVerifier ultra_verifier{ kernel_input.verification_key };
bool ultra_verified = ultra_verifier.verify_proof(kernel_input.proof);
// Verify the goblin proof (eccvm, translator, merge)
bool verified = goblin.verify(proof);
EXPECT_TRUE(verified);
EXPECT_TRUE(ultra_verified && verified);
}

// TODO(https://github.com/AztecProtocol/barretenberg/issues/787) Expand these tests.
Expand Down
35 changes: 31 additions & 4 deletions barretenberg/cpp/src/barretenberg/goblin/goblin.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "barretenberg/proof_system/circuit_builder/eccvm/eccvm_circuit_builder.hpp"
#include "barretenberg/proof_system/circuit_builder/goblin_translator_circuit_builder.hpp"
#include "barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.hpp"
#include "barretenberg/stdlib/recursion/honk/verifier/merge_recursive_verifier.hpp"
#include "barretenberg/translator_vm/goblin_translator_composer.hpp"
#include "barretenberg/ultra_honk/ultra_composer.hpp"

Expand All @@ -24,6 +25,7 @@ class Goblin {
};

struct Proof {
HonkProof merge_proof;
HonkProof eccvm_proof;
HonkProof translator_proof;
TranslationEvaluations translation_evaluations;
Expand All @@ -41,9 +43,17 @@ class Goblin {
using ECCVMComposer = proof_system::honk::ECCVMComposer;
using TranslatorBuilder = proof_system::GoblinTranslatorCircuitBuilder;
using TranslatorComposer = proof_system::honk::GoblinTranslatorComposer;
using RecursiveMergeVerifier =
proof_system::plonk::stdlib::recursion::goblin::MergeRecursiveVerifier_<GoblinUltraCircuitBuilder>;
using MergeVerifier = proof_system::honk::MergeVerifier_<proof_system::honk::flavor::GoblinUltra>;

std::shared_ptr<OpQueue> op_queue = std::make_shared<OpQueue>();

HonkProof merge_proof;

// on the first call to accumulate there is no merge proof to verify
bool merge_proof_exists{ false };

private:
// TODO(https://github.com/AztecProtocol/barretenberg/issues/798) unique_ptr use is a hack
std::unique_ptr<ECCVMBuilder> eccvm_builder;
Expand All @@ -59,23 +69,35 @@ class Goblin {
*/
AccumulationOutput accumulate(GoblinUltraCircuitBuilder& circuit_builder)
{
// TODO(https://github.com/AztecProtocol/barretenberg/issues/797) Complete the "kernel" logic by recursively
// verifying previous merge proof
// 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 a Honk proof for the main circuit
GoblinUltraComposer composer;
auto instance = composer.create_instance(circuit_builder);
auto prover = composer.create_prover(instance);
auto ultra_proof = prover.construct_proof();

// Construct and store the merge proof to be recursively verified on the next call to accumulate
auto merge_prover = composer.create_merge_prover(op_queue);
[[maybe_unused]] auto merge_proof = merge_prover.construct_proof();
merge_proof = merge_prover.construct_proof();

if (!merge_proof_exists) {
merge_proof_exists = true;
}

return { ultra_proof, instance->verification_key };
};

Proof prove()
{
Proof proof;

proof.merge_proof = std::move(merge_proof);

eccvm_builder = std::make_unique<ECCVMBuilder>(op_queue);
eccvm_composer = std::make_unique<ECCVMComposer>();
auto eccvm_prover = eccvm_composer->create_prover(*eccvm_builder);
Expand All @@ -87,11 +109,15 @@ class Goblin {
translator_composer = std::make_unique<TranslatorComposer>();
auto translator_prover = translator_composer->create_prover(*translator_builder, eccvm_prover.transcript);
proof.translator_proof = translator_prover.construct_proof();

return proof;
};

bool verify(const Proof& proof)
{
MergeVerifier merge_verifier;
bool merge_verified = merge_verifier.verify_proof(proof.merge_proof);

auto eccvm_verifier = eccvm_composer->create_verifier(*eccvm_builder);
bool eccvm_verified = eccvm_verifier.verify_proof(proof.eccvm_proof);

Expand All @@ -100,7 +126,8 @@ class Goblin {
// TODO(https://github.com/AztecProtocol/barretenberg/issues/799):
// Ensure translation_evaluations are passed correctly
bool translation_verified = translator_verifier.verify_translation(proof.translation_evaluations);
return eccvm_verified && accumulator_construction_verified && translation_verified;

return merge_verified && eccvm_verified && accumulator_construction_verified && translation_verified;
};
};
} // namespace barretenberg
9 changes: 2 additions & 7 deletions barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
#include "barretenberg/commitment_schemes/commitment_key.hpp"
#include "barretenberg/eccvm/eccvm_composer.hpp"
#include "barretenberg/goblin/goblin.hpp"
#include "barretenberg/goblin/translation_evaluations.hpp"
#include "barretenberg/proof_system/circuit_builder/eccvm/eccvm_circuit_builder.hpp"
#include "barretenberg/flavor/goblin_ultra.hpp"
#include "barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.hpp"
#include "barretenberg/proof_system/circuit_builder/ultra_circuit_builder.hpp"
#include "barretenberg/translator_vm/goblin_translator_composer.hpp"
#include "barretenberg/ultra_honk/ultra_composer.hpp"
#include "barretenberg/srs/global_crs.hpp"

namespace barretenberg {
class GoblinTestingUtils {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
#include "barretenberg/stdlib/recursion/honk/verifier/merge_recursive_verifier.hpp"

namespace proof_system::plonk::stdlib::recursion::goblin {

template <typename CircuitBuilder>
MergeRecursiveVerifier_<CircuitBuilder>::MergeRecursiveVerifier_(CircuitBuilder* builder)
: builder(builder)
{}

/**
* @brief Construct recursive verifier for Goblin Merge protocol, up to but not including the pairing
*
* @tparam Flavor
* @param proof
* @return std::array<typename Flavor::GroupElement, 2> Inputs to final pairing
*/
template <typename CircuitBuilder>
std::array<typename bn254<CircuitBuilder>::Element, 2> MergeRecursiveVerifier_<CircuitBuilder>::verify_proof(
const plonk::proof& proof)
{
transcript = std::make_shared<Transcript>(builder, proof.proof_data);

// Receive commitments [t_i^{shift}], [T_{i-1}], and [T_i]
std::array<Commitment, NUM_WIRES> C_T_prev;
std::array<Commitment, NUM_WIRES> C_t_shift;
std::array<Commitment, NUM_WIRES> C_T_current;
for (size_t idx = 0; idx < NUM_WIRES; ++idx) {
C_T_prev[idx] = transcript->template receive_from_prover<Commitment>("T_PREV_" + std::to_string(idx + 1));
C_t_shift[idx] = transcript->template receive_from_prover<Commitment>("t_SHIFT_" + std::to_string(idx + 1));
C_T_current[idx] = transcript->template receive_from_prover<Commitment>("T_CURRENT_" + std::to_string(idx + 1));
}

FF kappa = transcript->get_challenge("kappa");

// Receive transcript poly evaluations and add corresponding univariate opening claims {(\kappa, p(\kappa), [p(X)]}
std::array<FF, NUM_WIRES> T_prev_evals;
std::array<FF, NUM_WIRES> t_shift_evals;
std::array<FF, NUM_WIRES> T_current_evals;
std::vector<OpeningClaim> opening_claims;
for (size_t idx = 0; idx < NUM_WIRES; ++idx) {
T_prev_evals[idx] = transcript->template receive_from_prover<FF>("T_prev_eval_" + std::to_string(idx + 1));
opening_claims.emplace_back(OpeningClaim{ { kappa, T_prev_evals[idx] }, C_T_prev[idx] });
}
for (size_t idx = 0; idx < NUM_WIRES; ++idx) {
t_shift_evals[idx] = transcript->template receive_from_prover<FF>("t_shift_eval_" + std::to_string(idx + 1));
opening_claims.emplace_back(OpeningClaim{ { kappa, t_shift_evals[idx] }, C_t_shift[idx] });
}
for (size_t idx = 0; idx < NUM_WIRES; ++idx) {
T_current_evals[idx] =
transcript->template receive_from_prover<FF>("T_current_eval_" + std::to_string(idx + 1));
opening_claims.emplace_back(OpeningClaim{ { kappa, T_current_evals[idx] }, C_T_current[idx] });
}

// Check the identity T_i(\kappa) = T_{i-1}(\kappa) + t_i^{shift}(\kappa)
for (size_t idx = 0; idx < NUM_WIRES; ++idx) {
T_current_evals[idx].assert_equal(T_prev_evals[idx] + t_shift_evals[idx]);
}

FF alpha = transcript->get_challenge("alpha");

// Constuct batched commitment and batched evaluation from constituents using batching challenge \alpha
std::vector<FF> scalars;
std::vector<Commitment> commitments;
scalars.emplace_back(FF(builder, 1));
commitments.emplace_back(opening_claims[0].commitment);
auto batched_eval = opening_claims[0].opening_pair.evaluation;
auto alpha_pow = alpha;
for (size_t idx = 1; idx < opening_claims.size(); ++idx) {
auto& claim = opening_claims[idx];
scalars.emplace_back(alpha_pow);
commitments.emplace_back(claim.commitment);
batched_eval += alpha_pow * claim.opening_pair.evaluation;
alpha_pow *= alpha;
}

auto batched_commitment = Commitment::batch_mul(commitments, scalars);

OpeningClaim batched_claim = { { kappa, batched_eval }, batched_commitment };

auto pairing_points = KZG::compute_pairing_points(batched_claim, transcript);

return pairing_points;
}

template class MergeRecursiveVerifier_<GoblinUltraCircuitBuilder>;

} // namespace proof_system::plonk::stdlib::recursion::goblin
Loading