Skip to content

Commit 058fb20

Browse files
committed
fix: in avm cpp sim put counters (nullifier, notehash, msg) into a stack to be rolled back on error
1 parent 953f475 commit 058fb20

File tree

2 files changed

+38
-13
lines changed

2 files changed

+38
-13
lines changed

barretenberg/cpp/src/barretenberg/vm2/simulation/concrete_dbs.cpp

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,12 @@ TreeStates MerkleDB::get_tree_state() const
3838
{
3939
// No event generated.
4040
TreeSnapshots tree_snapshots = raw_merkle_db.get_tree_roots();
41+
TreeCounters tree_counters = tree_counters_stack.top();
4142
return {
42-
.noteHashTree = { .tree = tree_snapshots.noteHashTree, .counter = note_hash_counter },
43-
.nullifierTree = { .tree = tree_snapshots.nullifierTree, .counter = nullifier_counter },
44-
.l1ToL2MessageTree = { .tree = tree_snapshots.l1ToL2MessageTree, .counter = l2_to_l1_msg_counter },
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 },
4547
.publicDataTree = { .tree = tree_snapshots.publicDataTree, .counter = written_public_data_slots.size() },
4648
};
4749
}
@@ -143,6 +145,7 @@ bool MerkleDB::siloed_nullifier_write(const FF& nullifier)
143145

