7#include <gtest/gtest.h>
14#ifdef STARKNET_GARAGA_FLAVORS
20 UltraStarknetZKFlavor>;
22using FlavorTypes = testing::Types<UltraFlavor, UltraZKFlavor, UltraKeccakFlavor, UltraKeccakZKFlavor>;
38 using IO =
typename TestFixture::IO;
48 const size_t virtual_log_n =
Flavor::USE_PADDING ? CONST_PROOF_SIZE_LOG_N : prover_instance->log_dyadic_size();
49 size_t expected_proof_length =
51 EXPECT_EQ(ultra_proof.size(), expected_proof_length);
61 size_t num_gates = 10;
65 TestFixture::set_default_pairing_points_and_ipa_claim_and_proof(
builder);
67 TestFixture::prove_and_verify(
builder,
true);
74 for (
size_t i = 0; i < 16; ++i) {
75 for (
size_t j = 0; j < 16; ++j) {
76 uint64_t left =
static_cast<uint64_t
>(j);
77 uint64_t right =
static_cast<uint64_t
>(i);
78 uint32_t left_idx = circuit_builder.add_variable(
fr(left));
79 uint32_t right_idx = circuit_builder.add_variable(
fr(right));
80 uint32_t result_idx = circuit_builder.add_variable(
fr(left ^ right));
83 circuit_builder.add_variable(
fr(left) +
fr(right) + circuit_builder.get_variable(result_idx));
84 circuit_builder.create_big_add_gate(
85 { left_idx, right_idx, result_idx, add_idx,
fr(1),
fr(1),
fr(1),
fr(-1),
fr(0) });
88 TestFixture::set_default_pairing_points_and_ipa_claim_and_proof(circuit_builder);
90 TestFixture::prove_and_verify(circuit_builder,
true);
99 affine_element p1 = affine_element::random_element();
100 affine_element p2 = affine_element::random_element();
102 affine_element p3(element(p1) + element(p2));
104 uint32_t x1 = circuit_builder.add_variable(p1.x);
105 uint32_t y1 = circuit_builder.add_variable(p1.y);
106 uint32_t x2 = circuit_builder.add_variable(p2.x);
107 uint32_t y2 = circuit_builder.add_variable(p2.y);
108 uint32_t x3 = circuit_builder.add_variable(p3.x);
109 uint32_t y3 = circuit_builder.add_variable(p3.y);
111 circuit_builder.create_ecc_add_gate({ x1, y1, x2, y2, x3, y3,
true });
113 p3 = affine_element(element(p1) + element(p2));
114 x3 = circuit_builder.add_variable(p3.x);
115 y3 = circuit_builder.add_variable(p3.y);
116 circuit_builder.create_ecc_add_gate({ x1, y1, x2, y2, x3, y3,
true });
118 p3 = affine_element(element(p1) - element(p2));
119 x3 = circuit_builder.add_variable(p3.x);
120 y3 = circuit_builder.add_variable(p3.y);
121 circuit_builder.create_ecc_add_gate({ x1, y1, x2, y2, x3, y3,
false });
123 TestFixture::set_default_pairing_points_and_ipa_claim_and_proof(circuit_builder);
125 TestFixture::prove_and_verify(circuit_builder,
true);
147 const auto split_into_limbs = [&](
const uint512_t& input) {
148 constexpr size_t NUM_BITS = 68;
150 limbs[0] = input.slice(0, NUM_BITS).lo;
151 limbs[1] = input.slice(NUM_BITS * 1, NUM_BITS * 2).lo;
152 limbs[2] = input.slice(NUM_BITS * 2, NUM_BITS * 3).lo;
153 limbs[3] = input.slice(NUM_BITS * 3, NUM_BITS * 4).lo;
158 std::array<uint32_t, 4> limb_indices;
159 limb_indices[0] = circuit_builder.add_variable(limbs[0]);
160 limb_indices[1] = circuit_builder.add_variable(limbs[1]);
161 limb_indices[2] = circuit_builder.add_variable(limbs[2]);
162 limb_indices[3] = circuit_builder.add_variable(limbs[3]);
166 auto modulus_limbs = split_into_limbs(BINARY_BASIS_MODULUS -
uint512_t(modulus));
168 const auto a_indices = get_limb_witness_indices(split_into_limbs(
uint256_t(
a)));
169 const auto b_indices = get_limb_witness_indices(split_into_limbs(
uint256_t(
b)));
170 const auto q_indices = get_limb_witness_indices(split_into_limbs(
uint256_t(q)));
171 const auto r_indices = get_limb_witness_indices(split_into_limbs(
uint256_t(r)));
174 a_indices, b_indices, q_indices, r_indices, modulus_limbs,
176 const auto [lo_1_idx, hi_1_idx] = circuit_builder.evaluate_non_native_field_multiplication(
inputs);
179 const bool is_low_70_bits =
uint256_t(circuit_builder.get_variable(lo_1_idx)).
get_msb() < 70;
180 const bool is_high_70_bits =
uint256_t(circuit_builder.get_variable(hi_1_idx)).
get_msb() < 70;
181 if (is_low_70_bits && is_high_70_bits) {
183 circuit_builder.range_constrain_two_limbs(lo_1_idx, hi_1_idx, 70, 70);
186 circuit_builder.create_limbed_range_constraint(lo_1_idx, 72);
187 circuit_builder.create_limbed_range_constraint(hi_1_idx, 72);
190 TestFixture::set_default_pairing_points_and_ipa_claim_and_proof(circuit_builder);
192 TestFixture::prove_and_verify(circuit_builder,
true);
199 uint32_t
a = circuit_builder.add_variable(
fr(100));
200 uint32_t
b = circuit_builder.add_variable(
fr(100));
201 uint32_t c = circuit_builder.add_variable(
fr(100));
202 uint32_t d = circuit_builder.add_variable(
fr(100));
204 circuit_builder.assert_equal(
a,
b);
205 circuit_builder.assert_equal(
a, c);
206 circuit_builder.assert_equal(
a, d);
208 circuit_builder.create_small_range_constraint(
a, 1000);
209 circuit_builder.create_small_range_constraint(
b, 1001);
210 circuit_builder.create_small_range_constraint(c, 999);
211 circuit_builder.create_small_range_constraint(d, 1000);
213 circuit_builder.create_big_add_gate(
227 TestFixture::set_default_pairing_points_and_ipa_claim_and_proof(circuit_builder);
229 TestFixture::prove_and_verify(circuit_builder,
true);
240 uint16_t mask = (1 << 8) - 1;
242 uint32_t a_idx = circuit_builder.add_variable(
fr(
a));
243 uint32_t b_idx = circuit_builder.add_variable(
fr(
a));
244 ASSERT_NE(a_idx, b_idx);
245 uint32_t c_idx = circuit_builder.add_variable(
fr(
a));
246 ASSERT_NE(c_idx, b_idx);
247 circuit_builder.create_dyadic_range_constraint(b_idx, 8,
"bad range");
248 circuit_builder.assert_equal(a_idx, b_idx);
249 circuit_builder.create_dyadic_range_constraint(c_idx, 8,
"bad range");
250 circuit_builder.assert_equal(a_idx, c_idx);
252 TestFixture::set_default_pairing_points_and_ipa_claim_and_proof(circuit_builder);
254 TestFixture::prove_and_verify(circuit_builder,
true);
266 using IO =
typename TestFixture::IO;
271 using VKAndHash =
typename Flavor::VKAndHash;
277 this->set_default_pairing_points_and_ipa_claim_and_proof(
builder);
284 Prover prover(prover_instance,
vk);
285 auto proof = prover.construct_proof();
292 Verifier verifier(vk_and_hash);
304 using IO =
typename TestFixture::IO;
309 using VKAndHash =
typename Flavor::VKAndHash;
316 this->set_default_pairing_points_and_ipa_claim_and_proof(
builder);
321 Prover prover(prover_instance,
vk);
322 auto proof = prover.construct_proof();
325 Proof truncated_proof(proof.begin(), proof.end() - 10);
328 Verifier verifier(vk_and_hash);
340 using IO =
typename TestFixture::IO;
345 using VKAndHash =
typename Flavor::VKAndHash;
353 this->set_default_pairing_points_and_ipa_claim_and_proof(
builder);
358 Prover prover(prover_instance,
vk);
359 auto proof = prover.construct_proof();
362 Proof extended_proof(proof);
363 for (
size_t i = 0; i < 10; i++) {
368 Verifier verifier(vk_and_hash);
386 GTEST_SKIP() <<
"Masking area only exists for ZK flavors";
393 this->set_default_pairing_points_and_ipa_claim_and_proof(baseline_builder);
395 const size_t baseline_dyadic = baseline_instance->dyadic_size();
400 size_t prev_dyadic = 0;
401 bool found_jump =
false;
402 for (
size_t num_extra_gates = 0; num_extra_gates <= baseline_dyadic; num_extra_gates++) {
404 if (num_extra_gates > 0) {
407 this->set_default_pairing_points_and_ipa_claim_and_proof(
builder);
411 const size_t dyadic_size = prover_instance->dyadic_size();
412 const size_t final_active_idx = prover_instance->get_final_active_wire_idx();
416 <<
"final_active_idx (" << final_active_idx <<
") is within the disabled head region";
418 if (prev_dyadic != 0 && dyadic_size > prev_dyadic) {
420 EXPECT_EQ(dyadic_size, 2 * prev_dyadic);
425 this->set_default_pairing_points_and_ipa_claim_and_proof(tight_builder);
427 this->prove_and_verify(tight_instance,
true);
433 prev_dyadic = dyadic_size;
436 EXPECT_TRUE(found_jump) <<
"should have found a dyadic size jump within " << baseline_dyadic <<
" extra gates";
450 using IO =
typename TestFixture::IO;
453 for (
auto table_id : { plookup::MultiTableId::UINT32_XOR,
454 plookup::MultiTableId::UINT32_AND,
455 plookup::MultiTableId::SHA256_CH_INPUT }) {
460 table_id,
builder.get_variable(left_idx),
builder.get_variable(right_idx),
true);
461 builder.create_gates_from_plookup_accumulators(table_id, accumulators, left_idx, right_idx);
466 const size_t tables_size =
builder.get_tables_size();
467 ASSERT_GT(tables_size, 0) <<
"expected non-empty lookup tables";
469 const size_t table_offset =
builder.blocks.lookup.trace_offset();
470 const size_t tables_end = table_offset + tables_size;
473 <<
"lookup block should be past the disabled region";
474 EXPECT_GE(prover_instance->dyadic_size(), tables_end)
475 <<
"dyadic size (" << prover_instance->dyadic_size() <<
") must accommodate tables_end (" << tables_end
476 <<
") for table_offset=" << table_offset <<
" tables_size=" << tables_size;
488 GTEST_SKIP() <<
"Masking only applies to ZK flavors";
491 using IO =
typename TestFixture::IO;
497 auto check_masked = [](
const auto& poly,
const std::string&
label) {
498 bool has_masking =
false;
499 for (
size_t j = 0; j < NUM_MASKED_ROWS; j++) {
500 has_masking |= !poly[NUM_ZERO_ROWS + j].is_zero();
502 EXPECT_TRUE(has_masking) <<
label <<
" should be masked";
505 auto& polys = prover_instance->polynomials;
506 check_masked(polys.w_l(),
"w_l");
507 check_masked(polys.w_r(),
"w_r");
508 check_masked(polys.w_o(),
"w_o");
509 check_masked(polys.w_4(),
"w_4");
510 check_masked(polys.z_perm(),
"z_perm");
511 check_masked(polys.lookup_read_counts(),
"lookup_read_counts");
512 check_masked(polys.lookup_read_tags(),
"lookup_read_tags");
513 check_masked(polys.lookup_inverses(),
"lookup_inverses");
526 using IO =
typename TestFixture::IO;
535 auto unshifted = prover_instance->polynomials.get_unshifted();
536 auto to_be_shifted = prover_instance->polynomials.get_to_be_shifted();
538 constexpr auto repeated = Flavor::REPEATED_COMMITMENTS;
539 ASSERT_EQ(to_be_shifted.size(), repeated.first.count);
542 std::vector<Commitment> commitments;
543 commitments.push_back(Commitment::one());
544 for (
auto& poly : unshifted) {
545 commitments.push_back(
ck.commit(poly));
547 for (
auto& poly : to_be_shifted) {
548 commitments.push_back(
ck.commit(poly));
553 for (
size_t i = 0; i < repeated.first.count; i++) {
554 EXPECT_EQ(commitments[repeated.first.original_start +
offset + i],
555 commitments[repeated.first.duplicate_start +
offset + i])
556 <<
"REPEATED_COMMITMENTS commitment mismatch at index " << i;
561size_t count_occurrences(
const std::string& haystack,
const std::string& needle)
564 for (
size_t pos = haystack.find(needle); pos != std::string::npos;
565 pos = haystack.find(needle, pos + needle.size())) {
574TEST(HonkKeyGen, EmittedG1CountMatchesPrecomputedEntities)
579 std::ostringstream os;
582 EXPECT_EQ(count_occurrences(os.str(),
"Honk.G1Point"), VerificationKey::size());
#define EXPECT_THROW_WITH_MESSAGE(code, expectedMessageRegex)
CommitmentKey object over a pairing group 𝔾₁.
static constexpr bool HasZK
typename Curve::ScalarField FF
ECCVMCircuitBuilder CircuitBuilder
typename G1::affine_element Commitment
bb::CommitmentKey< Curve > CommitmentKey
FixedVKAndHash_< PrecomputedEntities< Commitment >, BF, ECCVMHardcodedVKAndHash > VerificationKey
The verification key stores commitments to the precomputed polynomials used by the verifier.
static constexpr bool USE_PADDING
static void add_arithmetic_gates_with_public_inputs(Builder &builder, const size_t num_gates=4)
Add a specified number of arithmetic gates (with public inputs) to the provided circuit.
static void add_arithmetic_gates(Builder &builder, const size_t num_gates=4)
Add a specified number of arithmetic gates to the provided circuit.
Base Native verification key class.
Contains all the information required by a Honk prover to create a proof, constructed from a finalize...
static constexpr size_t TRACE_OFFSET
NativeVerificationKey_< PrecomputedEntities< Commitment >, Codec, HashFunction, CommitmentKey > VerificationKey
Child class of UltraFlavor that runs with ZK Sumcheck.
element class. Implements ecc group arithmetic using Jacobian coordinates See https://hyperelliptic....
virtual uint16_t get_random_uint16()=0
virtual uint32_t get_random_uint32()=0
constexpr uint64_t get_msb() const
testing::Types< UltraFlavor, UltraKeccakFlavor, MegaFlavor > FlavorTypes
void output_vk_sol_ultra_honk(std::ostream &os, auto const &key, std::string const &class_name, bool include_types_import=false)
uintx< uint256_t > uint512_t
ReadData< bb::fr > get_lookup_accumulators(const MultiTableId id, const fr &key_a, const fr &key_b, const bool is_2_to_1_lookup)
Given a table ID and the key(s) for a key-value lookup, return the lookup accumulators.
Entry point for Barretenberg command-line interface.
field< Bn254FqParams > fq
TYPED_TEST_SUITE(CommitmentKeyTest, Curves)
field< Bn254FrParams > fr
TYPED_TEST(CommitmentKeyTest, CommitToZeroPoly)
UltraCircuitBuilder_< UltraExecutionTraceBlocks > UltraCircuitBuilder
TEST(BoomerangMegaCircuitBuilder, BasicCircuit)
CommitmentKey< Curve > ck
VerifierCommitmentKey< Curve > vk
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
static constexpr size_t LENGTH_WITHOUT_PUB_INPUTS(size_t log_n)
static constexpr uint256_t modulus
static field random_element(numeric::RNG *engine=nullptr) noexcept
An object storing two EC points that represent the inputs to a pairing check.