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
5
6namespace bb::avm2::simulation {
7
12
14 const NullifierTreeLeafPreimage& low_leaf_preimage,
15 bool exists)
16{
17 bool low_leaf_matches = low_leaf_preimage.leaf.nullifier == nullifier;
18 if (low_leaf_matches) {
19 if (!exists) {
20 throw std::runtime_error("Nullifier non-membership check failed");
21 }
22 } else {
23 if (!field_gt.ff_gt(nullifier, low_leaf_preimage.leaf.nullifier)) {
24 throw std::runtime_error("Low leaf value is GTE leaf value");
25 }
26 if (low_leaf_preimage.nextKey != 0 && !field_gt.ff_gt(low_leaf_preimage.nextKey, nullifier)) {
27 throw std::runtime_error("Leaf value is GTE low leaf next value");
28 }
29 if (exists) {
30 throw std::runtime_error("Nullifier membership check failed");
31 }
32 }
33}
34
35void NullifierTreeCheck::assert_read(const FF& source_nullifier,
37 bool exists,
38 const NullifierTreeLeafPreimage& low_leaf_preimage,
39 uint64_t low_leaf_index,
40 std::span<const FF> sibling_path,
41 const AppendOnlyTreeSnapshot& snapshot)
42{
43 FF nullifier = source_nullifier;
45 if (contract_address.has_value()) {
47 siloing_data = NullifierSiloingData{ .siloed_nullifier = nullifier, .address = contract_address.value() };
48 }
49 // Low leaf membership
50 FF low_leaf_hash = poseidon2.hash(low_leaf_preimage.get_hash_inputs());
51 merkle_check.assert_membership(low_leaf_hash, low_leaf_index, sibling_path, snapshot.root);
52
53 // Low leaf and value validation
54 validate_low_leaf(nullifier, low_leaf_preimage, exists);
55
57 .nullifier = source_nullifier,
58 .prev_snapshot = snapshot,
59 .next_snapshot = snapshot,
60 .low_leaf_preimage = low_leaf_preimage,
61 .low_leaf_hash = low_leaf_hash,
62 .low_leaf_index = low_leaf_index,
63 .siloing_data = siloing_data,
64 });
65}
66
69 uint64_t nullifier_counter,
70 const NullifierTreeLeafPreimage& low_leaf_preimage,
71 uint64_t low_leaf_index,
72 std::span<const FF> low_leaf_sibling_path,
73 const AppendOnlyTreeSnapshot& prev_snapshot,
74 std::optional<std::span<const FF>> insertion_sibling_path)
75{
76 FF nullifier = source_nullifier;
78 if (contract_address.has_value()) {
80 siloing_data = NullifierSiloingData{ .siloed_nullifier = nullifier, .address = contract_address.value() };
81 }
82 bool exists = !insertion_sibling_path.has_value();
83
84 // Low leaf validation
85 validate_low_leaf(nullifier, low_leaf_preimage, exists);
86
87 AppendOnlyTreeSnapshot next_snapshot = prev_snapshot;
89
90 FF low_leaf_hash = poseidon2.hash(low_leaf_preimage.get_hash_inputs());
91
92 if (exists) {
93 merkle_check.assert_membership(low_leaf_hash, low_leaf_index, low_leaf_sibling_path, prev_snapshot.root);
94 } else {
95 // Low leaf update
96 NullifierTreeLeafPreimage updated_low_leaf_preimage = low_leaf_preimage;
97 updated_low_leaf_preimage.nextIndex = prev_snapshot.nextAvailableLeafIndex;
98 updated_low_leaf_preimage.nextKey = nullifier;
99 FF updated_low_leaf_hash = poseidon2.hash(updated_low_leaf_preimage.get_hash_inputs());
100
101 FF intermediate_root = merkle_check.write(
102 low_leaf_hash, updated_low_leaf_hash, low_leaf_index, low_leaf_sibling_path, prev_snapshot.root);
103
104 // Insertion
106 NullifierLeafValue(nullifier), low_leaf_preimage.nextIndex, low_leaf_preimage.nextKey);
107
108 FF new_leaf_hash = poseidon2.hash(new_leaf_preimage.get_hash_inputs());
109
110 FF write_root = merkle_check.write(FF(0),
111 new_leaf_hash,
112 prev_snapshot.nextAvailableLeafIndex,
113 insertion_sibling_path.value(),
114 intermediate_root);
115
116 next_snapshot = AppendOnlyTreeSnapshot{
117 .root = write_root,
118 .nextAvailableLeafIndex = prev_snapshot.nextAvailableLeafIndex + 1,
119 };
120 append_data = NullifierAppendData{
121 .updated_low_leaf_hash = updated_low_leaf_hash,
122 .new_leaf_hash = new_leaf_hash,
123 .intermediate_root = intermediate_root,
124 };
125 }
126
128 .prev_snapshot = prev_snapshot,
129 .next_snapshot = next_snapshot,
130 .low_leaf_preimage = low_leaf_preimage,
131 .low_leaf_hash = low_leaf_hash,
132 .low_leaf_index = low_leaf_index,
133 .write = true,
134 .siloing_data = siloing_data,
135 .nullifier_counter = nullifier_counter,
136 .append_data = append_data });
137
138 return next_snapshot;
139}
140
145
150
155
156} // namespace bb::avm2::simulation
#define GENERATOR_INDEX__OUTER_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)
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
FF silo_nullifier(const FF &nullifier, AztecAddress contract_address)
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
EventEmitterInterface< NullifierTreeCheckEvent > & events
static FF hash(const std::vector< FF > &input)
Hashes a vector of field elements.
::bb::crypto::merkle_tree::NullifierLeafValue NullifierLeafValue
IndexedLeaf< NullifierLeafValue > NullifierTreeLeafPreimage
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