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
23void MerkleCheck::assert_membership(uint64_t domain_separator,
24 const FF& leaf_value,
25 uint64_t leaf_index,
26 std::span<const FF> sibling_path,
27 const FF& root)
28{
29 // Gadget breaks if tree_height > 64 (leaf_index is of type uint64_t)
30 BB_ASSERT_LTE(sibling_path.size(), static_cast<size_t>(64), "Merkle path length must be less than or equal to 64");
31
32 FF curr_value = leaf_value;
33 uint64_t curr_index = leaf_index;
34 for (const auto& sibling : sibling_path) {
35 bool index_is_even = (curr_index % 2 == 0);
36
37 curr_value = index_is_even ? poseidon2.hash({ FF(domain_separator), curr_value, sibling })
38 : poseidon2.hash({ FF(domain_separator), sibling, curr_value });
39
40 // Halve the index (to get the parent index) as we move up the tree.
41 curr_index >>= 1;
42 }
43
44 if (curr_index != 0) {
45 throw std::runtime_error("Merkle check's final node index must be 0");
46 }
47 if (curr_value != root) {
48 throw std::runtime_error("Merkle read check failed");
49 }
50
51 std::vector<FF> sibling_vec(sibling_path.begin(), sibling_path.end());
52 events.emit({
53 .merkle_hash_domain_separator = domain_separator,
54 .leaf_value = leaf_value,
55 .leaf_index = leaf_index,
56 .sibling_path = std::move(sibling_vec),
57 .root = root,
58 });
59}
60
78FF MerkleCheck::write(uint64_t domain_separator,
79 const FF& current_value,
80 const FF& new_value,
81 uint64_t leaf_index,
82 std::span<const FF> sibling_path,
83 const FF& current_root)
84{
85 // Gadget breaks if tree_height > 64 (leaf_index is of type uint64_t)
86 BB_ASSERT_LTE(sibling_path.size(), static_cast<size_t>(64), "Merkle path length must be less than or equal to 64");
87
88 FF read_value = current_value;
89 FF write_value = new_value;
90 uint64_t curr_index = leaf_index;
91
92 for (const auto& sibling : sibling_path) {
93 bool index_is_even = (curr_index % 2 == 0);
94
95 read_value = index_is_even ? poseidon2.hash({ FF(domain_separator), read_value, sibling })
96 : poseidon2.hash({ FF(domain_separator), sibling, read_value });
97 write_value = index_is_even ? poseidon2.hash({ FF(domain_separator), write_value, sibling })
98 : poseidon2.hash({ FF(domain_separator), sibling, write_value });
99
100 // Halve the index (to get the parent index) as we move up the tree.
101 curr_index >>= 1;
102 }
103
104 if (curr_index != 0) {
105 throw std::runtime_error("Merkle check's final node index must be 0");
106 }
107 if (read_value != current_root) {
108 throw std::runtime_error("Merkle read check failed");
109 }
110
111 std::vector<FF> sibling_vec(sibling_path.begin(), sibling_path.end());
112 events.emit({
113 .merkle_hash_domain_separator = domain_separator,
114 .leaf_value = current_value,
115 .new_leaf_value = new_value,
116 .leaf_index = leaf_index,
117 .sibling_path = std::move(sibling_vec),
118 .root = current_root,
119 .new_root = write_value,
120 });
121
122 return write_value;
123}
124
125} // namespace bb::avm2::simulation
#define BB_ASSERT_LTE(left, right,...)
Definition assert.hpp:158
FF write(uint64_t domain_separator, const FF &current_value, const FF &new_value, 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())....
EventEmitterInterface< MerkleCheckEvent > & events
void assert_membership(uint64_t domain_separator, const FF &leaf_value, 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,...
static FF hash(const std::vector< FF > &input)
Hashes a vector of field elements.
AVM range check gadget for witness generation.
AvmFlavorSettings::FF FF
Definition field.hpp:10
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13