Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
hinting_dbs.test.cpp
Go to the documentation of this file.
3#include "barretenberg/aztec/aztec_constants.hpp"
12
13#include <algorithm>
14#include <cstddef>
15#include <cstdlib>
16#include <gmock/gmock.h>
17#include <gtest/gtest.h>
18#include <vector>
19
20namespace bb::avm2::simulation {
21namespace {
22
23class HintingDBsTest : public ::testing::Test {
24 protected:
25 HintingDBsTest(const AvmProvingInputs& inputs)
26 : inputs(inputs)
27 , base_contract_db(HintedRawContractDB(inputs.hints))
28 , base_merkle_db(HintedRawMerkleDB(inputs.hints))
29 {}
30
31 template <typename Hint>
32 void compare_hints(const std::vector<Hint>& input_hints, const std::vector<Hint>& collected_hints)
33 {
34 for (const Hint& input_hint : input_hints) {
35 EXPECT_FALSE(std::ranges::find(collected_hints.begin(), collected_hints.end(), input_hint) ==
36 collected_hints.end());
37 }
38
39 for (const Hint& collected_hint : collected_hints) {
40 EXPECT_FALSE(std::ranges::find(input_hints.begin(), input_hints.end(), collected_hint) ==
41 input_hints.end());
42 }
43 }
44
45 public:
46 AvmProvingInputs inputs;
47 HintedRawContractDB base_contract_db;
48 HintedRawMerkleDB base_merkle_db;
49 HintingContractsDB hinting_contract_db = HintingContractsDB(base_contract_db);
50 HintingRawDB hinting_merkle_db = HintingRawDB(base_merkle_db);
51};
52
53class HintingDBsMinimalTest : public HintingDBsTest {
54 protected:
55 HintingDBsMinimalTest()
56 : HintingDBsTest(testing::get_minimal_proving_inputs())
57 {}
58};
59
60// A helper to reset the randomly generated values in avm_inputs.testdata.bin to avoid unrelated failures:
61AvmProvingInputs fix_hint_keys(AvmProvingInputs inputs)
62{
63 auto reset_action_counters = [&]<typename H>(std::vector<H>& hints) {
64 for (auto& hint : hints) {
65 hint.hint_key = 0;
66 }
67 };
68 auto reset_tree_id = [&]<typename H>(std::vector<H>& hints) {
69 for (auto& hint : hints) {
70 // The AVM handles treeIds 0 - 3:
71 hint.tree_id = MerkleTreeId(hint.tree_id % 4);
72 hint.hint_key = get_tree_info_helper(hint.tree_id, inputs.hints.starting_tree_roots);
73 }
74 };
75 reset_action_counters(inputs.hints.contract_instances);
76 reset_action_counters(inputs.hints.contract_classes);
77 reset_action_counters(inputs.hints.bytecode_commitments);
78 reset_tree_id(inputs.hints.get_sibling_path_hints);
79
80 return inputs;
81};
82
83class HintingDBsTestInputTest : public HintingDBsTest {
84 protected:
85 HintingDBsTestInputTest()
86 : HintingDBsTest(fix_hint_keys(
87 AvmProvingInputs::from(read_file("../src/barretenberg/vm2/testing/avm_inputs.testdata.bin"))))
88 {}
89};
90
91TEST_F(HintingDBsTestInputTest, GetContractInstance)
92{
93 for (const auto& instance_hint : inputs.hints.contract_instances) {
94 auto instance = hinting_contract_db.get_contract_instance(instance_hint.address);
95 EXPECT_TRUE(instance.has_value());
96 EXPECT_EQ(instance.value(), base_contract_db.get_contract_instance(instance_hint.address).value());
97 }
98
99 ExecutionHints collected_hints;
100 hinting_contract_db.dump_hints(collected_hints);
101 compare_hints(inputs.hints.contract_instances, collected_hints.contract_instances);
102}
103
104TEST_F(HintingDBsTestInputTest, GetContractClass)
105{
106 for (const auto& class_hint : inputs.hints.contract_classes) {
107 auto klass = hinting_contract_db.get_contract_class(class_hint.class_id);
108 EXPECT_TRUE(klass.has_value());
109 EXPECT_THAT(klass.value(), base_contract_db.get_contract_class(class_hint.class_id).value());
110 }
111
112 ExecutionHints collected_hints;
113 hinting_contract_db.dump_hints(collected_hints);
114 compare_hints(inputs.hints.contract_classes, collected_hints.contract_classes);
115}
116
117TEST_F(HintingDBsTestInputTest, GetBytecodeCommitment)
118{
119 for (const auto& hint : inputs.hints.bytecode_commitments) {
120 auto commitment = hinting_contract_db.get_bytecode_commitment(hint.class_id);
121 EXPECT_TRUE(commitment.has_value());
122 EXPECT_EQ(commitment.value(), base_contract_db.get_bytecode_commitment(hint.class_id).value());
123 }
124
125 ExecutionHints collected_hints;
126 hinting_contract_db.dump_hints(collected_hints);
127 compare_hints(inputs.hints.bytecode_commitments, collected_hints.bytecode_commitments);
128}
129
130TEST_F(HintingDBsTestInputTest, GetDebugFunctionName)
131{
132 for (const auto& hint : inputs.hints.debug_function_names) {
133 auto name = hinting_contract_db.get_debug_function_name(hint.address, hint.selector);
134 EXPECT_TRUE(name.has_value());
135 EXPECT_EQ(name.value(), base_contract_db.get_debug_function_name(hint.address, hint.selector).value());
136 }
137
138 ExecutionHints collected_hints;
139 hinting_contract_db.dump_hints(collected_hints);
140 compare_hints(inputs.hints.debug_function_names, collected_hints.debug_function_names);
141}
142
143TEST_F(HintingDBsMinimalTest, ContractDBCheckpoints)
144{
145 // The minimal tx has one create and one commit. The conditionals are in case the minimal tx ever changes, bricking
146 // this test:
148 // The hinting db will cause the underlying base db to push a checkpoint onto the stack and increment the action
149 // counter:
153 }
154 }
155 ExecutionHints collected_hints;
156 hinting_contract_db.dump_hints(collected_hints);
158 collected_hints.contract_db_create_checkpoint_hints);
160 collected_hints.contract_db_commit_checkpoint_hints);
161}
162
163TEST_F(HintingDBsTestInputTest, GetSiblingPath)
164{
165 for (const auto& hint : inputs.hints.get_sibling_path_hints) {
166 auto path = hinting_merkle_db.get_sibling_path(hint.tree_id, hint.index);
167 EXPECT_EQ(path, base_merkle_db.get_sibling_path(hint.tree_id, hint.index));
168 }
169
170 ExecutionHints collected_hints;
171 hinting_merkle_db.dump_hints(collected_hints);
172 compare_hints(inputs.hints.get_sibling_path_hints, collected_hints.get_sibling_path_hints);
173}
174
175TEST_F(HintingDBsMinimalTest, MerkleDBCheckpoints)
176{
177 // The minimal tx has one create and one commit. The conditionals are in case the minimal tx ever changes, bricking
178 // this test:
179 if (inputs.hints.create_checkpoint_hints.size() == 1) {
180 // The hinting db will cause the underlying base db to push a checkpoint onto the stack and increment the action
181 // counter:
183 if (inputs.hints.commit_checkpoint_hints.size() == 1) {
185 }
186 }
187 ExecutionHints collected_hints;
188 hinting_merkle_db.dump_hints(collected_hints);
189 compare_hints(inputs.hints.create_checkpoint_hints, collected_hints.create_checkpoint_hints);
190 compare_hints(inputs.hints.commit_checkpoint_hints, collected_hints.commit_checkpoint_hints);
191}
192
193class MockedHintingDBsTest : public ::testing::Test {
194 protected:
195 MockedHintingDBsTest() { ON_CALL(base_merkle_db, get_tree_roots).WillByDefault(::testing::Return(mock_tree_info)); }
196 ::testing::StrictMock<MockContractDB> base_contract_db;
197 ::testing::StrictMock<MockLowLevelMerkleDB> base_merkle_db;
198 HintingContractsDB hinting_contract_db = HintingContractsDB(base_contract_db);
199 HintingRawDB hinting_merkle_db = HintingRawDB(base_merkle_db);
200
201 TreeSnapshots mock_tree_info = {
202 { 1, 2 },
203 { 3, 2 },
204 { 5, 5 },
205 { 7, 3 },
206 };
207};
208
209TEST_F(MockedHintingDBsTest, GetLowLeaf)
210{
211 // Mock some slots:
212 std::vector<FF> update_preimage_slots = { 1, 2, 4 };
213 // get_low_indexed_leaf will call get_tree_roots:
214 EXPECT_CALL(base_merkle_db, get_tree_roots).Times(static_cast<int>(update_preimage_slots.size()));
215 EXPECT_CALL(base_merkle_db, get_low_indexed_leaf(world_state::MerkleTreeId::PUBLIC_DATA_TREE, ::testing::_))
216 .WillRepeatedly([&](world_state::MerkleTreeId, const FF& leaf_slot) {
217 for (size_t i = 0; i < update_preimage_slots.size(); ++i) {
218 if (leaf_slot == update_preimage_slots[i]) {
219 return GetLowIndexedLeafResponse(true, static_cast<uint64_t>(i));
220 }
221 }
222 throw std::runtime_error("Leaf not found");
223 });
224
225 // Call the db:
226 for (const auto& update_preimage_slot : update_preimage_slots) {
228 }
229 ExecutionHints collected_hints;
230 hinting_merkle_db.dump_hints(collected_hints);
231
232 // Check the collected hints:
233 EXPECT_EQ(collected_hints.get_previous_value_index_hints.size(), update_preimage_slots.size());
234 EXPECT_THAT(
235 collected_hints.get_previous_value_index_hints,
236 ::testing::ElementsAreArray({ GetPreviousValueIndexHint{ .hint_key = mock_tree_info.public_data_tree,
237 .tree_id = world_state::MerkleTreeId::PUBLIC_DATA_TREE,
238 .value = update_preimage_slots[0],
239 .index = 0,
240 .already_present = true },
241 GetPreviousValueIndexHint{ .hint_key = mock_tree_info.public_data_tree,
242 .tree_id = world_state::MerkleTreeId::PUBLIC_DATA_TREE,
243 .value = update_preimage_slots[1],
244 .index = 1,
245 .already_present = true },
246 GetPreviousValueIndexHint{ .hint_key = mock_tree_info.public_data_tree,
247 .tree_id = world_state::MerkleTreeId::PUBLIC_DATA_TREE,
248 .value = update_preimage_slots[2],
249 .index = 2,
250 .already_present = true } }));
251}
252
253TEST_F(MockedHintingDBsTest, GetLeafValue)
254{
255 // Mock some leaf values:
256 std::vector<FF> note_hash_leaf_values = { 11, 22, 44, 88 };
257 // get_leaf_value will call get_tree_roots:
258 EXPECT_CALL(base_merkle_db, get_tree_roots).Times(static_cast<int>(note_hash_leaf_values.size()));
259 EXPECT_CALL(base_merkle_db, get_leaf_value(world_state::MerkleTreeId::NOTE_HASH_TREE, ::testing::_))
260 .WillRepeatedly([&](world_state::MerkleTreeId, index_t index) {
261 if (index < note_hash_leaf_values.size()) {
262 return note_hash_leaf_values[index];
263 }
264 throw std::runtime_error("Leaf not found");
265 });
266
267 // Call the db:
268 for (index_t i = 0; i < note_hash_leaf_values.size(); i++) {
270 }
271 ExecutionHints collected_hints;
272 hinting_merkle_db.dump_hints(collected_hints);
273
274 // Check the collected hints:
275 EXPECT_EQ(collected_hints.get_leaf_value_hints.size(), note_hash_leaf_values.size());
276 EXPECT_THAT(collected_hints.get_leaf_value_hints,
277 ::testing::ElementsAreArray({
278 GetLeafValueHint{ .hint_key = mock_tree_info.note_hash_tree,
279 .tree_id = world_state::MerkleTreeId::NOTE_HASH_TREE,
280 .index = 0,
281 .value = note_hash_leaf_values[0] },
282 GetLeafValueHint{ .hint_key = mock_tree_info.note_hash_tree,
283 .tree_id = world_state::MerkleTreeId::NOTE_HASH_TREE,
284 .index = 1,
285 .value = note_hash_leaf_values[1] },
286 GetLeafValueHint{ .hint_key = mock_tree_info.note_hash_tree,
287 .tree_id = world_state::MerkleTreeId::NOTE_HASH_TREE,
288 .index = 2,
289 .value = note_hash_leaf_values[2] },
290 GetLeafValueHint{ .hint_key = mock_tree_info.note_hash_tree,
291 .tree_id = world_state::MerkleTreeId::NOTE_HASH_TREE,
292 .index = 3,
293 .value = note_hash_leaf_values[3] },
294 }));
295}
296
297TEST_F(MockedHintingDBsTest, GetLeafPreimagePublicDataTree)
298{
299 // Mock some leaf values:
300 std::vector<PublicDataLeafValue> public_leaf_values = { { 1, 3 }, { 2, 6 }, { 4, 7 } };
301 std::vector<IndexedLeaf<PublicDataLeafValue>> public_leaf_preimages = { { public_leaf_values[0], 1, 6 },
302 { public_leaf_values[1], 2, 4 },
303 { public_leaf_values[2], 0, 3 } };
304 // get_leaf_preimage_public_data_tree will call get_tree_roots:
305 EXPECT_CALL(base_merkle_db, get_tree_roots).Times(static_cast<int>(public_leaf_preimages.size()));
306 EXPECT_CALL(base_merkle_db, get_leaf_preimage_public_data_tree(::testing::_)).WillRepeatedly([&](index_t index) {
307 if (index < public_leaf_preimages.size()) {
308 return public_leaf_preimages[index];
309 }
310 throw std::runtime_error("Leaf preimage not found");
311 });
312
313 // Call the db:
314 for (index_t i = 0; i < public_leaf_preimages.size(); i++) {
315 hinting_merkle_db.get_leaf_preimage_public_data_tree(i);
316 }
317 ExecutionHints collected_hints;
318 hinting_merkle_db.dump_hints(collected_hints);
319
320 // Check the collected hints:
321 EXPECT_EQ(collected_hints.get_leaf_preimage_hints_public_data_tree.size(), public_leaf_preimages.size());
322 EXPECT_THAT(
323 collected_hints.get_leaf_preimage_hints_public_data_tree,
324 ::testing::ElementsAreArray(
325 { GetLeafPreimageHint<PublicDataTreeLeafPreimage>{
326 .hint_key = mock_tree_info.public_data_tree, .index = 0, .leaf_preimage = public_leaf_preimages[0] },
327 GetLeafPreimageHint<PublicDataTreeLeafPreimage>{
328 .hint_key = mock_tree_info.public_data_tree, .index = 1, .leaf_preimage = public_leaf_preimages[1] },
329 GetLeafPreimageHint<PublicDataTreeLeafPreimage>{ .hint_key = mock_tree_info.public_data_tree,
330 .index = 2,
331 .leaf_preimage = public_leaf_preimages[2] } }));
332}
333
334TEST_F(MockedHintingDBsTest, GetLeafPreimageNullifierTree)
335{
336 // Mock some leaf values:
337 std::vector<NullifierLeafValue> nullifier_leaf_values = { { 1 }, { 2 }, { 4 } };
338 std::vector<IndexedLeaf<NullifierLeafValue>> nullifier_leaf_preimages = { { nullifier_leaf_values[0], 1, 6 },
339 { nullifier_leaf_values[1], 2, 4 },
340 { nullifier_leaf_values[2], 0, 3 } };
341 // get_leaf_preimage_nullifier_tree will call get_tree_roots:
342 EXPECT_CALL(base_merkle_db, get_tree_roots).Times(static_cast<int>(nullifier_leaf_preimages.size()));
343 EXPECT_CALL(base_merkle_db, get_leaf_preimage_nullifier_tree(::testing::_)).WillRepeatedly([&](index_t index) {
344 if (index < nullifier_leaf_preimages.size()) {
345 return nullifier_leaf_preimages[index];
346 }
347 throw std::runtime_error("Leaf preimage not found");
348 });
349
350 // Call the db:
351 for (index_t i = 0; i < nullifier_leaf_preimages.size(); i++) {
352 hinting_merkle_db.get_leaf_preimage_nullifier_tree(i);
353 }
354 ExecutionHints collected_hints;
355 hinting_merkle_db.dump_hints(collected_hints);
356
357 // Check the collected hints:
358 EXPECT_EQ(collected_hints.get_leaf_preimage_hints_nullifier_tree.size(), nullifier_leaf_preimages.size());
359 EXPECT_THAT(
360 collected_hints.get_leaf_preimage_hints_nullifier_tree,
361 ::testing::ElementsAreArray(
362 { GetLeafPreimageHint<NullifierTreeLeafPreimage>{
363 .hint_key = mock_tree_info.nullifier_tree, .index = 0, .leaf_preimage = nullifier_leaf_preimages[0] },
364 GetLeafPreimageHint<NullifierTreeLeafPreimage>{
365 .hint_key = mock_tree_info.nullifier_tree, .index = 1, .leaf_preimage = nullifier_leaf_preimages[1] },
366 GetLeafPreimageHint<NullifierTreeLeafPreimage>{ .hint_key = mock_tree_info.nullifier_tree,
367 .index = 2,
368 .leaf_preimage = nullifier_leaf_preimages[2] } }));
369}
370
371TEST_F(MockedHintingDBsTest, InsertIndexedLeavesPublicDataTree)
372{
373 AppendOnlyTreeSnapshot state_before = mock_tree_info.public_data_tree;
374 // Mock the leaf values:
375 PublicDataLeafValue public_leaf_value = { 4, 7 };
376 PublicDataLeafValue low_leaf_value = { 2, 6 };
377 SiblingPath mock_path((PUBLIC_DATA_TREE_HEIGHT));
378 AppendOnlyTreeSnapshot mock_state_after = { mock_tree_info.public_data_tree.root++,
379 mock_tree_info.public_data_tree.next_available_leaf_index++ };
380 LeafUpdateWitnessData<PublicDataLeafValue> mock_low_witness_data =
381 LeafUpdateWitnessData<PublicDataLeafValue>{ { low_leaf_value, 0, 0 }, 0, mock_path };
382 // insert_indexed_leaves_public_data_tree will call get_tree_roots and get_tree_info (which itself will call
383 // get_tree_roots):
384 EXPECT_CALL(base_merkle_db, get_tree_roots).Times(2);
385 EXPECT_CALL(base_merkle_db, insert_indexed_leaves_public_data_tree(::testing::_))
386 .WillOnce([&](PublicDataLeafValue value) {
387 SequentialInsertionResult<PublicDataLeafValue> result = {
388 .low_leaf_witness_data = { mock_low_witness_data },
389 .insertion_witness_data = { { { value, 1, 6 }, 1, mock_path } }
390 };
391 mock_tree_info.public_data_tree = mock_state_after;
392 return result;
393 });
394
395 // Call the db:
396 hinting_merkle_db.insert_indexed_leaves_public_data_tree(public_leaf_value);
397 ExecutionHints collected_hints;
398 hinting_merkle_db.dump_hints(collected_hints);
399
400 // Check the collected hints:
401 EXPECT_EQ(collected_hints.sequential_insert_hints_public_data_tree.size(), 1);
402 EXPECT_THAT(collected_hints.sequential_insert_hints_public_data_tree,
403 ::testing::ElementsAre(SequentialInsertHint<PublicDataLeafValue>{
404 .hint_key = state_before,
405 .tree_id = world_state::MerkleTreeId::PUBLIC_DATA_TREE,
406 .leaf = public_leaf_value,
407 .low_leaves_witness_data = mock_low_witness_data,
408 .insertion_witness_data = { { public_leaf_value, 1, 6 }, 1, mock_path },
409 .state_after = mock_tree_info.public_data_tree }));
410}
411
412TEST_F(MockedHintingDBsTest, InsertIndexedLeavesNullifierTree)
413{
414 AppendOnlyTreeSnapshot state_before = mock_tree_info.nullifier_tree;
415 // Mock the leaf values:
416 NullifierLeafValue nullifier = { 4 };
417 NullifierLeafValue low_leaf_value = { 2 };
418 SiblingPath mock_path((NULLIFIER_TREE_HEIGHT));
419 AppendOnlyTreeSnapshot mock_state_after = { mock_tree_info.nullifier_tree.root++,
420 mock_tree_info.nullifier_tree.next_available_leaf_index++ };
421 LeafUpdateWitnessData<NullifierLeafValue> mock_low_witness_data =
422 LeafUpdateWitnessData<NullifierLeafValue>{ { low_leaf_value, 0, 0 }, 0, mock_path };
423 // insert_indexed_leaves_nullifier_tree will call get_tree_roots and get_tree_info (which itself will call
424 // get_tree_roots):
425 EXPECT_CALL(base_merkle_db, get_tree_roots).Times(2);
426 EXPECT_CALL(base_merkle_db, insert_indexed_leaves_nullifier_tree(::testing::_))
427 .WillOnce([&](NullifierLeafValue value) {
428 SequentialInsertionResult<NullifierLeafValue> result = { .low_leaf_witness_data = { mock_low_witness_data },
429 .insertion_witness_data = {
430 { { value, 1, 6 }, 1, mock_path } } };
431 mock_tree_info.nullifier_tree = mock_state_after;
432 return result;
433 });
434
435 // Call the db:
436 hinting_merkle_db.insert_indexed_leaves_nullifier_tree(nullifier);
437 ExecutionHints collected_hints;
438 hinting_merkle_db.dump_hints(collected_hints);
439
440 // Check the collected hints:
441 EXPECT_EQ(collected_hints.sequential_insert_hints_nullifier_tree.size(), 1);
442 EXPECT_THAT(collected_hints.sequential_insert_hints_nullifier_tree,
443 ::testing::ElementsAre(SequentialInsertHint<NullifierLeafValue>{
444 .hint_key = state_before,
445 .tree_id = world_state::MerkleTreeId::NULLIFIER_TREE,
446 .leaf = nullifier,
447 .low_leaves_witness_data = mock_low_witness_data,
448 .insertion_witness_data = { { nullifier, 1, 6 }, 1, mock_path },
449 .state_after = mock_tree_info.nullifier_tree }));
450}
451
452TEST_F(MockedHintingDBsTest, AppendLeaves)
453{
454 // Set initial state:
455 AppendOnlyTreeSnapshot initial_state = { 0, 0 };
456 mock_tree_info.note_hash_tree = initial_state;
457 // Mock the leaf values:
458 std::vector<FF> note_hash_leaf_values = { 11, 22, 44, 88 };
459 AppendOnlyTreeSnapshot expected_end_state = { 8, 4 };
460 TreeSnapshots expected_tree_info_after = mock_tree_info;
461 expected_tree_info_after.note_hash_tree = expected_end_state;
462 // append_leaves will call get_tree_info at the beginning and end of appending leaves:
463 EXPECT_CALL(base_merkle_db, get_tree_roots)
464 .WillOnce(::testing::Return(mock_tree_info))
465 .WillOnce(::testing::Return(expected_tree_info_after));
466 EXPECT_CALL(base_merkle_db, append_leaves(world_state::MerkleTreeId::NOTE_HASH_TREE, ::testing::_)).Times(1);
467
468 // Call the db:
469 hinting_merkle_db.append_leaves(world_state::MerkleTreeId::NOTE_HASH_TREE, note_hash_leaf_values);
470 ExecutionHints collected_hints;
471 hinting_merkle_db.dump_hints(collected_hints);
472
473 // Check the collected hints - one hint for all leaves:
474 EXPECT_EQ(collected_hints.append_leaves_hints.size(), 1);
475 EXPECT_THAT(collected_hints.append_leaves_hints,
476 ::testing::ElementsAre(AppendLeavesHint{ .hint_key = initial_state,
477 .state_after = expected_end_state,
478 .tree_id = world_state::MerkleTreeId::NOTE_HASH_TREE,
479 .leaves = note_hash_leaf_values }));
480}
481
482TEST_F(MockedHintingDBsTest, MerkleDBCheckpoints)
483{
484 uint32_t mock_checkpoint_id = 0;
485 EXPECT_CALL(base_merkle_db, get_checkpoint_id)
486 .WillOnce(::testing::Invoke([&]() { return mock_checkpoint_id; }))
487 .WillOnce(::testing::Invoke([&]() { return ++mock_checkpoint_id; }))
488 .WillOnce(::testing::Invoke([&]() { return mock_checkpoint_id; }))
489 .WillOnce(::testing::Invoke([&]() { return ++mock_checkpoint_id; }));
490 ;
491 EXPECT_CALL(base_merkle_db, create_checkpoint).Times(2);
492 // Call the db:
493 hinting_merkle_db.create_checkpoint();
494 hinting_merkle_db.create_checkpoint();
495
496 EXPECT_CALL(base_merkle_db, get_checkpoint_id)
497 .WillOnce(::testing::Invoke([&]() { return mock_checkpoint_id; }))
498 .WillOnce(::testing::Invoke([&]() { return --mock_checkpoint_id; }));
499 EXPECT_CALL(base_merkle_db, commit_checkpoint).Times(1);
500 hinting_merkle_db.commit_checkpoint();
501
502 // revert_checkpoint will call get_tree_roots before and after calling the underlying db::
503 EXPECT_CALL(base_merkle_db, get_tree_roots).Times(2);
504
505 EXPECT_CALL(base_merkle_db, get_checkpoint_id)
506 .WillOnce(::testing::Invoke([&]() { return mock_checkpoint_id; }))
507 .WillOnce(::testing::Invoke([&]() { return --mock_checkpoint_id; }));
508 EXPECT_CALL(base_merkle_db, revert_checkpoint).Times(1);
509 hinting_merkle_db.revert_checkpoint();
510 ExecutionHints collected_hints;
511 hinting_merkle_db.dump_hints(collected_hints);
512
513 // Check the collected hints:
514 EXPECT_EQ(collected_hints.create_checkpoint_hints.size(), 2);
515 EXPECT_EQ(collected_hints.commit_checkpoint_hints.size(), 1);
516 EXPECT_EQ(collected_hints.revert_checkpoint_hints.size(), 1);
517 mock_checkpoint_id = 0;
518 uint32_t mock_action_counter = 0;
519 EXPECT_THAT(collected_hints.create_checkpoint_hints,
520 ::testing::ElementsAreArray({ CreateCheckpointHint{
521 .action_counter = mock_action_counter++,
522 .old_checkpoint_id = mock_checkpoint_id,
523 .new_checkpoint_id = ++mock_checkpoint_id,
524 },
525 CreateCheckpointHint{
526 .action_counter = mock_action_counter++,
527 .old_checkpoint_id = mock_checkpoint_id,
528 .new_checkpoint_id = ++mock_checkpoint_id,
529 } }));
530 EXPECT_THAT(collected_hints.commit_checkpoint_hints,
531 ::testing::ElementsAre(CommitCheckpointHint{
532 .action_counter = mock_action_counter++,
533 .old_checkpoint_id = mock_checkpoint_id,
534 .new_checkpoint_id = --mock_checkpoint_id,
535 }));
536 EXPECT_THAT(collected_hints.revert_checkpoint_hints,
537 ::testing::ElementsAre(RevertCheckpointHint{
538 .action_counter = mock_action_counter++,
539 .old_checkpoint_id = mock_checkpoint_id,
540 .new_checkpoint_id = --mock_checkpoint_id,
541 .state_before = mock_tree_info,
542 .state_after = mock_tree_info,
543 }));
544}
545
546} // namespace
547} // namespace bb::avm2::simulation
std::optional< ContractInstance > get_contract_instance(const AztecAddress &address) const override
std::optional< ContractClass > get_contract_class(const ContractClassId &class_id) const override
std::optional< std::string > get_debug_function_name(const AztecAddress &address, const FunctionSelector &selector) const override
std::optional< FF > get_bytecode_commitment(const ContractClassId &class_id) const override
SiblingPath get_sibling_path(MerkleTreeId tree_id, index_t leaf_index) const override
std::optional< std::string > get_debug_function_name(const AztecAddress &address, const FunctionSelector &selector) const override
std::optional< ContractClass > get_contract_class(const ContractClassId &class_id) const override
std::optional< FF > get_bytecode_commitment(const ContractClassId &class_id) const override
void dump_hints(ExecutionHints &hints)
std::optional< ContractInstance > get_contract_instance(const AztecAddress &address) const override
void dump_hints(ExecutionHints &hints)
SiblingPath get_sibling_path(MerkleTreeId tree_id, index_t leaf_index) const override
GetLowIndexedLeafResponse get_low_indexed_leaf(MerkleTreeId tree_id, const FF &value) const override
FF get_leaf_value(MerkleTreeId tree_id, index_t leaf_index) const override
auto & get_tree_info_helper(world_state::MerkleTreeId tree_id, auto &tree_roots)
Definition db_types.hpp:72
AvmProvingInputs inputs
HintedRawMerkleDB base_merkle_db
HintingContractsDB hinting_contract_db
TreeSnapshots mock_tree_info
HintedRawContractDB base_contract_db
HintingRawDB hinting_merkle_db
AVM range check gadget for witness generation.
::bb::crypto::merkle_tree::fr_sibling_path SiblingPath
Definition db.hpp:36
::bb::world_state::MerkleTreeId MerkleTreeId
Definition db.hpp:35
AvmProvingInputs get_minimal_proving_inputs()
Definition fixtures.cpp:196
TEST_F(IPATest, ChallengesAreZero)
Definition ipa.test.cpp:160
std::vector< uint8_t > read_file(const std::string &filename, size_t bytes=0)
Definition file_io.hpp:31
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
std::string name
TreeSnapshots starting_tree_roots
Definition avm_io.hpp:375
std::vector< GetSiblingPathHint > get_sibling_path_hints
Definition avm_io.hpp:376
std::vector< DebugFunctionNameHint > debug_function_names
Definition avm_io.hpp:370
std::vector< ContractDBCreateCheckpointHint > contract_db_create_checkpoint_hints
Definition avm_io.hpp:371
std::vector< ContractDBCommitCheckpointHint > contract_db_commit_checkpoint_hints
Definition avm_io.hpp:372
std::vector< CommitCheckpointHint > commit_checkpoint_hints
Definition avm_io.hpp:388
std::vector< CreateCheckpointHint > create_checkpoint_hints
Definition avm_io.hpp:387
std::vector< ContractInstanceHint > contract_instances
Definition avm_io.hpp:367
std::vector< ContractClassHint > contract_classes
Definition avm_io.hpp:368
std::vector< BytecodeCommitmentHint > bytecode_commitments
Definition avm_io.hpp:369
VectorField result