Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
nullifier_tree_check.cpp
Go to the documentation of this file.
2
4
5#include <stdexcept>
6
7namespace bb::avm2::simulation {
8
23
42 const NullifierTreeLeafPreimage& low_leaf_preimage,
43 bool exists)
44{
45 bool low_leaf_matches = low_leaf_preimage.leaf.nullifier == nullifier;
46 // We base the checking on whether the low leaf matches instead of exists, to match PIL behavior.
47 if (low_leaf_matches) {
48 if (!exists) {
49 throw std::runtime_error("Nullifier non-membership check failed");
50 }
51 } else {
52 if (!field_gt.ff_gt(nullifier, low_leaf_preimage.leaf.nullifier)) {
53 throw std::runtime_error("Low leaf value is GTE leaf value");
54 }
55 if (low_leaf_preimage.nextKey != 0 && !field_gt.ff_gt(low_leaf_preimage.nextKey, nullifier)) {
56 throw std::runtime_error("Leaf value is GTE low leaf next value");
57 }
58 if (exists) {
59 throw std::runtime_error("Nullifier membership check failed");
60 }
61 }
62}
63
83void NullifierTreeCheck::assert_read(const FF& source_nullifier,
85 bool exists,
86 const NullifierTreeLeafPreimage& low_leaf_preimage,
87 uint64_t low_leaf_index,
88 std::span<const FF> sibling_path,
89 const AppendOnlyTreeSnapshot& snapshot)
90{
91 FF nullifier = source_nullifier;
93 if (contract_address.has_value()) {
95 siloing_data = NullifierSiloingData{ .siloed_nullifier = nullifier, .address = contract_address.value() };
96 }
97 // Low leaf membership
98 FF low_leaf_hash = poseidon2.hash(low_leaf_preimage.get_hash_inputs());
99 merkle_check.assert_membership(low_leaf_hash, low_leaf_index, sibling_path, snapshot.root);
100
101 // Low leaf and value validation
102 validate_low_leaf(nullifier, low_leaf_preimage, exists);
103
105 .nullifier = source_nullifier,
106 .prev_snapshot = snapshot,
107 .next_snapshot = snapshot,
108 .low_leaf_preimage = 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
142 uint64_t nullifier_counter,
143 const NullifierTreeLeafPreimage& low_leaf_preimage,
144 uint64_t low_leaf_index,
145 std::span<const FF> low_leaf_sibling_path,
146 const AppendOnlyTreeSnapshot& prev_snapshot,
147 std::optional<std::span<const FF>> insertion_sibling_path)
148{
149 FF nullifier = source_nullifier;
151 if (contract_address.has_value()) {
153 siloing_data = NullifierSiloingData{ .siloed_nullifier = nullifier, .address = contract_address.value() };
154 }
155 bool exists = !insertion_sibling_path.has_value();
156
157 // Low leaf validation
158 validate_low_leaf(nullifier, low_leaf_preimage, exists);
159
160 AppendOnlyTreeSnapshot next_snapshot = prev_snapshot;
162
163 FF low_leaf_hash = poseidon2.hash(low_leaf_preimage.get_hash_inputs());
164
165 if (exists) {
166 merkle_check.assert_membership(low_leaf_hash, low_leaf_index, low_leaf_sibling_path, prev_snapshot.root);
167 } else {
168 // Low leaf update
169 NullifierTreeLeafPreimage updated_low_leaf_preimage = low_leaf_preimage;
170 updated_low_leaf_preimage.nextIndex = prev_snapshot.next_available_leaf_index;
171 updated_low_leaf_preimage.nextKey = nullifier;
172 FF updated_low_leaf_hash = poseidon2.hash(updated_low_leaf_preimage.get_hash_inputs());
173
174 FF intermediate_root = merkle_check.write(
175 low_leaf_hash, updated_low_leaf_hash, low_leaf_index, low_leaf_sibling_path, prev_snapshot.root);
176
177 // Insertion
179 NullifierLeafValue(nullifier), low_leaf_preimage.nextIndex, low_leaf_preimage.nextKey);
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 = NullifierAppendData{
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 .low_leaf_preimage = low_leaf_preimage,
204 .low_leaf_hash = low_leaf_hash,
205 .low_leaf_index = low_leaf_index,
206 .write = true,
207 .siloing_data = siloing_data,
208 .nullifier_counter = nullifier_counter,
209 .append_data = append_data });
210
211 return next_snapshot;
212}
213
219
225
231
232} // namespace bb::avm2::simulation
#define DOM_SEP__SILOED_NULLIFIER
virtual void emit(Event &&event)=0
virtual bool ff_gt(const FF &a, const FF &b)=0
void validate_low_leaf(const FF &nullifier, const NullifierTreeLeafPreimage &low_leaf_preimage, bool exists)
Validates the low leaf preimage against the nullifier for membership/non-membership checks.
void on_checkpoint_committed() override
Emits a checkpoint commit event, finalizing pending nullifier tree changes.
AppendOnlyTreeSnapshot write(const FF &nullifier, std::optional< AztecAddress > contract_address, uint64_t nullifier_counter, const NullifierTreeLeafPreimage &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
Inserts a nullifier into the nullifier tree or verifies it already exists.
FF silo_nullifier(const FF &nullifier, AztecAddress contract_address)
Computes the siloed nullifier by hashing the contract address with the nullifier.
void assert_read(const FF &nullifier, std::optional< AztecAddress > contract_address, bool exists, const NullifierTreeLeafPreimage &low_leaf_preimage, uint64_t low_leaf_index, std::span< const FF > sibling_path, const AppendOnlyTreeSnapshot &snapshot) override
Performs a nullifier membership/non-membership check on the nullifier tree.
void on_checkpoint_reverted() override
Emits a checkpoint revert event, rolling back pending nullifier tree changes.
EventEmitterInterface< NullifierTreeCheckEvent > & events
void on_checkpoint_created() override
Emits a checkpoint creation event for the nullifier tree.
static FF hash(const std::vector< FF > &input)
Hashes a vector of field elements.
AVM range check gadget for witness generation.
crypto::merkle_tree::IndexedLeaf< crypto::merkle_tree::NullifierLeafValue > NullifierTreeLeafPreimage
Definition db_types.hpp:12
::bb::crypto::merkle_tree::NullifierLeafValue NullifierLeafValue
Definition db.hpp:39
AvmFlavorSettings::FF FF
Definition field.hpp:10
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
std::vector< fr > get_hash_inputs() const