@aztec/pxe 0.0.1-commit.54489865 → 0.0.1-commit.592b9384

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 (85) hide show
  1. package/dest/contract_function_simulator/contract_function_simulator.d.ts +2 -4
  2. package/dest/contract_function_simulator/contract_function_simulator.d.ts.map +1 -1
  3. package/dest/contract_function_simulator/contract_function_simulator.js +3 -5
  4. package/dest/contract_function_simulator/oracle/interfaces.d.ts +7 -7
  5. package/dest/contract_function_simulator/oracle/interfaces.d.ts.map +1 -1
  6. package/dest/contract_function_simulator/oracle/oracle.d.ts +3 -3
  7. package/dest/contract_function_simulator/oracle/oracle.d.ts.map +1 -1
  8. package/dest/contract_function_simulator/oracle/oracle.js +9 -9
  9. package/dest/contract_function_simulator/oracle/private_execution_oracle.d.ts +2 -3
  10. package/dest/contract_function_simulator/oracle/private_execution_oracle.d.ts.map +1 -1
  11. package/dest/contract_function_simulator/oracle/private_execution_oracle.js +4 -4
  12. package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts +15 -11
  13. package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts.map +1 -1
  14. package/dest/contract_function_simulator/oracle/utility_execution_oracle.js +23 -19
  15. package/dest/entrypoints/client/bundle/utils.d.ts +1 -1
  16. package/dest/entrypoints/client/bundle/utils.d.ts.map +1 -1
  17. package/dest/entrypoints/client/bundle/utils.js +2 -1
  18. package/dest/entrypoints/client/lazy/utils.d.ts +1 -1
  19. package/dest/entrypoints/client/lazy/utils.d.ts.map +1 -1
  20. package/dest/entrypoints/client/lazy/utils.js +2 -1
  21. package/dest/events/event_service.d.ts +4 -5
  22. package/dest/events/event_service.d.ts.map +1 -1
  23. package/dest/events/event_service.js +5 -6
  24. package/dest/logs/log_service.d.ts +4 -4
  25. package/dest/logs/log_service.d.ts.map +1 -1
  26. package/dest/logs/log_service.js +7 -10
  27. package/dest/notes/note_service.d.ts +4 -5
  28. package/dest/notes/note_service.d.ts.map +1 -1
  29. package/dest/notes/note_service.js +6 -7
  30. package/dest/oracle_version.d.ts +3 -3
  31. package/dest/oracle_version.d.ts.map +1 -1
  32. package/dest/oracle_version.js +2 -2
  33. package/dest/pxe.d.ts +1 -1
  34. package/dest/pxe.d.ts.map +1 -1
  35. package/dest/pxe.js +1 -1
  36. package/dest/storage/address_store/address_store.d.ts +1 -1
  37. package/dest/storage/address_store/address_store.d.ts.map +1 -1
  38. package/dest/storage/address_store/address_store.js +12 -11
  39. package/dest/storage/anchor_block_store/anchor_block_store.d.ts +9 -1
  40. package/dest/storage/anchor_block_store/anchor_block_store.d.ts.map +1 -1
  41. package/dest/storage/anchor_block_store/anchor_block_store.js +8 -1
  42. package/dest/storage/capsule_store/capsule_store.js +6 -8
  43. package/dest/storage/contract_store/contract_store.d.ts +1 -1
  44. package/dest/storage/contract_store/contract_store.d.ts.map +1 -1
  45. package/dest/storage/contract_store/contract_store.js +22 -13
  46. package/dest/storage/metadata.d.ts +1 -1
  47. package/dest/storage/metadata.js +1 -1
  48. package/dest/storage/note_store/note_store.d.ts +11 -1
  49. package/dest/storage/note_store/note_store.d.ts.map +1 -1
  50. package/dest/storage/note_store/note_store.js +169 -129
  51. package/dest/storage/private_event_store/private_event_store.d.ts +1 -1
  52. package/dest/storage/private_event_store/private_event_store.d.ts.map +1 -1
  53. package/dest/storage/private_event_store/private_event_store.js +126 -101
  54. package/dest/storage/tagging_store/recipient_tagging_store.d.ts +1 -1
  55. package/dest/storage/tagging_store/recipient_tagging_store.d.ts.map +1 -1
  56. package/dest/storage/tagging_store/recipient_tagging_store.js +31 -19
  57. package/dest/storage/tagging_store/sender_address_book_store.d.ts +1 -1
  58. package/dest/storage/tagging_store/sender_address_book_store.d.ts.map +1 -1
  59. package/dest/storage/tagging_store/sender_address_book_store.js +20 -14
  60. package/dest/storage/tagging_store/sender_tagging_store.d.ts +1 -1
  61. package/dest/storage/tagging_store/sender_tagging_store.d.ts.map +1 -1
  62. package/dest/storage/tagging_store/sender_tagging_store.js +183 -113
  63. package/package.json +16 -16
  64. package/src/contract_function_simulator/contract_function_simulator.ts +0 -4
  65. package/src/contract_function_simulator/oracle/interfaces.ts +8 -8
  66. package/src/contract_function_simulator/oracle/oracle.ts +21 -11
  67. package/src/contract_function_simulator/oracle/private_execution_oracle.ts +1 -5
  68. package/src/contract_function_simulator/oracle/utility_execution_oracle.ts +24 -20
  69. package/src/entrypoints/client/bundle/utils.ts +3 -1
  70. package/src/entrypoints/client/lazy/utils.ts +3 -1
  71. package/src/events/event_service.ts +4 -6
  72. package/src/logs/log_service.ts +6 -9
  73. package/src/notes/note_service.ts +5 -7
  74. package/src/oracle_version.ts +2 -2
  75. package/src/pxe.ts +0 -1
  76. package/src/storage/address_store/address_store.ts +15 -15
  77. package/src/storage/anchor_block_store/anchor_block_store.ts +8 -0
  78. package/src/storage/capsule_store/capsule_store.ts +8 -8
  79. package/src/storage/contract_store/contract_store.ts +22 -11
  80. package/src/storage/metadata.ts +1 -1
  81. package/src/storage/note_store/note_store.ts +185 -150
  82. package/src/storage/private_event_store/private_event_store.ts +151 -128
  83. package/src/storage/tagging_store/recipient_tagging_store.ts +31 -21
  84. package/src/storage/tagging_store/sender_address_book_store.ts +20 -14
  85. package/src/storage/tagging_store/sender_tagging_store.ts +210 -126
