Skip to content

Commit

Permalink
feat: sumcheck part of ECCVM recursive verifier instantiated as an Ul…
Browse files Browse the repository at this point in the history
…traCircuit (#6413)

This PR adds the ECCVM recursive verifier up to sumcheck (PCS incoming)
with the necessary additional functionality in bigfield. It also removes
some unnecessary fields in flavors that are obsolete.
  • Loading branch information
maramihali authored May 28, 2024
1 parent 1d785fd commit afe84a2
Show file tree
Hide file tree
Showing 26 changed files with 492 additions and 214 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,8 @@ class ECCVMCircuitBuilder {

[[nodiscard]] size_t get_num_gates() const
{
// (issue #2218)
// TODO(https://github.com/AztecProtocol/aztec-packages/issues/2218): Reduce the amount of computation needed
// for this method
return op_queue->get_num_rows();
}

Expand Down
23 changes: 14 additions & 9 deletions barretenberg/cpp/src/barretenberg/eccvm/eccvm_composer.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,26 +14,31 @@
#include "barretenberg/sumcheck/sumcheck_round.hpp"

using namespace bb;
using G1 = bb::g1;
using Fr = bb::fr;

class ECCVMComposerTests : public ::testing::Test {
protected:
// TODO(640): The Standard Honk on Grumpkin test suite fails unless the SRS is initialized for every test.
void SetUp() override { srs::init_grumpkin_crs_factory("../srs_db/grumpkin"); };
};
namespace {
auto& engine = numeric::get_debug_randomness();
}

/**
* @brief Adds operations in BN254 to the op_queue and then constructs and ECCVM circuit from the op_queue.
*
* @param engine
* @return ECCVMCircuitBuilder
*/
ECCVMCircuitBuilder generate_circuit(numeric::RNG* engine = nullptr)
{
std::shared_ptr<ECCOpQueue> op_queue = std::make_shared<ECCOpQueue>();
using Curve = curve::BN254;
using G1 = Curve::Element;
using Fr = Curve::ScalarField;

auto generators = G1::derive_generators("test generators", 3);

typename G1::element a = generators[0];
typename G1::element b = generators[1];
typename G1::element c = generators[2];
std::shared_ptr<ECCOpQueue> op_queue = std::make_shared<ECCOpQueue>();
G1 a = G1::random_element(engine);
G1 b = G1::random_element(engine);
G1 c = G1::random_element(engine);
Fr x = Fr::random_element(engine);
Fr y = Fr::random_element(engine);

Expand Down
110 changes: 9 additions & 101 deletions barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,120 +17,28 @@ bool ECCVMVerifier::verify_proof(const HonkProof& proof)
CommitmentLabels commitment_labels;

const auto circuit_size = transcript->template receive_from_prover<uint32_t>("circuit_size");
ASSERT(circuit_size == key->circuit_size);

if (circuit_size != key->circuit_size) {
return false;
for (auto [comm, label] : zip_view(commitments.get_wires(), commitment_labels.get_wires())) {
comm = transcript->template receive_from_prover<Commitment>(label);
}

// Utility for extracting commitments from transcript
const auto receive_commitment = [&](const std::string& label) {
return transcript->template receive_from_prover<Commitment>(label);
};

// Get commitments to VM wires
commitments.transcript_add = receive_commitment(commitment_labels.transcript_add);
commitments.transcript_mul = receive_commitment(commitment_labels.transcript_mul);
commitments.transcript_eq = receive_commitment(commitment_labels.transcript_eq);
commitments.transcript_msm_transition = receive_commitment(commitment_labels.transcript_msm_transition);
commitments.transcript_pc = receive_commitment(commitment_labels.transcript_pc);
commitments.transcript_msm_count = receive_commitment(commitment_labels.transcript_msm_count);
commitments.transcript_Px = receive_commitment(commitment_labels.transcript_Px);
commitments.transcript_Py = receive_commitment(commitment_labels.transcript_Py);
commitments.transcript_z1 = receive_commitment(commitment_labels.transcript_z1);
commitments.transcript_z2 = receive_commitment(commitment_labels.transcript_z2);
commitments.transcript_z1zero = receive_commitment(commitment_labels.transcript_z1zero);
commitments.transcript_z2zero = receive_commitment(commitment_labels.transcript_z2zero);
commitments.transcript_op = receive_commitment(commitment_labels.transcript_op);
commitments.transcript_accumulator_x = receive_commitment(commitment_labels.transcript_accumulator_x);
commitments.transcript_accumulator_y = receive_commitment(commitment_labels.transcript_accumulator_y);
commitments.transcript_msm_x = receive_commitment(commitment_labels.transcript_msm_x);
commitments.transcript_msm_y = receive_commitment(commitment_labels.transcript_msm_y);
commitments.precompute_pc = receive_commitment(commitment_labels.precompute_pc);
commitments.precompute_point_transition = receive_commitment(commitment_labels.precompute_point_transition);
commitments.precompute_round = receive_commitment(commitment_labels.precompute_round);
commitments.precompute_scalar_sum = receive_commitment(commitment_labels.precompute_scalar_sum);
commitments.precompute_s1hi = receive_commitment(commitment_labels.precompute_s1hi);
commitments.precompute_s1lo = receive_commitment(commitment_labels.precompute_s1lo);
commitments.precompute_s2hi = receive_commitment(commitment_labels.precompute_s2hi);
commitments.precompute_s2lo = receive_commitment(commitment_labels.precompute_s2lo);
commitments.precompute_s3hi = receive_commitment(commitment_labels.precompute_s3hi);
commitments.precompute_s3lo = receive_commitment(commitment_labels.precompute_s3lo);
commitments.precompute_s4hi = receive_commitment(commitment_labels.precompute_s4hi);
commitments.precompute_s4lo = receive_commitment(commitment_labels.precompute_s4lo);
commitments.precompute_skew = receive_commitment(commitment_labels.precompute_skew);
commitments.precompute_dx = receive_commitment(commitment_labels.precompute_dx);
commitments.precompute_dy = receive_commitment(commitment_labels.precompute_dy);
commitments.precompute_tx = receive_commitment(commitment_labels.precompute_tx);
commitments.precompute_ty = receive_commitment(commitment_labels.precompute_ty);
commitments.msm_transition = receive_commitment(commitment_labels.msm_transition);
commitments.msm_add = receive_commitment(commitment_labels.msm_add);
commitments.msm_double = receive_commitment(commitment_labels.msm_double);
commitments.msm_skew = receive_commitment(commitment_labels.msm_skew);
commitments.msm_accumulator_x = receive_commitment(commitment_labels.msm_accumulator_x);
commitments.msm_accumulator_y = receive_commitment(commitment_labels.msm_accumulator_y);
commitments.msm_pc = receive_commitment(commitment_labels.msm_pc);
commitments.msm_size_of_msm = receive_commitment(commitment_labels.msm_size_of_msm);
commitments.msm_count = receive_commitment(commitment_labels.msm_count);
commitments.msm_round = receive_commitment(commitment_labels.msm_round);
commitments.msm_add1 = receive_commitment(commitment_labels.msm_add1);
commitments.msm_add2 = receive_commitment(commitment_labels.msm_add2);
commitments.msm_add3 = receive_commitment(commitment_labels.msm_add3);
commitments.msm_add4 = receive_commitment(commitment_labels.msm_add4);
commitments.msm_x1 = receive_commitment(commitment_labels.msm_x1);
commitments.msm_y1 = receive_commitment(commitment_labels.msm_y1);
commitments.msm_x2 = receive_commitment(commitment_labels.msm_x2);
commitments.msm_y2 = receive_commitment(commitment_labels.msm_y2);
commitments.msm_x3 = receive_commitment(commitment_labels.msm_x3);
commitments.msm_y3 = receive_commitment(commitment_labels.msm_y3);
commitments.msm_x4 = receive_commitment(commitment_labels.msm_x4);
commitments.msm_y4 = receive_commitment(commitment_labels.msm_y4);
commitments.msm_collision_x1 = receive_commitment(commitment_labels.msm_collision_x1);
commitments.msm_collision_x2 = receive_commitment(commitment_labels.msm_collision_x2);
commitments.msm_collision_x3 = receive_commitment(commitment_labels.msm_collision_x3);
commitments.msm_collision_x4 = receive_commitment(commitment_labels.msm_collision_x4);
commitments.msm_lambda1 = receive_commitment(commitment_labels.msm_lambda1);
commitments.msm_lambda2 = receive_commitment(commitment_labels.msm_lambda2);
commitments.msm_lambda3 = receive_commitment(commitment_labels.msm_lambda3);
commitments.msm_lambda4 = receive_commitment(commitment_labels.msm_lambda4);
commitments.msm_slice1 = receive_commitment(commitment_labels.msm_slice1);
commitments.msm_slice2 = receive_commitment(commitment_labels.msm_slice2);
commitments.msm_slice3 = receive_commitment(commitment_labels.msm_slice3);
commitments.msm_slice4 = receive_commitment(commitment_labels.msm_slice4);
commitments.transcript_accumulator_empty = receive_commitment(commitment_labels.transcript_accumulator_empty);
commitments.transcript_reset_accumulator = receive_commitment(commitment_labels.transcript_reset_accumulator);
commitments.precompute_select = receive_commitment(commitment_labels.precompute_select);
commitments.lookup_read_counts_0 = receive_commitment(commitment_labels.lookup_read_counts_0);
commitments.lookup_read_counts_1 = receive_commitment(commitment_labels.lookup_read_counts_1);
commitments.transcript_base_infinity = receive_commitment(commitment_labels.transcript_base_infinity);
commitments.transcript_base_x_inverse = receive_commitment(commitment_labels.transcript_base_x_inverse);
commitments.transcript_base_y_inverse = receive_commitment(commitment_labels.transcript_base_y_inverse);
commitments.transcript_add_x_equal = receive_commitment(commitment_labels.transcript_add_x_equal);
commitments.transcript_add_y_equal = receive_commitment(commitment_labels.transcript_add_y_equal);
commitments.transcript_add_lambda = receive_commitment(commitment_labels.transcript_add_lambda);
commitments.transcript_msm_intermediate_x = receive_commitment(commitment_labels.transcript_msm_intermediate_x);
commitments.transcript_msm_intermediate_y = receive_commitment(commitment_labels.transcript_msm_intermediate_y);
commitments.transcript_msm_infinity = receive_commitment(commitment_labels.transcript_msm_infinity);
commitments.transcript_msm_x_inverse = receive_commitment(commitment_labels.transcript_msm_x_inverse);
commitments.transcript_msm_count_zero_at_transition =
receive_commitment(commitment_labels.transcript_msm_count_zero_at_transition);
commitments.transcript_msm_count_at_transition_inverse =
receive_commitment(commitment_labels.transcript_msm_count_at_transition_inverse);

// Get challenge for sorted list batching and wire four memory records
auto [beta, gamma] = transcript->template get_challenges<FF>("beta", "gamma");

relation_parameters.gamma = gamma;
auto beta_sqr = beta * beta;
relation_parameters.gamma = gamma;
relation_parameters.beta = beta;
relation_parameters.beta_sqr = beta_sqr;
relation_parameters.beta_sqr = beta * beta;
relation_parameters.beta_cube = beta_sqr * beta;
relation_parameters.eccvm_set_permutation_delta =
gamma * (gamma + beta_sqr) * (gamma + beta_sqr + beta_sqr) * (gamma + beta_sqr + beta_sqr + beta_sqr);
relation_parameters.eccvm_set_permutation_delta = relation_parameters.eccvm_set_permutation_delta.invert();

// Get commitment to permutation and lookup grand products
commitments.lookup_inverses = receive_commitment(commitment_labels.lookup_inverses);
commitments.z_perm = receive_commitment(commitment_labels.z_perm);
commitments.lookup_inverses =
transcript->template receive_from_prover<Commitment>(commitment_labels.lookup_inverses);
commitments.z_perm = transcript->template receive_from_prover<Commitment>(commitment_labels.z_perm);

// Execute Sumcheck Verifier
const size_t log_circuit_size = numeric::get_msb(circuit_size);
Expand Down Expand Up @@ -160,7 +68,7 @@ bool ECCVMVerifier::verify_proof(const HonkProof& proof)
// TODO(#768): Find a better way to do this. See issue for details.
bool univariate_opening_verified = false;
{
auto hack_commitment = receive_commitment("Translation:hack_commitment");
auto hack_commitment = transcript->template receive_from_prover<Commitment>("Translation:hack_commitment");

FF evaluation_challenge_x = transcript->template get_challenge<FF>("Translation:evaluation_challenge_x");

Expand Down
1 change: 0 additions & 1 deletion barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ class ECCVMVerifier {

std::shared_ptr<VerificationKey> key;
std::map<std::string, Commitment> commitments;
std::map<std::string, FF> pcs_fr_elements;
std::shared_ptr<Transcript> transcript;
};
} // namespace bb
Original file line number Diff line number Diff line change
@@ -1 +1 @@
barretenberg_module(eccvm_recursion eccvm stdlib_circuit_builders stdlib_primitives)
barretenberg_module(eccvm_recursion eccvm stdlib_honk_recursion)
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#include "barretenberg/eccvm_recursion/eccvm_recursive_flavor.hpp"
#include "barretenberg/flavor/relation_definitions.hpp"
#include "barretenberg/relations/ecc_vm/ecc_bools_relation_impl.hpp"
#include "barretenberg/stdlib/primitives/bigfield/bigfield.hpp"

namespace bb {
template class ECCVMBoolsRelationImpl<stdlib::bigfield<UltraCircuitBuilder, bb::Bn254FqParams>>;
template class ECCVMBoolsRelationImpl<stdlib::bigfield<MegaCircuitBuilder, bb::Bn254FqParams>>;
DEFINE_SUMCHECK_VERIFIER_RELATION_CLASS(ECCVMBoolsRelationImpl, ECCVMRecursiveFlavor_<UltraCircuitBuilder>);
DEFINE_SUMCHECK_VERIFIER_RELATION_CLASS(ECCVMBoolsRelationImpl, ECCVMRecursiveFlavor_<MegaCircuitBuilder>);
} // namespace bb
Original file line number Diff line number Diff line change
Expand Up @@ -55,5 +55,6 @@ TEST_F(EccRelationsConsistency, RecursiveToNativeConsistency)
validate_relation_execution<ECCVMPointTableRelation>();
validate_relation_execution<ECCVMTranscriptRelation>();
validate_relation_execution<ECCVMWnafRelation>();
validate_relation_execution<ECCVMBoolsRelation>();
}
} // namespace bb
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "barretenberg/relations/ecc_vm/ecc_wnaf_relation.hpp"
#include "barretenberg/relations/relation_parameters.hpp"
#include "barretenberg/stdlib/honk_recursion/transcript/transcript.hpp"
#include "barretenberg/stdlib/primitives/curves/grumpkin.hpp"

// NOLINTBEGIN(cppcoreguidelines-avoid-const-or-ref-data-members) ?

Expand All @@ -22,8 +23,10 @@ namespace bb {
template <typename BuilderType> class ECCVMRecursiveFlavor_ {
public:
using CircuitBuilder = BuilderType; // determines the arithmetisation of recursive verifier
using FF = stdlib::bigfield<CircuitBuilder, bb::Bn254FqParams>;
using BF = stdlib::field_t<CircuitBuilder>;
using Curve = stdlib::grumpkin<CircuitBuilder>;
using Commitment = Curve::AffineElement;
using FF = Curve::ScalarField;
using BF = Curve::BaseField;
using RelationSeparator = FF;
using NativeFlavor = ECCVMFlavor;
using NativeVerificationKey = NativeFlavor::VerificationKey;
Expand Down Expand Up @@ -70,6 +73,59 @@ template <typename BuilderType> class ECCVMRecursiveFlavor_ {
using Base::Base;
};

using VerifierCommitmentKey = bb::VerifierCommitmentKey<Curve>;
/**
* @brief The verification key is responsible for storing the the commitments to the precomputed (non-witness)
* polynomials used by the verifier.
*
* @note Note the discrepancy with what sort of data is stored here vs in the proving key. We may want to
* resolve that, and split out separate PrecomputedPolynomials/Commitments data for clarity but also for
* portability of our circuits.
*/
class VerificationKey
: public VerificationKey_<ECCVMFlavor::PrecomputedEntities<Commitment>, VerifierCommitmentKey> {
public:
VerificationKey(const size_t circuit_size, const size_t num_public_inputs)
{
this->circuit_size = circuit_size;
this->log_circuit_size = numeric::get_msb(circuit_size);
this->num_public_inputs = num_public_inputs;
};

/**
* @brief Construct a new Verification Key with stdlib types from a provided native verification
* key
*
* @param builder
* @param native_key Native verification key from which to extract the precomputed commitments
*/

VerificationKey(CircuitBuilder* builder, const std::shared_ptr<NativeVerificationKey>& native_key)
{
this->pcs_verification_key = std::make_shared<VerifierCommitmentKey>(
builder, native_key->circuit_size, native_key->pcs_verification_key);
this->circuit_size = native_key->circuit_size;
this->log_circuit_size = numeric::get_msb(this->circuit_size);
this->num_public_inputs = native_key->num_public_inputs;
this->pub_inputs_offset = native_key->pub_inputs_offset;

for (auto [native_commitment, commitment] : zip_view(native_key->get_all(), this->get_all())) {
commitment = Commitment::from_witness(builder, native_commitment);
}
}
};

/**
* @brief A container for the witness commitments.
*/
using WitnessCommitments = ECCVMFlavor::WitnessEntities<Commitment>;

using CommitmentLabels = ECCVMFlavor::CommitmentLabels;
// Reuse the VerifierCommitments from ECCVM
using VerifierCommitments = ECCVMFlavor::VerifierCommitments_<Commitment, VerificationKey>;
// Reuse the transcript from ECCVM
using Transcript = bb::BaseTranscript<bb::stdlib::recursion::honk::StdlibTranscriptParams<CircuitBuilder>>;

}; // NOLINTEND(cppcoreguidelines-avoid-const-or-ref-data-members)

} // namespace bb
Loading

0 comments on commit afe84a2

Please sign in to comment.