15#include <gmock/gmock.h>
16#include <gtest/gtest.h>
22class HintingDBsTest :
public ::testing::Test {
24 HintingDBsTest(
const AvmProvingInputs& inputs)
30 template <
typename H
int>
33 for (
const Hint& input_hint : input_hints) {
34 EXPECT_FALSE(std::ranges::find(collected_hints.begin(), collected_hints.end(), input_hint) ==
35 collected_hints.end());
38 for (
const Hint& collected_hint : collected_hints) {
39 EXPECT_FALSE(std::ranges::find(input_hints.begin(), input_hints.end(), collected_hint) ==
52class HintingDBsMinimalTest :
public HintingDBsTest {
54 HintingDBsMinimalTest()
55 : HintingDBsTest(AvmProvingInputs::from(
read_file(
"../src/barretenberg/vm2/testing/minimal_tx.testdata.bin")))
60AvmProvingInputs fix_hint_keys(AvmProvingInputs
inputs)
62 auto reset_action_counters = [&]<
typename H>(
std::vector<H>& hints) {
63 for (
auto& hint : hints) {
68 for (
auto& hint : hints) {
82class HintingDBsTestInputTest :
public HintingDBsTest {
84 HintingDBsTestInputTest()
85 : HintingDBsTest(fix_hint_keys(
86 AvmProvingInputs::from(
read_file(
"../src/barretenberg/vm2/testing/avm_inputs.testdata.bin"))))
90TEST_F(HintingDBsTestInputTest, GetContractInstance)
92 for (
const auto& instance_hint :
inputs.hints.contract_instances) {
98 ExecutionHints collected_hints;
103TEST_F(HintingDBsTestInputTest, GetContractClass)
105 for (
const auto& class_hint :
inputs.hints.contract_classes) {
107 EXPECT_TRUE(klass.has_value());
111 ExecutionHints collected_hints;
116TEST_F(HintingDBsTestInputTest, GetBytecodeCommitment)
118 for (
const auto& hint :
inputs.hints.bytecode_commitments) {
120 EXPECT_TRUE(commitment.has_value());
124 ExecutionHints collected_hints;
129TEST_F(HintingDBsTestInputTest, GetDebugFunctionName)
131 for (
const auto& hint :
inputs.hints.debug_function_names) {
133 EXPECT_TRUE(name.has_value());
137 ExecutionHints collected_hints;
142TEST_F(HintingDBsMinimalTest, ContractDBCheckpoints)
154 ExecutionHints collected_hints;
157 collected_hints.contract_db_create_checkpoint_hints);
159 collected_hints.contract_db_commit_checkpoint_hints);
162TEST_F(HintingDBsTestInputTest, GetSiblingPath)
164 for (
const auto& hint :
inputs.hints.get_sibling_path_hints) {
169 ExecutionHints collected_hints;
174TEST_F(HintingDBsMinimalTest, MerkleDBCheckpoints)
186 ExecutionHints collected_hints;
192class MockedHintingDBsTest :
public ::testing::Test {
194 MockedHintingDBsTest() { ON_CALL(base_merkle_db, get_tree_roots).WillByDefault(testing::Return(mock_tree_info)); }
208TEST_F(MockedHintingDBsTest, GetLowLeaf)
211 std::vector<FF> update_preimage_slots = { 1, 2, 4 };
214 EXPECT_CALL(
base_merkle_db, get_tree_roots).Times(
static_cast<int>(update_preimage_slots.size() * 2));
219 for (
size_t i = 0; i < update_preimage_slots.size(); ++i) {
220 if (leaf_slot == update_preimage_slots[i]) {
224 throw std::runtime_error(
"Leaf not found");
228 for (
const auto& update_preimage_slot : update_preimage_slots) {
231 ExecutionHints collected_hints;
235 EXPECT_EQ(collected_hints.get_previous_value_index_hints.size(), update_preimage_slots.size());
236 EXPECT_EQ(collected_hints.get_sibling_path_hints.size(), update_preimage_slots.size());
238 collected_hints.get_previous_value_index_hints,
239 testing::ElementsAreArray({ GetPreviousValueIndexHint{ .hint_key = mock_tree_info.public_data_tree,
240 .tree_id = world_state::MerkleTreeId::PUBLIC_DATA_TREE,
241 .value = update_preimage_slots[0],
243 .already_present = true },
244 GetPreviousValueIndexHint{ .hint_key = mock_tree_info.public_data_tree,
245 .tree_id = world_state::MerkleTreeId::PUBLIC_DATA_TREE,
246 .value = update_preimage_slots[1],
248 .already_present = true },
249 GetPreviousValueIndexHint{ .hint_key = mock_tree_info.public_data_tree,
250 .tree_id = world_state::MerkleTreeId::PUBLIC_DATA_TREE,
251 .value = update_preimage_slots[2],
253 .already_present = true } }));
254 EXPECT_THAT(collected_hints.get_sibling_path_hints,
255 testing::ElementsAreArray({ GetSiblingPathHint{ .hint_key = mock_tree_info.public_data_tree,
256 .tree_id = world_state::MerkleTreeId::PUBLIC_DATA_TREE,
259 GetSiblingPathHint{ .hint_key = mock_tree_info.public_data_tree,
260 .tree_id = world_state::MerkleTreeId::PUBLIC_DATA_TREE,
263 GetSiblingPathHint{ .hint_key = mock_tree_info.public_data_tree,
264 .tree_id = world_state::MerkleTreeId::PUBLIC_DATA_TREE,
266 .path = mock_path } }));
269TEST_F(MockedHintingDBsTest, GetLeafValue)
272 std::vector<FF> note_hash_leaf_values = { 11, 22, 44, 88 };
275 EXPECT_CALL(
base_merkle_db, get_tree_roots).Times(
static_cast<int>(note_hash_leaf_values.size() * 2));
278 EXPECT_CALL(
base_merkle_db, get_leaf_value(world_state::MerkleTreeId::NOTE_HASH_TREE, testing::_))
280 if (
index < note_hash_leaf_values.size()) {
281 return note_hash_leaf_values[index];
283 throw std::runtime_error(
"Leaf not found");
287 for (
index_t i = 0; i < note_hash_leaf_values.size(); i++) {
290 ExecutionHints collected_hints;
294 EXPECT_EQ(collected_hints.get_leaf_value_hints.size(), note_hash_leaf_values.size());
295 EXPECT_EQ(collected_hints.get_sibling_path_hints.size(), note_hash_leaf_values.size());
296 EXPECT_THAT(collected_hints.get_leaf_value_hints,
297 testing::ElementsAreArray({
298 GetLeafValueHint{ .hint_key = mock_tree_info.note_hash_tree,
299 .tree_id = world_state::MerkleTreeId::NOTE_HASH_TREE,
301 .value = note_hash_leaf_values[0] },
302 GetLeafValueHint{ .hint_key = mock_tree_info.note_hash_tree,
303 .tree_id = world_state::MerkleTreeId::NOTE_HASH_TREE,
305 .value = note_hash_leaf_values[1] },
306 GetLeafValueHint{ .hint_key = mock_tree_info.note_hash_tree,
307 .tree_id = world_state::MerkleTreeId::NOTE_HASH_TREE,
309 .value = note_hash_leaf_values[2] },
310 GetLeafValueHint{ .hint_key = mock_tree_info.note_hash_tree,
311 .tree_id = world_state::MerkleTreeId::NOTE_HASH_TREE,
313 .value = note_hash_leaf_values[3] },
315 EXPECT_THAT(collected_hints.get_sibling_path_hints,
316 testing::ElementsAreArray({ GetSiblingPathHint{ .hint_key = mock_tree_info.note_hash_tree,
317 .tree_id = world_state::MerkleTreeId::NOTE_HASH_TREE,
320 GetSiblingPathHint{ .hint_key = mock_tree_info.note_hash_tree,
321 .tree_id = world_state::MerkleTreeId::NOTE_HASH_TREE,
324 GetSiblingPathHint{ .hint_key = mock_tree_info.note_hash_tree,
325 .tree_id = world_state::MerkleTreeId::NOTE_HASH_TREE,
328 GetSiblingPathHint{ .hint_key = mock_tree_info.note_hash_tree,
329 .tree_id = world_state::MerkleTreeId::NOTE_HASH_TREE,
331 .path = mock_path } }));
334TEST_F(MockedHintingDBsTest, GetLeafPreimagePublicDataTree)
339 { public_leaf_values[1], 2, 4 },
340 { public_leaf_values[2], 0, 3 } };
344 EXPECT_CALL(
base_merkle_db, get_tree_roots).Times(
static_cast<int>(public_leaf_preimages.size() * 2));
348 if (
index < public_leaf_preimages.size()) {
349 return public_leaf_preimages[index];
351 throw std::runtime_error(
"Leaf preimage not found");
355 for (
index_t i = 0; i < public_leaf_preimages.size(); i++) {
358 ExecutionHints collected_hints;
362 EXPECT_EQ(collected_hints.get_leaf_preimage_hints_public_data_tree.size(), public_leaf_preimages.size());
363 EXPECT_EQ(collected_hints.get_sibling_path_hints.size(), public_leaf_preimages.size());
365 collected_hints.get_leaf_preimage_hints_public_data_tree,
366 testing::ElementsAreArray(
367 { GetLeafPreimageHint<PublicDataTreeLeafPreimage>{
368 .hint_key = mock_tree_info.public_data_tree, .index = 0, .leaf_preimage = public_leaf_preimages[0] },
369 GetLeafPreimageHint<PublicDataTreeLeafPreimage>{
370 .hint_key = mock_tree_info.public_data_tree, .index = 1, .leaf_preimage = public_leaf_preimages[1] },
371 GetLeafPreimageHint<PublicDataTreeLeafPreimage>{ .hint_key = mock_tree_info.public_data_tree,
373 .leaf_preimage = public_leaf_preimages[2] } }));
374 EXPECT_THAT(collected_hints.get_sibling_path_hints,
375 testing::ElementsAreArray({ GetSiblingPathHint{ .hint_key = mock_tree_info.public_data_tree,
376 .tree_id = world_state::MerkleTreeId::PUBLIC_DATA_TREE,
379 GetSiblingPathHint{ .hint_key = mock_tree_info.public_data_tree,
380 .tree_id = world_state::MerkleTreeId::PUBLIC_DATA_TREE,
383 GetSiblingPathHint{ .hint_key = mock_tree_info.public_data_tree,
384 .tree_id = world_state::MerkleTreeId::PUBLIC_DATA_TREE,
386 .path = mock_path } }));
389TEST_F(MockedHintingDBsTest, GetLeafPreimageNullifierTree)
394 { nullifier_leaf_values[1], 2, 4 },
395 { nullifier_leaf_values[2], 0, 3 } };
399 EXPECT_CALL(
base_merkle_db, get_tree_roots).Times(
static_cast<int>(nullifier_leaf_preimages.size() * 2));
403 if (
index < nullifier_leaf_preimages.size()) {
404 return nullifier_leaf_preimages[index];
406 throw std::runtime_error(
"Leaf preimage not found");
410 for (
index_t i = 0; i < nullifier_leaf_preimages.size(); i++) {
413 ExecutionHints collected_hints;
417 EXPECT_EQ(collected_hints.get_leaf_preimage_hints_nullifier_tree.size(), nullifier_leaf_preimages.size());
418 EXPECT_EQ(collected_hints.get_sibling_path_hints.size(), nullifier_leaf_preimages.size());
420 collected_hints.get_leaf_preimage_hints_nullifier_tree,
421 testing::ElementsAreArray(
422 { GetLeafPreimageHint<NullifierTreeLeafPreimage>{
423 .hint_key = mock_tree_info.nullifier_tree, .index = 0, .leaf_preimage = nullifier_leaf_preimages[0] },
424 GetLeafPreimageHint<NullifierTreeLeafPreimage>{
425 .hint_key = mock_tree_info.nullifier_tree, .index = 1, .leaf_preimage = nullifier_leaf_preimages[1] },
426 GetLeafPreimageHint<NullifierTreeLeafPreimage>{ .hint_key = mock_tree_info.nullifier_tree,
428 .leaf_preimage = nullifier_leaf_preimages[2] } }));
429 EXPECT_THAT(collected_hints.get_sibling_path_hints,
430 testing::ElementsAreArray({ GetSiblingPathHint{ .hint_key = mock_tree_info.nullifier_tree,
431 .tree_id = world_state::MerkleTreeId::NULLIFIER_TREE,
434 GetSiblingPathHint{ .hint_key = mock_tree_info.nullifier_tree,
435 .tree_id = world_state::MerkleTreeId::NULLIFIER_TREE,
438 GetSiblingPathHint{ .hint_key = mock_tree_info.nullifier_tree,
439 .tree_id = world_state::MerkleTreeId::NULLIFIER_TREE,
441 .path = mock_path } }));
444TEST_F(MockedHintingDBsTest, InsertIndexedLeavesPublicDataTree)
446 AppendOnlyTreeSnapshot state_before =
mock_tree_info.public_data_tree;
451 AppendOnlyTreeSnapshot mock_state_after = {
mock_tree_info.public_data_tree.root++,
458 EXPECT_CALL(
base_merkle_db, insert_indexed_leaves_public_data_tree(testing::_))
460 SequentialInsertionResult<PublicDataLeafValue> result = {
461 .low_leaf_witness_data = { mock_low_witness_data },
462 .insertion_witness_data = { { {
value, 1, 6 }, 1, mock_path } }
470 ExecutionHints collected_hints;
474 EXPECT_EQ(collected_hints.sequential_insert_hints_public_data_tree.size(), 1);
475 EXPECT_THAT(collected_hints.sequential_insert_hints_public_data_tree,
476 testing::ElementsAre(SequentialInsertHint<PublicDataLeafValue>{
477 .hint_key = state_before,
478 .tree_id = world_state::MerkleTreeId::PUBLIC_DATA_TREE,
479 .leaf = public_leaf_value,
480 .low_leaves_witness_data = mock_low_witness_data,
481 .insertion_witness_data = { { public_leaf_value, 1, 6 }, 1, mock_path },
485TEST_F(MockedHintingDBsTest, InsertIndexedLeavesNullifierTree)
487 AppendOnlyTreeSnapshot state_before =
mock_tree_info.nullifier_tree;
492 AppendOnlyTreeSnapshot mock_state_after = {
mock_tree_info.nullifier_tree.root++,
499 EXPECT_CALL(
base_merkle_db, insert_indexed_leaves_nullifier_tree(testing::_))
501 SequentialInsertionResult<NullifierLeafValue> result = { .low_leaf_witness_data = { mock_low_witness_data },
502 .insertion_witness_data = {
503 { {
value, 1, 6 }, 1, mock_path } } };
510 ExecutionHints collected_hints;
514 EXPECT_EQ(collected_hints.sequential_insert_hints_nullifier_tree.size(), 1);
515 EXPECT_THAT(collected_hints.sequential_insert_hints_nullifier_tree,
516 testing::ElementsAre(SequentialInsertHint<NullifierLeafValue>{
517 .hint_key = state_before,
518 .tree_id = world_state::MerkleTreeId::NULLIFIER_TREE,
520 .low_leaves_witness_data = mock_low_witness_data,
521 .insertion_witness_data = { { nullifier, 1, 6 }, 1, mock_path },
525TEST_F(MockedHintingDBsTest, AppendLeaves)
530 std::vector<FF> note_hash_leaf_values = { 11, 22, 44, 88 };
533 auto this_path = mock_path;
534 auto this_index =
mock_tree_info.note_hash_tree.next_available_leaf_index;
536 this_index % 2 == 0 ? note_hash_leaf_values[this_index + 1] : note_hash_leaf_values[this_index - 1];
537 this_path[0] = this_sibling;
538 AppendLeafResult result = {
mock_tree_info.note_hash_tree.root, mock_path };
545 expected_end_state.note_hash_tree = { int_state.root + 2 * note_hash_leaf_values.size(),
546 int_state.next_available_leaf_index + note_hash_leaf_values.size() };
550 .WillOnce(testing::Return(expected_end_state));
551 EXPECT_CALL(
base_merkle_db, append_leaves(world_state::MerkleTreeId::NOTE_HASH_TREE, testing::_))
554 for (
const auto& leaf : leaves) {
555 results.push_back(mock_append_internal(world_state::MerkleTreeId::NOTE_HASH_TREE, leaf));
561 hinting_merkle_db.append_leaves(world_state::MerkleTreeId::NOTE_HASH_TREE, note_hash_leaf_values);
562 ExecutionHints collected_hints;
567 for (
const auto& leaf : note_hash_leaf_values) {
568 AppendOnlyTreeSnapshot state_after = { int_state.root + 2, int_state.next_available_leaf_index + 1 };
569 expected_append_hints.push_back(AppendLeavesHint{ .hint_key = int_state,
570 .state_after = state_after,
571 .tree_id = world_state::MerkleTreeId::NOTE_HASH_TREE,
572 .leaves = { leaf } });
573 expected_sibling_hints.push_back(GetSiblingPathHint{ .hint_key = state_after,
574 .tree_id = world_state::MerkleTreeId::NOTE_HASH_TREE,
575 .index = int_state.next_available_leaf_index,
576 .path = mock_path });
577 int_state = state_after;
581 EXPECT_EQ(collected_hints.append_leaves_hints.size(), note_hash_leaf_values.size());
582 EXPECT_EQ(collected_hints.get_sibling_path_hints.size(), note_hash_leaf_values.size());
583 EXPECT_THAT(collected_hints.append_leaves_hints, testing::ElementsAreArray(expected_append_hints));
584 EXPECT_THAT(collected_hints.get_sibling_path_hints, testing::ElementsAreArray(expected_sibling_hints));
587TEST_F(MockedHintingDBsTest, MerkleDBCheckpoints)
589 uint32_t mock_checkpoint_id = 0;
591 .WillOnce(testing::Return(mock_checkpoint_id))
592 .WillOnce(testing::Return(++mock_checkpoint_id))
593 .WillOnce(testing::Return(mock_checkpoint_id))
594 .WillOnce(testing::Return(++mock_checkpoint_id));
602 .WillOnce(testing::Return(mock_checkpoint_id))
603 .WillOnce(testing::Return(--mock_checkpoint_id));
611 .WillOnce(testing::Return(mock_checkpoint_id))
612 .WillOnce(testing::Return(--mock_checkpoint_id));
615 ExecutionHints collected_hints;
619 EXPECT_EQ(collected_hints.create_checkpoint_hints.size(), 2);
620 EXPECT_EQ(collected_hints.commit_checkpoint_hints.size(), 1);
621 EXPECT_EQ(collected_hints.revert_checkpoint_hints.size(), 1);
622 mock_checkpoint_id = 0;
623 uint32_t mock_action_counter = 0;
624 EXPECT_THAT(collected_hints.create_checkpoint_hints,
625 testing::ElementsAreArray({ CreateCheckpointHint{
626 .action_counter = mock_action_counter++,
627 .old_checkpoint_id = mock_checkpoint_id,
628 .new_checkpoint_id = ++mock_checkpoint_id,
630 CreateCheckpointHint{
631 .action_counter = mock_action_counter++,
632 .old_checkpoint_id = mock_checkpoint_id,
633 .new_checkpoint_id = ++mock_checkpoint_id,
635 EXPECT_THAT(collected_hints.commit_checkpoint_hints,
636 testing::ElementsAre(CommitCheckpointHint{
637 .action_counter = mock_action_counter++,
638 .old_checkpoint_id = mock_checkpoint_id,
639 .new_checkpoint_id = --mock_checkpoint_id,
641 EXPECT_THAT(collected_hints.revert_checkpoint_hints,
642 testing::ElementsAre(RevertCheckpointHint{
643 .action_counter = mock_action_counter++,
644 .old_checkpoint_id = mock_checkpoint_id,
645 .new_checkpoint_id = --mock_checkpoint_id,
646 .state_before = mock_tree_info,
647 .state_after = mock_tree_info,
std::shared_ptr< Napi::ThreadSafeFunction > instance
std::shared_ptr< Napi::ThreadSafeFunction > revert_checkpoint
std::shared_ptr< Napi::ThreadSafeFunction > commit_checkpoint
std::shared_ptr< Napi::ThreadSafeFunction > create_checkpoint
#define NULLIFIER_TREE_HEIGHT
#define NOTE_HASH_TREE_HEIGHT
#define PUBLIC_DATA_TREE_HEIGHT
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
void commit_checkpoint() override
std::optional< FF > get_bytecode_commitment(const ContractClassId &class_id) const override
void create_checkpoint() override
void dump_hints(ExecutionHints &hints)
std::optional< ContractInstance > get_contract_instance(const AztecAddress &address) const override
void create_checkpoint() 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
void commit_checkpoint() override
auto & get_tree_info_helper(world_state::MerkleTreeId tree_id, auto &tree_roots)
HintingContractsDB hinting_contract_db
TreeSnapshots mock_tree_info
HintedRawMerkleDB base_merkle_db
HintingRawDB hinting_merkle_db
HintedRawContractDB base_contract_db
::bb::crypto::merkle_tree::fr_sibling_path SiblingPath
::bb::world_state::MerkleTreeId MerkleTreeId
fr_sibling_path get_sibling_path(TypeOfTree &tree, index_t index, bool includeUncommitted=true, bool expected_success=true)
TEST_F(IPATest, ChallengesAreZero)
std::vector< uint8_t > read_file(const std::string &filename, size_t bytes=0)
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
TreeSnapshots starting_tree_roots
std::vector< GetSiblingPathHint > get_sibling_path_hints
std::vector< DebugFunctionNameHint > debug_function_names
std::vector< ContractDBCreateCheckpointHint > contract_db_create_checkpoint_hints
std::vector< ContractDBCommitCheckpointHint > contract_db_commit_checkpoint_hints
std::vector< CommitCheckpointHint > commit_checkpoint_hints
std::vector< CreateCheckpointHint > create_checkpoint_hints
std::vector< ContractInstanceHint > contract_instances
std::vector< ContractClassHint > contract_classes
std::vector< BytecodeCommitmentHint > bytecode_commitments