22#include <gtest/gtest.h>
36 vk.ordered_extra_range_constraints_numerator =
37 proving_key->commitment_key.commit(proving_key->polynomials.ordered_extra_range_constraints_numerator);
48 for (
const auto&
fr : frs) {
49 elements.push_back(
fr);
84 constexpr size_t frs_per_G = FrCodec::calc_num_fields<Flavor::Commitment>();
89 manifest.
add_entry(0,
"Gemini:masking_poly_comm", frs_per_G);
93 std::vector<std::string> wire_labels = {
94 "CONCATENATED_RANGE_CONSTRAINTS_0",
"CONCATENATED_RANGE_CONSTRAINTS_1",
95 "CONCATENATED_RANGE_CONSTRAINTS_2",
"CONCATENATED_RANGE_CONSTRAINTS_3",
96 "CONCATENATED_NON_RANGE",
97 "ORDERED_RANGE_CONSTRAINTS_0",
"ORDERED_RANGE_CONSTRAINTS_1",
98 "ORDERED_RANGE_CONSTRAINTS_2",
"ORDERED_RANGE_CONSTRAINTS_3",
99 "ORDERED_RANGE_CONSTRAINTS_4",
102 for (
const auto&
label : wire_labels) {
110 manifest.
add_entry(1,
"Z_PERM", frs_per_G);
115 manifest.
add_entry(2,
"Libra:concatenation_commitment", frs_per_G);
121 for (
size_t i = 0; i < LOG_MINI; ++i) {
132 for (
size_t i = LOG_MINI + 1; i < NUM_SUMCHECK_ROUNDS; ++i) {
139 const size_t eval_round = 3 + NUM_SUMCHECK_ROUNDS;
141 manifest.
add_entry(eval_round,
"Libra:claimed_evaluation", 1);
142 manifest.
add_entry(eval_round,
"Libra:grand_sum_commitment", frs_per_G);
143 manifest.
add_entry(eval_round,
"Libra:quotient_commitment", frs_per_G);
147 const size_t gemini_fold_round = eval_round + 1;
148 for (
size_t i = 1; i < NUM_SUMCHECK_ROUNDS; ++i) {
154 const size_t gemini_eval_round = gemini_fold_round + 1;
155 for (
size_t i = 1; i <= NUM_SUMCHECK_ROUNDS; ++i) {
159 manifest.
add_entry(gemini_eval_round,
"Libra:concatenation_eval", 1);
160 manifest.
add_entry(gemini_eval_round,
"Libra:shifted_grand_sum_eval", 1);
161 manifest.
add_entry(gemini_eval_round,
"Libra:grand_sum_eval", 1);
162 manifest.
add_entry(gemini_eval_round,
"Libra:quotient_eval", 1);
166 const size_t shplonk_round = gemini_eval_round + 1;
167 manifest.
add_entry(shplonk_round,
"Shplonk:Q", frs_per_G);
171 const size_t kzg_round = shplonk_round + 1;
172 manifest.
add_entry(kzg_round,
"KZG:W", frs_per_G);
178 static void add_random_ops(std::shared_ptr<bb::ECCOpQueue>& op_queue,
size_t count = 1)
180 for (
size_t i = 0; i < count; i++) {
181 op_queue->random_op_ultra_only();
185 static void add_mixed_ops(std::shared_ptr<bb::ECCOpQueue>& op_queue,
size_t count = 100)
190 for (
size_t i = 0; i < count; i++) {
191 op_queue->add_accumulate(P1);
192 op_queue->mul_accumulate(P2, z);
194 op_queue->eq_and_reset();
199 const Fq& evaluation_challenge_x,
200 const size_t circuit_size_parameter = 500)
205 op_queue->construct_zk_columns();
210 op_queue->merge_fixed_append(op_queue->get_append_offset_for_prover());
212 return CircuitBuilder{ batching_challenge_v, evaluation_challenge_x, op_queue };
216 const Fq& evaluation_challenge_x,
217 const Fq& batching_challenge_v)
222 auto initial_transcript = prover_transcript->export_proof();
226 verifier_transcript->template receive_from_prover<Fq>(
"init");
237 op_queue_commitments[0] =
238 proving_key->proving_key->commitment_key.commit(proving_key->proving_key->polynomials.op);
239 op_queue_commitments[1] =
240 proving_key->proving_key->commitment_key.commit(proving_key->proving_key->polynomials.x_lo_y_hi);
241 op_queue_commitments[2] =
242 proving_key->proving_key->commitment_key.commit(proving_key->proving_key->polynomials.x_hi_z_1);
243 op_queue_commitments[3] =
244 proving_key->proving_key->commitment_key.commit(proving_key->proving_key->polynomials.y_lo_z_2);
247 uint256_t accumulated_result = prover.get_accumulated_result();
252 evaluation_challenge_x,
253 batching_challenge_v,
255 op_queue_commitments);
259 return result.pairing_points.check() &&
result.reduction_succeeded;
263 const Fq& evaluation_challenge_x,
264 const Fq& batching_challenge_v)
268 auto initial_transcript = prover_transcript->export_proof();
271 verifier_transcript->template receive_from_prover<Fq>(
"init");
279 op_queue_commitments[0] =
280 proving_key->proving_key->commitment_key.commit(proving_key->proving_key->polynomials.op);
281 op_queue_commitments[1] =
282 proving_key->proving_key->commitment_key.commit(proving_key->proving_key->polynomials.x_lo_y_hi);
283 op_queue_commitments[2] =
284 proving_key->proving_key->commitment_key.commit(proving_key->proving_key->polynomials.x_hi_z_1);
285 op_queue_commitments[3] =
286 proving_key->proving_key->commitment_key.commit(proving_key->proving_key->polynomials.y_lo_z_2);
290 evaluation_challenge_x,
291 batching_challenge_v,
292 prover.get_accumulated_result(),
293 op_queue_commitments);
296 return result.pairing_points.check() &&
result.reduction_succeeded;
299 template <
typename FullRelation,
typename ShortRelation>
302 const FF& scaling_factor)
305 for (
auto [extended_edge, short_edge] :
zip_view(extended_edges.get_all(), in.get_all())) {
306 extended_edge = short_edge.template extend_to<TranslatorFlavor::MAX_PARTIAL_RELATION_LENGTH>();
309 typename FullRelation::SumcheckTupleOfUnivariatesOverSubrelations full_accumulators{};
310 typename ShortRelation::SumcheckTupleOfUnivariatesOverSubrelations short_accumulators{};
311 FullRelation::accumulate(full_accumulators, extended_edges, params, scaling_factor);
312 ShortRelation::accumulate(short_accumulators, in, params, scaling_factor);
314 EXPECT_EQ(short_accumulators, full_accumulators);
321 for (
auto& edge :
result.get_all()) {
349 CircuitBuilder circuit_builder = generate_test_circuit(batching_challenge_v, evaluation_challenge_x);
354 prover_transcript->export_proof();
376 CircuitBuilder circuit_builder = generate_test_circuit(batching_challenge_v, evaluation_challenge_x);
379 bool verified = prove_and_verify(circuit_builder, evaluation_challenge_x, batching_challenge_v);
380 EXPECT_TRUE(verified);
385 const auto run_test = [&](
bool random_inputs) {
387 const auto input = get_short_edge_input(random_inputs);
391 expect_short_relation_matches_full_edges<TranslatorPermutationRelation<FF>,
393 expect_short_relation_matches_full_edges<TranslatorDeltaRangeConstraintRelation<FF>,
395 input, params, scaling_factor);
396 expect_short_relation_matches_full_edges<TranslatorOpcodeConstraintRelation<FF>,
398 input, params, scaling_factor);
399 expect_short_relation_matches_full_edges<TranslatorAccumulatorTransferRelation<FF>,
401 input, params, scaling_factor);
402 expect_short_relation_matches_full_edges<TranslatorDecompositionRelation<FF>,
404 input, params, scaling_factor);
405 expect_short_relation_matches_full_edges<TranslatorNonNativeFieldRelation<FF>,
407 input, params, scaling_factor);
408 expect_short_relation_matches_full_edges<TranslatorZeroConstraintsRelation<FF>,
410 input, params, scaling_factor);
424 CircuitBuilder circuit_builder = generate_test_circuit(batching_challenge_v, evaluation_challenge_x);
427 EXPECT_TRUE(prove_and_verify(circuit_builder, evaluation_challenge_x, batching_challenge_v));
428 EXPECT_TRUE(prove_and_verify_short_monomial(circuit_builder, evaluation_challenge_x, batching_challenge_v));
446 op_queue->no_op_ultra_only();
448 add_mixed_ops(op_queue, 100);
450 auto circuit_builder =
CircuitBuilder{ batching_challenge_v, evaluation_challenge_x, op_queue,
true };
453 bool verified = prove_and_verify(circuit_builder, evaluation_challenge_x, batching_challenge_v);
454 EXPECT_TRUE(verified);
471 prover_transcript->export_proof();
479 auto compare_computed_vk_against_fixed = [&](
size_t circuit_size_parameter) {
481 generate_test_circuit(batching_challenge_v, evaluation_challenge_x, circuit_size_parameter);
485 auto labels = TranslatorFlavor::VerificationKey::get_labels();
488 for (
auto [vk_commitment, fixed_commitment] :
zip_view(computed_vk.get_all(), fixed_vk.get_all())) {
489 if (vk_commitment != fixed_commitment) {
491 info(
"Commitment(uint256_t(\"0x", vk_commitment.x,
"\"),");
492 info(
" uint256_t(\"0x", vk_commitment.y,
"\")),");
494 EXPECT_EQ(vk_commitment, fixed_commitment) <<
"Mismatch at label: " << labels[
index];
498 EXPECT_EQ(computed_vk, fixed_vk);
502 const size_t circuit_size_parameter_1 = 1 << 2;
503 const size_t circuit_size_parameter_2 = 1 << 3;
505 compare_computed_vk_against_fixed(circuit_size_parameter_1);
506 compare_computed_vk_against_fixed(circuit_size_parameter_2);
511 if (computed_hash != hardcoded_hash) {
512 info(
"VK hash mismatch! Update TranslatorHardcodedVKAndHash::vk_hash() with:");
513 info(
"0x", computed_hash);
515 EXPECT_EQ(computed_hash, hardcoded_hash) <<
"Hardcoded VK hash does not match computed hash";
530 CircuitBuilder circuit_builder = generate_test_circuit(batching_challenge_v, evaluation_challenge_x);
542 verifier_transcript->enable_manifest();
545 uint256_t accumulated_result = prover.get_accumulated_result();
549 op_queue_commitments[0] = proving_key->proving_key->commitment_key.commit(proving_key->proving_key->polynomials.op);
550 op_queue_commitments[1] =
551 proving_key->proving_key->commitment_key.commit(proving_key->proving_key->polynomials.x_lo_y_hi);
552 op_queue_commitments[2] =
553 proving_key->proving_key->commitment_key.commit(proving_key->proving_key->polynomials.x_hi_z_1);
554 op_queue_commitments[3] =
555 proving_key->proving_key->commitment_key.commit(proving_key->proving_key->polynomials.y_lo_z_2);
560 evaluation_challenge_x,
561 batching_challenge_v,
563 op_queue_commitments);
569 auto expected_manifest = build_expected_translator_manifest();
570 auto verifier_manifest = verifier_transcript->get_manifest();
572 EXPECT_EQ(verifier_manifest, expected_manifest);
600 for (
auto& e : evals.get_all()) {
608 for (
auto& e : evals.get_minicircuit_wires()) {
609 EXPECT_TRUE(covered.insert(&e).second) <<
"minicircuit wire overlaps with a previous entity";
611 EXPECT_EQ(covered.size(), Flavor::NUM_MINICIRCUIT_WIRES);
613 for (
auto& e : evals.get_minicircuit_wires_shifted()) {
614 EXPECT_TRUE(covered.insert(&e).second) <<
"minicircuit wire shift overlaps with a previous entity";
616 EXPECT_EQ(covered.size(), 2 * Flavor::NUM_MINICIRCUIT_WIRES);
618 for (
auto& e : evals.get_full_circuit_entities()) {
619 EXPECT_TRUE(covered.insert(&e).second) <<
"full-circuit entity overlaps with a previous entity";
621 EXPECT_EQ(covered.size(), 2 * Flavor::NUM_MINICIRCUIT_WIRES + Flavor::NUM_FULL_CIRCUIT_EVALUATIONS);
624 for (
auto& e : evals.get_concatenated()) {
625 EXPECT_TRUE(covered.insert(&e).second) <<
"concatenated poly overlaps with a previous entity";
627 EXPECT_EQ(covered.size(),
628 2 * Flavor::NUM_MINICIRCUIT_WIRES + Flavor::NUM_FULL_CIRCUIT_EVALUATIONS +
629 Flavor::NUM_CONCATENATED_POLYS);
633 EXPECT_EQ(remaining, Flavor::NUM_COMPUTABLE_PRECOMPUTED);
636 for (
auto& e : evals.get_all()) {
637 if (covered.find(&e) == covered.end()) {
642 EXPECT_EQ(remaining, 0UL);
663 CircuitBuilder circuit_builder = generate_test_circuit(batching_challenge_v, evaluation_challenge_x);
668 auto pcs_unshifted = pk->proving_key->polynomials.get_pcs_unshifted();
669 auto pcs_to_be_shifted = pk->proving_key->polynomials.get_pcs_to_be_shifted();
672 const auto&
ck = pk->proving_key->commitment_key;
673 std::vector<Commitment> unshifted_comms;
674 for (
auto& poly : pcs_unshifted) {
675 unshifted_comms.push_back(
ck.commit(poly));
677 std::vector<Commitment> shifted_comms;
678 for (
auto& poly : pcs_to_be_shifted) {
679 shifted_comms.push_back(
ck.commit(poly));
683 std::vector<Commitment> commitments;
684 commitments.push_back(Commitment::one());
685 commitments.insert(commitments.end(), unshifted_comms.begin(), unshifted_comms.end());
686 commitments.insert(commitments.end(), shifted_comms.begin(), shifted_comms.end());
688 constexpr auto repeated = Flavor::REPEATED_COMMITMENTS;
693 auto check_range = [&](
const auto& range,
const std::string&
label) {
694 for (
size_t i = 0; i < range.count; i++) {
695 EXPECT_EQ(commitments[range.original_start +
offset + i], commitments[range.duplicate_start +
offset + i])
696 <<
label <<
" commitment mismatch at index " << i;
700 check_range(repeated.first,
"Range 1");
701 check_range(repeated.second,
"Range 2");
711 for (
auto& v : mid) {
717 for (
auto& v : full_circuit) {
722 std::vector<FF> challenge(Flavor::CONST_TRANSLATOR_LOG_N);
723 for (
auto& u : challenge) {
729 Flavor::set_minicircuit_evaluations(evals, mid);
730 Flavor::complete_full_circuit_evaluations(evals, full_circuit,
std::span<const FF>(challenge));
733 auto all = evals.get_all();
735 EXPECT_NE(all[i],
FF(0)) <<
"Entity " << i <<
" was not populated by verifier methods";
static bool prove_and_verify(const CircuitBuilder &circuit_builder, const Fq &evaluation_challenge_x, const Fq &batching_challenge_v)
static TranslatorShortMonomialFlavor::ProverUnivariates< 2 > get_short_edge_input(bool random_inputs)
static void add_random_ops(std::shared_ptr< bb::ECCOpQueue > &op_queue, size_t count=1)
Flavor::Commitment Commitment
static void expect_short_relation_matches_full_edges(const TranslatorShortMonomialFlavor::ProverUnivariates< 2 > &in, const RelationParameters< FF > ¶ms, const FF &scaling_factor)
static CircuitBuilder generate_test_circuit(const Fq &batching_challenge_v, const Fq &evaluation_challenge_x, const size_t circuit_size_parameter=500)
static void SetUpTestSuite()
static void add_mixed_ops(std::shared_ptr< bb::ECCOpQueue > &op_queue, size_t count=100)
static TranscriptManifest build_expected_translator_manifest()
Build the expected transcript manifest for Translator verification.
static bool prove_and_verify_short_monomial(const CircuitBuilder &circuit_builder, const Fq &evaluation_challenge_x, const Fq &batching_challenge_v)
Common transcript class for both parties. Stores the data for the current round, as well as the manif...
Manages ECC operations for the Goblin proving system.
A base class labelling all entities (for instance, all of the polynomials used by the prover during s...
static constexpr bool HasZK
typename Curve::ScalarField FF
static constexpr size_t NUM_ALL_ENTITIES
typename G1::affine_element Commitment
bb::CommitmentKey< Curve > CommitmentKey
Simple verification key class for fixed-size circuits (ECCVM, Translator, AVM).
static std::vector< fr > serialize_to_fields(const T &val)
Conversion from transcript values to bb::frs.
A wrapper for Relations to expose methods used by the Sumcheck prover or verifier to add the contribu...
void add_entry(size_t round, const std::string &element_label, size_t element_size)
void add_challenge(size_t round, const std::string &label)
Add a single challenge label to the manifest for the given round.
TranslatorCircuitBuilder creates a circuit that evaluates the correctness of the evaluation of EccOpQ...
static constexpr size_t NUM_RANDOM_OPS_END
static constexpr size_t NUM_RANDOM_OPS_START
static bool check(const Builder &circuit)
Check the witness satisifies the circuit.
A base class labelling all entities (for instance, all of the polynomials used by the prover during s...
static constexpr size_t NUM_FULL_CIRCUIT_EVALUATIONS
BaseTranscript< Codec, HashFunction > Transcript
static constexpr size_t CONST_TRANSLATOR_LOG_N
static constexpr size_t PROOF_LENGTH
TranslatorCircuitBuilder CircuitBuilder
Curve::AffineElement Commitment
static constexpr size_t NUM_MINICIRCUIT_EVALUATIONS
static constexpr size_t LOG_MINI_CIRCUIT_SIZE
HonkProof construct_proof()
Translator verifier class that verifies the proof of the Translator circuit.
ReductionResult reduce_to_pairing_check()
Reduce the translator proof to a pairing check.
A univariate polynomial represented by its values on {0, 1,..., domain_end - 1}.
static FF hash(const std::vector< FF > &input)
Hashes a vector of field elements.
static affine_element random_element(numeric::RNG *engine=nullptr) noexcept
Samples a random point on the curve.
group_elements::affine_element< Fq, Fr, Params > affine_element
RNG & get_debug_randomness(bool reset, std::uint_fast64_t seed)
std::filesystem::path bb_crs_path()
void init_file_crs_factory(const std::filesystem::path &path)
Entry point for Barretenberg command-line interface.
field< Bn254FqParams > fq
TEST_F(IPATest, ChallengesAreZero)
field< Bn254FrParams > fr
CommitmentKey< Curve > ck
VerifierCommitmentKey< Curve > vk
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
std::string to_string(bb::avm2::ValueTag tag)
Container for parameters used by the grand product (permutation, lookup) Honk relations.
static RelationParameters get_random()
static std::vector< Commitment > get_all()
static field random_element(numeric::RNG *engine=nullptr) noexcept
TranslatorFlavor::VerificationKey create_vk_from_proving_key(const std::shared_ptr< TranslatorFlavor::ProvingKey > &proving_key)
TranslatorFlavor::FF compute_translator_vk_hash()