@@ -1,6 +1,5 @@
1
1
  import { BlockNumber } from '@aztec/foundation/branded-types';
2
2
  import { Fr } from '@aztec/foundation/curves/bn254';
3
- import { toArray } from '@aztec/foundation/iterable';
4
3
  import { createLogger } from '@aztec/foundation/log';
5
4
  import { Semaphore } from '@aztec/foundation/queue';
6
5
  import type { AztecAsyncKVStore, AztecAsyncMap, AztecAsyncMultiMap } from '@aztec/kv-store';
@@ -81,43 +80,45 @@ export class PrivateEventStore implements StagedStore {
81
80
  metadata: PrivateEventMetadata,
82
81
  jobId: string,
83
82
  ) {
84
- return this.#withJobLock(jobId, async () => {
85
- const { contractAddress, scope, txHash, l2BlockNumber, l2BlockHash, txIndexInBlock, eventIndexInTx } = metadata;
86
- const eventId = siloedEventCommitment.toString();
87
-
88
- this.logger.verbose('storing private event log (job stage)', {
89
- eventId,
90
- contractAddress,
91
- scope,
92
- msgContent,
93
- l2BlockNumber,
94
- });
95
-
96
- const existing = await this.#readEvent(eventId, jobId);
83
+ return this.#withJobLock(jobId, () =>
84
+ this.#store.transactionAsync(async () => {
85
+ const { contractAddress, scope, txHash, l2BlockNumber, l2BlockHash, txIndexInBlock, eventIndexInTx } = metadata;
86
+ const eventId = siloedEventCommitment.toString();
97
87
 
98
- if (existing) {
99
- // If we already stored this event, we still want to make sure to track it for the given scope
100
- existing.addScope(scope.toString());
101
- this.#writeEvent(eventId, existing, jobId);
102
- } else {
103
- this.#writeEvent(
88
+ this.logger.verbose('storing private event log (job stage)', {
104
89
  eventId,
105
- new StoredPrivateEvent(
106
- randomness,
107
- msgContent,
108
- l2BlockNumber,
109
- l2BlockHash,
110
- txHash,
111
- txIndexInBlock,
112
- eventIndexInTx,
113
- contractAddress,
114
- eventSelector,
115
- new Set([scope.toString()]),
116
- ),
117
- jobId,
118
- );
119
- }
120
- });
90
+ contractAddress,
91
+ scope,
92
+ msgContent,
93
+ l2BlockNumber,
94
+ });
95
+
96
+ const existing = await this.#readEvent(eventId, jobId);
97
+
98
+ if (existing) {
99
+ // If we already stored this event, we still want to make sure to track it for the given scope
100
+ existing.addScope(scope.toString());
101
+ this.#writeEvent(eventId, existing, jobId);
102
+ } else {
103
+ this.#writeEvent(
104
+ eventId,
105
+ new StoredPrivateEvent(
106
+ randomness,
107
+ msgContent,
108
+ l2BlockNumber,
109
+ l2BlockHash,
110
+ txHash,
111
+ txIndexInBlock,
112
+ eventIndexInTx,
113
+ contractAddress,
114
+ eventSelector,
115
+ new Set([scope.toString()]),
116
+ ),
117
+ jobId,
118
+ );
119
+ }
120
+ }),
121
+ );
121
122
  }
