Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
call_stack_metadata_collector.test.cpp
Go to the documentation of this file.
2
3#include <gmock/gmock.h>
4#include <gtest/gtest.h>
5
11
12namespace bb::avm2::simulation {
13namespace {
14
15using ::testing::_;
16using ::testing::ElementsAre;
17using ::testing::Return;
18using ::testing::ReturnRef;
19using ::testing::StrictMock;
20
21TEST(CallStackMetadataCollectorTest, SingleCallEnterAndExit)
22{
23 CallStackMetadataCollector collector;
24 AztecAddress contract_addr(0x1234);
25 uint32_t caller_pc = 100;
26 uint32_t exit_pc = 200;
27 Gas gas_limit{ 1000, 2000 };
28 std::vector<FF> calldata = { FF(0xabcd), FF(0xef01) };
29 std::vector<FF> return_data = { FF(0x5678), FF(0x9abc) };
30
31 // Set phase
32 collector.set_phase(CoarseTransactionPhase::APP_LOGIC);
33
34 // Enter call
35 CalldataProvider calldata_provider = [&calldata](uint32_t /*max_size*/) -> std::vector<FF> { return calldata; };
36
37 collector.notify_enter_call(contract_addr, caller_pc, calldata_provider, false, gas_limit);
38
39 // Exit call
40 ReturnDataProvider return_data_provider = [&return_data](uint32_t /*max_size*/) -> std::vector<FF> {
41 return return_data;
42 };
43 InternalCallStackProvider internal_call_stack_provider = []() -> std::vector<PC> {
44 // This means that there where 2 internal calls, one at pc 0 and one at pc 10.
45 // We are currently at PC exit_pc but the provider does not provide this.
46 return { 0, 10 };
47 };
48
49 collector.notify_exit_call(true, exit_pc, std::nullopt, return_data_provider, internal_call_stack_provider);
50
51 // Dump and verify
52 auto metadata = collector.dump_call_stack_metadata();
53 ASSERT_EQ(metadata.size(), 1U);
54
55 const auto& call_metadata = metadata[0];
56 EXPECT_EQ(call_metadata.timestamp, 0U);
57 EXPECT_EQ(call_metadata.phase, CoarseTransactionPhase::APP_LOGIC);
58 EXPECT_EQ(call_metadata.contract_address, contract_addr);
59 EXPECT_EQ(call_metadata.caller_pc, caller_pc);
60 EXPECT_EQ(call_metadata.internal_call_stack_at_exit, std::vector<PC>({ 0, 10, exit_pc }));
61 EXPECT_EQ(call_metadata.calldata, calldata);
62 EXPECT_EQ(call_metadata.output, return_data);
63 EXPECT_EQ(call_metadata.is_static_call, false);
64 EXPECT_EQ(call_metadata.gas_limit, gas_limit);
65 EXPECT_EQ(call_metadata.reverted, false);
66 EXPECT_EQ(call_metadata.halting_message, std::nullopt);
67 EXPECT_EQ(call_metadata.num_nested_calls, 0U);
68 EXPECT_TRUE(call_metadata.nested.empty());
69}
70
71TEST(CallStackMetadataCollectorTest, NestedCalls)
72{
73 CallStackMetadataCollector collector;
74 AztecAddress contract1(0x1111);
75 AztecAddress contract2(0x2222);
76 AztecAddress contract3(0x3333);
77
78 collector.set_phase(CoarseTransactionPhase::APP_LOGIC);
79
80 // Enter first call
81 std::vector<FF> calldata1 = { FF(0xaaaa) };
82 CalldataProvider calldata_provider1 = [&calldata1](uint32_t /*max_size*/) -> std::vector<FF> { return calldata1; };
83
84 collector.notify_enter_call(contract1, 100, calldata_provider1, false, Gas{ 1000, 2000 });
85
86 // Enter second call (nested)
87 std::vector<FF> calldata2 = { FF(0xbbbb) };
88 CalldataProvider calldata_provider2 = [&calldata2](uint32_t /*max_size*/) -> std::vector<FF> { return calldata2; };
89
90 collector.notify_enter_call(contract2, 200, calldata_provider2, false, Gas{ 500, 1000 });
91
92 // Enter third call (nested in nested)
93 std::vector<FF> calldata3 = { FF(0xcccc) };
94 CalldataProvider calldata_provider3 = [&calldata3](uint32_t /*max_size*/) -> std::vector<FF> { return calldata3; };
95
96 collector.notify_enter_call(contract3, 300, calldata_provider3, true, Gas{ 200, 400 });
97
98 // Exit third call
99 std::vector<FF> return_data3 = { FF(0x3333) };
100 ReturnDataProvider return_data_provider3 = [&return_data3](uint32_t /*max_size*/) -> std::vector<FF> {
101 return return_data3;
102 };
103 InternalCallStackProvider internal_call_stack_provider3 = []() -> std::vector<PC> { return { 300 }; };
104
105 collector.notify_exit_call(true, 399, std::nullopt, return_data_provider3, internal_call_stack_provider3);
106
107 // Exit second call
108 std::vector<FF> return_data2 = { FF(0x2222) };
109 ReturnDataProvider return_data_provider2 = [&return_data2](uint32_t /*max_size*/) -> std::vector<FF> {
110 return return_data2;
111 };
112 InternalCallStackProvider internal_call_stack_provider2 = []() -> std::vector<PC> { return { 200 }; };
113
114 collector.notify_exit_call(
115 false, 299, "Nested call reverted", return_data_provider2, internal_call_stack_provider2);
116
117 // Exit first call
118 std::vector<FF> return_data1 = { FF(0x1111) };
119 ReturnDataProvider return_data_provider1 = [&return_data1](uint32_t /*max_size*/) -> std::vector<FF> {
120 return return_data1;
121 };
122 InternalCallStackProvider internal_call_stack_provider1 = []() -> std::vector<PC> { return { 100 }; };
123
124 collector.notify_exit_call(true, 199, std::nullopt, return_data_provider1, internal_call_stack_provider1);
125
126 // Dump and verify
127 auto metadata = collector.dump_call_stack_metadata();
128 ASSERT_EQ(metadata.size(), 1U);
129
130 const auto& outer_call = metadata[0];
131 EXPECT_EQ(outer_call.timestamp, 0U);
132 EXPECT_EQ(outer_call.num_nested_calls, 1U);
133 EXPECT_EQ(outer_call.nested.size(), 1U);
134 EXPECT_EQ(outer_call.output, return_data1);
135 EXPECT_EQ(outer_call.reverted, false);
136 EXPECT_EQ(outer_call.halting_message, std::nullopt);
137 EXPECT_EQ(outer_call.internal_call_stack_at_exit, std::vector<PC>({ 100, 199 }));
138
139 const auto& middle_call = outer_call.nested[0];
140 EXPECT_EQ(middle_call.timestamp, 1U);
141 EXPECT_EQ(middle_call.num_nested_calls, 1U);
142 EXPECT_EQ(middle_call.nested.size(), 1U);
143 EXPECT_EQ(middle_call.output, return_data2);
144 EXPECT_EQ(middle_call.reverted, true);
145 EXPECT_EQ(middle_call.halting_message, "Nested call reverted");
146 EXPECT_EQ(middle_call.internal_call_stack_at_exit, std::vector<PC>({ 200, 299 }));
147
148 const auto& inner_call = middle_call.nested[0];
149 EXPECT_EQ(inner_call.timestamp, 2U);
150 EXPECT_EQ(inner_call.num_nested_calls, 0U);
151 EXPECT_EQ(inner_call.nested.size(), 0U);
152 EXPECT_EQ(inner_call.output, return_data3);
153 EXPECT_EQ(inner_call.reverted, false);
154 EXPECT_EQ(inner_call.halting_message, std::nullopt);
155 EXPECT_EQ(inner_call.is_static_call, true);
156 EXPECT_EQ(inner_call.internal_call_stack_at_exit, std::vector<PC>({ 300, 399 }));
157}
158
159TEST(CallStackMetadataCollectorTest, MultipleSiblingCalls)
160{
161 CallStackMetadataCollector collector;
162 AztecAddress contract0(0x0000);
163 AztecAddress contract1(0xaaaa);
164 AztecAddress contract2(0xbbbb);
165
166 collector.set_phase(CoarseTransactionPhase::APP_LOGIC);
167
168 // Outer call.
169 std::vector<FF> calldata0 = { FF(0x0000) };
170 CalldataProvider calldata_provider0 = [&calldata0](uint32_t /*max_size*/) -> std::vector<FF> { return calldata0; };
171 collector.notify_enter_call(contract0, 0, calldata_provider0, false, Gas{ 0, 0 });
172
173 // First call
174 std::vector<FF> calldata1 = { FF(0x1111) };
175 CalldataProvider calldata_provider1 = [&calldata1](uint32_t /*max_size*/) -> std::vector<FF> { return calldata1; };
176
177 collector.notify_enter_call(contract1, 100, calldata_provider1, false, Gas{ 1000, 2000 });
178
179 ReturnDataProvider return_data_provider1 = [](uint32_t /*max_size*/) -> std::vector<FF> { return { FF(0xaaaa) }; };
180 InternalCallStackProvider internal_call_stack_provider1 = []() -> std::vector<PC> { return { 100, 200 }; };
181
182 collector.notify_exit_call(true, 150, std::nullopt, return_data_provider1, internal_call_stack_provider1);
183
184 // Second call (sibling)
185 std::vector<FF> calldata2 = { FF(0x2222) };
186 CalldataProvider calldata_provider2 = [&calldata2](uint32_t /*max_size*/) -> std::vector<FF> { return calldata2; };
187
188 collector.notify_enter_call(contract2, 200, calldata_provider2, false, Gas{ 500, 1000 });
189
190 ReturnDataProvider return_data_provider2 = [](uint32_t /*max_size*/) -> std::vector<FF> { return { FF(0xbbbb) }; };
191 InternalCallStackProvider internal_call_stack_provider2 = []() -> std::vector<PC> { return { 200, 300 }; };
192
193 collector.notify_exit_call(true, 250, std::nullopt, return_data_provider2, internal_call_stack_provider2);
194
195 // Outer call (return).
196 ReturnDataProvider return_data_provider0 = [](uint32_t /*max_size*/) -> std::vector<FF> { return { FF(0x0000) }; };
197 InternalCallStackProvider internal_call_stack_provider0 = []() -> std::vector<PC> { return { 0, 100 }; };
198 collector.notify_exit_call(true, 0, std::nullopt, return_data_provider0, internal_call_stack_provider0);
199
200 // Verify both calls are present
201 auto metadata = collector.dump_call_stack_metadata();
202 ASSERT_EQ(metadata.size(), 1U);
203
204 const auto& outer_call = metadata[0];
205 EXPECT_EQ(outer_call.timestamp, 0U);
206 EXPECT_EQ(outer_call.num_nested_calls, 2U);
207 EXPECT_EQ(outer_call.halting_message, std::nullopt);
208 ASSERT_EQ(outer_call.nested.size(), 2U);
209 EXPECT_EQ(outer_call.nested[0].timestamp, 1U);
210 EXPECT_EQ(outer_call.nested[0].halting_message, std::nullopt);
211 EXPECT_EQ(outer_call.nested[1].timestamp, 2U);
212 EXPECT_EQ(outer_call.nested[1].halting_message, std::nullopt);
213 EXPECT_EQ(outer_call.nested[0].contract_address, contract1);
214 EXPECT_EQ(outer_call.nested[1].contract_address, contract2);
215}
216
217TEST(CallStackMetadataCollectorTest, CalldataSizeLimit)
218{
219 CallStackMetadataCollector collector;
220 AztecAddress contract_addr(0x1234);
221 std::vector<FF> large_calldata(2000, FF(0xabcd)); // Larger than max_calldata_size (1024)
222
223 collector.set_phase(CoarseTransactionPhase::APP_LOGIC);
224
225 CalldataProvider calldata_provider = [&large_calldata](uint32_t max_size) -> std::vector<FF> {
226 // Provider should respect max_size
227 if (large_calldata.size() > max_size) {
228 return std::vector<FF>(large_calldata.begin(), large_calldata.begin() + max_size);
229 }
230 return large_calldata;
231 };
232
233 collector.notify_enter_call(contract_addr, 100, calldata_provider, false, Gas{ 1000, 2000 });
234
235 ReturnDataProvider return_data_provider = [](uint32_t /*max_size*/) -> std::vector<FF> { return {}; };
236 InternalCallStackProvider internal_call_stack_provider = []() -> std::vector<PC> { return { 100, 200 }; };
237
238 collector.notify_exit_call(true, 200, std::nullopt, return_data_provider, internal_call_stack_provider);
239
240 auto metadata = collector.dump_call_stack_metadata();
241 ASSERT_EQ(metadata.size(), 1U);
242 // Calldata should be limited to max_calldata_size (1024)
243 EXPECT_EQ(metadata[0].calldata.size(), 1024U);
244 EXPECT_EQ(metadata[0].halting_message, std::nullopt);
245}
246
247TEST(CallStackMetadataCollectorTest, ReturnDataSizeLimit)
248{
249 CallStackMetadataCollector collector;
250 AztecAddress contract_addr(0x5678);
251 std::vector<FF> calldata = { FF(0x1234) };
252
253 collector.set_phase(CoarseTransactionPhase::APP_LOGIC);
254
255 CalldataProvider calldata_provider = [&calldata](uint32_t /*max_size*/) -> std::vector<FF> { return calldata; };
256
257 collector.notify_enter_call(contract_addr, 100, calldata_provider, false, Gas{ 1000, 2000 });
258
259 std::vector<FF> large_return_data(2000, FF(0xef01)); // Larger than max_return_data_size (1024)
260 ReturnDataProvider return_data_provider = [&large_return_data](uint32_t max_size) -> std::vector<FF> {
261 // Provider should respect max_size
262 if (large_return_data.size() > max_size) {
263 return std::vector<FF>(large_return_data.begin(), large_return_data.begin() + max_size);
264 }
265 return large_return_data;
266 };
267 InternalCallStackProvider internal_call_stack_provider = []() -> std::vector<PC> { return { 100, 200 }; };
268
269 collector.notify_exit_call(true, 200, std::nullopt, return_data_provider, internal_call_stack_provider);
270
271 auto metadata = collector.dump_call_stack_metadata();
272 ASSERT_EQ(metadata.size(), 1U);
273 // Return data should be limited to max_return_data_size (1024)
274 EXPECT_EQ(metadata[0].output.size(), 1024U);
275 EXPECT_EQ(metadata[0].halting_message, std::nullopt);
276}
277
278TEST(CallStackMetadataCollectorTest, PhaseTracking)
279{
280 CallStackMetadataCollector collector;
281 AztecAddress contract1(0x1111);
282 AztecAddress contract2(0x2222);
283 AztecAddress contract3(0x3333);
284
285 // First call in SETUP phase
286 collector.set_phase(CoarseTransactionPhase::SETUP);
287 std::vector<FF> calldata1 = { FF(0xaaaa) };
288 CalldataProvider calldata_provider1 = [&calldata1](uint32_t /*max_size*/) -> std::vector<FF> { return calldata1; };
289
290 collector.notify_enter_call(contract1, 100, calldata_provider1, false, Gas{ 1000, 2000 });
291 collector.notify_exit_call(
292 true,
293 150,
295 [](uint32_t) -> std::vector<FF> { return {}; },
296 []() -> std::vector<PC> { return { 100, 200 }; });
297
298 // Second call in APP_LOGIC phase
299 collector.set_phase(CoarseTransactionPhase::APP_LOGIC);
300 std::vector<FF> calldata2 = { FF(0xbbbb) };
301 CalldataProvider calldata_provider2 = [&calldata2](uint32_t /*max_size*/) -> std::vector<FF> { return calldata2; };
302
303 collector.notify_enter_call(contract2, 200, calldata_provider2, false, Gas{ 500, 1000 });
304 collector.notify_exit_call(
305 true,
306 250,
308 [](uint32_t) -> std::vector<FF> { return {}; },
309 []() -> std::vector<PC> { return { 200, 300 }; });
310
311 // Third call in TEARDOWN phase
312 collector.set_phase(CoarseTransactionPhase::TEARDOWN);
313 std::vector<FF> calldata3 = { FF(0xcccc) };
314 CalldataProvider calldata_provider3 = [&calldata3](uint32_t /*max_size*/) -> std::vector<FF> { return calldata3; };
315
316 collector.notify_enter_call(contract3, 300, calldata_provider3, false, Gas{ 200, 400 });
317 collector.notify_exit_call(
318 true,
319 350,
321 [](uint32_t) -> std::vector<FF> { return {}; },
322 []() -> std::vector<PC> { return { 300, 400 }; });
323
324 auto metadata = collector.dump_call_stack_metadata();
325 ASSERT_EQ(metadata.size(), 3U);
326
327 EXPECT_EQ(metadata[0].phase, CoarseTransactionPhase::SETUP);
328 EXPECT_EQ(metadata[0].halting_message, std::nullopt);
329 EXPECT_EQ(metadata[1].phase, CoarseTransactionPhase::APP_LOGIC);
330 EXPECT_EQ(metadata[1].halting_message, std::nullopt);
331 EXPECT_EQ(metadata[2].phase, CoarseTransactionPhase::TEARDOWN);
332 EXPECT_EQ(metadata[2].halting_message, std::nullopt);
333}
334
335// Test helper functions
336class MakeProviderTest : public ::testing::Test {
337 protected:
338 StrictMock<MockContext> mock_context;
339};
340
341TEST_F(MakeProviderTest, MakeCalldataProviderSuccess)
342{
343 uint32_t cd_offset = 100;
344 uint32_t cd_size = 5;
345 std::vector<MemoryValue> calldata_values = {
346 MemoryValue::from<FF>(FF(0xaaaa)), MemoryValue::from<FF>(FF(0xbbbb)), MemoryValue::from<FF>(FF(0xcccc)),
347 MemoryValue::from<FF>(FF(0xdddd)), MemoryValue::from<FF>(FF(0xeeee)),
348 };
349
350 // These are called when creating the provider
351 EXPECT_CALL(mock_context, get_parent_cd_addr()).WillOnce(Return(cd_offset));
352 EXPECT_CALL(mock_context, get_parent_cd_size()).WillOnce(Return(cd_size));
353
354 auto provider = make_calldata_provider(mock_context);
355
356 // This is called when invoking the provider
357 EXPECT_CALL(mock_context, get_calldata(cd_offset, cd_size)).WillOnce(Return(calldata_values));
358
359 auto result = provider(1024);
360
361 EXPECT_THAT(result, ElementsAre(FF(0xaaaa), FF(0xbbbb), FF(0xcccc), FF(0xdddd), FF(0xeeee)));
362}
363
364TEST_F(MakeProviderTest, MakeCalldataProviderRespectsMaxSize)
365{
366 uint32_t cd_offset = 0;
367 uint32_t cd_size = 2000; // Larger than max_size
368 uint32_t max_size = 10;
369 std::vector<MemoryValue> calldata_values(2000);
370 for (size_t i = 0; i < 2000; ++i) {
371 calldata_values[i] = MemoryValue::from<FF>(FF(i));
372 }
373
374 // These are called when creating the provider
375 EXPECT_CALL(mock_context, get_parent_cd_addr()).WillOnce(Return(cd_offset));
376 EXPECT_CALL(mock_context, get_parent_cd_size()).WillOnce(Return(cd_size));
377
378 auto provider = make_calldata_provider(mock_context);
379
380 // This is called when invoking the provider
381 EXPECT_CALL(mock_context, get_calldata(cd_offset, max_size))
382 .WillOnce([&calldata_values, max_size](uint32_t, uint32_t) {
383 return std::vector<MemoryValue>(calldata_values.begin(), calldata_values.begin() + max_size);
384 });
385
386 auto result = provider(max_size);
387
388 ASSERT_EQ(result.size(), max_size);
389}
390
391TEST_F(MakeProviderTest, MakeCalldataProviderHandlesException)
392{
393 static AztecAddress contract_addr(0x1234);
394 uint32_t cd_offset = 100;
395 uint32_t cd_size = 5;
396
397 // These are called when creating the provider
398 EXPECT_CALL(mock_context, get_parent_cd_addr()).WillOnce(Return(cd_offset));
399 EXPECT_CALL(mock_context, get_parent_cd_size()).WillOnce(Return(cd_size));
400
401 auto provider = make_calldata_provider(mock_context);
402
403 // This is called when invoking the provider, and throws
404 EXPECT_CALL(mock_context, get_calldata(cd_offset, _))
405 .WillOnce(::testing::Throw(std::runtime_error("Test exception")));
406 // The exception handler may call get_address() and get_pc() for logging (optional)
407 EXPECT_CALL(mock_context, get_address()).Times(::testing::AnyNumber()).WillRepeatedly(ReturnRef(contract_addr));
408 EXPECT_CALL(mock_context, get_pc()).Times(::testing::AnyNumber()).WillRepeatedly(Return(200));
409
410 auto result = provider(1024);
411
412 // Should return empty vector on exception
413 EXPECT_TRUE(result.empty());
414}
415
416TEST_F(MakeProviderTest, MakeReturnDataProviderSuccess)
417{
418 uint32_t rd_addr = 200;
419 uint32_t rd_size = 3;
420 std::vector<MemoryValue> return_data_values = {
421 MemoryValue::from<FF>(FF(0x1111)),
422 MemoryValue::from<FF>(FF(0x2222)),
423 MemoryValue::from<FF>(FF(0x3333)),
424 };
425 auto zero = MemoryValue::from<FF>(FF(0));
426
427 auto provider = make_return_data_provider(mock_context, rd_addr, rd_size);
428
429 // This is called when invoking the provider
430 StrictMock<MockMemory> memory;
431 EXPECT_CALL(::testing::Const(mock_context), get_memory()).WillOnce(ReturnRef(memory));
432 ON_CALL(memory, get)
433 .WillByDefault([&return_data_values, rd_addr, rd_size, &zero](uint32_t i) -> const MemoryValue& {
434 // if offset is not in range [rd_addr, rd_addr + rd_size], return 0
435 if (i < rd_addr || i >= rd_addr + rd_size) {
436 return zero;
437 }
438 const auto offset_into_rd = i - rd_addr;
439 return return_data_values[offset_into_rd];
440 });
441 EXPECT_CALL(memory, get).Times(static_cast<int>(rd_size));
442
443 auto result = provider(1024);
444
445 EXPECT_THAT(result, ElementsAre(FF(0x1111), FF(0x2222), FF(0x3333)));
446}
447
448TEST_F(MakeProviderTest, MakeReturnDataProviderRespectsMaxSize)
449{
450 uint32_t rd_addr = 0;
451 uint32_t rd_size = 2000; // Larger than max_size
452 uint32_t max_size = 15;
453 std::vector<MemoryValue> return_data_values(2000);
454 for (size_t i = 0; i < 2000; ++i) {
455 return_data_values[i] = MemoryValue::from<FF>(FF(i * 2));
456 }
457
458 auto provider = make_return_data_provider(mock_context, rd_addr, rd_size);
459
460 // This is called when invoking the provider
461 StrictMock<MockMemory> memory;
462 EXPECT_CALL(::testing::Const(mock_context), get_memory()).WillOnce(ReturnRef(memory));
463 ON_CALL(memory, get).WillByDefault([&return_data_values](uint32_t i) -> const MemoryValue& {
464 return return_data_values[i];
465 });
466 EXPECT_CALL(memory, get).Times(static_cast<int>(max_size));
467
468 auto result = provider(max_size);
469
470 ASSERT_EQ(result.size(), max_size);
471}
472
473TEST_F(MakeProviderTest, MakeReturnDataProviderHandlesException)
474{
475 uint32_t rd_addr = 200;
476 uint32_t rd_size = 3;
477 static AztecAddress contract_addr(0x5678);
478
479 auto provider = make_return_data_provider(mock_context, rd_addr, rd_size);
480
481 // This is called when invoking the provider, and throws
482 StrictMock<MockMemory> memory;
483 EXPECT_CALL(::testing::Const(mock_context), get_memory())
484 .WillOnce(::testing::Throw(std::runtime_error("Test exception")));
485
486 // The exception handler may call get_address() and get_pc() for logging (optional)
487 EXPECT_CALL(mock_context, get_address()).Times(::testing::AnyNumber()).WillRepeatedly(ReturnRef(contract_addr));
488 EXPECT_CALL(mock_context, get_pc()).Times(::testing::AnyNumber()).WillRepeatedly(Return(300));
489
490 auto result = provider(1024);
491
492 // Should return empty vector on exception
493 EXPECT_TRUE(result.empty());
494}
495
496} // namespace
497} // namespace bb::avm2::simulation
StrictMock< MockContext > mock_context
std::function< std::vector< PC >()> InternalCallStackProvider
ReturnDataProvider make_return_data_provider(const ContextInterface &context, uint32_t rd_offset, uint32_t rd_size)
std::function< std::vector< FF >(uint32_t max_size)> CalldataProvider
std::function< std::vector< FF >(uint32_t max_size)> ReturnDataProvider
CalldataProvider make_calldata_provider(const ContextInterface &context)
TaggedValue MemoryValue
AvmFlavorSettings::FF FF
Definition field.hpp:10
TEST_F(IPATest, ChallengesAreZero)
Definition ipa.test.cpp:185
TEST(BoomerangMegaCircuitBuilder, BasicCircuit)
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
std::vector< MemoryValue > calldata
uint32_t cd_offset
MemoryStore memory