6#include <gtest/gtest.h>
12#ifdef STARKNET_GARAGA_FLAVORS
18 UltraStarknetZKFlavor>;
20using FlavorTypes = testing::Types<UltraFlavor, UltraZKFlavor, UltraKeccakFlavor, UltraKeccakZKFlavor>;
36 using IO =
typename TestFixture::IO;
46 const size_t virtual_log_n =
Flavor::USE_PADDING ? CONST_PROOF_SIZE_LOG_N : prover_instance->log_dyadic_size();
47 size_t expected_proof_length =
49 EXPECT_EQ(ultra_proof.size(), expected_proof_length);
59 size_t num_gates = 10;
63 TestFixture::set_default_pairing_points_and_ipa_claim_and_proof(
builder);
65 TestFixture::prove_and_verify(
builder,
true);
72 for (
size_t i = 0; i < 16; ++i) {
73 for (
size_t j = 0; j < 16; ++j) {
74 uint64_t left =
static_cast<uint64_t
>(j);
75 uint64_t right =
static_cast<uint64_t
>(i);
76 uint32_t left_idx = circuit_builder.add_variable(
fr(left));
77 uint32_t right_idx = circuit_builder.add_variable(
fr(right));
78 uint32_t result_idx = circuit_builder.add_variable(
fr(left ^ right));
81 circuit_builder.add_variable(
fr(left) +
fr(right) + circuit_builder.get_variable(result_idx));
82 circuit_builder.create_big_add_gate(
83 { left_idx, right_idx, result_idx, add_idx,
fr(1),
fr(1),
fr(1),
fr(-1),
fr(0) });
86 TestFixture::set_default_pairing_points_and_ipa_claim_and_proof(circuit_builder);
88 TestFixture::prove_and_verify(circuit_builder,
true);
97 affine_element p1 = affine_element::random_element();
98 affine_element p2 = affine_element::random_element();
100 affine_element p3(element(p1) + element(p2));
102 uint32_t x1 = circuit_builder.add_variable(p1.x);
103 uint32_t y1 = circuit_builder.add_variable(p1.y);
104 uint32_t x2 = circuit_builder.add_variable(p2.x);
105 uint32_t y2 = circuit_builder.add_variable(p2.y);
106 uint32_t x3 = circuit_builder.add_variable(p3.x);
107 uint32_t y3 = circuit_builder.add_variable(p3.y);
109 circuit_builder.create_ecc_add_gate({ x1, y1, x2, y2, x3, y3,
true });
111 p3 = affine_element(element(p1) + element(p2));
112 x3 = circuit_builder.add_variable(p3.x);
113 y3 = circuit_builder.add_variable(p3.y);
114 circuit_builder.create_ecc_add_gate({ x1, y1, x2, y2, x3, y3,
true });
116 p3 = affine_element(element(p1) - element(p2));
117 x3 = circuit_builder.add_variable(p3.x);
118 y3 = circuit_builder.add_variable(p3.y);
119 circuit_builder.create_ecc_add_gate({ x1, y1, x2, y2, x3, y3,
false });
121 TestFixture::set_default_pairing_points_and_ipa_claim_and_proof(circuit_builder);
123 TestFixture::prove_and_verify(circuit_builder,
true);
145 const auto split_into_limbs = [&](
const uint512_t& input) {
146 constexpr size_t NUM_BITS = 68;
148 limbs[0] = input.slice(0, NUM_BITS).lo;
149 limbs[1] = input.slice(NUM_BITS * 1, NUM_BITS * 2).lo;
150 limbs[2] = input.slice(NUM_BITS * 2, NUM_BITS * 3).lo;
151 limbs[3] = input.slice(NUM_BITS * 3, NUM_BITS * 4).lo;
156 std::array<uint32_t, 4> limb_indices;
157 limb_indices[0] = circuit_builder.add_variable(limbs[0]);
158 limb_indices[1] = circuit_builder.add_variable(limbs[1]);
159 limb_indices[2] = circuit_builder.add_variable(limbs[2]);
160 limb_indices[3] = circuit_builder.add_variable(limbs[3]);
164 auto modulus_limbs = split_into_limbs(BINARY_BASIS_MODULUS -
uint512_t(modulus));
166 const auto a_indices = get_limb_witness_indices(split_into_limbs(
uint256_t(
a)));
167 const auto b_indices = get_limb_witness_indices(split_into_limbs(
uint256_t(
b)));
168 const auto q_indices = get_limb_witness_indices(split_into_limbs(
uint256_t(q)));
169 const auto r_indices = get_limb_witness_indices(split_into_limbs(
uint256_t(r)));
172 a_indices, b_indices, q_indices, r_indices, modulus_limbs,
174 const auto [lo_1_idx, hi_1_idx] = circuit_builder.evaluate_non_native_field_multiplication(
inputs);
177 const bool is_low_70_bits =
uint256_t(circuit_builder.get_variable(lo_1_idx)).
get_msb() < 70;
178 const bool is_high_70_bits =
uint256_t(circuit_builder.get_variable(hi_1_idx)).
get_msb() < 70;
179 if (is_low_70_bits && is_high_70_bits) {
181 circuit_builder.range_constrain_two_limbs(lo_1_idx, hi_1_idx, 70, 70);
184 circuit_builder.create_limbed_range_constraint(lo_1_idx, 72);
185 circuit_builder.create_limbed_range_constraint(hi_1_idx, 72);
188 TestFixture::set_default_pairing_points_and_ipa_claim_and_proof(circuit_builder);
190 TestFixture::prove_and_verify(circuit_builder,
true);
197 uint32_t
a = circuit_builder.add_variable(
fr(100));
198 uint32_t
b = circuit_builder.add_variable(
fr(100));
199 uint32_t c = circuit_builder.add_variable(
fr(100));
200 uint32_t d = circuit_builder.add_variable(
fr(100));
202 circuit_builder.assert_equal(
a,
b);
203 circuit_builder.assert_equal(
a, c);
204 circuit_builder.assert_equal(
a, d);
206 circuit_builder.create_small_range_constraint(
a, 1000);
207 circuit_builder.create_small_range_constraint(
b, 1001);
208 circuit_builder.create_small_range_constraint(c, 999);
209 circuit_builder.create_small_range_constraint(d, 1000);
211 circuit_builder.create_big_add_gate(
225 TestFixture::set_default_pairing_points_and_ipa_claim_and_proof(circuit_builder);
227 TestFixture::prove_and_verify(circuit_builder,
true);
238 uint16_t mask = (1 << 8) - 1;
240 uint32_t a_idx = circuit_builder.add_variable(
fr(
a));
241 uint32_t b_idx = circuit_builder.add_variable(
fr(
a));
242 ASSERT_NE(a_idx, b_idx);
243 uint32_t c_idx = circuit_builder.add_variable(
fr(
a));
244 ASSERT_NE(c_idx, b_idx);
245 circuit_builder.create_dyadic_range_constraint(b_idx, 8,
"bad range");
246 circuit_builder.assert_equal(a_idx, b_idx);
247 circuit_builder.create_dyadic_range_constraint(c_idx, 8,
"bad range");
248 circuit_builder.assert_equal(a_idx, c_idx);
250 TestFixture::set_default_pairing_points_and_ipa_claim_and_proof(circuit_builder);
252 TestFixture::prove_and_verify(circuit_builder,
true);
264 using IO =
typename TestFixture::IO;
269 using VKAndHash =
typename Flavor::VKAndHash;
275 this->set_default_pairing_points_and_ipa_claim_and_proof(
builder);
282 Prover prover(prover_instance,
vk);
283 auto proof = prover.construct_proof();
290 Verifier verifier(vk_and_hash);
302 using IO =
typename TestFixture::IO;
307 using VKAndHash =
typename Flavor::VKAndHash;
314 this->set_default_pairing_points_and_ipa_claim_and_proof(
builder);
319 Prover prover(prover_instance,
vk);
320 auto proof = prover.construct_proof();
323 Proof truncated_proof(proof.begin(), proof.end() - 10);
326 Verifier verifier(vk_and_hash);
338 using IO =
typename TestFixture::IO;
343 using VKAndHash =
typename Flavor::VKAndHash;
351 this->set_default_pairing_points_and_ipa_claim_and_proof(
builder);
356 Prover prover(prover_instance,
vk);
357 auto proof = prover.construct_proof();
360 Proof extended_proof(proof);
361 for (
size_t i = 0; i < 10; i++) {
366 Verifier verifier(vk_and_hash);
384 GTEST_SKIP() <<
"Masking area only exists for ZK flavors";
391 this->set_default_pairing_points_and_ipa_claim_and_proof(baseline_builder);
393 const size_t baseline_dyadic = baseline_instance->dyadic_size();
398 size_t prev_dyadic = 0;
399 bool found_jump =
false;
400 for (
size_t num_extra_gates = 0; num_extra_gates <= baseline_dyadic; num_extra_gates++) {
402 if (num_extra_gates > 0) {
405 this->set_default_pairing_points_and_ipa_claim_and_proof(
builder);
409 const size_t dyadic_size = prover_instance->dyadic_size();
410 const size_t final_active_idx = prover_instance->get_final_active_wire_idx();
414 <<
"final_active_idx (" << final_active_idx <<
") is within the disabled head region";
416 if (prev_dyadic != 0 && dyadic_size > prev_dyadic) {
418 EXPECT_EQ(dyadic_size, 2 * prev_dyadic);
423 this->set_default_pairing_points_and_ipa_claim_and_proof(tight_builder);
425 this->prove_and_verify(tight_instance,
true);
431 prev_dyadic = dyadic_size;
434 EXPECT_TRUE(found_jump) <<
"should have found a dyadic size jump within " << baseline_dyadic <<
" extra gates";
448 using IO =
typename TestFixture::IO;
451 for (
auto table_id : { plookup::MultiTableId::UINT32_XOR,
452 plookup::MultiTableId::UINT32_AND,
453 plookup::MultiTableId::SHA256_CH_INPUT }) {
458 table_id,
builder.get_variable(left_idx),
builder.get_variable(right_idx),
true);
459 builder.create_gates_from_plookup_accumulators(table_id, accumulators, left_idx, right_idx);
464 const size_t tables_size =
builder.get_tables_size();
465 ASSERT_GT(tables_size, 0) <<
"expected non-empty lookup tables";
467 const size_t table_offset =
builder.blocks.lookup.trace_offset();
468 const size_t tables_end = table_offset + tables_size;
471 <<
"lookup block should be past the disabled region";
472 EXPECT_GE(prover_instance->dyadic_size(), tables_end)
473 <<
"dyadic size (" << prover_instance->dyadic_size() <<
") must accommodate tables_end (" << tables_end
474 <<
") for table_offset=" << table_offset <<
" tables_size=" << tables_size;
486 GTEST_SKIP() <<
"Masking only applies to ZK flavors";
489 using IO =
typename TestFixture::IO;
495 auto check_masked = [](
const auto& poly,
const std::string& label) {
496 bool has_masking =
false;
497 for (
size_t j = 0; j < NUM_MASKED_ROWS; j++) {
498 has_masking |= !poly[NUM_ZERO_ROWS + j].is_zero();
500 EXPECT_TRUE(has_masking) << label <<
" should be masked";
503 auto& polys = prover_instance->polynomials;
504 check_masked(polys.w_l,
"w_l");
505 check_masked(polys.w_r,
"w_r");
506 check_masked(polys.w_o,
"w_o");
507 check_masked(polys.w_4,
"w_4");
508 check_masked(polys.z_perm,
"z_perm");
509 check_masked(polys.lookup_read_counts,
"lookup_read_counts");
510 check_masked(polys.lookup_read_tags,
"lookup_read_tags");
511 check_masked(polys.lookup_inverses,
"lookup_inverses");
524 using IO =
typename TestFixture::IO;
533 auto unshifted = prover_instance->polynomials.get_unshifted();
534 auto to_be_shifted = prover_instance->polynomials.get_to_be_shifted();
537 ASSERT_EQ(to_be_shifted.size(), repeated.first.count);
540 std::vector<Commitment> commitments;
541 commitments.push_back(Commitment::one());
542 for (
auto& poly : unshifted) {
543 commitments.push_back(
ck.commit(poly));
545 for (
auto& poly : to_be_shifted) {
546 commitments.push_back(
ck.commit(poly));
551 for (
size_t i = 0; i < repeated.first.count; i++) {
552 EXPECT_EQ(commitments[repeated.first.original_start +
offset + i],
553 commitments[repeated.first.duplicate_start +
offset + i])
554 <<
"REPEATED_COMMITMENTS commitment mismatch at index " << i;
#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 constexpr RepeatedCommitmentsData REPEATED_COMMITMENTS
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
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
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
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.