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 <stdexcept>
5#include <vector>
6
7namespace bb::avm2::simulation {
8
22void MerkleCheck::assert_membership(const FF& leaf_value,
23 const uint64_t leaf_index,
24 std::span<const FF> sibling_path,
25 const FF& root)
26{
27 // Gadget breaks if tree_height > 64 (leaf_index is of type uint64_t)
28 assert(sibling_path.size() <= 64 && "Merkle path length must be less than or equal to 64");
29
30 FF curr_value = leaf_value;
31 uint64_t curr_index = leaf_index;
32 for (const auto& sibling : sibling_path) {
33 bool index_is_even = (curr_index % 2 == 0);
34
35 curr_value = index_is_even ? poseidon2.hash({ curr_value, sibling }) : poseidon2.hash({ sibling, curr_value });
36
37 // Halve the index (to get the parent index) as we move up the tree.
38 curr_index >>= 1;
39 }
40
41 if (curr_index != 0) {
42 throw std::runtime_error("Merkle check's final node index must be 0");
43 }
44 if (curr_value != root) {
45 throw std::runtime_error("Merkle read check failed");
46 }
47
48 std::vector<FF> sibling_vec(sibling_path.begin(), sibling_path.end());
49 events.emit({
50 .leaf_value = leaf_value,
51 .leaf_index = leaf_index,
52 .sibling_path = std::move(sibling_vec),
53 .root = root,
54 });
55}
56
73FF MerkleCheck::write(const FF& current_value,
74 const FF& new_value,
75 const uint64_t leaf_index,
76 std::span<const FF> sibling_path,
77 const FF& current_root)
78{
79 // Gadget breaks if tree_height > 64 (leaf_index is of type uint64_t)
80 assert(sibling_path.size() <= 64 && "Merkle path length must be less than or equal to 64");
81
82 FF read_value = current_value;
83 FF write_value = new_value;
84 uint64_t curr_index = leaf_index;
85
86 for (const auto& sibling : sibling_path) {
87 bool index_is_even = (curr_index % 2 == 0);
88
89 read_value = index_is_even ? poseidon2.hash({ read_value, sibling }) : poseidon2.hash({ sibling, read_value });
90 write_value =
91 index_is_even ? poseidon2.hash({ write_value, sibling }) : poseidon2.hash({ sibling, write_value });
92
93 // Halve the index (to get the parent index) as we move up the tree.
94 curr_index >>= 1;
95 }
96
97 if (curr_index != 0) {
98 throw std::runtime_error("Merkle check's final node index must be 0");
99 }
100 if (read_value != current_root) {
101 throw std::runtime_error("Merkle read check failed");
102 }
103
104 std::vector<FF> sibling_vec(sibling_path.begin(), sibling_path.end());
105 events.emit({
106 .leaf_value = current_value,
107 .new_leaf_value = new_value,
108 .leaf_index = leaf_index,
109 .sibling_path = std::move(sibling_vec),
110 .root = current_root,
111 .new_root = write_value,
112 });
113
114 return write_value;
115}
116
117} // 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
Assert the membership of the current leaf value (same logic as assert_membership())....
void assert_membership(const FF &leaf_value, const uint64_t leaf_index, std::span< const FF > sibling_path, const FF &root) override
Assert membership of a leaf in a Merkle tree, i.e., verify that the leaf value, leaf index,...
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