122
123
 
123
124
  /**
@@ -131,76 +132,88 @@ export class PrivateEventStore implements StagedStore {
131
132
  * @returns - The event log contents, augmented with metadata about the transaction and block in which the event was
132
133
  * included.
133
134
  */
134
- public async getPrivateEvents(
135
+ public getPrivateEvents(
135
136
  eventSelector: EventSelector,
136
137
  filter: PrivateEventStoreFilter,
137
138
  ): Promise<PackedPrivateEvent[]> {
138
- const events: Array<{
139
- l2BlockNumber: number;
140
- txIndexInBlock: number;
141
- eventIndexInTx: number;
142
- event: PackedPrivateEvent;
143
- }> = [];
139
+ return this.#store.transactionAsync(async () => {
140
+ const key = this.#keyFor(filter.contractAddress, eventSelector);
141
+ const targetScopes = new Set(filter.scopes.map(s => s.toString()));
144
142
 
145
- const key = this.#keyFor(filter.contractAddress, eventSelector);
146
- const targetScopes = new Set(filter.scopes.map(s => s.toString()));
143
+ // Map from eventId to the promise that reads the event buffer.
144
+ // We start reads during iteration to keep DB requests pending and avoid IndexedDB auto-commit.
145
+ const eventReadPromises: Map<string, Promise<Buffer | undefined>> = new Map();
147
146
 
148
- const eventIds: string[] = await toArray(this.#eventsByContractAndEventSelector.getValuesAsync(key));
147
+ for await (const eventId of this.#eventsByContractAndEventSelector.getValuesAsync(key)) {
148
+ eventReadPromises.set(eventId, this.#events.getAsync(eventId));
149
+ }
149
150
 
150
- for (const eventId of eventIds) {
151
- const eventBuffer = await this.#events.getAsync(eventId);
151
+ const eventIds = [...eventReadPromises.keys()];
152
+ const eventBuffers = await Promise.all(eventReadPromises.values());
152
153
 
153
- // Defensive, if it happens, there's a problem with how we're handling #eventsByContractAndEventSelector
154
- if (!eventBuffer) {
155
- this.logger.verbose(
156
- `EventId ${eventId} does not exist in main index but it is referenced from contract event selector index`,
157
- );
158
- continue;
159
- }
154
+ const events: Array<{
155
+ l2BlockNumber: number;
156
+ txIndexInBlock: number;
157
+ eventIndexInTx: number;
158
+ event: PackedPrivateEvent;
159
+ }> = [];
160
160
 
161
- const storedPrivateEvent = StoredPrivateEvent.fromBuffer(eventBuffer);
161
+ for (let i = 0; i < eventIds.length; i++) {
162
+ const eventId = eventIds[i];
163
+ const eventBuffer = eventBuffers[i];
162
164
 
163
- // Filter by block range
164
- if (storedPrivateEvent.l2BlockNumber < filter.fromBlock || storedPrivateEvent.l2BlockNumber >= filter.toBlock) {
165
- continue;
166
- }
165
+ // Defensive, if it happens, there's a problem with how we're handling #eventsByContractAndEventSelector
166
+ if (!eventBuffer) {
167
+ this.logger.verbose(
168
+ `EventId ${eventId} does not exist in main index but it is referenced from contract event selector index`,
169
+ );
170
+ continue;
171
+ }
167
172
 
168
- // Filter by scopes
169
- if (storedPrivateEvent.scopes.intersection(targetScopes).size === 0) {
170
- continue;
171
- }
173
+ const storedPrivateEvent = StoredPrivateEvent.fromBuffer(eventBuffer);
174
+
175
+ // Filter by block range
176
+ if (storedPrivateEvent.l2BlockNumber < filter.fromBlock || storedPrivateEvent.l2BlockNumber >= filter.toBlock) {
177
+ continue;
178
+ }
172
179
 
173
- // Filter by txHash
174
- if (filter.txHash && !storedPrivateEvent.txHash.equals(filter.txHash)) {
175
- continue;
180
+ // Filter by scopes
181
+ if (storedPrivateEvent.scopes.intersection(targetScopes).size === 0) {
182
+ continue;
183
+ }
184
+
185
+ // Filter by txHash
186
+ if (filter.txHash && !storedPrivateEvent.txHash.equals(filter.txHash)) {
187
+ continue;
188
+ }
189
+
190
+ events.push({
191
+ l2BlockNumber: storedPrivateEvent.l2BlockNumber,
192
+ txIndexInBlock: storedPrivateEvent.txIndexInBlock,
193
+ eventIndexInTx: storedPrivateEvent.eventIndexInTx,
194
+ event: {
195
+ packedEvent: storedPrivateEvent.msgContent,
196
+ l2BlockNumber: BlockNumber(storedPrivateEvent.l2BlockNumber),
197
+ txHash: storedPrivateEvent.txHash,
198
+ l2BlockHash: storedPrivateEvent.l2BlockHash,
199
+ eventSelector,
200
+ },
201
+ });
176
202
  }
177
203
 
178
- events.push({
179
- l2BlockNumber: storedPrivateEvent.l2BlockNumber,
180
- txIndexInBlock: storedPrivateEvent.txIndexInBlock,
181
- eventIndexInTx: storedPrivateEvent.eventIndexInTx,
182
- event: {
183
- packedEvent: storedPrivateEvent.msgContent,
184
- l2BlockNumber: BlockNumber(storedPrivateEvent.l2BlockNumber),
185
- txHash: storedPrivateEvent.txHash,
186
- l2BlockHash: storedPrivateEvent.l2BlockHash,
187
- eventSelector,
188
- },
204
+ // Sort by block number, then by tx index within block, then by event index within tx
205
+ events.sort((a, b) => {
206
+ if (a.l2BlockNumber !== b.l2BlockNumber) {
207
+ return a.l2BlockNumber - b.l2BlockNumber;
208
+ }
209
+ if (a.txIndexInBlock !== b.txIndexInBlock) {
210
+ return a.txIndexInBlock - b.txIndexInBlock;
211
+ }
212
+ return a.eventIndexInTx - b.eventIndexInTx;
189
213
  });
190
- }
191
214
 
192
- // Sort by block number, then by tx index within block, then by event index within tx
193
- events.sort((a, b) => {
194
- if (a.l2BlockNumber !== b.l2BlockNumber) {
195
- return a.l2BlockNumber - b.l2BlockNumber;
196
- }
197
- if (a.txIndexInBlock !== b.txIndexInBlock) {
198
- return a.txIndexInBlock - b.txIndexInBlock;
199
- }
200
- return a.eventIndexInTx - b.eventIndexInTx;
215
+ return events.map(ev => ev.event);
201
216
  });
202
-
203
- return events.map(ev => ev.event);
204
217
  }
205
218
 
206
219
  /**
@@ -221,29 +234,39 @@ export class PrivateEventStore implements StagedStore {
221
234
  * IMPORTANT: This method must be called within a transaction to ensure atomicity.
222
235
  */
223
236
  public async rollback(blockNumber: number, synchedBlockNumber: number): Promise<void> {
224
- let removedCount = 0;
237
+ // First pass: collect all event IDs for all blocks, starting reads during iteration to keep tx alive.
238
+ const eventsByBlock: Map<number, { eventId: string; eventReadPromise: Promise<Buffer | undefined> }[]> = new Map();
225
239
 
226
240
  for (let block = blockNumber + 1; block <= synchedBlockNumber; block++) {
227
- const eventIds: string[] = await toArray(this.#eventsByBlockNumber.getValuesAsync(block));
241
+ const blockEvents: { eventId: string; eventReadPromise: Promise<Buffer | undefined> }[] = [];
242
+ for await (const eventId of this.#eventsByBlockNumber.getValuesAsync(block)) {
243
+ // Start read immediately during iteration to keep IndexedDB transaction alive
244
+ blockEvents.push({ eventId, eventReadPromise: this.#events.getAsync(eventId) });
245
+ }
246
+ if (blockEvents.length > 0) {
247
+ eventsByBlock.set(block, blockEvents);
248
+ }
249
+ }
228
250
 
229
- if (eventIds.length > 0) {
230
- await this.#eventsByBlockNumber.delete(block);
251
+ // Second pass: await reads and perform deletes
252
+ let removedCount = 0;
253
+ for (const [block, events] of eventsByBlock) {
254
+ await this.#eventsByBlockNumber.delete(block);
231
255
 
232
- for (const eventId of eventIds) {
233
- const buffer = await this.#events.getAsync(eventId);
234
- if (!buffer) {
235
- throw new Error(`Event not found for eventId ${eventId}`);
236
- }
256
+ for (const { eventId, eventReadPromise } of events) {
257
+ const buffer = await eventReadPromise;
258
+ if (!buffer) {
259
+ throw new Error(`Event not found for eventId ${eventId}`);
260
+ }
237
261
 
238
- const entry = StoredPrivateEvent.fromBuffer(buffer);
239
- await this.#events.delete(eventId);
240
- await this.#eventsByContractAndEventSelector.deleteValue(
241
- this.#keyFor(entry.contractAddress, entry.eventSelector),
242
- eventId,
243
- );
262
+ const entry = StoredPrivateEvent.fromBuffer(buffer);
263
+ await this.#events.delete(eventId);
264
+ await this.#eventsByContractAndEventSelector.deleteValue(
265
+ this.#keyFor(entry.contractAddress, entry.eventSelector),
266
+ eventId,
267
+ );
244
268
 
245
- removedCount++;
246
- }
269
+ removedCount++;
247
270
  }
248
271
  }
249
272
 
@@ -260,28 +283,30 @@ export class PrivateEventStore implements StagedStore {
260
283
  *
261
284
  * @param jobId - The jobId identifying which staged data to commit
262
285
  */
263
- commit(jobId: string): Promise<void> {
264
- return this.#withJobLock(jobId, async () => {
265
- for (const [eventId, entry] of this.#getEventsForJob(jobId).entries()) {
266
- const lookupKey = this.#keyFor(entry.contractAddress, entry.eventSelector);
267
- this.logger.verbose('storing private event log', { eventId, lookupKey });
268
-
269
- await Promise.all([
270
- this.#events.set(eventId, entry.toBuffer()),
271
- this.#eventsByContractAndEventSelector.set(lookupKey, eventId),
272
- this.#eventsByBlockNumber.set(entry.l2BlockNumber, eventId),
273
- ]);
274
- }
286
+ async commit(jobId: string): Promise<void> {
287
+ // Note: Don't use #withJobLock here - commit runs within JobCoordinator's transactionAsync,
288
+ // and awaiting the lock would create a microtask boundary with no pending DB request,
289
+ // causing IndexedDB to auto-commit the transaction.
290
+ for (const [eventId, entry] of this.#getEventsForJob(jobId).entries()) {
291
+ const lookupKey = this.#keyFor(entry.contractAddress, entry.eventSelector);
292
+ this.logger.verbose('storing private event log', { eventId, lookupKey });
293
+
294
+ await Promise.all([
295
+ this.#events.set(eventId, entry.toBuffer()),
296
+ this.#eventsByContractAndEventSelector.set(lookupKey, eventId),
297
+ this.#eventsByBlockNumber.set(entry.l2BlockNumber, eventId),
298
+ ]);
299
+ }
275
300
 
276
- this.#clearJobData(jobId);
277
- });
301
+ this.#clearJobData(jobId);
278
302
  }
279
303
 
280
304
  /**
281
305
  * Discards in memory job data without persisting it.
282
306
  */
283
307
  discardStaged(jobId: string): Promise<void> {
284
- return this.#withJobLock(jobId, () => Promise.resolve(this.#clearJobData(jobId)));
308
+ this.#clearJobData(jobId);
309
+ return Promise.resolve();
285
310
  }
286
311
 
287
312
  /**
@@ -290,13 +315,11 @@ export class PrivateEventStore implements StagedStore {
290
315
  * Returns undefined if the event does not exist in the store overall.
291
316
  */
292
317
  async #readEvent(eventId: string, jobId: string): Promise<StoredPrivateEvent | undefined> {
293
- const eventForJob = this.#getEventsForJob(jobId).get(eventId);
294
- if (eventForJob) {
295
- return eventForJob;
296
- }
297
-
318
+ // Always issue DB read to keep IndexedDB transaction alive (they auto-commit when a new micro-task starts and there
319
+ // are no pending read requests). The staged value still takes precedence if it exists.
298
320
  const buffer = await this.#events.getAsync(eventId);
299
- return buffer ? StoredPrivateEvent.fromBuffer(buffer) : undefined;
321
+ const eventForJob = this.#getEventsForJob(jobId).get(eventId);
322
+ return eventForJob ?? (buffer ? StoredPrivateEvent.fromBuffer(buffer) : undefined);
300
323
  }
301
324
 
302
325
  /**
@@ -45,7 +45,11 @@ export class RecipientTaggingStore implements StagedStore {
45
45
  }
46
46
 
47
47
  async #readHighestAgedIndex(jobId: string, secret: string): Promise<number | undefined> {
48
- return this.#getHighestAgedIndexForJob(jobId).get(secret) ?? (await this.#highestAgedIndex.getAsync(secret));
48
+ // Always issue DB read to keep IndexedDB transaction alive (they auto-commit when a new micro-task starts and there
49
+ // are no pending read requests). The staged value still takes precedence if it exists.
50
+ const dbValue = await this.#highestAgedIndex.getAsync(secret);
51
+ const staged = this.#getHighestAgedIndexForJob(jobId).get(secret);
52
+ return staged ?? dbValue;
49
53
  }
50
54
 
51
55
  #writeHighestAgedIndex(jobId: string, secret: string, index: number) {
@@ -62,9 +66,11 @@ export class RecipientTaggingStore implements StagedStore {
62
66
  }
63
67
 
64
68
  async #readHighestFinalizedIndex(jobId: string, secret: string): Promise<number | undefined> {
65
- return (
66
- this.#getHighestFinalizedIndexForJob(jobId).get(secret) ?? (await this.#highestFinalizedIndex.getAsync(secret))
67
- );
69
+ // Always issue DB read to keep IndexedDB transaction alive (they auto-commit when a new micro-task starts and there
70
+ // are no pending read requests). The staged value still takes precedence if it exists.
71
+ const dbValue = await this.#highestFinalizedIndex.getAsync(secret);
72
+ const staged = this.#getHighestFinalizedIndexForJob(jobId).get(secret);
73
+ return staged ?? dbValue;
68
74
  }
69
75
 
70
76
  #writeHighestFinalizedIndex(jobId: string, secret: string, index: number) {
@@ -101,29 +107,33 @@ export class RecipientTaggingStore implements StagedStore {
101
107
  }
102
108
 
103
109
  getHighestAgedIndex(secret: DirectionalAppTaggingSecret, jobId: string): Promise<number | undefined> {
104
- return this.#readHighestAgedIndex(jobId, secret.toString());
110
+ return this.#store.transactionAsync(() => this.#readHighestAgedIndex(jobId, secret.toString()));
105
111
  }
106
112
 
107
- async updateHighestAgedIndex(secret: DirectionalAppTaggingSecret, index: number, jobId: string): Promise<void> {
108
- const currentIndex = await this.#readHighestAgedIndex(jobId, secret.toString());
109
- if (currentIndex !== undefined && index <= currentIndex) {
110
- // Log sync should never set a lower highest aged index.
111
- throw new Error(`New highest aged index (${index}) must be higher than the current one (${currentIndex})`);
112
- }
113
- this.#writeHighestAgedIndex(jobId, secret.toString(), index);
113
+ updateHighestAgedIndex(secret: DirectionalAppTaggingSecret, index: number, jobId: string): Promise<void> {
114
+ return this.#store.transactionAsync(async () => {
115
+ const currentIndex = await this.#readHighestAgedIndex(jobId, secret.toString());
116
+ if (currentIndex !== undefined && index <= currentIndex) {
117
+ // Log sync should never set a lower highest aged index.
118
+ throw new Error(`New highest aged index (${index}) must be higher than the current one (${currentIndex})`);
119
+ }
120
+ this.#writeHighestAgedIndex(jobId, secret.toString(), index);
121
+ });
114
122
  }
115
123
 
116
124
  getHighestFinalizedIndex(secret: DirectionalAppTaggingSecret, jobId: string): Promise<number | undefined> {
117
- return this.#readHighestFinalizedIndex(jobId, secret.toString());
125
+ return this.#store.transactionAsync(() => this.#readHighestFinalizedIndex(jobId, secret.toString()));
118
126
  }
119
127
 
120
- async updateHighestFinalizedIndex(secret: DirectionalAppTaggingSecret, index: number, jobId: string): Promise<void> {
121
- const currentIndex = await this.#readHighestFinalizedIndex(jobId, secret.toString());
122
- if (currentIndex !== undefined && index < currentIndex) {
123
- // Log sync should never set a lower highest finalized index but it can happen that it would try to set the same
124
- // one because we are loading logs from highest aged index + 1 and not from the highest finalized index.
125
- throw new Error(`New highest finalized index (${index}) must be higher than the current one (${currentIndex})`);
126
- }
127
- this.#writeHighestFinalizedIndex(jobId, secret.toString(), index);
128
+ updateHighestFinalizedIndex(secret: DirectionalAppTaggingSecret, index: number, jobId: string): Promise<void> {
129
+ return this.#store.transactionAsync(async () => {
130
+ const currentIndex = await this.#readHighestFinalizedIndex(jobId, secret.toString());
131
+ if (currentIndex !== undefined && index < currentIndex) {
132
+ // Log sync should never set a lower highest finalized index but it can happen that it would try to set the same
133
+ // one because we are loading logs from highest aged index + 1 and not from the highest finalized index.
134
+ throw new Error(`New highest finalized index (${index}) must be higher than the current one (${currentIndex})`);
135
+ }
136
+ this.#writeHighestFinalizedIndex(jobId, secret.toString(), index);
137
+ });
128
138
  }
129
139
  }
@@ -16,27 +16,33 @@ export class SenderAddressBookStore {
16
16
  this.#addressBook = this.#store.openMap('address_book');
17
17
  }
18
18
 
19
- async addSender(address: AztecAddress): Promise<boolean> {
20
- if (await this.#addressBook.hasAsync(address.toString())) {
21
- return false;
22
- }
19
+ addSender(address: AztecAddress): Promise<boolean> {
20
+ return this.#store.transactionAsync(async () => {
21
+ if (await this.#addressBook.hasAsync(address.toString())) {
22
+ return false;
23
+ }
23
24
 
24
- await this.#addressBook.set(address.toString(), true);
25
+ await this.#addressBook.set(address.toString(), true);
25
26
 
26
- return true;
27
+ return true;
28
+ });
27
29
  }
28
30
 
29
- async getSenders(): Promise<AztecAddress[]> {
30
- return (await toArray(this.#addressBook.keysAsync())).map(AztecAddress.fromString);
31
+ getSenders(): Promise<AztecAddress[]> {
32
+ return this.#store.transactionAsync(async () => {
33
+ return (await toArray(this.#addressBook.keysAsync())).map(AztecAddress.fromString);
34
+ });
31
35
  }
32
36
 
33
- async removeSender(address: AztecAddress): Promise<boolean> {
34
- if (!(await this.#addressBook.hasAsync(address.toString()))) {
35
- return false;
36
- }
37
+ removeSender(address: AztecAddress): Promise<boolean> {
38
+ return this.#store.transactionAsync(async () => {
39
+ if (!(await this.#addressBook.hasAsync(address.toString()))) {
40
+ return false;
41
+ }
37
42
 
38
- await this.#addressBook.delete(address.toString());
43
+ await this.#addressBook.delete(address.toString());
39
44
 
40
- return true;
45
+ return true;
46
+ });
41
47
  }
42
48
  }