Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
relation_correctness.test.cpp
Go to the documentation of this file.
18
19#include <gtest/gtest.h>
20using namespace bb;
21
22void ensure_non_zero(auto& polynomial)
23{
24 bool has_non_zero_coefficient = false;
25 for (auto& coeff : polynomial.coeffs()) {
26 has_non_zero_coefficient |= !coeff.is_zero();
27 }
28 ASSERT_TRUE(has_non_zero_coefficient);
29}
30
31template <typename Flavor> void create_some_add_gates(auto& circuit_builder)
32{
33 using FF = typename Flavor::FF;
34 auto a = FF::random_element();
35
36 // Add some basic add gates; incorporate a public input for non-trivial PI-delta
37 uint32_t a_idx = circuit_builder.add_public_variable(a);
38 FF b = FF::random_element();
39 FF c = a + b;
40 FF d = a + c;
41 uint32_t b_idx = circuit_builder.add_variable(b);
42 uint32_t c_idx = circuit_builder.add_variable(c);
43 uint32_t d_idx = circuit_builder.add_variable(d);
44 for (size_t i = 0; i < 16; i++) {
45 circuit_builder.create_add_gate({ a_idx, b_idx, c_idx, 1, 1, -1, 0 });
46 circuit_builder.create_add_gate({ d_idx, c_idx, a_idx, 1, -1, -1, 0 });
47 }
48
49 // Add an Ultra-style big add gate with use of next row to test q_arith = 2
50 FF e = a + b + c + d;
51 uint32_t e_idx = circuit_builder.add_variable(e);
52
53 uint32_t zero_idx = circuit_builder.zero_idx;
54 circuit_builder.create_big_add_gate({ a_idx, b_idx, c_idx, d_idx, -1, -1, -1, -1, 0 }, true); // use next row
55 circuit_builder.create_big_add_gate({ zero_idx, zero_idx, zero_idx, e_idx, 0, 0, 0, 0, 0 }, false);
56}
57
58template <typename Flavor> void create_some_lookup_gates(auto& circuit_builder)
59{
60 using FF = typename Flavor::FF;
61 // Add some lookup gates (related to pedersen hashing)
62 auto pedersen_input_value = FF::random_element();
63 const auto input_hi =
64 uint256_t(pedersen_input_value)
65 .slice(plookup::fixed_base::table::BITS_PER_LO_SCALAR,
66 plookup::fixed_base::table::BITS_PER_LO_SCALAR + plookup::fixed_base::table::BITS_PER_HI_SCALAR);
67 const auto input_lo = uint256_t(pedersen_input_value).slice(0, bb::plookup::fixed_base::table::BITS_PER_LO_SCALAR);
68 const auto input_hi_index = circuit_builder.add_variable(input_hi);
69 const auto input_lo_index = circuit_builder.add_variable(input_lo);
70
71 const auto sequence_data_hi =
73 const auto sequence_data_lo =
75
76 circuit_builder.create_gates_from_plookup_accumulators(
77 plookup::MultiTableId::FIXED_BASE_LEFT_HI, sequence_data_hi, input_hi_index);
78 circuit_builder.create_gates_from_plookup_accumulators(
79 plookup::MultiTableId::FIXED_BASE_LEFT_LO, sequence_data_lo, input_lo_index);
80}
81
82template <typename Flavor> void create_some_delta_range_constraint_gates(auto& circuit_builder)
83{
84 // Add a sort gate (simply checks that consecutive inputs have a difference of < 4)
85 using FF = typename Flavor::FF;
86 auto a_idx = circuit_builder.add_variable(FF(0));
87 auto b_idx = circuit_builder.add_variable(FF(1));
88 auto c_idx = circuit_builder.add_variable(FF(2));
89 auto d_idx = circuit_builder.add_variable(FF(3));
90 circuit_builder.create_sort_constraint({ a_idx, b_idx, c_idx, d_idx });
91}
92
93template <typename Flavor> void create_some_RAM_gates(auto& circuit_builder)
94{
95 using FF = typename Flavor::FF;
96 // Add some RAM gates
97 uint32_t ram_values[8]{
98 circuit_builder.add_variable(FF::random_element()), circuit_builder.add_variable(FF::random_element()),
99 circuit_builder.add_variable(FF::random_element()), circuit_builder.add_variable(FF::random_element()),
100 circuit_builder.add_variable(FF::random_element()), circuit_builder.add_variable(FF::random_element()),
101 circuit_builder.add_variable(FF::random_element()), circuit_builder.add_variable(FF::random_element()),
102 };
103
104 size_t ram_id = circuit_builder.create_RAM_array(8);
105
106 for (size_t i = 0; i < 8; ++i) {
107 circuit_builder.init_RAM_element(ram_id, i, ram_values[i]);
108 }
109
110 auto a_idx = circuit_builder.read_RAM_array(ram_id, circuit_builder.add_variable(5));
111 EXPECT_EQ(a_idx != ram_values[5], true);
112
113 auto b_idx = circuit_builder.read_RAM_array(ram_id, circuit_builder.add_variable(4));
114 auto c_idx = circuit_builder.read_RAM_array(ram_id, circuit_builder.add_variable(1));
115
116 circuit_builder.write_RAM_array(ram_id, circuit_builder.add_variable(4), circuit_builder.add_variable(500));
117 auto d_idx = circuit_builder.read_RAM_array(ram_id, circuit_builder.add_variable(4));
118
119 EXPECT_EQ(circuit_builder.get_variable(d_idx), 500);
120
121 // ensure these vars get used in another arithmetic gate
122 const auto e_value = circuit_builder.get_variable(a_idx) + circuit_builder.get_variable(b_idx) +
123 circuit_builder.get_variable(c_idx) + circuit_builder.get_variable(d_idx);
124 auto e_idx = circuit_builder.add_variable(e_value);
125
126 circuit_builder.create_big_add_gate({ a_idx, b_idx, c_idx, d_idx, -1, -1, -1, -1, 0 }, true);
127 circuit_builder.create_big_add_gate(
128 {
129 circuit_builder.zero_idx,
130 circuit_builder.zero_idx,
131 circuit_builder.zero_idx,
132 e_idx,
133 0,
134 0,
135 0,
136 0,
137 0,
138 },
139 false);
140}
141
142template <typename Flavor> void create_some_elliptic_curve_addition_gates(auto& circuit_builder)
143{
144 // Add an elliptic curve addition gate
145 grumpkin::g1::affine_element p1 = grumpkin::g1::affine_element::random_element();
146 grumpkin::g1::affine_element p2 = grumpkin::g1::affine_element::random_element();
147
149
150 uint32_t x1 = circuit_builder.add_variable(p1.x);
151 uint32_t y1 = circuit_builder.add_variable(p1.y);
152 uint32_t x2 = circuit_builder.add_variable(p2.x);
153 uint32_t y2 = circuit_builder.add_variable(p2.y);
154 uint32_t x3 = circuit_builder.add_variable(p3.x);
155 uint32_t y3 = circuit_builder.add_variable(p3.y);
156
157 circuit_builder.create_ecc_add_gate({ x1, y1, x2, y2, x3, y3, -1 });
158}
159
160template <typename Flavor> void create_some_ecc_op_queue_gates(auto& circuit_builder)
161{
162 using G1 = typename Flavor::Curve::Group;
163 using FF = typename Flavor::FF;
164 static_assert(IsMegaFlavor<Flavor>);
165 const size_t num_ecc_operations = 10; // arbitrary
166 for (size_t i = 0; i < num_ecc_operations; ++i) {
167 auto point = G1::affine_one * FF::random_element();
168 auto scalar = FF::random_element();
169 circuit_builder.queue_ecc_mul_accum(point, scalar);
170 }
171}
172
173class UltraRelationCorrectnessTests : public ::testing::Test {
174 protected:
176};
177
188// TODO(luke): Add a gate that sets q_arith = 3 to check secondary arithmetic relation
190{
191 using Flavor = UltraFlavor;
192
193 // Create a builder and then add an assortment of gates designed to ensure that the constraint(s) represented
194 // by each relation are non-trivially exercised.
196
197 // Create an assortment of representative gates
198 create_some_add_gates<Flavor>(builder);
199 create_some_lookup_gates<Flavor>(builder);
200 create_some_delta_range_constraint_gates<Flavor>(builder);
201 create_some_elliptic_curve_addition_gates<Flavor>(builder);
202 create_some_RAM_gates<Flavor>(builder);
204
205 // Create a prover (it will compute proving key and witness)
207
209
210 // Check that selectors are nonzero to ensure corresponding relation has nontrivial contribution
211 for (auto selector : decider_pk->polynomials.get_gate_selectors()) {
212 ensure_non_zero(selector);
213 }
214
215 auto& prover_polynomials = decider_pk->polynomials;
216 auto params = decider_pk->relation_parameters;
217
218 RelationChecker<Flavor>::check_all(prover_polynomials, params);
219}
220
222{
223 using Flavor = MegaFlavor;
224
225 // Create a composer and then add an assortment of gates designed to ensure that the constraint(s) represented
226 // by each relation are non-trivially exercised.
228
229 // Create an assortment of representative gates
230 create_some_add_gates<Flavor>(builder);
231 create_some_lookup_gates<Flavor>(builder);
232 create_some_delta_range_constraint_gates<Flavor>(builder);
233 create_some_elliptic_curve_addition_gates<Flavor>(builder);
234 create_some_RAM_gates<Flavor>(builder);
235 create_some_ecc_op_queue_gates<Flavor>(builder); // Goblin!
237
238 // Create a prover (it will compute proving key and witness)
240
242
243 // Check that selectors are nonzero to ensure corresponding relation has nontrivial contribution
244 for (auto selector : decider_pk->polynomials.get_gate_selectors()) {
245 ensure_non_zero(selector);
246 }
247
248 // Check the databus entities are non-zero
249 for (auto selector : decider_pk->polynomials.get_databus_entities()) {
250 ensure_non_zero(selector);
251 }
252 auto& prover_polynomials = decider_pk->polynomials;
253 auto params = decider_pk->relation_parameters;
254
255 RelationChecker<Flavor>::check_all(prover_polynomials, params);
256}
Curve::ScalarField FF
static void check_all(const auto &polynomials, const auto &params)
Check that the provided polynomials satisfy all relations for a given Flavor.
static void complete_proving_key_for_test(const std::shared_ptr< DeciderProvingKey_< Flavor > > &decider_pk)
TEST only method for completing computation of the prover polynomials using random challenges.
element class. Implements ecc group arithmetic using Jacobian coordinates See https://hyperelliptic....
Definition element.hpp:33
constexpr uint256_t slice(uint64_t start, uint64_t end) const
AluTraceBuilder builder
Definition alu.test.cpp:123
FF a
FF b
@ Ultra
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.
@ FIXED_BASE_LEFT_LO
Definition types.hpp:100
@ FIXED_BASE_LEFT_HI
Definition types.hpp:101
std::filesystem::path bb_crs_path()
void init_file_crs_factory(const std::filesystem::path &path)
Entry point for Barretenberg command-line interface.
TEST_F(IPATest, ChallengesAreZero)
Definition ipa.test.cpp:123
typename Flavor::FF FF
UltraCircuitBuilder_< UltraExecutionTraceBlocks > UltraCircuitBuilder
MegaCircuitBuilder_< field< Bn254FrParams > > MegaCircuitBuilder
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
Curve::AffineElement G1
static constexpr size_t BITS_PER_LO_SCALAR
static void add_default_to_public_inputs(Builder &builder)
Adds default public inputs to the builder.
void create_some_delta_range_constraint_gates(auto &circuit_builder)
void create_some_RAM_gates(auto &circuit_builder)
void create_some_ecc_op_queue_gates(auto &circuit_builder)
void create_some_elliptic_curve_addition_gates(auto &circuit_builder)
void create_some_lookup_gates(auto &circuit_builder)
void ensure_non_zero(auto &polynomial)
void create_some_add_gates(auto &circuit_builder)