Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
concrete_dbs.cpp
Go to the documentation of this file.
5
6namespace bb::avm2::simulation {
7
8// Contracts DB starts.
10{
12 // If we didn't get a contract instance, we don't prove anything.
13 // It is the responsibility of the caller to prove what the protocol expects.
14 if (!instance.has_value()) {
15 return std::nullopt;
16 }
17 // If we did get a contract instance, we need to prove that the address is derived from the instance.
18 address_derivation.assert_derivation(address, instance.value());
19 return instance;
20}
21
23{
25 // If we didn't get a contract class, we don't prove anything.
26 // It is the responsibility of the caller to prove what the protocol expects.
27 if (!klass.has_value()) {
28 return std::nullopt;
29 }
30 // If we did get a contract class, we need to prove that the class_id is derived from the class.
31 class_id_derivation.assert_derivation(class_id, klass.value());
32 return klass;
33}
34
35// Merkle DB starts.
36
38{
39 // No event generated.
41 TreeCounters tree_counters = tree_counters_stack.top();
42 return {
43 .noteHashTree = { .tree = tree_snapshots.noteHashTree, .counter = tree_counters.note_hash_counter },
44 .nullifierTree = { .tree = tree_snapshots.nullifierTree, .counter = tree_counters.nullifier_counter },
45 .l1ToL2MessageTree = { .tree = tree_snapshots.l1ToL2MessageTree,
46 .counter = tree_counters.l2_to_l1_msg_counter },
47 .publicDataTree = { .tree = tree_snapshots.publicDataTree, .counter = written_public_data_slots.size() },
48 };
49}
50
52{
53 auto [present, index] = raw_merkle_db.get_low_indexed_leaf(MerkleTreeId::PUBLIC_DATA_TREE,
55 auto path = raw_merkle_db.get_sibling_path(MerkleTreeId::PUBLIC_DATA_TREE, index);
57
58 FF value = present ? preimage.leaf.value : 0;
59
62
63 return value;
64}
65
67 const FF& slot,
68 const FF& value,
69 bool is_protocol_write)
70{
73
75
76 auto& low_leaf_hint = hint.low_leaf_witness_data.at(0);
77 auto& insertion_hint = hint.insertion_witness_data.at(0);
78
81 value,
82 low_leaf_hint.leaf,
83 low_leaf_hint.index,
84 low_leaf_hint.path,
85 snapshot_before,
86 insertion_hint.path,
87 is_protocol_write);
88
89 (void)snapshot_after; // Silence unused variable warning when assert is stripped out
90 // Sanity check.
91 assert(snapshot_after == raw_merkle_db.get_tree_roots().publicDataTree);
92 if (!is_protocol_write) {
94 }
95}
96
101
106
108{
109 return nullifier_exists_internal(/*contract_address*/ std::nullopt, nullifier);
110}
111
113{
114 FF siloed_nullifier = nullifier;
115 if (contract_address.has_value()) {
116 // Unconstrained siloing to fetch the hint, since the hints are keyed by siloed data.
117 // The siloing will later be constrained in the nullifier tree check gadget.
118 siloed_nullifier = unconstrained_silo_nullifier(contract_address.value(), nullifier);
119 }
120
121 auto [present, low_leaf_index] = raw_merkle_db.get_low_indexed_leaf(MerkleTreeId::NULLIFIER_TREE, siloed_nullifier);
122 auto low_leaf_path = raw_merkle_db.get_sibling_path(MerkleTreeId::NULLIFIER_TREE, low_leaf_index);
123 auto low_leaf_preimage = raw_merkle_db.get_leaf_preimage_nullifier_tree(low_leaf_index);
124
127 present,
128 low_leaf_preimage,
129 low_leaf_index,
130 low_leaf_path,
132
133 return present;
134}
135
140
142{
143 return nullifier_write_internal(/*contract_address*/ std::nullopt, nullifier);
144}
145
147{
148 uint32_t nullifier_counter = tree_counters_stack.top().nullifier_counter;
149 FF siloed_nullifier = nullifier;
150 if (contract_address.has_value()) {
151 // Unconstrained siloing to fetch the hint, since the hints are keyed by siloed data.
152 // The siloing will later be constrained in the nullifier tree check gadget.
153 siloed_nullifier = unconstrained_silo_nullifier(contract_address.value(), nullifier);
154 }
155
156 auto [present, low_leaf_index] = raw_merkle_db.get_low_indexed_leaf(MerkleTreeId::NULLIFIER_TREE, siloed_nullifier);
158
159 SiblingPath low_leaf_path;
160 IndexedLeaf<NullifierLeafValue> low_leaf_preimage;
162
163 if (present) {
164 low_leaf_path = raw_merkle_db.get_sibling_path(MerkleTreeId::NULLIFIER_TREE, low_leaf_index);
165 low_leaf_preimage = raw_merkle_db.get_leaf_preimage_nullifier_tree(low_leaf_index);
166 } else {
167 auto insertion_result = raw_merkle_db.insert_indexed_leaves_nullifier_tree(siloed_nullifier);
168
169 low_leaf_path = insertion_result.low_leaf_witness_data.at(0).path;
170 low_leaf_preimage = insertion_result.low_leaf_witness_data.at(0).leaf;
171 insertion_path = insertion_result.insertion_witness_data.at(0).path;
172 }
173
176 nullifier_counter,
177 low_leaf_preimage,
178 low_leaf_index,
179 low_leaf_path,
180 snapshot_before,
181 insertion_path);
182
183 (void)snapshot_after; // Silence unused variable warning when assert is stripped out
184 // Sanity check.
185 assert(snapshot_after == raw_merkle_db.get_tree_roots().nullifierTree);
186
187 if (!present) {
188 tree_counters_stack.top().nullifier_counter++;
189 }
190
191 return !present;
192}
193
194bool MerkleDB::note_hash_exists(uint64_t leaf_index, const FF& unique_note_hash) const
195{
196 auto leaf_value = raw_merkle_db.get_leaf_value(MerkleTreeId::NOTE_HASH_TREE, leaf_index);
197 auto path = raw_merkle_db.get_sibling_path(MerkleTreeId::NOTE_HASH_TREE, leaf_index);
198 return note_hash_tree_check.note_hash_exists(
199 unique_note_hash, leaf_value, leaf_index, path, raw_merkle_db.get_tree_roots().noteHashTree);
200}
201
203{
204 uint32_t note_hash_counter = tree_counters_stack.top().note_hash_counter;
205
207 // Unconstrained siloing and uniqueness to fetch the hint, since the hints are keyed by the unique note hash.
208 // The siloing and uniqueness will later be constrained in the note hash tree check gadget.
209 FF siloed_note_hash = unconstrained_silo_note_hash(contract_address, note_hash);
210 FF unique_note_hash = unconstrained_make_unique_note_hash(
211 siloed_note_hash, note_hash_tree_check.get_first_nullifier(), note_hash_counter);
212 auto append_result =
213 raw_merkle_db.append_leaves(MerkleTreeId::NOTE_HASH_TREE, std::vector<FF>{ unique_note_hash })[0];
214
215 AppendOnlyTreeSnapshot snapshot_after = note_hash_tree_check.append_note_hash(
216 note_hash, contract_address, note_hash_counter, append_result.path, snapshot_before);
217
218 (void)snapshot_after; // Silence unused variable warning when assert is stripped out
219 // Sanity check.
220 assert(snapshot_after == raw_merkle_db.get_tree_roots().noteHashTree);
221
222 tree_counters_stack.top().note_hash_counter++;
223}
224
225void MerkleDB::siloed_note_hash_write(const FF& siloed_note_hash)
226{
227
228 uint32_t note_hash_counter = tree_counters_stack.top().note_hash_counter;
230 // Unconstrained siloing and uniqueness to fetch the hint, since the hints are keyed by the unique note hash.
231 // The siloing and uniqueness will later be constrained in the note hash tree check gadget.
232 FF unique_note_hash = unconstrained_make_unique_note_hash(
233 siloed_note_hash, note_hash_tree_check.get_first_nullifier(), note_hash_counter);
234 auto hint = raw_merkle_db.append_leaves(MerkleTreeId::NOTE_HASH_TREE, std::vector<FF>{ unique_note_hash })[0];
235
236 AppendOnlyTreeSnapshot snapshot_after =
237 note_hash_tree_check.append_siloed_note_hash(siloed_note_hash, note_hash_counter, hint.path, snapshot_before);
238
239 (void)snapshot_after; // Silence unused variable warning when assert is stripped out
240 // Sanity check.
241 assert(snapshot_after == raw_merkle_db.get_tree_roots().noteHashTree);
242
243 tree_counters_stack.top().note_hash_counter++;
244}
245
246void MerkleDB::unique_note_hash_write(const FF& unique_note_hash)
247{
248 uint32_t note_hash_counter = tree_counters_stack.top().note_hash_counter;
250 auto hint = raw_merkle_db.append_leaves(MerkleTreeId::NOTE_HASH_TREE, std::vector<FF>{ unique_note_hash })[0];
251
252 AppendOnlyTreeSnapshot snapshot_after =
253 note_hash_tree_check.append_unique_note_hash(unique_note_hash, note_hash_counter, hint.path, snapshot_before);
254
255 (void)snapshot_after; // Silence unused variable warning when assert is stripped out
256 // Sanity check.
257 assert(snapshot_after == raw_merkle_db.get_tree_roots().noteHashTree);
258
259 tree_counters_stack.top().note_hash_counter++;
260}
261
262bool MerkleDB::l1_to_l2_msg_exists(uint64_t leaf_index, const FF& msg_hash) const
263{
264 auto leaf_value = raw_merkle_db.get_leaf_value(MerkleTreeId::L1_TO_L2_MESSAGE_TREE, leaf_index);
265 auto path = raw_merkle_db.get_sibling_path(MerkleTreeId::L1_TO_L2_MESSAGE_TREE, leaf_index);
267 msg_hash, leaf_value, leaf_index, path, raw_merkle_db.get_tree_roots().l1ToL2MessageTree);
268}
269
271{
272 // The public data tree is not padded.
273 raw_merkle_db.pad_tree(MerkleTreeId::NOTE_HASH_TREE,
274 MAX_NOTE_HASHES_PER_TX - tree_counters_stack.top().note_hash_counter);
275 raw_merkle_db.pad_tree(MerkleTreeId::NULLIFIER_TREE,
276 MAX_NULLIFIERS_PER_TX - tree_counters_stack.top().nullifier_counter);
277}
278
280{
284 for (auto& listener : checkpoint_listeners) {
285 listener->on_checkpoint_created();
286 }
287}
288
290{
293 TreeCounters current_counters = tree_counters_stack.top();
295 tree_counters_stack.top() = current_counters;
296 for (auto& listener : checkpoint_listeners) {
297 listener->on_checkpoint_committed();
298 }
299}
300
302{
306 for (auto& listener : checkpoint_listeners) {
307 listener->on_checkpoint_reverted();
308 }
309}
310
312{
314}
315
316} // namespace bb::avm2::simulation
#define MAX_NOTE_HASHES_PER_TX
#define MAX_NULLIFIERS_PER_TX
ContractDBInterface & raw_contract_db
std::optional< ContractInstance > get_contract_instance(const AztecAddress &address) const override
std::optional< ContractClass > get_contract_class(const ContractClassId &class_id) const override
virtual std::optional< ContractInstance > get_contract_instance(const AztecAddress &address) const =0
virtual std::optional< ContractClass > get_contract_class(const ContractClassId &class_id) const =0
virtual bool exists(const FF &msg_hash, const FF &leaf_value, uint64_t leaf_index, std::span< const FF > sibling_path, const AppendOnlyTreeSnapshot &snapshot)=0
virtual IndexedLeaf< PublicDataLeafValue > get_leaf_preimage_public_data_tree(index_t leaf_index) const =0
virtual std::vector< AppendLeafResult > append_leaves(MerkleTreeId tree_id, std::span< const FF > leaves)=0
virtual void pad_tree(MerkleTreeId tree_id, size_t num_leaves)=0
virtual IndexedLeaf< NullifierLeafValue > get_leaf_preimage_nullifier_tree(index_t leaf_index) const =0
virtual SequentialInsertionResult< NullifierLeafValue > insert_indexed_leaves_nullifier_tree(const NullifierLeafValue &leaf_value)=0
virtual GetLowIndexedLeafResponse get_low_indexed_leaf(MerkleTreeId tree_id, const FF &value) const =0
virtual SiblingPath get_sibling_path(MerkleTreeId tree_id, index_t leaf_index) const =0
virtual uint32_t get_checkpoint_id() const =0
virtual SequentialInsertionResult< PublicDataLeafValue > insert_indexed_leaves_public_data_tree(const PublicDataLeafValue &leaf_value)=0
virtual const TreeSnapshots & get_tree_roots() const =0
virtual FF get_leaf_value(MerkleTreeId tree_id, index_t leaf_index) const =0
WrittenPublicDataSlotsInterface & written_public_data_slots
void note_hash_write(const AztecAddress &contract_address, const FF &note_hash) override
std::vector< CheckpointNotifiable * > checkpoint_listeners
std::stack< TreeCounters > tree_counters_stack
bool nullifier_exists(const AztecAddress &contract_address, const FF &nullifier) const override
LowLevelMerkleDBInterface & raw_merkle_db
void unique_note_hash_write(const FF &note_hash) override
TreeStates get_tree_state() const override
bool was_storage_written(const AztecAddress &contract_address, const FF &slot) const override
NullifierTreeCheckInterface & nullifier_tree_check
uint32_t get_checkpoint_id() const override
bool nullifier_write_internal(std::optional< AztecAddress > contract_address, const FF &nullifier)
bool note_hash_exists(uint64_t leaf_index, const FF &unique_note_hash) const override
void siloed_note_hash_write(const FF &note_hash) override
FF storage_read(const AztecAddress &contract_address, const FF &slot) const override
bool siloed_nullifier_exists(const FF &nullifier) const override
bool nullifier_write(const AztecAddress &contract_address, const FF &nullifier) override
PublicDataTreeCheckInterface & public_data_tree_check
void storage_write(const AztecAddress &contract_address, const FF &slot, const FF &value, bool is_protocol_write) override
bool nullifier_exists_internal(std::optional< AztecAddress > contract_address, const FF &nullifier) const
bool siloed_nullifier_write(const FF &nullifier) override
L1ToL2MessageTreeCheckInterface & l1_to_l2_msg_tree_check
bool l1_to_l2_msg_exists(uint64_t leaf_index, const FF &msg_hash) const override
virtual 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)=0
virtual 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)=0
virtual AppendOnlyTreeSnapshot write(const FF &slot, const AztecAddress &contract_address, const FF &value, const PublicDataTreeLeafPreimage &low_leaf_preimage, uint64_t low_leaf_index, std::span< const FF > low_leaf_sibling_path, const AppendOnlyTreeSnapshot &prev_snapshot, std::span< const FF > insertion_sibling_path, bool is_protocol_write)=0
virtual void assert_read(const FF &slot, const AztecAddress &contract_address, const FF &value, const PublicDataTreeLeafPreimage &low_leaf_preimage, uint64_t low_leaf_index, std::span< const FF > sibling_path, const AppendOnlyTreeSnapshot &snapshot)=0
virtual bool contains(const AztecAddress &contract_address, const FF &slot)=0
virtual void insert(const AztecAddress &contract_address, const FF &slot)=0
::bb::crypto::merkle_tree::fr_sibling_path SiblingPath
FF unconstrained_make_unique_note_hash(const FF &siloed_note_hash, const FF &first_nullifier, uint64_t note_hash_counter)
Definition merkle.cpp:41
::bb::crypto::merkle_tree::PublicDataLeafValue PublicDataLeafValue
FF unconstrained_compute_leaf_slot(const AztecAddress &contract_address, const FF &slot)
Definition merkle.cpp:26
FF unconstrained_silo_note_hash(const AztecAddress &contract_address, const FF &note_hash)
Definition merkle.cpp:36
FF unconstrained_silo_nullifier(const AztecAddress &contract_address, const FF &nullifier)
Definition merkle.cpp:31
FF ContractClassId
AvmFlavorSettings::FF FF
Definition field.hpp:10
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
AppendOnlyTreeSnapshot noteHashTree
AppendOnlyTreeSnapshot nullifierTree
AppendOnlyTreeSnapshot l1ToL2MessageTree
AppendOnlyTreeSnapshot publicDataTree