10#include <gtest/gtest.h>
23 for (
size_t i = 0; i < 16; ++i) {
24 for (
size_t j = 0; j < 16; ++j) {
25 uint64_t left =
static_cast<uint64_t
>(j);
26 uint64_t right =
static_cast<uint64_t
>(i);
27 uint32_t left_idx =
builder.add_variable(
fr(left));
28 uint32_t right_idx =
builder.add_variable(
fr(right));
29 uint32_t result_idx =
builder.add_variable(
fr(left ^ right));
31 uint32_t add_idx =
builder.add_variable(
fr(left) +
fr(right) +
builder.get_variable(result_idx));
33 { left_idx, right_idx, result_idx, add_idx,
fr(1),
fr(1),
fr(1),
fr(-1),
fr(0) });
38 EXPECT_EQ(result,
true);
42 EXPECT_EQ(duplicate_builder.get_estimated_num_finalized_gates(),
builder.get_estimated_num_finalized_gates());
53 const auto input_lo_index = circuit_builder.
add_variable(input_lo);
68 std::vector<uint8_t> input_buf;
69 write(input_buf, base_point);
70 const auto offset_generators =
77 for (
size_t i = 0; i < num_tables; ++i) {
83 EXPECT_EQ(
uint256_t(round_scalar), expected_scalar);
85 auto next_scalar =
static_cast<uint256_t>(
86 (i == num_tables - 1) ?
fr(0)
90 EXPECT_EQ(
slice, (
uint256_t(input_lo) >> (i * table_bits)) & mask);
93 offset_generators[i]);
95 EXPECT_EQ(round_x, expected_point.
x);
96 EXPECT_EQ(round_y, expected_point.
y);
97 for (
size_t j = 0; j < table_bits; ++j) {
98 accumulator = accumulator.
dbl();
100 expected_scalar >>= table_bits;
105 EXPECT_EQ(result,
true);
114 for (
auto& wire_3_witness_idx :
builder.blocks.lookup.w_o()) {
115 if (wire_3_witness_idx !=
builder.zero_idx()) {
116 wire_3_witness_idx =
builder.zero_idx();
130 EXPECT_EQ(result,
true);
136 for (
size_t i = 0; i < 16; ++i) {
137 for (
size_t j = 0; j < 16; ++j) {
138 uint64_t left =
static_cast<uint64_t
>(j);
139 uint64_t right =
static_cast<uint64_t
>(i);
140 uint32_t left_idx =
builder.add_variable(
fr(left));
141 uint32_t right_idx =
builder.add_variable(
fr(right));
142 uint32_t result_idx =
builder.add_variable(
fr(left ^ right));
144 uint32_t add_idx =
builder.add_variable(
fr(left) +
fr(right) +
builder.get_variable(result_idx));
146 { left_idx, right_idx, result_idx, add_idx,
fr(1),
fr(1),
fr(1),
fr(-1),
fr(0) });
151 EXPECT_EQ(result,
true);
165 uint32_t x1 =
builder.add_variable(p1.
x);
166 uint32_t y1 =
builder.add_variable(p1.
y);
167 uint32_t x2 =
builder.add_variable(p2.x);
168 uint32_t y2 =
builder.add_variable(p2.y);
169 uint32_t x3 =
builder.add_variable(p3.x);
170 uint32_t y3 =
builder.add_variable(p3.y);
172 builder.create_ecc_add_gate({ x1, y1, x2, y2, x3, y3, 1 });
175 EXPECT_EQ(result,
true);
177 builder.create_ecc_add_gate({ x1 + 1, y1, x2, y2, x3, y3, 1 });
198 uint32_t x1 =
builder.add_variable(p1.
x);
199 uint32_t y1 =
builder.add_variable(p1.
y);
200 uint32_t x2_invalid =
builder.add_variable(invalid_x);
201 uint32_t y2 =
builder.add_variable(p2.y);
202 uint32_t x3 =
builder.add_variable(p3_correct.x);
203 uint32_t y3 =
builder.add_variable(p3_correct.y);
206 builder.create_ecc_add_gate({ x1, y1, x2_invalid, y2, x3, y3, 1 });
210 EXPECT_EQ(result,
false);
222 uint32_t x1 =
builder.add_variable(p1.
x);
223 uint32_t y1 =
builder.add_variable(p1.
y);
224 uint32_t x3 =
builder.add_variable(p3.x);
225 uint32_t y3 =
builder.add_variable(p3.y);
227 builder.create_ecc_dbl_gate({ x1, y1, x3, y3 });
230 EXPECT_EQ(result,
true);
239 auto a_idx =
builder.add_variable(
a);
240 auto b_idx =
builder.add_variable(
b);
241 auto c_idx =
builder.add_variable(
b);
242 auto d_idx =
builder.add_variable(
a);
256 EXPECT_EQ(result,
true);
259 builder.real_variable_tags[
builder.real_variable_index[a_idx]] = 2;
269 auto a_idx =
builder.add_variable(
a);
270 auto b_idx =
builder.add_variable(
a);
271 builder.assert_equal(a_idx, b_idx);
272 auto c_idx =
builder.add_variable(c);
273 auto d_idx =
builder.add_variable(c);
274 builder.assert_equal(c_idx, d_idx);
275 auto e_idx =
builder.add_variable(
a);
276 auto f_idx =
builder.add_variable(
a);
277 builder.assert_equal(e_idx, f_idx);
278 auto g_idx =
builder.add_variable(c);
279 auto h_idx =
builder.add_variable(c);
280 builder.assert_equal(g_idx, h_idx);
295 EXPECT_EQ(result,
true);
298 builder.real_variable_tags[
builder.real_variable_index[a_idx]] = 2;
307 auto a_idx =
builder.add_variable(
a);
308 auto b_idx =
builder.add_variable(
b);
309 auto c_idx =
builder.add_variable(
b);
310 auto d_idx =
builder.add_variable(
a + 1);
312 builder.create_add_gate({ a_idx, b_idx,
builder.zero_idx(), 1, 1, 0, 0 });
313 builder.create_add_gate({ c_idx, d_idx,
builder.zero_idx(), 1, 1, 0, -1 });
316 EXPECT_EQ(result,
true);
327 EXPECT_EQ(result,
false);
338 auto a_idx =
builder.add_variable(
a);
339 auto b_idx =
builder.add_variable(
b);
340 auto c_idx =
builder.add_variable(c);
341 auto d_idx =
builder.add_variable(d);
342 builder.create_sort_constraint({ a_idx, b_idx, c_idx, d_idx });
345 EXPECT_EQ(result,
true);
350 std::vector<uint32_t> res;
351 for (
size_t i = 0; i < variables.size(); i++) {
352 res.emplace_back(
builder.add_variable(variables[i]));
370 auto b_idx =
builder.add_variable(
b);
371 auto c_idx =
builder.add_variable(c);
372 auto d_idx =
builder.add_variable(d);
373 auto e_idx =
builder.add_variable(e);
374 auto f_idx =
builder.add_variable(f);
375 auto g_idx =
builder.add_variable(g);
376 auto h_idx =
builder.add_variable(h);
377 builder.create_sort_constraint_with_edges({ a_idx, b_idx, c_idx, d_idx, e_idx, f_idx, g_idx, h_idx },
a, h);
379 EXPECT_EQ(result,
true);
385 auto b_idx =
builder.add_variable(
b);
386 auto c_idx =
builder.add_variable(c);
387 auto d_idx =
builder.add_variable(d);
388 auto e_idx =
builder.add_variable(e);
389 auto f_idx =
builder.add_variable(f);
390 auto g_idx =
builder.add_variable(g);
391 auto h_idx =
builder.add_variable(h);
392 builder.create_sort_constraint_with_edges({ a_idx, b_idx, c_idx, d_idx, e_idx, f_idx, g_idx, h_idx },
a, g);
395 EXPECT_EQ(result,
false);
400 auto b_idx =
builder.add_variable(
b);
401 auto c_idx =
builder.add_variable(c);
402 auto d_idx =
builder.add_variable(d);
403 auto e_idx =
builder.add_variable(e);
404 auto f_idx =
builder.add_variable(f);
405 auto g_idx =
builder.add_variable(g);
406 auto h_idx =
builder.add_variable(h);
407 builder.create_sort_constraint_with_edges({ a_idx, b_idx, c_idx, d_idx, e_idx, f_idx, g_idx, h_idx },
b, h);
410 EXPECT_EQ(result,
false);
415 auto c_idx =
builder.add_variable(c);
416 auto d_idx =
builder.add_variable(d);
417 auto e_idx =
builder.add_variable(e);
418 auto f_idx =
builder.add_variable(f);
419 auto g_idx =
builder.add_variable(g);
420 auto h_idx =
builder.add_variable(h);
421 auto b2_idx =
builder.add_variable(
fr(15));
422 builder.create_sort_constraint_with_edges({ a_idx, b2_idx, c_idx, d_idx, e_idx, f_idx, g_idx, h_idx },
b, h);
424 EXPECT_EQ(result,
false);
428 auto idx =
add_variables(
builder, { 1, 2, 5, 6, 7, 10, 11, 13, 16, 17, 20, 22, 22, 25,
429 26, 29, 29, 32, 32, 33, 35, 38, 39, 39, 42, 42, 43, 45 });
430 builder.create_sort_constraint_with_edges(idx, 1, 45);
432 EXPECT_EQ(result,
true);
436 auto idx =
add_variables(
builder, { 1, 2, 5, 6, 7, 10, 11, 13, 16, 17, 20, 22, 22, 25,
437 26, 29, 29, 32, 32, 33, 35, 38, 39, 39, 42, 42, 43, 45 });
439 builder.create_sort_constraint_with_edges(idx, 1, 29);
441 EXPECT_EQ(result,
false);
450 for (
size_t i = 0; i < indices.size(); i++) {
451 builder.create_new_range_constraint(indices[i], 8);
454 builder.create_sort_constraint(indices);
456 EXPECT_EQ(result,
true);
461 for (
size_t i = 0; i < indices.size(); i++) {
462 builder.create_new_range_constraint(indices[i], 3);
465 builder.create_unconstrained_gates(indices);
467 EXPECT_EQ(result,
true);
472 for (
size_t i = 0; i < indices.size(); i++) {
473 builder.create_new_range_constraint(indices[i], 8);
475 builder.create_sort_constraint(indices);
477 EXPECT_EQ(result,
false);
482 add_variables(
builder, { 1, 2, 3, 4, 5, 6, 10, 8, 15, 11, 32, 21, 42, 79, 16, 10, 3, 26, 19, 51 });
483 for (
size_t i = 0; i < indices.size(); i++) {
484 builder.create_new_range_constraint(indices[i], 128);
486 builder.create_unconstrained_gates(indices);
488 EXPECT_EQ(result,
true);
493 add_variables(
builder, { 1, 2, 3, 80, 5, 6, 29, 8, 15, 11, 32, 21, 42, 79, 16, 10, 3, 26, 13, 14 });
494 for (
size_t i = 0; i < indices.size(); i++) {
495 builder.create_new_range_constraint(indices[i], 79);
497 builder.create_unconstrained_gates(indices);
499 EXPECT_EQ(result,
false);
504 add_variables(
builder, { 1, 0, 3, 80, 5, 6, 29, 8, 15, 11, 32, 21, 42, 79, 16, 10, 3, 26, 13, 14 });
505 for (
size_t i = 0; i < indices.size(); i++) {
506 builder.create_new_range_constraint(indices[i], 79);
508 builder.create_unconstrained_gates(indices);
510 EXPECT_EQ(result,
false);
518 for (
size_t i = 0; i < idx.size(); i++) {
519 builder.create_new_range_constraint(idx[i], 8);
527 EXPECT_EQ(result,
true);
534 for (
size_t i = 0; i < idx.size(); i++) {
535 builder.create_new_range_constraint(idx[i], 12);
543 EXPECT_EQ(result,
true);
551 std::vector<fr>
a = { 1, 3, 4, 7, 7, 8, 11, 14, 15, 15, 18, 19, 21, 21, 24, 25, 26, 27, 30, 32 };
552 std::vector<uint32_t> ind;
553 for (
size_t i = 0; i <
a.size(); i++)
554 ind.emplace_back(
builder.add_variable(
a[i]));
555 builder.create_sort_constraint(ind);
558 EXPECT_EQ(result,
true);
563 std::vector<fr>
a = { 1, 3, 4, 7, 7, 8, 16, 14, 15, 15, 18, 19, 21, 21, 24, 25, 26, 27, 30, 32 };
564 std::vector<uint32_t> ind;
565 for (
size_t i = 0; i <
a.size(); i++)
566 ind.emplace_back(
builder.add_variable(
a[i]));
567 builder.create_sort_constraint(ind);
570 EXPECT_EQ(result,
false);
581 auto a_idx =
builder.add_variable(
a);
582 auto b_idx =
builder.add_variable(
b);
583 auto c_idx =
builder.add_variable(c);
584 auto d_idx =
builder.add_variable(d);
585 builder.create_sort_constraint({ a_idx, b_idx, c_idx, d_idx });
588 EXPECT_EQ(result,
false);
598 auto a_idx =
builder.add_variable(
fr(e));
600 builder.decompose_into_default_range(a_idx, 134);
606 auto a_idx_1 =
builder.add_variable(
fr(e_1));
608 builder.decompose_into_default_range(a_idx_1, 127);
611 EXPECT_EQ(result,
true);
622 const auto split_into_limbs = [&](
const uint512_t& input) {
623 constexpr size_t NUM_BITS = 68;
625 limbs[0] = input.slice(0, NUM_BITS).lo;
626 limbs[1] = input.slice(NUM_BITS * 1, NUM_BITS * 2).lo;
627 limbs[2] = input.slice(NUM_BITS * 2, NUM_BITS * 3).lo;
628 limbs[3] = input.slice(NUM_BITS * 3, NUM_BITS * 4).lo;
634 std::array<uint32_t, 4> limb_indices;
635 limb_indices[0] =
builder.add_variable(limbs[0]);
636 limb_indices[1] =
builder.add_variable(limbs[1]);
637 limb_indices[2] =
builder.add_variable(limbs[2]);
638 limb_indices[3] =
builder.add_variable(limbs[3]);
644 auto modulus_limbs = split_into_limbs(BINARY_BASIS_MODULUS -
uint512_t(modulus));
647 const auto a_indices = get_limb_witness_indices(split_into_limbs(
uint256_t(
a)));
648 const auto b_indices = get_limb_witness_indices(split_into_limbs(
uint256_t(
b)));
649 const auto q_indices = get_limb_witness_indices(split_into_limbs(
uint256_t(q)));
650 const auto r_indices = get_limb_witness_indices(split_into_limbs(
uint256_t(r)));
654 a_indices, b_indices, q_indices, r_indices, modulus_limbs,
656 const auto [lo_1_idx, hi_1_idx] =
builder.evaluate_non_native_field_multiplication(inputs);
658 return { lo_1_idx, hi_1_idx };
663 const size_t num_iterations = 50;
664 for (
size_t i = 0; i < num_iterations; i++) {
681 const auto [lo_1_idx, hi_1_idx] = helper_non_native_multiplication(
builder,
a,
b, q, r, modulus);
686 if (is_low_70_bits && is_high_70_bits) {
688 builder.range_constrain_two_limbs(lo_1_idx, hi_1_idx, 70, 70);
691 builder.decompose_into_default_range(lo_1_idx, 72);
692 builder.decompose_into_default_range(hi_1_idx, 72);
696 EXPECT_EQ(result,
true);
705 uint256_t a_u256 =
uint256_t(
"0x00ab1504deacff852326adf4a01099e9340f232e2a631042852fce3c4eb8a51b");
706 uint256_t b_u256 =
uint256_t(
"0x1be457323502cfcd85f8cfa54c8c4fea146b9db2a7d86b29d966d61b714ee249");
707 uint256_t q_u256 =
uint256_t(
"0x00629b9d576dfc6b5c28a4a254d5e8e3384124f6a898858e95265254a01414d5");
708 uint256_t r_u256 =
uint256_t(
"0x2c1590eb70a48dce72f7686bbf79b59bf7926c99bc16aba92e474c65a04ea2a0");
721 EXPECT_EQ(q_computed, q_u256);
722 EXPECT_EQ(r_computed, r_u256);
726 const auto [lo_1_idx, hi_1_idx] =
727 helper_non_native_multiplication(
builder, a_u256, b_u256, q_u256, r_u256, modulus);
731 ASSERT(is_high_70_bits ==
false);
734 builder.decompose_into_default_range(lo_1_idx, 72);
735 builder.decompose_into_default_range(hi_1_idx, 72);
737 EXPECT_EQ(result_a,
true);
740 builder.range_constrain_two_limbs(lo_1_idx, hi_1_idx, 70, 70);
742 EXPECT_EQ(result_b,
false);
743 EXPECT_EQ(
builder.err(),
"range_constrain_two_limbs: hi limb.");
768 const auto [lo_1_idx, hi_1_idx] = helper_non_native_multiplication(
builder,
a,
b, q, r, modulus);
773 if (is_low_70_bits && is_high_70_bits) {
775 builder.range_constrain_two_limbs(lo_1_idx, hi_1_idx, 70, 70);
778 builder.decompose_into_default_range(lo_1_idx, 72);
779 builder.decompose_into_default_range(hi_1_idx, 72);
783 EXPECT_EQ(result,
true);
787 for (
size_t i = 0; i <
builder.blocks.nnf.size(); ++i) {
788 EXPECT_EQ(
builder.blocks.nnf.q_arith()[i], 0);
789 EXPECT_EQ(
builder.blocks.nnf.q_delta_range()[i], 0);
790 EXPECT_EQ(
builder.blocks.nnf.q_elliptic()[i], 0);
791 EXPECT_EQ(
builder.blocks.nnf.q_lookup_type()[i], 0);
792 EXPECT_EQ(
builder.blocks.nnf.q_poseidon2_external()[i], 0);
793 EXPECT_EQ(
builder.blocks.nnf.q_poseidon2_internal()[i], 0);
801 uint32_t rom_values[8]{
808 size_t rom_id =
builder.create_ROM_array(8);
810 for (
size_t i = 0; i < 8; ++i) {
811 builder.set_ROM_element(rom_id, i, rom_values[i]);
814 uint32_t a_idx =
builder.read_ROM_array(rom_id,
builder.add_variable(5));
815 EXPECT_EQ(a_idx != rom_values[5],
true);
816 uint32_t b_idx =
builder.read_ROM_array(rom_id,
builder.add_variable(4));
817 uint32_t c_idx =
builder.read_ROM_array(rom_id,
builder.add_variable(1));
819 const auto d_value =
builder.get_variable(a_idx) +
builder.get_variable(b_idx) +
builder.get_variable(c_idx);
820 uint32_t d_idx =
builder.add_variable(d_value);
835 EXPECT_EQ(result,
true);
848 uint32_t ram_value_idx =
builder.add_variable(ram_value);
849 size_t ram_id =
builder.create_RAM_array(1);
850 builder.init_RAM_element(ram_id, 0, ram_value_idx);
853 uint32_t read_idx =
builder.add_variable(0);
854 uint32_t a_idx =
builder.read_RAM_array(ram_id, read_idx);
866 builder.get_variable(ram_value_idx),
876 uint32_t ram_values[8]{
883 size_t ram_id =
builder.create_RAM_array(8);
885 for (
size_t i = 0; i < 8; ++i) {
886 builder.init_RAM_element(ram_id, i, ram_values[i]);
889 uint32_t a_idx =
builder.read_RAM_array(ram_id,
builder.add_variable(5));
890 EXPECT_EQ(a_idx != ram_values[5],
true);
892 uint32_t b_idx =
builder.read_RAM_array(ram_id,
builder.add_variable(4));
893 uint32_t c_idx =
builder.read_RAM_array(ram_id,
builder.add_variable(1));
896 uint32_t d_idx =
builder.read_RAM_array(ram_id,
builder.add_variable(4));
898 EXPECT_EQ(
builder.get_variable(d_idx), 500);
901 const auto e_value =
builder.get_variable(a_idx) +
builder.get_variable(b_idx) +
builder.get_variable(c_idx) +
903 uint32_t e_idx =
builder.add_variable(e_value);
933 EXPECT_EQ(result,
true);
938 EXPECT_EQ(duplicate_builder.get_estimated_num_finalized_gates(),
builder.get_estimated_num_finalized_gates());
946 uint32_t
a =
builder.add_variable(100);
947 uint32_t
b =
builder.add_variable(100);
948 uint32_t c =
builder.add_variable(100);
949 uint32_t d =
builder.add_variable(100);
955 builder.create_new_range_constraint(
a, 1000);
956 builder.create_new_range_constraint(
b, 1001);
957 builder.create_new_range_constraint(c, 999);
958 builder.create_new_range_constraint(d, 1000);
974 EXPECT_EQ(result,
true);
982 uint32_t
a =
builder.add_variable(0xdead);
983 uint32_t
b =
builder.add_variable(0xbeef);
986 {
a,
a,
builder.zero_idx(),
fr(1), -
fr(0xdead) -
fr(0xbeef), 0, 0,
fr(0xdead) *
fr(0xbeef) });
988 {
b,
b,
builder.zero_idx(),
fr(1), -
fr(0xdead) -
fr(0xbeef), 0, 0,
fr(0xdead) *
fr(0xbeef) });
994 builder.create_new_range_constraint(
b, 0xbeef);
1006 uint32_t c =
builder.add_variable(0xbeef);
#define ASSERT(expression,...)
virtual uint32_t add_variable(const FF &in)
FF get_variable(const uint32_t index) const
Get the value of the variable v_{index}.
static void add_lookup_gates(Builder &builder, size_t num_iterations=1)
Add lookup gates using the uint32 XOR lookup table (table size 4096)
static bool check(const Builder &circuit)
Check the witness satisifies the circuit.
plookup::ReadData< uint32_t > create_gates_from_plookup_accumulators(const plookup::MultiTableId &id, const plookup::ReadData< FF > &read_values, const uint32_t key_a_index, std::optional< uint32_t > key_b_index=std::nullopt)
Perform a series of lookups, one for each 'row' in read_values.
static AffineElement commit_native(const std::vector< Fq > &inputs, GeneratorContext context={})
Given a vector of fields, generate a pedersen commitment using the indexed generators.
element class. Implements ecc group arithmetic using Jacobian coordinates See https://hyperelliptic....
constexpr element dbl() const noexcept
static std::vector< affine_element > derive_generators(const std::vector< uint8_t > &domain_separator_bytes, const size_t num_generators, const size_t starting_index=0)
Derives generator points via hash-to-curve.
constexpr uint256_t slice(uint64_t start, uint64_t end) const
constexpr uint64_t get_msb() const
static constexpr affine_element lhs_generator_point()
grumpkin::g1::affine_element affine_element
uintx< uint256_t > uint512_t
RNG & get_debug_randomness(bool reset, std::uint_fast64_t seed)
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.
std::vector< uint32_t > add_variables(UltraCircuitBuilder &builder, std::vector< fr > variables)
void write(std::vector< uint8_t > &buf, ClientIVC::VerificationKey const &vk)
field< Bn254FrParams > fr
C slice(C const &container, size_t start)
UltraCircuitBuilder_< UltraExecutionTraceBlocks > UltraCircuitBuilder
TEST(BoomerangMegaCircuitBuilder, BasicCircuit)
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
static constexpr field neg_one()
static constexpr field one()
static constexpr uint256_t modulus
static field random_element(numeric::RNG *engine=nullptr) noexcept
static constexpr field zero()
static constexpr size_t MAX_TABLE_SIZE
static constexpr size_t BITS_PER_TABLE
static constexpr size_t BITS_PER_LO_SCALAR
static constexpr size_t NUM_TABLES_PER_LO_MULTITABLE