@aztec/pxe 4.0.0-nightly.20260112 → 4.0.0-nightly.20260113

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/dest/block_synchronizer/block_synchronizer.d.ts +4 -2
  2. package/dest/block_synchronizer/block_synchronizer.d.ts.map +1 -1
  3. package/dest/block_synchronizer/block_synchronizer.js +19 -13
  4. package/dest/contract_function_simulator/oracle/private_execution.d.ts +1 -1
  5. package/dest/contract_function_simulator/oracle/private_execution.d.ts.map +1 -1
  6. package/dest/contract_function_simulator/oracle/private_execution.js +1 -2
  7. package/dest/contract_function_simulator/oracle/private_execution_oracle.d.ts +1 -16
  8. package/dest/contract_function_simulator/oracle/private_execution_oracle.d.ts.map +1 -1
  9. package/dest/contract_function_simulator/oracle/private_execution_oracle.js +2 -30
  10. package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts +1 -1
  11. package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts.map +1 -1
  12. package/dest/contract_function_simulator/oracle/utility_execution_oracle.js +15 -13
  13. package/dest/logs/log_service.d.ts +3 -2
  14. package/dest/logs/log_service.d.ts.map +1 -1
  15. package/dest/logs/log_service.js +4 -2
  16. package/dest/private_kernel/hints/build_private_kernel_reset_private_inputs.d.ts +2 -2
  17. package/dest/private_kernel/hints/build_private_kernel_reset_private_inputs.d.ts.map +1 -1
  18. package/dest/private_kernel/hints/build_private_kernel_reset_private_inputs.js +2 -2
  19. package/dest/private_kernel/private_kernel_execution_prover.d.ts +1 -1
  20. package/dest/private_kernel/private_kernel_execution_prover.d.ts.map +1 -1
  21. package/dest/private_kernel/private_kernel_execution_prover.js +3 -4
  22. package/dest/private_kernel/private_kernel_oracle.d.ts +3 -2
  23. package/dest/private_kernel/private_kernel_oracle.d.ts.map +1 -1
  24. package/dest/private_kernel/private_kernel_oracle_impl.d.ts +2 -2
  25. package/dest/private_kernel/private_kernel_oracle_impl.d.ts.map +1 -1
  26. package/dest/private_kernel/private_kernel_oracle_impl.js +2 -3
  27. package/dest/pxe.d.ts +1 -1
  28. package/dest/pxe.d.ts.map +1 -1
  29. package/dest/pxe.js +4 -1
  30. package/dest/storage/capsule_store/capsule_store.d.ts +24 -9
  31. package/dest/storage/capsule_store/capsule_store.d.ts.map +1 -1
  32. package/dest/storage/capsule_store/capsule_store.js +132 -23
  33. package/dest/storage/note_store/note_store.d.ts +4 -2
  34. package/dest/storage/note_store/note_store.d.ts.map +1 -1
  35. package/dest/storage/note_store/note_store.js +50 -48
  36. package/dest/storage/private_event_store/private_event_store.d.ts +4 -2
  37. package/dest/storage/private_event_store/private_event_store.d.ts.map +1 -1
  38. package/dest/storage/private_event_store/private_event_store.js +28 -28
  39. package/dest/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.d.ts +1 -1
  40. package/dest/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.d.ts.map +1 -1
  41. package/dest/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.js +1 -1
  42. package/dest/tagging/sender_sync/utils/get_status_change_of_pending.d.ts +1 -1
  43. package/dest/tagging/sender_sync/utils/get_status_change_of_pending.d.ts.map +1 -1
  44. package/dest/tagging/sender_sync/utils/get_status_change_of_pending.js +2 -2
  45. package/package.json +16 -16
  46. package/src/block_synchronizer/block_synchronizer.ts +23 -12
  47. package/src/contract_function_simulator/oracle/private_execution.ts +0 -2
  48. package/src/contract_function_simulator/oracle/private_execution_oracle.ts +1 -36
  49. package/src/contract_function_simulator/oracle/utility_execution_oracle.ts +15 -10
  50. package/src/logs/log_service.ts +2 -1
  51. package/src/private_kernel/hints/build_private_kernel_reset_private_inputs.ts +1 -2
  52. package/src/private_kernel/private_kernel_execution_prover.ts +2 -4
  53. package/src/private_kernel/private_kernel_oracle.ts +2 -1
  54. package/src/private_kernel/private_kernel_oracle_impl.ts +2 -8
  55. package/src/pxe.ts +2 -0
  56. package/src/storage/capsule_store/capsule_store.ts +159 -23
  57. package/src/storage/note_store/note_store.ts +58 -56
  58. package/src/storage/private_event_store/private_event_store.ts +33 -33
  59. package/src/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.ts +4 -1
  60. package/src/tagging/sender_sync/utils/get_status_change_of_pending.ts +6 -2
@@ -102,9 +102,11 @@ import { NoteDao } from '@aztec/stdlib/note';
102
102
  * specified block number. It restores any notes that were nullified after the given block
103
103
  * and deletes any active notes created after that block.
104
104
  *
105
+ * IMPORTANT: This method must be called within a transaction to ensure atomicity.
106
+ *
105
107
  * @param blockNumber - The new chain tip after a reorg
106
108
  * @param synchedBlockNumber - The block number up to which PXE managed to sync before the reorg happened.
