Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
indexed_tree_check.cpp
Go to the documentation of this file.
2
3#include <stdexcept>
4
5namespace bb::avm2::simulation {
6
17{
18 return poseidon2.hash({ siloing_params.siloing_separator, siloing_params.address, value });
19}
20
38void IndexedTreeCheck::validate_low_leaf(const FF& value, const IndexedTreeLeafData& low_leaf_preimage, bool exists)
39{
40 bool low_leaf_matches = low_leaf_preimage.value == value;
41 // We base the checking on whether the low leaf matches instead of exists, to match PIL behavior.
42 if (low_leaf_matches) {
43 if (!exists) {
44 throw std::runtime_error("Indexed tree non-membership check failed");
45 }
46 } else {
47 if (!field_gt.ff_gt(value, low_leaf_preimage.value)) {
48 throw std::runtime_error("Low leaf value is GTE leaf value");
49 }
50 if (low_leaf_preimage.next_value != 0 && !field_gt.ff_gt(low_leaf_preimage.next_value, value)) {
51 throw std::runtime_error("Leaf value is GTE low leaf next value");
52 }
53 if (exists) {
54 throw std::runtime_error("Indexed tree membership check failed");
55 }
56 }
57}
58
77void IndexedTreeCheck::assert_read(const FF& source_value,
79 bool exists,
80 const IndexedTreeLeafData& low_leaf_preimage,
81 uint64_t low_leaf_index,
82 std::span<const FF> sibling_path,
83 const AppendOnlyTreeSnapshot& snapshot)
84{
85 FF value = source_value;
87 if (siloing_params.has_value()) {
88 value = silo(value, siloing_params.value());
89 siloing_data = IndexedLeafSiloingData{
91 .parameters = siloing_params.value(),
92 };
93 }
94 // Low leaf membership
95 FF low_leaf_hash = poseidon2.hash(low_leaf_preimage.get_hash_inputs());
96 merkle_check.assert_membership(
97 merkle_hash_domain_separator, low_leaf_hash, low_leaf_index, sibling_path, snapshot.root);
98
99 // Low leaf and value validation
100 validate_low_leaf(value, low_leaf_preimage, exists);
101
103 .value = source_value,
104 .prev_snapshot = snapshot,
105 .next_snapshot = snapshot,
106 .tree_height = sibling_path.size(),
107 .merkle_hash_separator = FF(merkle_hash_domain_separator),
108 .low_leaf_data = low_leaf_preimage,
109 .low_leaf_hash = low_leaf_hash,
110 .low_leaf_index = low_leaf_index,
111 .siloing_data = siloing_data,
112 });
113}
114
141 std::optional<uint64_t> public_inputs_index,
142 const IndexedTreeLeafData& low_leaf_preimage,
143 uint64_t low_leaf_index,
144 std::span<const FF> low_leaf_sibling_path,
145 const AppendOnlyTreeSnapshot& prev_snapshot,
146 std::optional<std::span<const FF>> insertion_sibling_path)
147{
148 FF value = source_value;
150 if (siloing_params.has_value()) {
151 value = silo(value, siloing_params.value());
152 siloing_data = IndexedLeafSiloingData{ .siloed_value = value, .parameters = siloing_params.value() };
153 }
154 bool exists = !insertion_sibling_path.has_value();
155
156 // Low leaf validation
157 validate_low_leaf(value, low_leaf_preimage, exists);
158
159 AppendOnlyTreeSnapshot next_snapshot = prev_snapshot;
161
162 FF low_leaf_hash = poseidon2.hash(low_leaf_preimage.get_hash_inputs());
163
164 if (exists) {
165 merkle_check.assert_membership(
166 merkle_hash_domain_separator, low_leaf_hash, low_leaf_index, low_leaf_sibling_path, prev_snapshot.root);
167 } else {
168 // Low leaf update
169 IndexedTreeLeafData updated_low_leaf_preimage = low_leaf_preimage;
170 updated_low_leaf_preimage.next_index = prev_snapshot.next_available_leaf_index;
171 updated_low_leaf_preimage.next_value = value;
172 FF updated_low_leaf_hash = poseidon2.hash(updated_low_leaf_preimage.get_hash_inputs());
173
174 FF intermediate_root = merkle_check.write(merkle_hash_domain_separator,
175 low_leaf_hash,
176 updated_low_leaf_hash,
177 low_leaf_index,
178 low_leaf_sibling_path,
179 prev_snapshot.root);
180
181 // Insertion
182 IndexedTreeLeafData new_leaf_preimage = {
183 .value = value,
184 .next_value = low_leaf_preimage.next_value,
185 .next_index = low_leaf_preimage.next_index,
186 };
187
188 FF new_leaf_hash = poseidon2.hash(new_leaf_preimage.get_hash_inputs());
189
191 FF(0),
192 new_leaf_hash,
193 prev_snapshot.next_available_leaf_index,
194 insertion_sibling_path.value(),
195 intermediate_root);
196
197 next_snapshot = AppendOnlyTreeSnapshot{
198 .root = write_root,
199 .next_available_leaf_index = prev_snapshot.next_available_leaf_index + 1,
200 };
201 append_data = IndexedLeafAppendData{
202 .updated_low_leaf_hash = updated_low_leaf_hash,
203 .new_leaf_hash = new_leaf_hash,
204 .intermediate_root = intermediate_root,
205 };
206 }
207
209 .prev_snapshot = prev_snapshot,
210 .next_snapshot = next_snapshot,
211 .tree_height = low_leaf_sibling_path.size(),
212 .merkle_hash_separator = FF(merkle_hash_domain_separator),
213 .low_leaf_data = low_leaf_preimage,
214 .low_leaf_hash = low_leaf_hash,
215 .low_leaf_index = low_leaf_index,
216 .write = true,
217 .siloing_data = siloing_data,
218 .public_inputs_index = public_inputs_index,
219 .append_data = append_data });
220
221 return next_snapshot;
222}
223
229
235
241
242} // namespace bb::avm2::simulation
virtual void emit(Event &&event)=0
virtual bool ff_gt(const FF &a, const FF &b)=0
void on_checkpoint_committed() override
Emits a checkpoint commit event, finalizing pending indexed tree changes.
void assert_read(const FF &value, std::optional< IndexedTreeSiloingParameters > siloing_params, bool exists, const IndexedTreeLeafData &low_leaf_preimage, uint64_t low_leaf_index, std::span< const FF > sibling_path, const AppendOnlyTreeSnapshot &snapshot) override
Performs a membership/non-membership read check on an indexed tree.
void on_checkpoint_created() override
Emits a checkpoint creation event for the indexed tree.
void validate_low_leaf(const FF &value, const IndexedTreeLeafData &low_leaf_preimage, bool exists)
Validates the low leaf preimage against the target value for membership/non-membership.
EventEmitterInterface< IndexedTreeCheckEvent > & events
void on_checkpoint_reverted() override
Emits a checkpoint revert event, rolling back pending indexed tree changes.
AppendOnlyTreeSnapshot write(const FF &value, std::optional< IndexedTreeSiloingParameters > siloing_params, std::optional< uint64_t > public_inputs_index, const IndexedTreeLeafData &low_leaf_preimage, uint64_t low_leaf_index, std::span< const FF > low_leaf_sibling_path, const AppendOnlyTreeSnapshot &prev_snapshot, std::optional< std::span< const FF > > insertion_sibling_path) override
Writes a value into an indexed tree, or validates it already exists.
FF silo(const FF &nullifier, IndexedTreeSiloingParameters siloing_params)
Computes the siloed value by hashing the separator, address, and value via Poseidon2.
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