Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
merkle_check.cpp
Go to the documentation of this file.
2
3#include <cassert>
4#include <cstdint>
5
7
8namespace bb::avm2::simulation {
9
10void MerkleCheck::assert_membership(const FF& leaf_value,
11 const uint64_t leaf_index,
12 std::span<const FF> sibling_path,
13 const FF& root)
14{
15 // Gadget breaks if tree_height > 64
16 assert(sibling_path.size() <= 64 && "Merkle path length must be less than or equal to 64");
17
18 FF curr_value = leaf_value;
19 uint64_t curr_index = leaf_index;
20 for (const auto& sibling : sibling_path) {
21 bool index_is_even = (curr_index % 2 == 0);
22
23 curr_value = index_is_even ? poseidon2.hash({ curr_value, sibling }) : poseidon2.hash({ sibling, curr_value });
24
25 // Halve the index (to get the parent index) as we move up the tree.
26 curr_index >>= 1;
27 }
28
29 if (curr_index != 0) {
30 throw std::runtime_error("Merkle check's final node index must be 0");
31 }
32 if (curr_value != root) {
33 throw std::runtime_error("Merkle read check failed");
34 }
35
36 std::vector<FF> sibling_vec(sibling_path.begin(), sibling_path.end());
37 events.emit(
38 { .leaf_value = leaf_value, .leaf_index = leaf_index, .sibling_path = std::move(sibling_vec), .root = root });
39}
40
41FF MerkleCheck::write(const FF& current_value,
42 const FF& new_value,
43 const uint64_t leaf_index,
44 std::span<const FF> sibling_path,
45 const FF& current_root)
46{
47 // Gadget breaks if tree_height > 64
48 assert(sibling_path.size() <= 64 && "Merkle path length must be less than or equal to 64");
49
50 FF read_value = current_value;
51 FF write_value = new_value;
52 uint64_t curr_index = leaf_index;
53
54 for (const auto& sibling : sibling_path) {
55 bool index_is_even = (curr_index % 2 == 0);
56
57 read_value = index_is_even ? poseidon2.hash({ read_value, sibling }) : poseidon2.hash({ sibling, read_value });
58 write_value =
59 index_is_even ? poseidon2.hash({ write_value, sibling }) : poseidon2.hash({ sibling, write_value });
60
61 // Halve the index (to get the parent index) as we move up the tree.
62 curr_index >>= 1;
63 }
64
65 if (curr_index != 0) {
66 throw std::runtime_error("Merkle check's final node index must be 0");
67 }
68 if (read_value != current_root) {
69 throw std::runtime_error("Merkle read check failed");
70 }
71
72 std::vector<FF> sibling_vec(sibling_path.begin(), sibling_path.end());
73 events.emit({ .leaf_value = current_value,
74 .new_leaf_value = new_value,
75 .leaf_index = leaf_index,
76 .sibling_path = std::move(sibling_vec),
77 .root = current_root,
78 .new_root = write_value });
79
80 return write_value;
81}
82
83} // namespace bb::avm2::simulation
FF write(const FF &current_value, const FF &new_value, const uint64_t leaf_index, std::span< const FF > sibling_path, const FF &current_root) override
void assert_membership(const FF &leaf_value, const uint64_t leaf_index, std::span< const FF > sibling_path, const FF &root) override
EventEmitterInterface< MerkleCheckEvent > & events
static FF hash(const std::vector< FF > &input)
Hashes a vector of field elements.
AvmFlavorSettings::FF FF
Definition field.hpp:10
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13