144146
bool MerkleDB::nullifier_write_internal(std::optional<AztecAddress> contract_address, const FF& nullifier)
145147
{
148+
uint32_t nullifier_counter = tree_counters_stack.top().nullifier_counter;
146149
FF siloed_nullifier = nullifier;
147150
if (contract_address.has_value()) {
148151
// Unconstrained siloing to fetch the hint, since the hints are keyed by siloed data.
@@ -182,7 +185,7 @@ bool MerkleDB::nullifier_write_internal(std::optional<AztecAddress> contract_add
182185
assert(snapshot_after == raw_merkle_db.get_tree_roots().nullifierTree);
183186

184187
if (!present) {
185-
nullifier_counter++;
188+
tree_counters_stack.top().nullifier_counter++;
186189
}
187190

188191
return !present;
@@ -198,6 +201,8 @@ bool MerkleDB::note_hash_exists(uint64_t leaf_index, const FF& unique_note_hash)
198201

199202
void MerkleDB::note_hash_write(const AztecAddress& contract_address, const FF& note_hash)
200203
{
204+
uint32_t note_hash_counter = tree_counters_stack.top().note_hash_counter;
205+
201206
AppendOnlyTreeSnapshot snapshot_before = raw_merkle_db.get_tree_roots().noteHashTree;
202207
// Unconstrained siloing and uniqueness to fetch the hint, since the hints are keyed by the unique note hash.
203208
// The siloing and uniqueness will later be constrained in the note hash tree check gadget.
@@ -214,11 +219,13 @@ void MerkleDB::note_hash_write(const AztecAddress& contract_address, const FF& n
214219
// Sanity check.
215220
assert(snapshot_after == raw_merkle_db.get_tree_roots().noteHashTree);
216221

217-
note_hash_counter++;
222+
tree_counters_stack.top().note_hash_counter++;
218223
}
219224

220225
void MerkleDB::siloed_note_hash_write(const FF& siloed_note_hash)
221226
{
227+
228+
uint32_t note_hash_counter = tree_counters_stack.top().note_hash_counter;
222229
AppendOnlyTreeSnapshot snapshot_before = raw_merkle_db.get_tree_roots().noteHashTree;
223230
// Unconstrained siloing and uniqueness to fetch the hint, since the hints are keyed by the unique note hash.
224231
// The siloing and uniqueness will later be constrained in the note hash tree check gadget.
@@ -233,11 +240,12 @@ void MerkleDB::siloed_note_hash_write(const FF& siloed_note_hash)
233240
// Sanity check.
234241
assert(snapshot_after == raw_merkle_db.get_tree_roots().noteHashTree);
235242

236-
note_hash_counter++;
243+
tree_counters_stack.top().note_hash_counter++;
237244
}
238245

239246
void MerkleDB::unique_note_hash_write(const FF& unique_note_hash)
240247
{
248+
uint32_t note_hash_counter = tree_counters_stack.top().note_hash_counter;
241249
AppendOnlyTreeSnapshot snapshot_before = raw_merkle_db.get_tree_roots().noteHashTree;
242250
auto hint = raw_merkle_db.append_leaves(MerkleTreeId::NOTE_HASH_TREE, std::vector<FF>{ unique_note_hash })[0];
243251

@@ -248,7 +256,7 @@ void MerkleDB::unique_note_hash_write(const FF& unique_note_hash)
248256
// Sanity check.
249257
assert(snapshot_after == raw_merkle_db.get_tree_roots().noteHashTree);
250258

251-
note_hash_counter++;
259+
tree_counters_stack.top().note_hash_counter++;
252260
}
253261

254262
bool MerkleDB::l1_to_l2_msg_exists(uint64_t leaf_index, const FF& msg_hash) const
@@ -262,14 +270,17 @@ bool MerkleDB::l1_to_l2_msg_exists(uint64_t leaf_index, const FF& msg_hash) cons
262270
void MerkleDB::pad_trees()
263271
{
264272
// The public data tree is not padded.
265-
raw_merkle_db.pad_tree(MerkleTreeId::NOTE_HASH_TREE, MAX_NOTE_HASHES_PER_TX - note_hash_counter);
266-
raw_merkle_db.pad_tree(MerkleTreeId::NULLIFIER_TREE, MAX_NULLIFIERS_PER_TX - nullifier_counter);
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);
267277
}
268278

269279
void MerkleDB::create_checkpoint()
270280
{
271281
raw_merkle_db.create_checkpoint();
272282
written_public_data_slots.create_checkpoint();
283+
tree_counters_stack.push(tree_counters_stack.top());
273284
for (auto& listener : checkpoint_listeners) {
274285
listener->on_checkpoint_created();
275286
}
@@ -279,6 +290,9 @@ void MerkleDB::commit_checkpoint()
279290
{
280291
raw_merkle_db.commit_checkpoint();
281292
written_public_data_slots.commit_checkpoint();
293+
TreeCounters current_counters = tree_counters_stack.top();
294+
tree_counters_stack.pop();
295+
tree_counters_stack.top() = current_counters;
282296
for (auto& listener : checkpoint_listeners) {
283297
listener->on_checkpoint_committed();
284298
}
@@ -288,6 +302,7 @@ void MerkleDB::revert_checkpoint()
288302
{
289303
raw_merkle_db.revert_checkpoint();
290304
written_public_data_slots.revert_checkpoint();
305+
tree_counters_stack.pop();
291306
for (auto& listener : checkpoint_listeners) {
292307
listener->on_checkpoint_reverted();
293308
}

barretenberg/cpp/src/barretenberg/vm2/simulation/concrete_dbs.hpp

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,17 @@
1414

1515
namespace bb::avm2::simulation {
1616

17+
struct TreeCounters {
18+
uint32_t note_hash_counter;
19+
uint32_t nullifier_counter;
20+
uint32_t l2_to_l1_msg_counter;
21+
// public data tree counter is tracked via the written public data slots tree
22+
23+
bool operator==(const TreeCounters& other) const = default;
24+
25+
MSGPACK_FIELDS(note_hash_counter, nullifier_counter, l2_to_l1_msg_counter);
26+
};
27+
1728
// Generates events.
1829
class ContractDB final : public ContractDBInterface {
1930
public:
@@ -105,13 +116,12 @@ class MerkleDB final : public HighLevelMerkleDBInterface {
105116
WrittenPublicDataSlotsInterface& written_public_data_slots;
106117
L1ToL2MessageTreeCheckInterface& l1_to_l2_msg_tree_check;
107118

108-
// Counters only in the HighLevel interface.
109-
uint32_t nullifier_counter = 0;
110-
uint32_t note_hash_counter = 0;
111-
uint32_t l2_to_l1_msg_counter = 0;
112119
// Set for semantics.
113120
using Slot = FF;
114121
std::vector<CheckpointNotifiable*> checkpoint_listeners;
122+
123+
// Stack of tree counters for checkpoints. Starts empty.
124+
std::stack<TreeCounters> tree_counters_stack{ { { 0, 0, 0 } } };
115125
};
116126

117127
} // namespace bb::avm2::simulation

0 commit comments

Comments
 (0)