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(low_leaf_hash, low_leaf_index, sibling_path, snapshot.root);
97
98 // Low leaf and value validation
99 validate_low_leaf(value, low_leaf_preimage, exists);
100
102 .value = source_value,
103 .prev_snapshot = snapshot,
104 .next_snapshot = snapshot,
105 .tree_height = sibling_path.size(),
106 .low_leaf_data = low_leaf_preimage,
107 .low_leaf_hash = low_leaf_hash,
108 .low_leaf_index = low_leaf_index,
109 .siloing_data = siloing_data,
110 });
111}
112
139 std::optional<uint64_t> public_inputs_index,
140 const IndexedTreeLeafData& low_leaf_preimage,
141 uint64_t low_leaf_index,
142 std::span<const FF> low_leaf_sibling_path,
143 const AppendOnlyTreeSnapshot& prev_snapshot,
144 std::optional<std::span<const FF>> insertion_sibling_path)
145{
146 FF value = source_value;
148 if (siloing_params.has_value()) {
149 value = silo(value, siloing_params.value());
150 siloing_data = IndexedLeafSiloingData{ .siloed_value = value, .parameters = siloing_params.value() };
151 }
152 bool exists = !insertion_sibling_path.has_value();
153
154 // Low leaf validation
155 validate_low_leaf(value, low_leaf_preimage, exists);
156
157 AppendOnlyTreeSnapshot next_snapshot = prev_snapshot;
159
160 FF low_leaf_hash = poseidon2.hash(low_leaf_preimage.get_hash_inputs());
161
162 if (exists) {
163 merkle_check.assert_membership(low_leaf_hash, low_leaf_index, low_leaf_sibling_path, prev_snapshot.root);
164 } else {
165 // Low leaf update
166 IndexedTreeLeafData updated_low_leaf_preimage = low_leaf_preimage;
167 updated_low_leaf_preimage.next_index = prev_snapshot.next_available_leaf_index;
168 updated_low_leaf_preimage.next_value = value;
169 FF updated_low_leaf_hash = poseidon2.hash(updated_low_leaf_preimage.get_hash_inputs());
170
171 FF intermediate_root = merkle_check.write(
172 low_leaf_hash, updated_low_leaf_hash, low_leaf_index, low_leaf_sibling_path, prev_snapshot.root);
173
174 // Insertion
175 IndexedTreeLeafData new_leaf_preimage = {
176 .value = value,
177 .next_value = low_leaf_preimage.next_value,
178 .next_index = low_leaf_preimage.next_index,
179 };
180
181 FF new_leaf_hash = poseidon2.hash(new_leaf_preimage.get_hash_inputs());
182
183 FF write_root = merkle_check.write(FF(0),
184 new_leaf_hash,
185 prev_snapshot.next_available_leaf_index,
186 insertion_sibling_path.value(),
187 intermediate_root);
188
189 next_snapshot = AppendOnlyTreeSnapshot{
190 .root = write_root,
191 .next_available_leaf_index = prev_snapshot.next_available_leaf_index + 1,
192 };
193 append_data = IndexedLeafAppendData{
194 .updated_low_leaf_hash = updated_low_leaf_hash,
195 .new_leaf_hash = new_leaf_hash,
196 .intermediate_root = intermediate_root,
197 };
198 }
199
201 .prev_snapshot = prev_snapshot,
202 .next_snapshot = next_snapshot,
203 .tree_height = low_leaf_sibling_path.size(),
204 .low_leaf_data = low_leaf_preimage,
205 .low_leaf_hash = low_leaf_hash,
206 .low_leaf_index = low_leaf_index,
207 .write = true,
208 .siloing_data = siloing_data,
209 .public_inputs_index = public_inputs_index,
210 .append_data = append_data });
211
212 return next_snapshot;
213}
214
220
226
232
233} // 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