Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
lookup.test.cpp
Go to the documentation of this file.
1#include "ultra_honk.test.hpp"
2#include <gtest/gtest.h>
3
4using namespace bb;
5
6using FlavorTypes = testing::Types<UltraFlavor, UltraZKFlavor>;
8
12TYPED_TEST(UltraHonkTests, LookupXorConstraint)
13{
14 auto circuit_builder = UltraCircuitBuilder();
15
16 uint32_t left_value = engine.get_random_uint32();
17 uint32_t right_value = engine.get_random_uint32();
18
19 fr left_fr(left_value);
20 fr right_fr(right_value);
21
22 uint32_t left_idx = circuit_builder.add_variable(left_fr);
23 uint32_t right_idx = circuit_builder.add_variable(right_fr);
24
25 const auto lookup_accumulators =
26 plookup::get_lookup_accumulators(plookup::MultiTableId::UINT32_XOR, left_fr, right_fr, true);
27
28 EXPECT_EQ(lookup_accumulators[plookup::ColumnIdx::C3][0], left_value ^ right_value);
29
30 circuit_builder.create_gates_from_plookup_accumulators(
31 plookup::MultiTableId::UINT32_XOR, lookup_accumulators, left_idx, right_idx);
32 TestFixture::set_default_pairing_points_and_ipa_claim_and_proof(circuit_builder);
33
34 TestFixture::prove_and_verify(circuit_builder, /*expected_result=*/true);
35}
36
40TYPED_TEST(UltraHonkTests, LookupAndConstraint)
41{
42 auto circuit_builder = UltraCircuitBuilder();
43
44 uint32_t left_value = engine.get_random_uint32();
45 uint32_t right_value = engine.get_random_uint32();
46
47 fr left_fr(left_value);
48 fr right_fr(right_value);
49
50 uint32_t left_idx = circuit_builder.add_variable(left_fr);
51 uint32_t right_idx = circuit_builder.add_variable(right_fr);
52
53 const auto lookup_accumulators =
54 plookup::get_lookup_accumulators(plookup::MultiTableId::UINT32_AND, left_fr, right_fr, true);
55
56 EXPECT_EQ(lookup_accumulators[plookup::ColumnIdx::C3][0], left_value & right_value);
57
58 circuit_builder.create_gates_from_plookup_accumulators(
59 plookup::MultiTableId::UINT32_AND, lookup_accumulators, left_idx, right_idx);
60 TestFixture::set_default_pairing_points_and_ipa_claim_and_proof(circuit_builder);
61
62 TestFixture::prove_and_verify(circuit_builder, /*expected_result=*/true);
63}
64
68TYPED_TEST(UltraHonkTests, LookupFixedBaseScalarMul)
69{
70 auto circuit_builder = UltraCircuitBuilder();
71
72 fr input_value = fr::random_element();
73 const fr input_lo = static_cast<uint256_t>(input_value).slice(0, plookup::fixed_base::table::BITS_PER_LO_SCALAR);
74 const auto input_lo_index = circuit_builder.add_variable(input_lo);
75
76 const auto sequence_data_lo = plookup::get_lookup_accumulators(plookup::MultiTableId::FIXED_BASE_LEFT_LO, input_lo);
77
78 const auto lookup_witnesses = circuit_builder.create_gates_from_plookup_accumulators(
79 plookup::MultiTableId::FIXED_BASE_LEFT_LO, sequence_data_lo, input_lo_index);
80
81 const size_t num_lookups = plookup::fixed_base::table::NUM_TABLES_PER_LO_MULTITABLE;
82
83 EXPECT_EQ(num_lookups, lookup_witnesses[plookup::ColumnIdx::C1].size());
84
85 {
86 const auto mask = plookup::fixed_base::table::MAX_TABLE_SIZE - 1;
87
89 std::vector<uint8_t> input_buf;
90 write(input_buf, base_point);
91 const auto offset_generators =
92 grumpkin::g1::derive_generators(input_buf, plookup::fixed_base::table::NUM_TABLES_PER_LO_MULTITABLE);
93
94 grumpkin::g1::element accumulator = base_point;
95 uint256_t expected_scalar(input_lo);
96 const auto table_bits = plookup::fixed_base::table::BITS_PER_TABLE;
97 const auto num_tables = plookup::fixed_base::table::NUM_TABLES_PER_LO_MULTITABLE;
98 for (size_t i = 0; i < num_tables; ++i) {
99
100 auto round_scalar = circuit_builder.get_variable(lookup_witnesses[plookup::ColumnIdx::C1][i]);
101 auto round_x = circuit_builder.get_variable(lookup_witnesses[plookup::ColumnIdx::C2][i]);
102 auto round_y = circuit_builder.get_variable(lookup_witnesses[plookup::ColumnIdx::C3][i]);
103
104 EXPECT_EQ(uint256_t(round_scalar), expected_scalar);
105
106 auto next_scalar = static_cast<uint256_t>(
107 (i == num_tables - 1) ? fr(0)
108 : circuit_builder.get_variable(lookup_witnesses[plookup::ColumnIdx::C1][i + 1]));
109
110 uint256_t slice = static_cast<uint256_t>(round_scalar) - (next_scalar << table_bits);
111 EXPECT_EQ(slice, (uint256_t(input_lo) >> (i * table_bits)) & mask);
112
113 grumpkin::g1::affine_element expected_point(accumulator * static_cast<uint256_t>(slice) +
114 offset_generators[i]);
115
116 EXPECT_EQ(round_x, expected_point.x);
117 EXPECT_EQ(round_y, expected_point.y);
118 for (size_t j = 0; j < table_bits; ++j) {
119 accumulator = accumulator.dbl();
120 }
121 expected_scalar >>= table_bits;
122 }
123 }
124 TestFixture::set_default_pairing_points_and_ipa_claim_and_proof(circuit_builder);
125
126 TestFixture::prove_and_verify(circuit_builder, /*expected_result=*/true);
127}
128
132TYPED_TEST(UltraHonkTests, LookupFailureBaselineValid)
133{
137 TestFixture::set_default_pairing_points_and_ipa_claim_and_proof(builder);
138
139 TestFixture::prove_and_verify(builder, /*expected_result=*/true);
140}
141
153TYPED_TEST(UltraHonkTests, LookupFailureCorruptedReadCountsAndTags)
154{
155 using ProverInstance = typename TestFixture::ProverInstance;
156
160 TestFixture::set_default_pairing_points_and_ipa_claim_and_proof(builder);
161
162 auto prover_instance = std::make_shared<ProverInstance>(builder);
163 auto& polynomials = prover_instance->polynomials;
164
165 // Erroneously update the read counts/tags at an arbitrary index
166 polynomials.lookup_inverses = polynomials.lookup_inverses.full();
167 polynomials.lookup_read_counts = polynomials.lookup_read_counts.full();
168 polynomials.lookup_read_counts.at(25) = 1;
169 polynomials.lookup_read_tags = polynomials.lookup_read_tags.full();
170 polynomials.lookup_read_tags.at(25) = 1;
171
172 TestFixture::prove_and_verify(prover_instance, /*expected_result=*/false);
173}
174
181TYPED_TEST(UltraHonkTests, LookupFailureCorruptedWireValue)
182{
183 using ProverInstance = typename TestFixture::ProverInstance;
184
188 TestFixture::set_default_pairing_points_and_ipa_claim_and_proof(builder);
189
190 auto prover_instance = std::make_shared<ProverInstance>(builder);
191 auto& polynomials = prover_instance->polynomials;
192
193 bool altered = false;
194 // Find a lookup gate and alter one of the wire values
195 for (auto [i, q_lookup] : polynomials.q_lookup.indexed_values()) {
196 if (!q_lookup.is_zero() && polynomials.q_lookup.is_valid_set_index(i)) {
197 polynomials.w_o.at(i) += 1;
198 altered = true;
199 break;
200 }
201 }
202 ASSERT_TRUE(altered);
203
204 TestFixture::prove_and_verify(prover_instance, /*expected_result=*/false);
205}
206
213TYPED_TEST(UltraHonkTests, LookupFailureErroneousLookupSelector)
214{
215 using ProverInstance = typename TestFixture::ProverInstance;
216
220 TestFixture::set_default_pairing_points_and_ipa_claim_and_proof(builder);
221
222 auto prover_instance = std::make_shared<ProverInstance>(builder);
223 auto& polynomials = prover_instance->polynomials;
224
225 // Turn the lookup selector on for an arbitrary row where it is not already active
226 polynomials.lookup_inverses = polynomials.lookup_inverses.full();
227 polynomials.q_lookup = polynomials.q_lookup.full();
228 ASSERT_TRUE(polynomials.q_lookup[25] != 1);
229 polynomials.q_lookup.at(25) = 1;
230
231 TestFixture::prove_and_verify(prover_instance, /*expected_result=*/false);
232}
233
237TYPED_TEST(UltraHonkTests, LookupMixedXorAndOperations)
238{
239 auto circuit_builder = UltraCircuitBuilder();
240
241 // Interleave XOR and AND operations
242 for (size_t k = 0; k < 5; ++k) {
243 fr left_fr(engine.get_random_uint32());
244 fr right_fr(engine.get_random_uint32());
245
246 uint32_t left_idx = circuit_builder.add_variable(left_fr);
247 uint32_t right_idx = circuit_builder.add_variable(right_fr);
248
249 // XOR lookup
250 const auto xor_accumulators =
251 plookup::get_lookup_accumulators(plookup::MultiTableId::UINT32_XOR, left_fr, right_fr, true);
252 circuit_builder.create_gates_from_plookup_accumulators(
253 plookup::MultiTableId::UINT32_XOR, xor_accumulators, left_idx, right_idx);
254
255 // AND lookup (reuse same witness indices)
256 const auto and_accumulators =
257 plookup::get_lookup_accumulators(plookup::MultiTableId::UINT32_AND, left_fr, right_fr, true);
258 circuit_builder.create_gates_from_plookup_accumulators(
259 plookup::MultiTableId::UINT32_AND, and_accumulators, left_idx, right_idx);
260 }
261
262 TestFixture::set_default_pairing_points_and_ipa_claim_and_proof(circuit_builder);
263 TestFixture::prove_and_verify(circuit_builder, /*expected_result=*/true);
264}
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 void add_arithmetic_gates(Builder &builder, const size_t num_gates=4)
Add a specified number of arithmetic gates to the provided circuit.
A ProverInstance is normally constructed from a finalized circuit and it contains all the information...
element class. Implements ecc group arithmetic using Jacobian coordinates See https://hyperelliptic....
Definition element.hpp:33
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.
Definition group.hpp:87
virtual uint32_t get_random_uint32()=0
static constexpr affine_element lhs_generator_point()
AluTraceBuilder builder
Definition alu.test.cpp:124
numeric::RNG & engine
testing::Types< MegaFlavor, UltraFlavor, UltraZKFlavor, UltraRollupFlavor > FlavorTypes
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.
Definition api.hpp:5
TYPED_TEST_SUITE(ShpleminiTest, TestSettings)
field< Bn254FrParams > fr
Definition fr.hpp:174
void write(B &buf, field2< base_field, Params > const &value)
C slice(C const &container, size_t start)
Definition container.hpp:9
UltraCircuitBuilder_< UltraExecutionTraceBlocks > UltraCircuitBuilder
TYPED_TEST(ShpleminiTest, CorrectnessOfMultivariateClaimBatching)
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
static field random_element(numeric::RNG *engine=nullptr) noexcept