Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
gas.test.cpp
Go to the documentation of this file.
1#include <gmock/gmock.h>
2#include <gtest/gtest.h>
3
4#include <cstdint>
5
6#include "barretenberg/aztec/aztec_constants.hpp"
21
22namespace bb::avm2::constraining {
23namespace {
24
25using tracegen::ExecutionTraceBuilder;
26using tracegen::PrecomputedTraceBuilder;
27using tracegen::TestTraceContainer;
29using C = Column;
30using gas = bb::avm2::gas<FF>;
32
33TEST(GasConstrainingTest, EmptyRow)
34{
35 check_relation<gas>(testing::empty_trace());
36}
37
38TEST(GasConstrainingTest, AllSubrelations)
39{
40 uint32_t opcode_l2_gas = 100;
41 uint32_t addressing_gas = 50;
42 uint32_t base_da_gas = 3;
43 uint32_t dynamic_l2_gas = 10;
44 uint32_t dynamic_da_gas = 5;
45 uint32_t dynamic_l2_gas_factor = 2;
46 uint32_t dynamic_da_gas_factor = 1;
47 uint32_t l2_gas_limit = 1000;
48 uint32_t da_gas_limit = 800;
49 uint32_t prev_l2_gas_used = 500;
50 uint32_t prev_da_gas_used = 200;
51 uint64_t total_gas_l2 =
52 prev_l2_gas_used + opcode_l2_gas + addressing_gas + (dynamic_l2_gas * dynamic_l2_gas_factor);
53 uint64_t total_gas_da = prev_da_gas_used + base_da_gas + (dynamic_da_gas * dynamic_da_gas_factor);
54
55 TestTraceContainer trace({ {
56 { C::execution_sel_check_gas, 1 },
57 // looked up in execution.pil
58 { C::execution_opcode_gas, opcode_l2_gas },
59 { C::execution_addressing_gas, addressing_gas },
60 { C::execution_base_da_gas, base_da_gas },
61 { C::execution_dynamic_l2_gas, dynamic_l2_gas },
62 { C::execution_dynamic_da_gas, dynamic_da_gas },
63 // event
64 { C::execution_l2_gas_limit, l2_gas_limit },
65 { C::execution_da_gas_limit, da_gas_limit },
66 { C::execution_prev_l2_gas_used, prev_l2_gas_used },
67 { C::execution_prev_da_gas_used, prev_da_gas_used },
68 { C::execution_dynamic_l2_gas_factor, dynamic_l2_gas_factor },
69 { C::execution_dynamic_da_gas_factor, dynamic_da_gas_factor },
70 // Derived cumulative gas used.
71 { C::execution_total_gas_l2, total_gas_l2 },
72 { C::execution_total_gas_da, total_gas_da },
73 // out
74 { C::execution_out_of_gas_l2, 0 },
75 { C::execution_out_of_gas_da, 0 },
76 { C::execution_sel_out_of_gas, 0 },
77 } });
78
79 // Add GT lookup values
80 // L2 gas
81 trace.set(0,
82 { {
83 { C::gt_sel, 1 },
84 { C::gt_input_a, total_gas_l2 },
85 { C::gt_input_b, l2_gas_limit },
86 { C::gt_res, 0 },
87 } });
88 // DA gas
89 trace.set(1,
90 { {
91 { C::gt_sel, 1 },
92 { C::gt_input_a, total_gas_da },
93 { C::gt_input_b, da_gas_limit },
94 { C::gt_res, 0 },
95 } });
96
97 check_relation<gas>(trace);
98 check_interaction<ExecutionTraceBuilder,
101
102 // Can't cheat OOG.
103 trace.set(0,
104 { {
105 { C::execution_out_of_gas_l2, 0 },
106 { C::execution_out_of_gas_da, 0 },
107 { C::execution_sel_out_of_gas, 1 },
108 } });
109 EXPECT_THROW(check_relation<gas>(trace), std::runtime_error);
110 trace.set(0,
111 { {
112 { C::execution_out_of_gas_l2, 1 },
113 { C::execution_out_of_gas_da, 1 },
114 { C::execution_sel_out_of_gas, 1 },
115 } });
116 EXPECT_THROW_WITH_MESSAGE((check_interaction<ExecutionTraceBuilder, lookup_gas_is_out_of_gas_l2_settings>(trace)),
117 "Failed.*LOOKUP_GAS_IS_OUT_OF_GAS_L2. Could not find tuple in destination.");
118 EXPECT_THROW_WITH_MESSAGE((check_interaction<ExecutionTraceBuilder, lookup_gas_is_out_of_gas_da_settings>(trace)),
119 "Failed.*LOOKUP_GAS_IS_OUT_OF_GAS_DA. Could not find tuple in destination.");
120}
121
122TEST(GasConstrainingTest, OutOfGasBase)
123{
124 uint32_t opcode_l2_gas = 100;
125 uint32_t addressing_gas = 50;
126 uint32_t base_da_gas = 100;
127 uint32_t dynamic_l2_gas = 0;
128 uint32_t dynamic_da_gas = 0;
129 uint32_t dynamic_l2_gas_factor = 2;
130 uint32_t dynamic_da_gas_factor = 1;
131 uint32_t l2_gas_limit = 100;
132 uint32_t da_gas_limit = 80;
133 uint32_t prev_l2_gas_used = 0;
134 uint32_t prev_da_gas_used = 0;
135 uint64_t total_gas_l2 =
136 prev_l2_gas_used + opcode_l2_gas + addressing_gas + (dynamic_l2_gas * dynamic_l2_gas_factor);
137 uint64_t total_gas_da = prev_da_gas_used + base_da_gas + (dynamic_da_gas * dynamic_da_gas_factor);
138
139 TestTraceContainer trace({ {
140 { C::execution_sel_check_gas, 1 },
141 // looked up in execution.pil
142 { C::execution_opcode_gas, opcode_l2_gas },
143 { C::execution_addressing_gas, addressing_gas },
144 { C::execution_base_da_gas, base_da_gas },
145 { C::execution_dynamic_l2_gas, dynamic_l2_gas },
146 { C::execution_dynamic_da_gas, dynamic_da_gas },
147 // event
148 { C::execution_l2_gas_limit, l2_gas_limit },
149 { C::execution_da_gas_limit, da_gas_limit },
150 { C::execution_prev_l2_gas_used, prev_l2_gas_used },
151 { C::execution_prev_da_gas_used, prev_da_gas_used },
152 { C::execution_dynamic_l2_gas_factor, dynamic_l2_gas_factor },
153 { C::execution_dynamic_da_gas_factor, dynamic_da_gas_factor },
154 // Derived cumulative gas used.
155 { C::execution_total_gas_l2, total_gas_l2 },
156 { C::execution_total_gas_da, total_gas_da },
157 // out
158 { C::execution_out_of_gas_l2, 1 },
159 { C::execution_out_of_gas_da, 1 },
160 { C::execution_sel_out_of_gas, 1 },
161 } });
162
163 // Add GT lookup values
164 // L2 gas
165 trace.set(0,
166 { {
167 { C::gt_sel, 1 },
168 { C::gt_input_a, total_gas_l2 },
169 { C::gt_input_b, l2_gas_limit },
170 { C::gt_res, 1 },
171 } });
172 // DA gas
173 trace.set(1,
174 { {
175 { C::gt_sel, 1 },
176 { C::gt_input_a, total_gas_da },
177 { C::gt_input_b, da_gas_limit },
178 { C::gt_res, 1 },
179 } });
180
181 check_relation<gas>(trace);
182 check_interaction<ExecutionTraceBuilder,
185
186 // Can't cheat OOG.
187 trace.set(0,
188 { {
189 { C::execution_out_of_gas_l2, 0 },
190 { C::execution_out_of_gas_da, 0 },
191 { C::execution_sel_out_of_gas, 0 },
192 } });
193
194 EXPECT_THROW_WITH_MESSAGE((check_interaction<ExecutionTraceBuilder, lookup_gas_is_out_of_gas_l2_settings>(trace)),
195 "Failed.*LOOKUP_GAS_IS_OUT_OF_GAS_L2. Could not find tuple in destination.");
196 EXPECT_THROW_WITH_MESSAGE((check_interaction<ExecutionTraceBuilder, lookup_gas_is_out_of_gas_da_settings>(trace)),
197 "Failed.*LOOKUP_GAS_IS_OUT_OF_GAS_DA. Could not find tuple in destination.");
198}
199
200TEST(GasConstrainingTest, OutOfGasDynamic)
201{
202 uint32_t opcode_l2_gas = 1;
203 uint32_t addressing_gas = 0;
204 uint32_t base_da_gas = 3;
205 uint32_t dynamic_l2_gas = 10;
206 uint32_t dynamic_da_gas = 9;
207 uint32_t dynamic_l2_gas_factor = 10;
208 uint32_t dynamic_da_gas_factor = 10;
209 uint32_t l2_gas_limit = 100;
210 uint32_t da_gas_limit = 80;
211 uint32_t prev_l2_gas_used = 0;
212 uint32_t prev_da_gas_used = 0;
213 uint64_t total_gas_l2 =
214 prev_l2_gas_used + opcode_l2_gas + addressing_gas + (dynamic_l2_gas * dynamic_l2_gas_factor);
215 uint64_t total_gas_da = prev_da_gas_used + base_da_gas + (dynamic_da_gas * dynamic_da_gas_factor);
216
217 TestTraceContainer trace({ {
218 { C::execution_sel_check_gas, 1 },
219 // looked up in execution.pil
220 { C::execution_opcode_gas, opcode_l2_gas },
221 { C::execution_addressing_gas, addressing_gas },
222 { C::execution_base_da_gas, base_da_gas },
223 { C::execution_dynamic_l2_gas, dynamic_l2_gas },
224 { C::execution_dynamic_da_gas, dynamic_da_gas },
225 // event
226 { C::execution_l2_gas_limit, l2_gas_limit },
227 { C::execution_da_gas_limit, da_gas_limit },
228 { C::execution_prev_l2_gas_used, prev_l2_gas_used },
229 { C::execution_prev_da_gas_used, prev_da_gas_used },
230 { C::execution_dynamic_l2_gas_factor, dynamic_l2_gas_factor },
231 { C::execution_dynamic_da_gas_factor, dynamic_da_gas_factor },
232 // Derived cumulative gas used.
233 { C::execution_total_gas_l2, total_gas_l2 },
234 { C::execution_total_gas_da, total_gas_da },
235 // out
236 { C::execution_out_of_gas_l2, 1 },
237 { C::execution_out_of_gas_da, 1 },
238 { C::execution_sel_out_of_gas, 1 },
239 } });
240
241 // Add GT lookup values
242 // L2 gas
243 trace.set(0,
244 { {
245 { C::gt_sel, 1 },
246 { C::gt_input_a, total_gas_l2 },
247 { C::gt_input_b, l2_gas_limit },
248 { C::gt_res, 1 },
249 } });
250 // DA gas
251 trace.set(1,
252 { {
253 { C::gt_sel, 1 },
254 { C::gt_input_a, total_gas_da },
255 { C::gt_input_b, da_gas_limit },
256 { C::gt_res, 1 },
257 } });
258 check_relation<gas>(trace);
259 check_interaction<ExecutionTraceBuilder,
262
263 // Can't cheat OOG.
264 trace.set(0,
265 { {
266 { C::execution_out_of_gas_l2, 0 },
267 { C::execution_out_of_gas_da, 0 },
268 { C::execution_sel_out_of_gas, 0 },
269 } });
270 EXPECT_THROW_WITH_MESSAGE((check_interaction<ExecutionTraceBuilder, lookup_gas_is_out_of_gas_l2_settings>(trace)),
271 "Failed.*LOOKUP_GAS_IS_OUT_OF_GAS_L2. Could not find tuple in destination.");
272 EXPECT_THROW_WITH_MESSAGE((check_interaction<ExecutionTraceBuilder, lookup_gas_is_out_of_gas_da_settings>(trace)),
273 "Failed.*LOOKUP_GAS_IS_OUT_OF_GAS_DA. Could not find tuple in destination.");
274}
275
276TEST(GasConstrainingTest, NoCheckNoOOG)
277{
278 TestTraceContainer trace({ {
279 { C::execution_sel_check_gas, 0 },
280 // out
281 { C::execution_out_of_gas_l2, 0 },
282 { C::execution_out_of_gas_da, 0 },
283 { C::execution_sel_out_of_gas, 0 },
284 } });
285 check_relation<gas>(trace);
286
287 // Can't cheat OOG.
288 trace.set(0,
289 { {
290 { C::execution_out_of_gas_l2, 1 },
291 { C::execution_out_of_gas_da, 1 },
292 { C::execution_sel_out_of_gas, 1 },
293 } });
294 EXPECT_THROW(check_relation<gas>(trace), std::runtime_error);
295}
296
297TEST(GasConstrainingTest, DynGasFactorToRadix)
298{
299 PrecomputedTraceBuilder precomputed_builder;
300
301 uint32_t radix = 10;
302 uint32_t num_limbs = 20;
303 uint32_t num_p_limbs = static_cast<uint32_t>(get_p_limbs_per_radix_size(radix));
304 TestTraceContainer trace(
305 { {
306 { C::execution_sel, 1 },
307 { C::execution_register_1_, radix },
308 { C::execution_register_2_, num_limbs },
309 { C::execution_sel_check_gas, 1 },
310 // To Radix BE Dynamic Gas
311 { C::execution_sel_gas_to_radix, 1 },
312 { C::execution_dyn_gas_id, AVM_DYN_GAS_ID_TORADIX },
313 { C::execution_two_five_six, 256 },
314 { C::execution_sel_radix_gt_256, 0 },
315 { C::execution_sel_lookup_num_p_limbs, 1 },
316 { C::execution_num_p_limbs, num_p_limbs },
317 { C::execution_sel_use_num_limbs, num_limbs > num_p_limbs ? 1 : 0 },
318 { C::execution_dynamic_l2_gas_factor, num_limbs > num_p_limbs ? num_limbs : num_p_limbs },
319 // GT Trace, used to check if radix > 256
320 { C::gt_sel, 1 },
321 { C::gt_input_a, radix },
322 { C::gt_input_b, 256 },
323 { C::gt_res, 0 },
324 },
325 {
326 // Gt Trace, compare num_limbs > num_p_limbs
327 { C::gt_sel, 1 },
328 { C::gt_input_a, num_limbs },
329 { C::gt_input_b, num_p_limbs },
330 { C::gt_res, num_limbs > num_p_limbs ? 1 : 0 },
331 } });
332
335
336 check_interaction<ExecutionTraceBuilder,
341
342 trace.set(C::execution_dynamic_l2_gas_factor, 0, 100); // Set to some random value is incorrect
343 EXPECT_THROW_WITH_MESSAGE((check_relation<execution>(trace, execution::SR_DYN_L2_FACTOR_TO_RADIX_BE)),
345}
346
347TEST(GasConstrainingTest, DynGasFactorInvalidRadix)
348{
349 PrecomputedTraceBuilder precomputed_builder;
350
351 uint32_t radix = 1000;
352 uint32_t num_limbs = 20;
353 uint32_t num_p_limbs = 32; // When radix > 256, we set num_p_limbs to 32.
354 TestTraceContainer trace(
355 { {
356 { C::execution_sel, 1 },
357 { C::execution_register_1_, radix },
358 { C::execution_register_2_, num_limbs },
359 { C::execution_sel_check_gas, 1 },
360 // To Radix BE Dynamic Gas
361 { C::execution_sel_gas_to_radix, 1 },
362 { C::execution_dyn_gas_id, AVM_DYN_GAS_ID_TORADIX },
363 { C::execution_two_five_six, 256 },
364 { C::execution_sel_radix_gt_256, radix > 256 ? 1 : 0 },
365 { C::execution_sel_lookup_num_p_limbs, radix <= 256 ? 1 : 0 },
366 { C::execution_num_p_limbs, num_p_limbs },
367 { C::execution_sel_use_num_limbs, num_limbs > num_p_limbs ? 1 : 0 },
368 { C::execution_dynamic_l2_gas_factor, num_limbs > num_p_limbs ? num_limbs : num_p_limbs },
369 // GT Trace, used to check if radix > 256
370 { C::gt_sel, 1 },
371 { C::gt_input_a, radix },
372 { C::gt_input_b, 256 },
373 { C::gt_res, radix > 256 ? 1 : 0 },
374 },
375 {
376 // Gt Trace, compare num_limbs > num_p_limbs
377 { C::gt_sel, 1 },
378 { C::gt_input_a, num_limbs },
379 { C::gt_input_b, num_p_limbs },
380 { C::gt_res, num_limbs > num_p_limbs ? 1 : 0 },
381 } });
382
385
386 check_interaction<ExecutionTraceBuilder,
390 check_relation<execution>(trace,
394}
395
396TEST(GasConstrainingTest, DynGasFactorToRadixInvalidRadixLt2)
397{
398 PrecomputedTraceBuilder precomputed_builder;
399
400 uint32_t radix = 1; // Invalid radix (must be >= 2)
401 uint32_t num_limbs = 20;
402 uint32_t num_p_limbs = static_cast<uint32_t>(get_p_limbs_per_radix_size(radix)); // Returns 0
403 TestTraceContainer trace({ {
404 { C::execution_sel, 1 },
405 { C::execution_register_1_, radix },
406 { C::execution_register_2_, num_limbs },
407 { C::execution_sel_check_gas, 1 },
408 // To Radix BE Dynamic Gas
409 { C::execution_sel_gas_to_radix, 1 },
410 { C::execution_dyn_gas_id, AVM_DYN_GAS_ID_TORADIX },
411 { C::execution_two_five_six, 256 },
412 { C::execution_sel_radix_gt_256, 0 },
413 { C::execution_sel_lookup_num_p_limbs, 1 },
414 { C::execution_num_p_limbs, num_p_limbs },
415 { C::execution_sel_use_num_limbs, 1 }, // num_limbs (20) > num_p_limbs (0)
416 { C::execution_dynamic_l2_gas_factor, num_limbs }, // max(20, 0) = 20
417 // GT Trace, used to check if radix > 256
418 { C::gt_sel, 1 },
419 { C::gt_input_a, radix },
420 { C::gt_input_b, 256 },
421 { C::gt_res, 0 },
422 },
423 {
424 // Gt Trace, compare num_limbs > num_p_limbs
425 { C::gt_sel, 1 },
426 { C::gt_input_a, num_limbs },
427 { C::gt_input_b, num_p_limbs },
428 { C::gt_res, 1 }, // 20 > 0
429 } });
430
433
434 // To Radix fails because radix < 2, but the lookup constraints must still satisfied for the gas relation to hold.
435 check_interaction<ExecutionTraceBuilder,
440}
441
442} // namespace
443} // namespace bb::avm2::constraining
#define EXPECT_THROW_WITH_MESSAGE(code, expectedMessageRegex)
Definition assert.hpp:224
static std::string get_subrelation_label(size_t index)
Definition execution.hpp:80
static constexpr size_t SR_DYN_L2_FACTOR_TO_RADIX_BE
Definition execution.hpp:50
static constexpr size_t SR_DYN_GAS_ID_DECOMPOSITION
Definition execution.hpp:48
static constexpr size_t SR_NUM_P_LIMBS_CEIL
Definition execution.hpp:49
void process_misc(TraceContainer &trace, const uint32_t num_rows=PRECOMPUTED_TRACE_SIZE)
Populate miscellaneous precomputed columns: first_row selector and idx (row index).
void process_to_radix_safe_limbs(TraceContainer &trace)
Populate the TORADIXBE safe-limbs table (one row per radix 0..255).
void set(Column col, uint32_t row, const FF &value, bool use_atomic_limbs=false)
PrecomputedTraceBuilder precomputed_builder
Definition alu.test.cpp:120
TestTraceContainer trace
void check_interaction(tracegen::TestTraceContainer &trace)
TEST(AvmFixedVKTests, FixedVKCommitments)
Test that the fixed VK commitments agree with the ones computed from precomputed columns.
TestTraceContainer empty_trace()
Definition fixtures.cpp:156
size_t get_p_limbs_per_radix_size(size_t radix)
Gets the number of limbs that the modulus, p, decomposes into for a given radix.
Definition to_radix.cpp:75
lookup_settings< lookup_gas_is_out_of_gas_l2_settings_ > lookup_gas_is_out_of_gas_l2_settings
lookup_settings< lookup_gas_is_out_of_gas_da_settings_ > lookup_gas_is_out_of_gas_da_settings
lookup_settings< lookup_execution_get_p_limbs_settings_ > lookup_execution_get_p_limbs_settings
constexpr size_t NUM_RADIXES
Definition to_radix.hpp:11
lookup_settings< lookup_execution_check_radix_gt_256_settings_ > lookup_execution_check_radix_gt_256_settings
lookup_settings< lookup_execution_get_max_limbs_settings_ > lookup_execution_get_max_limbs_settings
NiceMock< MockExecution > execution