107
- */ async rollbackNotesAndNullifiers(blockNumber, synchedBlockNumber) {
109
+ */ async rollback(blockNumber, synchedBlockNumber) {
108
110
  await this.#rewindNullifiersAfterBlock(blockNumber, synchedBlockNumber);
109
111
  await this.#deleteActiveNotesAfterBlock(blockNumber);
110
112
  }
@@ -115,24 +117,22 @@ import { NoteDao } from '@aztec/stdlib/note';
115
117
  * Note: This only affects #notes (active notes), not #nullifiedNotes.
116
118
  *
117
119
  * @param blockNumber - Notes created after this block number will be deleted
118
- */ #deleteActiveNotesAfterBlock(blockNumber) {
119
- return this.#store.transactionAsync(async ()=>{
120
- const notes = await toArray(this.#notes.valuesAsync());
121
- for (const note of notes){
122
- const noteDao = NoteDao.fromBuffer(note);
123
- if (noteDao.l2BlockNumber > blockNumber) {
124
- const noteIndex = toBufferBE(noteDao.index, 32).toString('hex');
125
- await this.#notes.delete(noteIndex);
126
- await this.#notesToScope.delete(noteIndex);
127
- await this.#nullifierToNoteId.delete(noteDao.siloedNullifier.toString());
128
- const scopes = await toArray(this.#scopes.keysAsync());
129
- for (const scope of scopes){
130
- await this.#notesByContractAndScope.get(scope).deleteValue(noteDao.contractAddress.toString(), noteIndex);
131
- await this.#notesByStorageSlotAndScope.get(scope).deleteValue(noteDao.storageSlot.toString(), noteIndex);
132
- }
120
+ */ async #deleteActiveNotesAfterBlock(blockNumber) {
121
+ const notes = await toArray(this.#notes.valuesAsync());
122
+ for (const note of notes){
123
+ const noteDao = NoteDao.fromBuffer(note);
124
+ if (noteDao.l2BlockNumber > blockNumber) {
125
+ const noteIndex = toBufferBE(noteDao.index, 32).toString('hex');
126
+ await this.#notes.delete(noteIndex);
127
+ await this.#notesToScope.delete(noteIndex);
128
+ await this.#nullifierToNoteId.delete(noteDao.siloedNullifier.toString());
129
+ const scopes = await toArray(this.#scopes.keysAsync());
130
+ for (const scope of scopes){
131
+ await this.#notesByContractAndScope.get(scope).deleteValue(noteDao.contractAddress.toString(), noteIndex);
132
+ await this.#notesByStorageSlotAndScope.get(scope).deleteValue(noteDao.storageSlot.toString(), noteIndex);
133
133
  }
134
134
  }
135
- });
135
+ }
136
136
  }
137
137
  /**
138
138
  * Rewinds nullifications after a given block number.
@@ -144,39 +144,41 @@ import { NoteDao } from '@aztec/stdlib/note';
144
144
  * @param blockNumber - Revert nullifications that occurred after this block
145
145
  * @param synchedBlockNumber - Upper bound for the block range to process
146
146
  */ async #rewindNullifiersAfterBlock(blockNumber, synchedBlockNumber) {
147
- await this.#store.transactionAsync(async ()=>{
148
- const nullifiersToUndo = [];
149
- const currentBlockNumber = blockNumber + 1;
150
- for(let i = currentBlockNumber; i <= synchedBlockNumber; i++){
151
- nullifiersToUndo.push(...await toArray(this.#nullifiersByBlockNumber.getValuesAsync(i)));
147
+ const nullifiersToUndo = [];
148
+ const currentBlockNumber = blockNumber + 1;
149
+ for(let i = currentBlockNumber; i <= synchedBlockNumber; i++){
150
+ nullifiersToUndo.push(...await toArray(this.#nullifiersByBlockNumber.getValuesAsync(i)));
151
+ }
152
+ const notesIndexesToReinsert = await Promise.all(nullifiersToUndo.map((nullifier)=>this.#nullifiedNotesByNullifier.getAsync(nullifier)));
153
+ const notNullNoteIndexes = notesIndexesToReinsert.filter((noteIndex)=>noteIndex != undefined);
154
+ const nullifiedNoteBuffers = await Promise.all(notNullNoteIndexes.map((noteIndex)=>this.#nullifiedNotes.getAsync(noteIndex)));
155
+ const noteDaos = nullifiedNoteBuffers.filter((buffer)=>buffer != undefined).map((buffer)=>NoteDao.fromBuffer(buffer));
156
+ for (const dao of noteDaos){
157
+ const noteIndex = toBufferBE(dao.index, 32).toString('hex');
158
+ const scopes = await toArray(this.#nullifiedNotesToScope.getValuesAsync(noteIndex));
159
+ if (scopes.length === 0) {
160
+ // We should never run into this error because notes always have a scope assigned to them - either on initial
161
+ // insertion via `addNotes` or when removing their nullifiers.
162
+ throw new Error(`No scopes found for nullified note with index ${noteIndex}`);
152
163
  }
153
- const notesIndexesToReinsert = await Promise.all(nullifiersToUndo.map((nullifier)=>this.#nullifiedNotesByNullifier.getAsync(nullifier)));
154
- const notNullNoteIndexes = notesIndexesToReinsert.filter((noteIndex)=>noteIndex != undefined);
155
- const nullifiedNoteBuffers = await Promise.all(notNullNoteIndexes.map((noteIndex)=>this.#nullifiedNotes.getAsync(noteIndex)));
156
- const noteDaos = nullifiedNoteBuffers.filter((buffer)=>buffer != undefined).map((buffer)=>NoteDao.fromBuffer(buffer));
157
- for (const dao of noteDaos){
158
- const noteIndex = toBufferBE(dao.index, 32).toString('hex');
159
- await this.#notes.set(noteIndex, dao.toBuffer());
160
- await this.#nullifierToNoteId.set(dao.siloedNullifier.toString(), noteIndex);
161
- const scopes = await toArray(this.#nullifiedNotesToScope.getValuesAsync(noteIndex));
162
- if (scopes.length === 0) {
163
- // We should never run into this error because notes always have a scope assigned to them - either on initial
164
- // insertion via `addNotes` or when removing their nullifiers.
165
- throw new Error(`No scopes found for nullified note with index ${noteIndex}`);
166
- }
167
- for (const scope of scopes){
168
- await this.#notesByContractAndScope.get(scope.toString()).set(dao.contractAddress.toString(), noteIndex);
169
- await this.#notesByStorageSlotAndScope.get(scope.toString()).set(dao.storageSlot.toString(), noteIndex);
170
- await this.#notesToScope.set(noteIndex, scope);
171
- }
172
- await this.#nullifiedNotes.delete(noteIndex);
173
- await this.#nullifiedNotesToScope.delete(noteIndex);
174
- await this.#nullifiersByBlockNumber.deleteValue(dao.l2BlockNumber, dao.siloedNullifier.toString());
175
- await this.#nullifiedNotesByContract.deleteValue(dao.contractAddress.toString(), noteIndex);
176
- await this.#nullifiedNotesByStorageSlot.deleteValue(dao.storageSlot.toString(), noteIndex);
177
- await this.#nullifiedNotesByNullifier.delete(dao.siloedNullifier.toString());
164
+ for (const scope of scopes){
165
+ await Promise.all([
166
+ this.#notesByContractAndScope.get(scope.toString()).set(dao.contractAddress.toString(), noteIndex),
167
+ this.#notesByStorageSlotAndScope.get(scope.toString()).set(dao.storageSlot.toString(), noteIndex),
168
+ this.#notesToScope.set(noteIndex, scope)
169
+ ]);
178
170
  }
179
- });
171
+ await Promise.all([
172
+ this.#notes.set(noteIndex, dao.toBuffer()),
173
+ this.#nullifierToNoteId.set(dao.siloedNullifier.toString(), noteIndex),
174
+ this.#nullifiedNotes.delete(noteIndex),
175
+ this.#nullifiedNotesToScope.delete(noteIndex),
176
+ this.#nullifiersByBlockNumber.deleteValue(dao.l2BlockNumber, dao.siloedNullifier.toString()),
177
+ this.#nullifiedNotesByContract.deleteValue(dao.contractAddress.toString(), noteIndex),
178
+ this.#nullifiedNotesByStorageSlot.deleteValue(dao.storageSlot.toString(), noteIndex),
179
+ this.#nullifiedNotesByNullifier.delete(dao.siloedNullifier.toString())
180
+ ]);
181
+ }
180
182
  }
181
183
  /**
182
184
  * Retrieves notes based on the provided filter criteria.
@@ -49,8 +49,10 @@ export declare class PrivateEventStore {
49
49
  /**
50
50
  * Rolls back private events that were stored after a given `blockNumber` and up to `synchedBlockNumber` (the block
51
51
  * number up to which PXE managed to sync before the reorg happened).
52
+ *
53
+ * IMPORTANT: This method must be called within a transaction to ensure atomicity.
52
54
  */
53
- rollbackEventsAfterBlock(blockNumber: number, synchedBlockNumber: number): Promise<void>;
55
+ rollback(blockNumber: number, synchedBlockNumber: number): Promise<void>;
54
56
  }
55
57
  export {};
56
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJpdmF0ZV9ldmVudF9zdG9yZS5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3N0b3JhZ2UvcHJpdmF0ZV9ldmVudF9zdG9yZS9wcml2YXRlX2V2ZW50X3N0b3JlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sRUFBRSxFQUFFLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUdwRCxPQUFPLEtBQUssRUFBRSxpQkFBaUIsRUFBaUIsTUFBTSxpQkFBaUIsQ0FBQztBQUN4RSxPQUFPLEtBQUssRUFBRSxhQUFhLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUN2RCxPQUFPLEtBQUssRUFBRSxZQUFZLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUVoRSxPQUFPLEVBQUUsS0FBSyxJQUFJLEVBQUUsTUFBTSxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFFckQsT0FBTyxLQUFLLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFFdkQsTUFBTSxNQUFNLHVCQUF1QixHQUFHO0lBQ3BDLGVBQWUsRUFBRSxZQUFZLENBQUM7SUFDOUIsU0FBUyxFQUFFLE1BQU0sQ0FBQztJQUNsQixPQUFPLEVBQUUsTUFBTSxDQUFDO0lBQ2hCLE1BQU0sRUFBRSxZQUFZLEVBQUUsQ0FBQztJQUN2QixNQUFNLENBQUMsRUFBRSxNQUFNLENBQUM7Q0FDakIsQ0FBQztBQWFGLEtBQUssb0JBQW9CLEdBQUcsSUFBSSxHQUFHO0lBQ2pDLGVBQWUsRUFBRSxZQUFZLENBQUM7SUFDOUIsS0FBSyxFQUFFLFlBQVksQ0FBQztDQUNyQixDQUFDO0FBRUY7O0dBRUc7QUFDSCxxQkFBYSxpQkFBaUI7O0lBVzVCLE1BQU0seUNBQXVDO0lBRTdDLFlBQVksS0FBSyxFQUFFLGlCQUFpQixFQU1uQztJQU1EOzs7Ozs7Ozs7O09BVUc7SUFDSCxvQkFBb0IsQ0FDbEIsYUFBYSxFQUFFLGFBQWEsRUFDNUIsVUFBVSxFQUFFLEVBQUUsRUFDZCxVQUFVLEVBQUUsRUFBRSxFQUFFLEVBQ2hCLG9CQUFvQixFQUFFLE1BQU0sRUFDNUIsUUFBUSxFQUFFLG9CQUFvQixHQUM3QixPQUFPLENBQUMsSUFBSSxDQUFDLENBa0NmO0lBRUQ7Ozs7Ozs7Ozs7T0FVRztJQUNVLGdCQUFnQixDQUMzQixhQUFhLEVBQUUsYUFBYSxFQUM1QixNQUFNLEVBQUUsdUJBQXVCLEdBQzlCLE9BQU8sQ0FBQyxrQkFBa0IsRUFBRSxDQUFDLENBd0MvQjtJQUVEOzs7T0FHRztJQUNVLHdCQUF3QixDQUFDLFdBQVcsRUFBRSxNQUFNLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FxQ3BHO0NBQ0YifQ==
58
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJpdmF0ZV9ldmVudF9zdG9yZS5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3N0b3JhZ2UvcHJpdmF0ZV9ldmVudF9zdG9yZS9wcml2YXRlX2V2ZW50X3N0b3JlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sRUFBRSxFQUFFLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUdwRCxPQUFPLEtBQUssRUFBRSxpQkFBaUIsRUFBaUIsTUFBTSxpQkFBaUIsQ0FBQztBQUN4RSxPQUFPLEtBQUssRUFBRSxhQUFhLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUN2RCxPQUFPLEtBQUssRUFBRSxZQUFZLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUVoRSxPQUFPLEVBQUUsS0FBSyxJQUFJLEVBQUUsTUFBTSxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFFckQsT0FBTyxLQUFLLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFFdkQsTUFBTSxNQUFNLHVCQUF1QixHQUFHO0lBQ3BDLGVBQWUsRUFBRSxZQUFZLENBQUM7SUFDOUIsU0FBUyxFQUFFLE1BQU0sQ0FBQztJQUNsQixPQUFPLEVBQUUsTUFBTSxDQUFDO0lBQ2hCLE1BQU0sRUFBRSxZQUFZLEVBQUUsQ0FBQztJQUN2QixNQUFNLENBQUMsRUFBRSxNQUFNLENBQUM7Q0FDakIsQ0FBQztBQWFGLEtBQUssb0JBQW9CLEdBQUcsSUFBSSxHQUFHO0lBQ2pDLGVBQWUsRUFBRSxZQUFZLENBQUM7SUFDOUIsS0FBSyxFQUFFLFlBQVksQ0FBQztDQUNyQixDQUFDO0FBRUY7O0dBRUc7QUFDSCxxQkFBYSxpQkFBaUI7O0lBVzVCLE1BQU0seUNBQXVDO0lBRTdDLFlBQVksS0FBSyxFQUFFLGlCQUFpQixFQU1uQztJQU1EOzs7Ozs7Ozs7O09BVUc7SUFDSCxvQkFBb0IsQ0FDbEIsYUFBYSxFQUFFLGFBQWEsRUFDNUIsVUFBVSxFQUFFLEVBQUUsRUFDZCxVQUFVLEVBQUUsRUFBRSxFQUFFLEVBQ2hCLG9CQUFvQixFQUFFLE1BQU0sRUFDNUIsUUFBUSxFQUFFLG9CQUFvQixHQUM3QixPQUFPLENBQUMsSUFBSSxDQUFDLENBa0NmO0lBRUQ7Ozs7Ozs7Ozs7T0FVRztJQUNVLGdCQUFnQixDQUMzQixhQUFhLEVBQUUsYUFBYSxFQUM1QixNQUFNLEVBQUUsdUJBQXVCLEdBQzlCLE9BQU8sQ0FBQyxrQkFBa0IsRUFBRSxDQUFDLENBd0MvQjtJQUVEOzs7OztPQUtHO0lBQ1UsUUFBUSxDQUFDLFdBQVcsRUFBRSxNQUFNLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FtQ3BGO0NBQ0YifQ==
@@ -1 +1 @@
1
- {"version":3,"file":"private_event_store.d.ts","sourceRoot":"","sources":["../../../src/storage/private_event_store/private_event_store.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,EAAE,EAAE,MAAM,gCAAgC,CAAC;AAGpD,OAAO,KAAK,EAAE,iBAAiB,EAAiB,MAAM,iBAAiB,CAAC;AACxE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAEhE,OAAO,EAAE,KAAK,IAAI,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAErD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAEvD,MAAM,MAAM,uBAAuB,GAAG;IACpC,eAAe,EAAE,YAAY,CAAC;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,YAAY,EAAE,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAaF,KAAK,oBAAoB,GAAG,IAAI,GAAG;IACjC,eAAe,EAAE,YAAY,CAAC;IAC9B,KAAK,EAAE,YAAY,CAAC;CACrB,CAAC;AAEF;;GAEG;AACH,qBAAa,iBAAiB;;IAW5B,MAAM,yCAAuC;IAE7C,YAAY,KAAK,EAAE,iBAAiB,EAMnC;IAMD;;;;;;;;;;OAUG;IACH,oBAAoB,CAClB,aAAa,EAAE,aAAa,EAC5B,UAAU,EAAE,EAAE,EACd,UAAU,EAAE,EAAE,EAAE,EAChB,oBAAoB,EAAE,MAAM,EAC5B,QAAQ,EAAE,oBAAoB,GAC7B,OAAO,CAAC,IAAI,CAAC,CAkCf;IAED;;;;;;;;;;OAUG;IACU,gBAAgB,CAC3B,aAAa,EAAE,aAAa,EAC5B,MAAM,EAAE,uBAAuB,GAC9B,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAwC/B;IAED;;;OAGG;IACU,wBAAwB,CAAC,WAAW,EAAE,MAAM,EAAE,kBAAkB,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAqCpG;CACF"}
1
+ {"version":3,"file":"private_event_store.d.ts","sourceRoot":"","sources":["../../../src/storage/private_event_store/private_event_store.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,EAAE,EAAE,MAAM,gCAAgC,CAAC;AAGpD,OAAO,KAAK,EAAE,iBAAiB,EAAiB,MAAM,iBAAiB,CAAC;AACxE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAEhE,OAAO,EAAE,KAAK,IAAI,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAErD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAEvD,MAAM,MAAM,uBAAuB,GAAG;IACpC,eAAe,EAAE,YAAY,CAAC;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,YAAY,EAAE,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAaF,KAAK,oBAAoB,GAAG,IAAI,GAAG;IACjC,eAAe,EAAE,YAAY,CAAC;IAC9B,KAAK,EAAE,YAAY,CAAC;CACrB,CAAC;AAEF;;GAEG;AACH,qBAAa,iBAAiB;;IAW5B,MAAM,yCAAuC;IAE7C,YAAY,KAAK,EAAE,iBAAiB,EAMnC;IAMD;;;;;;;;;;OAUG;IACH,oBAAoB,CAClB,aAAa,EAAE,aAAa,EAC5B,UAAU,EAAE,EAAE,EACd,UAAU,EAAE,EAAE,EAAE,EAChB,oBAAoB,EAAE,MAAM,EAC5B,QAAQ,EAAE,oBAAoB,GAC7B,OAAO,CAAC,IAAI,CAAC,CAkCf;IAED;;;;;;;;;;OAUG;IACU,gBAAgB,CAC3B,aAAa,EAAE,aAAa,EAC5B,MAAM,EAAE,uBAAuB,GAC9B,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAwC/B;IAED;;;;;OAKG;IACU,QAAQ,CAAC,WAAW,EAAE,MAAM,EAAE,kBAAkB,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAmCpF;CACF"}
@@ -123,36 +123,36 @@ import { TxHash } from '@aztec/stdlib/tx';
123
123
  /**
124
124
  * Rolls back private events that were stored after a given `blockNumber` and up to `synchedBlockNumber` (the block
125
125
  * number up to which PXE managed to sync before the reorg happened).
126
- */ async rollbackEventsAfterBlock(blockNumber, synchedBlockNumber) {
127
- await this.#store.transactionAsync(async ()=>{
128
- let removedCount = 0;
129
- for(let block = blockNumber + 1; block <= synchedBlockNumber; block++){
130
- const indices = await this.#eventsByBlockNumber.getAsync(block);
131
- if (indices) {
132
- await this.#eventsByBlockNumber.delete(block);
133
- for (const eventCommitmentIndex of indices){
134
- const entry = await this.#eventLogs.getAsync(eventCommitmentIndex);
135
- if (!entry) {
136
- throw new Error(`Event log not found for eventCommitmentIndex ${eventCommitmentIndex}`);
137
- }
138
- await this.#eventLogs.delete(eventCommitmentIndex);
139
- await this.#seenLogs.delete(eventCommitmentIndex);
140
- // Update #eventsByContractScopeSelector using the stored lookupKey
141
- const existingIndices = await this.#eventsByContractScopeSelector.getAsync(entry.lookupKey);
142
- if (!existingIndices || existingIndices.length === 0) {
143
- throw new Error(`No indices found in #eventsByContractScopeSelector for key ${entry.lookupKey}`);
144
- }
145
- const filteredIndices = existingIndices.filter((idx)=>idx !== eventCommitmentIndex);
146
- if (filteredIndices.length === 0) {
147
- await this.#eventsByContractScopeSelector.delete(entry.lookupKey);
148
- } else {
149
- await this.#eventsByContractScopeSelector.set(entry.lookupKey, filteredIndices);
150
- }
151
- removedCount++;
126
+ *
127
+ * IMPORTANT: This method must be called within a transaction to ensure atomicity.
128
+ */ async rollback(blockNumber, synchedBlockNumber) {
129
+ let removedCount = 0;
130
+ for(let block = blockNumber + 1; block <= synchedBlockNumber; block++){
131
+ const indices = await this.#eventsByBlockNumber.getAsync(block);
132
+ if (indices) {
133
+ await this.#eventsByBlockNumber.delete(block);
134
+ for (const eventCommitmentIndex of indices){
135
+ const entry = await this.#eventLogs.getAsync(eventCommitmentIndex);
136
+ if (!entry) {
137
+ throw new Error(`Event log not found for eventCommitmentIndex ${eventCommitmentIndex}`);
152
138
  }
139
+ await this.#eventLogs.delete(eventCommitmentIndex);
140
+ await this.#seenLogs.delete(eventCommitmentIndex);
141
+ // Update #eventsByContractScopeSelector using the stored lookupKey
142
+ const existingIndices = await this.#eventsByContractScopeSelector.getAsync(entry.lookupKey);
143
+ if (!existingIndices || existingIndices.length === 0) {
144
+ throw new Error(`No indices found in #eventsByContractScopeSelector for key ${entry.lookupKey}`);
145
+ }
146
+ const filteredIndices = existingIndices.filter((idx)=>idx !== eventCommitmentIndex);
147
+ if (filteredIndices.length === 0) {
148
+ await this.#eventsByContractScopeSelector.delete(entry.lookupKey);
149
+ } else {
150
+ await this.#eventsByContractScopeSelector.set(entry.lookupKey, filteredIndices);
151
+ }
152
+ removedCount++;
153
153
  }
154
154
  }
155
- this.logger.verbose(`Rolled back ${removedCount} private events after block ${blockNumber}`);
156
- });
155
+ }
156
+ this.logger.verbose(`Rolled back ${removedCount} private events after block ${blockNumber}`);
157
157
  }
158
158
  }
@@ -11,4 +11,4 @@ import type { RecipientTaggingStore } from '../../storage/tagging_store/recipien
11
11
  * in the tagging data provider is indexed by the secret and hence completely disjoint.
12
12
  */
13
13
  export declare function loadPrivateLogsForSenderRecipientPair(secret: DirectionalAppTaggingSecret, app: AztecAddress, aztecNode: AztecNode, taggingStore: RecipientTaggingStore, anchorBlockNumber: BlockNumber): Promise<TxScopedL2Log[]>;
14
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG9hZF9wcml2YXRlX2xvZ3NfZm9yX3NlbmRlcl9yZWNpcGllbnRfcGFpci5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3RhZ2dpbmcvcmVjaXBpZW50X3N5bmMvbG9hZF9wcml2YXRlX2xvZ3NfZm9yX3NlbmRlcl9yZWNpcGllbnRfcGFpci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssRUFBRSxXQUFXLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUNuRSxPQUFPLEtBQUssRUFBRSxZQUFZLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUNoRSxPQUFPLEtBQUssRUFBRSxTQUFTLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUNqRSxPQUFPLEtBQUssRUFBRSwyQkFBMkIsRUFBRSxhQUFhLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUVyRixPQUFPLEtBQUssRUFBRSxxQkFBcUIsRUFBRSxNQUFNLHdEQUF3RCxDQUFDO0FBS3BHOzs7Ozs7R0FNRztBQUNILHdCQUFzQixxQ0FBcUMsQ0FDekQsTUFBTSxFQUFFLDJCQUEyQixFQUNuQyxHQUFHLEVBQUUsWUFBWSxFQUNqQixTQUFTLEVBQUUsU0FBUyxFQUNwQixZQUFZLEVBQUUscUJBQXFCLEVBQ25DLGlCQUFpQixFQUFFLFdBQVcsR0FDN0IsT0FBTyxDQUFDLGFBQWEsRUFBRSxDQUFDLENBeUcxQiJ9
14
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG9hZF9wcml2YXRlX2xvZ3NfZm9yX3NlbmRlcl9yZWNpcGllbnRfcGFpci5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3RhZ2dpbmcvcmVjaXBpZW50X3N5bmMvbG9hZF9wcml2YXRlX2xvZ3NfZm9yX3NlbmRlcl9yZWNpcGllbnRfcGFpci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssRUFBRSxXQUFXLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUNuRSxPQUFPLEtBQUssRUFBRSxZQUFZLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUNoRSxPQUFPLEtBQUssRUFBRSxTQUFTLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUNqRSxPQUFPLEtBQUssRUFBRSwyQkFBMkIsRUFBRSxhQUFhLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUVyRixPQUFPLEtBQUssRUFBRSxxQkFBcUIsRUFBRSxNQUFNLHdEQUF3RCxDQUFDO0FBS3BHOzs7Ozs7R0FNRztBQUNILHdCQUFzQixxQ0FBcUMsQ0FDekQsTUFBTSxFQUFFLDJCQUEyQixFQUNuQyxHQUFHLEVBQUUsWUFBWSxFQUNqQixTQUFTLEVBQUUsU0FBUyxFQUNwQixZQUFZLEVBQUUscUJBQXFCLEVBQ25DLGlCQUFpQixFQUFFLFdBQVcsR0FDN0IsT0FBTyxDQUFDLGFBQWEsRUFBRSxDQUFDLENBNEcxQiJ9
@@ -1 +1 @@
1
- {"version":3,"file":"load_private_logs_for_sender_recipient_pair.d.ts","sourceRoot":"","sources":["../../../src/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AACnE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAC;AACjE,OAAO,KAAK,EAAE,2BAA2B,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAErF,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,wDAAwD,CAAC;AAKpG;;;;;;GAMG;AACH,wBAAsB,qCAAqC,CACzD,MAAM,EAAE,2BAA2B,EACnC,GAAG,EAAE,YAAY,EACjB,SAAS,EAAE,SAAS,EACpB,YAAY,EAAE,qBAAqB,EACnC,iBAAiB,EAAE,WAAW,GAC7B,OAAO,CAAC,aAAa,EAAE,CAAC,CAyG1B"}
1
+ {"version":3,"file":"load_private_logs_for_sender_recipient_pair.d.ts","sourceRoot":"","sources":["../../../src/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AACnE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAC;AACjE,OAAO,KAAK,EAAE,2BAA2B,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAErF,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,wDAAwD,CAAC;AAKpG;;;;;;GAMG;AACH,wBAAsB,qCAAqC,CACzD,MAAM,EAAE,2BAA2B,EACnC,GAAG,EAAE,YAAY,EACjB,SAAS,EAAE,SAAS,EACpB,YAAY,EAAE,qBAAqB,EACnC,iBAAiB,EAAE,WAAW,GAC7B,OAAO,CAAC,aAAa,EAAE,CAAC,CA4G1B"}
@@ -55,7 +55,7 @@ import { loadLogsForRange } from './utils/load_logs_for_range.js';
55
55
  throw new Error('Node failed to return latest block header when syncing logs');
56
56
  }
57
57
  [finalizedBlockNumber, currentTimestamp] = [
58
- l2Tips.finalized.number,
58
+ l2Tips.finalized.block.number,
59
59
  latestBlockHeader.globalVariables.timestamp
60
60
  ];
61
61
  }
@@ -8,4 +8,4 @@ export declare function getStatusChangeOfPending(pending: TxHash[], aztecNode: A
8
8
  txHashesToFinalize: TxHash[];
9
9
  txHashesToDrop: TxHash[];
10
10
  }>;
11
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2V0X3N0YXR1c19jaGFuZ2Vfb2ZfcGVuZGluZy5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3RhZ2dpbmcvc2VuZGVyX3N5bmMvdXRpbHMvZ2V0X3N0YXR1c19jaGFuZ2Vfb2ZfcGVuZGluZy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssRUFBRSxTQUFTLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUNqRSxPQUFPLEVBQUUsTUFBTSxFQUFZLE1BQU0sa0JBQWtCLENBQUM7QUFFcEQ7OztHQUdHO0FBQ0gsd0JBQXNCLHdCQUF3QixDQUM1QyxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQ2pCLFNBQVMsRUFBRSxTQUFTLEdBQ25CLE9BQU8sQ0FBQztJQUFFLGtCQUFrQixFQUFFLE1BQU0sRUFBRSxDQUFDO0lBQUMsY0FBYyxFQUFFLE1BQU0sRUFBRSxDQUFBO0NBQUUsQ0FBQyxDQWlDckUifQ==
11
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2V0X3N0YXR1c19jaGFuZ2Vfb2ZfcGVuZGluZy5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3RhZ2dpbmcvc2VuZGVyX3N5bmMvdXRpbHMvZ2V0X3N0YXR1c19jaGFuZ2Vfb2ZfcGVuZGluZy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssRUFBRSxTQUFTLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUNqRSxPQUFPLEVBQUUsTUFBTSxFQUFZLE1BQU0sa0JBQWtCLENBQUM7QUFFcEQ7OztHQUdHO0FBQ0gsd0JBQXNCLHdCQUF3QixDQUM1QyxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQ2pCLFNBQVMsRUFBRSxTQUFTLEdBQ25CLE9BQU8sQ0FBQztJQUFFLGtCQUFrQixFQUFFLE1BQU0sRUFBRSxDQUFDO0lBQUMsY0FBYyxFQUFFLE1BQU0sRUFBRSxDQUFBO0NBQUUsQ0FBQyxDQXFDckUifQ==
@@ -1 +1 @@
1
- {"version":3,"file":"get_status_change_of_pending.d.ts","sourceRoot":"","sources":["../../../../src/tagging/sender_sync/utils/get_status_change_of_pending.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAC;AACjE,OAAO,EAAE,MAAM,EAAY,MAAM,kBAAkB,CAAC;AAEpD;;;GAGG;AACH,wBAAsB,wBAAwB,CAC5C,OAAO,EAAE,MAAM,EAAE,EACjB,SAAS,EAAE,SAAS,GACnB,OAAO,CAAC;IAAE,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAAC,cAAc,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAiCrE"}
1
+ {"version":3,"file":"get_status_change_of_pending.d.ts","sourceRoot":"","sources":["../../../../src/tagging/sender_sync/utils/get_status_change_of_pending.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAC;AACjE,OAAO,EAAE,MAAM,EAAY,MAAM,kBAAkB,CAAC;AAEpD;;;GAGG;AACH,wBAAsB,wBAAwB,CAC5C,OAAO,EAAE,MAAM,EAAE,EACjB,SAAS,EAAE,SAAS,GACnB,OAAO,CAAC;IAAE,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAAC,cAAc,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAqCrE"}
@@ -4,7 +4,7 @@ import { TxStatus } from '@aztec/stdlib/tx';
4
4
  * dropped.
5
5
  */ export async function getStatusChangeOfPending(pending, aztecNode) {
6
6
  // Get receipts for all pending tx hashes and the finalized block number.
7
- const [receipts, { finalized }] = await Promise.all([
7
+ const [receipts, tips] = await Promise.all([
8
8
  Promise.all(pending.map((pendingTxHash)=>aztecNode.getTxReceipt(pendingTxHash))),
9
9
  aztecNode.getL2Tips()
10
10
  ]);
@@ -13,7 +13,7 @@ import { TxStatus } from '@aztec/stdlib/tx';
13
13
  for(let i = 0; i < receipts.length; i++){
14
14
  const receipt = receipts[i];
15
15
  const txHash = pending[i];
16
- if (receipt.status === TxStatus.SUCCESS && receipt.blockNumber && receipt.blockNumber <= finalized.number) {
16
+ if (receipt.status === TxStatus.SUCCESS && receipt.blockNumber && receipt.blockNumber <= tips.finalized.block.number) {
17
17
  // Tx has been included in a block and the corresponding block is finalized --> we mark the indexes as
18
18
  // finalized.
19
19
  txHashesToFinalize.push(txHash);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aztec/pxe",
3
- "version": "4.0.0-nightly.20260112",
3
+ "version": "4.0.0-nightly.20260113",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  "./server": "./dest/entrypoints/server/index.js",
@@ -61,19 +61,19 @@
61
61
  ]
62
62
  },
63
63
  "dependencies": {
64
- "@aztec/bb-prover": "4.0.0-nightly.20260112",
65
- "@aztec/bb.js": "4.0.0-nightly.20260112",
66
- "@aztec/builder": "4.0.0-nightly.20260112",
67
- "@aztec/constants": "4.0.0-nightly.20260112",
68
- "@aztec/ethereum": "4.0.0-nightly.20260112",
69
- "@aztec/foundation": "4.0.0-nightly.20260112",
70
- "@aztec/key-store": "4.0.0-nightly.20260112",
71
- "@aztec/kv-store": "4.0.0-nightly.20260112",
72
- "@aztec/noir-protocol-circuits-types": "4.0.0-nightly.20260112",
73
- "@aztec/noir-types": "4.0.0-nightly.20260112",
74
- "@aztec/protocol-contracts": "4.0.0-nightly.20260112",
75
- "@aztec/simulator": "4.0.0-nightly.20260112",
76
- "@aztec/stdlib": "4.0.0-nightly.20260112",
64
+ "@aztec/bb-prover": "4.0.0-nightly.20260113",
65
+ "@aztec/bb.js": "4.0.0-nightly.20260113",
66
+ "@aztec/builder": "4.0.0-nightly.20260113",
67
+ "@aztec/constants": "4.0.0-nightly.20260113",
68
+ "@aztec/ethereum": "4.0.0-nightly.20260113",
69
+ "@aztec/foundation": "4.0.0-nightly.20260113",
70
+ "@aztec/key-store": "4.0.0-nightly.20260113",
71
+ "@aztec/kv-store": "4.0.0-nightly.20260113",
72
+ "@aztec/noir-protocol-circuits-types": "4.0.0-nightly.20260113",
73
+ "@aztec/noir-types": "4.0.0-nightly.20260113",
74
+ "@aztec/protocol-contracts": "4.0.0-nightly.20260113",
75
+ "@aztec/simulator": "4.0.0-nightly.20260113",
76
+ "@aztec/stdlib": "4.0.0-nightly.20260113",
77
77
  "koa": "^2.16.1",
78
78
  "koa-router": "^13.1.1",
79
79
  "lodash.omit": "^4.5.0",
@@ -82,8 +82,8 @@
82
82
  "viem": "npm:@aztec/viem@2.38.2"
83
83
  },
84
84
  "devDependencies": {
85
- "@aztec/merkle-tree": "4.0.0-nightly.20260112",
86
- "@aztec/noir-test-contracts.js": "4.0.0-nightly.20260112",
85
+ "@aztec/merkle-tree": "4.0.0-nightly.20260113",
86
+ "@aztec/noir-test-contracts.js": "4.0.0-nightly.20260113",
87
87
  "@jest/globals": "^30.0.0",
88
88
  "@types/jest": "^30.0.0",
89
89
  "@types/lodash.omit": "^4.5.7",
@@ -1,5 +1,7 @@
1
1
  import { BlockNumber } from '@aztec/foundation/branded-types';
2
+ import { Fr } from '@aztec/foundation/curves/bn254';
2
3
  import { type Logger, createLogger } from '@aztec/foundation/log';
4
+ import type { AztecAsyncKVStore } from '@aztec/kv-store';
3
5
  import type { L2TipsKVStore } from '@aztec/kv-store/stores';
4
6
  import { L2BlockStream, type L2BlockStreamEvent, type L2BlockStreamEventHandler } from '@aztec/stdlib/block';
5
7
  import type { AztecNode } from '@aztec/stdlib/interfaces/client';
@@ -21,6 +23,7 @@ export class BlockSynchronizer implements L2BlockStreamEventHandler {
21
23
 
22
24
  constructor(
23
25
  private node: AztecNode,
26
+ private store: AztecAsyncKVStore,
24
27
  private anchorBlockStore: AnchorBlockStore,
25
28
  private noteStore: NoteStore,
26
29
  private privateEventStore: PrivateEventStore,
@@ -50,28 +53,36 @@ export class BlockSynchronizer implements L2BlockStreamEventHandler {
50
53
 
51
54
  switch (event.type) {
52
55
  case 'blocks-added': {
53
- const lastBlock = event.blocks.at(-1)!.block;
56
+ const lastBlock = event.blocks.at(-1)!;
54
57
  this.log.verbose(`Updated pxe last block to ${lastBlock.number}`, {
55
58
  blockHash: lastBlock.hash(),
56
59
  archive: lastBlock.archive.root.toString(),
57
60
  header: lastBlock.header.toInspect(),
58
61
  });
59
- await this.anchorBlockStore.setHeader(lastBlock.getBlockHeader());
62
+ await this.anchorBlockStore.setHeader(lastBlock.header);
60
63
  break;
61
64
  }
62
65
  case 'chain-pruned': {
63
66
  this.log.warn(`Pruning data after block ${event.block.number} due to reorg`);
64
- // We first unnullify and then remove so that unnullified notes that were created after the block number end up deleted.
65
- const lastSynchedBlockNumber = (await this.anchorBlockStore.getBlockHeader()).getBlockNumber();
66
- await this.noteStore.rollbackNotesAndNullifiers(event.block.number, lastSynchedBlockNumber);
67
- await this.privateEventStore.rollbackEventsAfterBlock(event.block.number, lastSynchedBlockNumber);
68
- // Update the header to the last block.
69
- const newHeader = await this.node.getBlockHeader(event.block.number);
70
- if (!newHeader) {
71
- this.log.error(`Block header not found for block number ${event.block.number} during chain prune`);
72
- } else {
73
- await this.anchorBlockStore.setHeader(newHeader);
67
+
68
+ const oldAnchorBlockNumber = (await this.anchorBlockStore.getBlockHeader()).getBlockNumber();
69
+ // Note that the following is not necessarily the anchor block that will be used in the transaction - if
70
+ // the chain has already moved past the reorg, we'll also see blocks-added events that will push the anchor
71
+ // forward.
72
+ const newAnchorBlockHeader = await this.node.getBlockHeaderByHash(Fr.fromString(event.block.hash));
73
+
74
+ if (!newAnchorBlockHeader) {
75
+ throw new Error(
76
+ `Block header for block number ${event.block.number} and hash ${event.block.hash} not found during chain prune. This likely indicates a bug in the node, as we receive block stream events and fetch block headers from the same node.`,
77
+ );
74
78
  }
79
+
80
+ // Operations are wrapped in a single transaction to ensure atomicity.
81
+ await this.store.transactionAsync(async () => {
82
+ await this.noteStore.rollback(event.block.number, oldAnchorBlockNumber);
83
+ await this.privateEventStore.rollback(event.block.number, oldAnchorBlockNumber);
84
+ await this.anchorBlockStore.setHeader(newAnchorBlockHeader);
85
+ });
75
86
  break;
76
87
  }
77
88
  }
@@ -85,7 +85,6 @@ export async function executePrivateFunction(
85
85
 
86
86
  const rawReturnValues = await privateExecutionOracle.privateLoadFromExecutionCache(publicInputs.returnsHash);
87
87
 
88
- const noteHashLeafIndexMap = privateExecutionOracle.getNoteHashLeafIndexMap();
89
88
  const newNotes = privateExecutionOracle.getNewNotes();
90
89
  const noteHashNullifierCounterMap = privateExecutionOracle.getNoteHashNullifierCounterMap();
91
90
  const offchainEffects = privateExecutionOracle.getOffchainEffects();
@@ -108,7 +107,6 @@ export async function executePrivateFunction(
108
107
  Buffer.from(artifact.verificationKey!, 'base64'),
109
108
  partialWitness,
110
109
  publicInputs,
111
- noteHashLeafIndexMap,
112
110
  newNotes,
113
111
  noteHashNullifierCounterMap,
114
112
  rawReturnValues,
@@ -14,7 +14,7 @@ import {
14
14
  } from '@aztec/stdlib/abi';
15
15
  import type { AuthWitness } from '@aztec/stdlib/auth-witness';
16
16
  import { AztecAddress } from '@aztec/stdlib/aztec-address';
17
- import { computeUniqueNoteHash, siloNoteHash, siloNullifier } from '@aztec/stdlib/hash';
17
+ import { siloNullifier } from '@aztec/stdlib/hash';
18
18
  import type { AztecNode } from '@aztec/stdlib/interfaces/client';
19
19
  import { PrivateContextInputs } from '@aztec/stdlib/kernel';
20
20
  import { type ContractClassLog, DirectionalAppTaggingSecret, type PreTag } from '@aztec/stdlib/logs';
@@ -64,16 +64,6 @@ export class PrivateExecutionOracle extends UtilityExecutionOracle implements IP
64
64
  * Users can also use this to get a clearer idea of what's happened during a simulation.
65
65
  */
66
66
  private newNotes: NoteAndSlot[] = [];
67
- /**
68
- * Notes from previous transactions that are returned to the oracle call `getNotes` during this execution.
69
- * The mapping maps from the unique siloed note hash to the index for notes created in private executions.
70
- * It maps from siloed note hash to the index for notes created by public functions.
71
- *
72
- * They are not part of the ExecutionNoteCache and being forwarded to nested contexts via `extend()`
73
- * because these notes are meant to be maintained on a per-call basis
74
- * They should act as references for the read requests output by an app circuit via public inputs.
75
- */
76
- private noteHashLeafIndexMap: Map<bigint, bigint> = new Map();
77
67
  private noteHashNullifierCounterMap: Map<number, number> = new Map();
78
68
  private contractClassLogs: CountedContractClassLog[] = [];
79
69
  private offchainEffects: { data: Fr[] }[] = [];
@@ -162,14 +152,6 @@ export class PrivateExecutionOracle extends UtilityExecutionOracle implements IP
162
152
  return toACVMWitness(0, fields);
163
153
  }
164
154
 
165
- /**
166
- * The KernelProver will use this to fully populate witnesses and provide hints to the kernel circuit
167
- * regarding which note hash each settled read request corresponds to.
168
- */
169
- public getNoteHashLeafIndexMap() {
170
- return this.noteHashLeafIndexMap;
171
- }
172
-
173
155
  /**
174
156
  * Get the data for the newly created notes.
175
157
  */
@@ -404,23 +386,6 @@ export class PrivateExecutionOracle extends UtilityExecutionOracle implements IP
404
386
  .join(', ')}`,
405
387
  );
406
388
 
407
- const noteHashesAndIndexes = await Promise.all(
408
- notes.map(async n => {
409
- if (n.index !== undefined) {
410
- const siloedNoteHash = await siloNoteHash(n.contractAddress, n.noteHash);
411
- const uniqueNoteHash = await computeUniqueNoteHash(n.noteNonce, siloedNoteHash);
412
-
413
- return { hash: uniqueNoteHash, index: n.index };
414
- }
415
- }),
416
- );
417
-
418
- noteHashesAndIndexes
419
- .filter(n => n !== undefined)
420
- .forEach(n => {
421
- this.noteHashLeafIndexMap.set(n!.hash.toBigInt(), n!.index);
422
- });
423
-
424
389
  return notes;
425
390
  }
426
391
 
@@ -354,6 +354,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
354
354
  this.recipientTaggingStore,
355
355
  this.senderAddressBookStore,
356
356
  this.addressStore,
357
+ this.jobId,
357
358
  );
358
359
 
359
360
  await logService.syncTaggedLogs(this.contractAddress, pendingTaggedLogArrayBaseSlot, this.scopes);
@@ -385,11 +386,11 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
385
386
  // We read all note and event validation requests and process them all concurrently. This makes the process much
386
387
  // faster as we don't need to wait for the network round-trip.
387
388
  const noteValidationRequests = (
388
- await this.capsuleStore.readCapsuleArray(contractAddress, noteValidationRequestsArrayBaseSlot)
389
+ await this.capsuleStore.readCapsuleArray(contractAddress, noteValidationRequestsArrayBaseSlot, this.jobId)
389
390
  ).map(NoteValidationRequest.fromFields);
390
391
 
391
392
  const eventValidationRequests = (
392
- await this.capsuleStore.readCapsuleArray(contractAddress, eventValidationRequestsArrayBaseSlot)
393
+ await this.capsuleStore.readCapsuleArray(contractAddress, eventValidationRequestsArrayBaseSlot, this.jobId)
393
394
  ).map(EventValidationRequest.fromFields);
394
395
 
395
396
  const noteService = new NoteService(this.noteStore, this.aztecNode, this.anchorBlockStore);
@@ -424,8 +425,8 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
424
425
  await Promise.all([...noteDeliveries, ...eventDeliveries]);
425
426
 
426
427
  // Requests are cleared once we're done.
427
- await this.capsuleStore.setCapsuleArray(contractAddress, noteValidationRequestsArrayBaseSlot, []);
428
- await this.capsuleStore.setCapsuleArray(contractAddress, eventValidationRequestsArrayBaseSlot, []);
428
+ await this.capsuleStore.setCapsuleArray(contractAddress, noteValidationRequestsArrayBaseSlot, [], this.jobId);
429
+ await this.capsuleStore.setCapsuleArray(contractAddress, eventValidationRequestsArrayBaseSlot, [], this.jobId);
429
430
  }
430
431
 
431
432
  public async utilityBulkRetrieveLogs(
@@ -441,7 +442,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
441
442
  // We read all log retrieval requests and process them all concurrently. This makes the process much faster as we
442
443
  // don't need to wait for the network round-trip.
443
444
  const logRetrievalRequests = (
444
- await this.capsuleStore.readCapsuleArray(contractAddress, logRetrievalRequestsArrayBaseSlot)
445
+ await this.capsuleStore.readCapsuleArray(contractAddress, logRetrievalRequestsArrayBaseSlot, this.jobId)
445
446
  ).map(LogRetrievalRequest.fromFields);
446
447
 
447
448
  const logService = new LogService(
@@ -452,18 +453,20 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
452
453
  this.recipientTaggingStore,
453
454
  this.senderAddressBookStore,
454
455
  this.addressStore,
456
+ this.jobId,
455
457
  );
456
458
 
457
459
  const maybeLogRetrievalResponses = await logService.bulkRetrieveLogs(logRetrievalRequests);
458
460
 
459
461
  // Requests are cleared once we're done.
460
- await this.capsuleStore.setCapsuleArray(contractAddress, logRetrievalRequestsArrayBaseSlot, []);
462
+ await this.capsuleStore.setCapsuleArray(contractAddress, logRetrievalRequestsArrayBaseSlot, [], this.jobId);
461
463
 
462
464
  // The responses are stored as Option<LogRetrievalResponse> in a second CapsuleArray.
463
465
  await this.capsuleStore.setCapsuleArray(
464
466
  contractAddress,
465
467
  logRetrievalResponsesArrayBaseSlot,
466
468
  maybeLogRetrievalResponses.map(LogRetrievalResponse.toSerializedOption),
469
+ this.jobId,
467
470
  );
468
471
  }
469
472
 
@@ -472,7 +475,8 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
472
475
  // TODO(#10727): instead of this check that this.contractAddress is allowed to access the external DB
473
476
  throw new Error(`Contract ${contractAddress} is not allowed to access ${this.contractAddress}'s PXE DB`);
474
477
  }
475
- return this.capsuleStore.storeCapsule(this.contractAddress, slot, capsule);
478
+ this.capsuleStore.storeCapsule(this.contractAddress, slot, capsule, this.jobId);
479
+ return Promise.resolve();
476
480
  }
477
481
 
478
482
  public async utilityLoadCapsule(contractAddress: AztecAddress, slot: Fr): Promise<Fr[] | null> {
@@ -483,7 +487,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
483
487
  return (
484
488
  // TODO(#12425): On the following line, the pertinent capsule gets overshadowed by the transient one. Tackle this.
485
489
  this.capsules.find(c => c.contractAddress.equals(contractAddress) && c.storageSlot.equals(slot))?.data ??
486
- (await this.capsuleStore.loadCapsule(this.contractAddress, slot))
490
+ (await this.capsuleStore.loadCapsule(this.contractAddress, slot, this.jobId))
487
491
  );
488
492
  }
489
493
 
@@ -492,7 +496,8 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
492
496
  // TODO(#10727): instead of this check that this.contractAddress is allowed to access the external DB
493
497
  throw new Error(`Contract ${contractAddress} is not allowed to access ${this.contractAddress}'s PXE DB`);
494
498
  }
495
- return this.capsuleStore.deleteCapsule(this.contractAddress, slot);
499
+ this.capsuleStore.deleteCapsule(this.contractAddress, slot, this.jobId);
500
+ return Promise.resolve();
496
501
  }
497
502
 
498
503
  public utilityCopyCapsule(
@@ -505,7 +510,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
505
510
  // TODO(#10727): instead of this check that this.contractAddress is allowed to access the external DB
506
511
  throw new Error(`Contract ${contractAddress} is not allowed to access ${this.contractAddress}'s PXE DB`);
507
512
  }
508
- return this.capsuleStore.copyCapsule(this.contractAddress, srcSlot, dstSlot, numEntries);
513
+ return this.capsuleStore.copyCapsule(this.contractAddress, srcSlot, dstSlot, numEntries, this.jobId);
509
514
  }
510
515
 
511
516
  // TODO(#11849): consider replacing this oracle with a pure Noir implementation of aes decryption.
@@ -26,6 +26,7 @@ export class LogService {
26
26
  private readonly recipientTaggingStore: RecipientTaggingStore,
27
27
  private readonly senderAddressBookStore: SenderAddressBookStore,
28
28
  private readonly addressStore: AddressStore,
29
+ private readonly jobId: string,
29
30
  ) {}
30
31
 
31
32
  public async bulkRetrieveLogs(logRetrievalRequests: LogRetrievalRequest[]): Promise<(LogRetrievalResponse | null)[]> {
@@ -186,7 +187,7 @@ export class LogService {
186
187
  });
187
188
 
188
189
  // TODO: This looks like it could belong more at the oracle interface level
189
- return this.capsuleStore.appendToCapsuleArray(contractAddress, capsuleArrayBaseSlot, pendingTaggedLogs);
190
+ return this.capsuleStore.appendToCapsuleArray(contractAddress, capsuleArrayBaseSlot, pendingTaggedLogs, this.jobId);
190
191
  }
191
192
 
192
193
  async #getCompleteAddress(account: AztecAddress): Promise<CompleteAddress> {
@@ -138,7 +138,7 @@ export class PrivateKernelResetPrivateInputsBuilder {
138
138
  }
139
139
  }
140
140
 
141
- async build(oracle: PrivateKernelOracle, noteHashLeafIndexMap: Map<bigint, bigint>) {
141
+ async build(oracle: PrivateKernelOracle) {
142
142
  if (privateKernelResetDimensionNames.every(name => !this.requestedDimensions[name])) {
143
143
  throw new Error('Reset is not required.');
144
144
  }
@@ -190,7 +190,6 @@ export class PrivateKernelResetPrivateInputsBuilder {
190
190
  this.previousKernel.validationRequests.noteHashReadRequests,
191
191
  this.previousKernel.end.noteHashes,
192
192
  this.noteHashResetActions,
193
- noteHashLeafIndexMap,
194
193
  ),
195
194
  await buildNullifierReadRequestHintsFromResetActions(
196
195
  { getNullifierMembershipWitness: getNullifierMembershipWitnessResolver(oracle) },