@aztec/pxe 0.0.1-commit.e61ad554 → 0.0.1-commit.f146247c

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 (130) hide show
  1. package/dest/block_synchronizer/block_synchronizer.d.ts +3 -3
  2. package/dest/block_synchronizer/block_synchronizer.d.ts.map +1 -1
  3. package/dest/block_synchronizer/block_synchronizer.js +5 -5
  4. package/dest/contract_function_simulator/contract_function_simulator.d.ts +2 -4
  5. package/dest/contract_function_simulator/contract_function_simulator.d.ts.map +1 -1
  6. package/dest/contract_function_simulator/contract_function_simulator.js +7 -9
  7. package/dest/contract_function_simulator/oracle/interfaces.d.ts +8 -8
  8. package/dest/contract_function_simulator/oracle/interfaces.d.ts.map +1 -1
  9. package/dest/contract_function_simulator/oracle/oracle.d.ts +3 -3
  10. package/dest/contract_function_simulator/oracle/oracle.d.ts.map +1 -1
  11. package/dest/contract_function_simulator/oracle/oracle.js +15 -15
  12. package/dest/contract_function_simulator/oracle/private_execution_oracle.d.ts +2 -3
  13. package/dest/contract_function_simulator/oracle/private_execution_oracle.d.ts.map +1 -1
  14. package/dest/contract_function_simulator/oracle/private_execution_oracle.js +4 -4
  15. package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts +20 -16
  16. package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts.map +1 -1
  17. package/dest/contract_function_simulator/oracle/utility_execution_oracle.js +23 -19
  18. package/dest/debug/pxe_debug_utils.d.ts +16 -6
  19. package/dest/debug/pxe_debug_utils.d.ts.map +1 -1
  20. package/dest/debug/pxe_debug_utils.js +17 -8
  21. package/dest/entrypoints/client/bundle/utils.d.ts +1 -1
  22. package/dest/entrypoints/client/bundle/utils.d.ts.map +1 -1
  23. package/dest/entrypoints/client/bundle/utils.js +12 -6
  24. package/dest/entrypoints/client/lazy/utils.d.ts +2 -2
  25. package/dest/entrypoints/client/lazy/utils.d.ts.map +1 -1
  26. package/dest/entrypoints/client/lazy/utils.js +13 -7
  27. package/dest/entrypoints/pxe_creation_options.d.ts +3 -2
  28. package/dest/entrypoints/pxe_creation_options.d.ts.map +1 -1
  29. package/dest/entrypoints/server/utils.d.ts +1 -1
  30. package/dest/entrypoints/server/utils.d.ts.map +1 -1
  31. package/dest/entrypoints/server/utils.js +19 -8
  32. package/dest/events/event_service.d.ts +4 -5
  33. package/dest/events/event_service.d.ts.map +1 -1
  34. package/dest/events/event_service.js +5 -6
  35. package/dest/job_coordinator/job_coordinator.d.ts +3 -2
  36. package/dest/job_coordinator/job_coordinator.d.ts.map +1 -1
  37. package/dest/job_coordinator/job_coordinator.js +3 -2
  38. package/dest/logs/log_service.d.ts +5 -4
  39. package/dest/logs/log_service.d.ts.map +1 -1
  40. package/dest/logs/log_service.js +8 -11
  41. package/dest/notes/note_service.d.ts +4 -5
  42. package/dest/notes/note_service.d.ts.map +1 -1
  43. package/dest/notes/note_service.js +6 -7
  44. package/dest/oracle_version.d.ts +3 -3
  45. package/dest/oracle_version.d.ts.map +1 -1
  46. package/dest/oracle_version.js +2 -2
  47. package/dest/private_kernel/private_kernel_execution_prover.d.ts +3 -2
  48. package/dest/private_kernel/private_kernel_execution_prover.d.ts.map +1 -1
  49. package/dest/private_kernel/private_kernel_execution_prover.js +2 -2
  50. package/dest/private_kernel/private_kernel_oracle.d.ts +3 -3
  51. package/dest/private_kernel/private_kernel_oracle.d.ts.map +1 -1
  52. package/dest/pxe.d.ts +1 -1
  53. package/dest/pxe.d.ts.map +1 -1
  54. package/dest/pxe.js +8 -6
  55. package/dest/storage/address_store/address_store.d.ts +1 -1
  56. package/dest/storage/address_store/address_store.d.ts.map +1 -1
  57. package/dest/storage/address_store/address_store.js +12 -11
  58. package/dest/storage/anchor_block_store/anchor_block_store.d.ts +9 -1
  59. package/dest/storage/anchor_block_store/anchor_block_store.d.ts.map +1 -1
  60. package/dest/storage/anchor_block_store/anchor_block_store.js +8 -1
  61. package/dest/storage/capsule_store/capsule_store.js +6 -8
  62. package/dest/storage/contract_store/contract_store.d.ts +1 -1
  63. package/dest/storage/contract_store/contract_store.d.ts.map +1 -1
  64. package/dest/storage/contract_store/contract_store.js +22 -13
  65. package/dest/storage/metadata.d.ts +1 -1
  66. package/dest/storage/metadata.js +1 -1
  67. package/dest/storage/note_store/note_store.d.ts +11 -1
  68. package/dest/storage/note_store/note_store.d.ts.map +1 -1
  69. package/dest/storage/note_store/note_store.js +143 -105
  70. package/dest/storage/private_event_store/private_event_store.d.ts +1 -1
  71. package/dest/storage/private_event_store/private_event_store.d.ts.map +1 -1
  72. package/dest/storage/private_event_store/private_event_store.js +84 -61
  73. package/dest/storage/private_event_store/stored_private_event.d.ts +4 -4
  74. package/dest/storage/private_event_store/stored_private_event.d.ts.map +1 -1
  75. package/dest/storage/private_event_store/stored_private_event.js +2 -2
  76. package/dest/storage/tagging_store/recipient_tagging_store.d.ts +1 -1
  77. package/dest/storage/tagging_store/recipient_tagging_store.d.ts.map +1 -1
  78. package/dest/storage/tagging_store/recipient_tagging_store.js +31 -19
  79. package/dest/storage/tagging_store/sender_address_book_store.d.ts +1 -1
  80. package/dest/storage/tagging_store/sender_address_book_store.d.ts.map +1 -1
  81. package/dest/storage/tagging_store/sender_address_book_store.js +20 -14
  82. package/dest/storage/tagging_store/sender_tagging_store.d.ts +1 -1
  83. package/dest/storage/tagging_store/sender_tagging_store.d.ts.map +1 -1
  84. package/dest/storage/tagging_store/sender_tagging_store.js +183 -113
  85. package/dest/tagging/get_all_logs_by_tags.d.ts +4 -4
  86. package/dest/tagging/get_all_logs_by_tags.d.ts.map +1 -1
  87. package/dest/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.d.ts +3 -3
  88. package/dest/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.d.ts.map +1 -1
  89. package/dest/tagging/recipient_sync/utils/load_logs_for_range.d.ts +3 -3
  90. package/dest/tagging/recipient_sync/utils/load_logs_for_range.d.ts.map +1 -1
  91. package/dest/tagging/sender_sync/sync_sender_tagging_indexes.d.ts +3 -3
  92. package/dest/tagging/sender_sync/sync_sender_tagging_indexes.d.ts.map +1 -1
  93. package/dest/tagging/sender_sync/utils/load_and_store_new_tagging_indexes.d.ts +3 -3
  94. package/dest/tagging/sender_sync/utils/load_and_store_new_tagging_indexes.d.ts.map +1 -1
  95. package/package.json +16 -16
  96. package/src/block_synchronizer/block_synchronizer.ts +17 -19
  97. package/src/contract_function_simulator/contract_function_simulator.ts +6 -6
  98. package/src/contract_function_simulator/oracle/interfaces.ts +10 -10
  99. package/src/contract_function_simulator/oracle/oracle.ts +27 -17
  100. package/src/contract_function_simulator/oracle/private_execution_oracle.ts +1 -5
  101. package/src/contract_function_simulator/oracle/utility_execution_oracle.ts +32 -26
  102. package/src/debug/pxe_debug_utils.ts +23 -9
  103. package/src/entrypoints/client/bundle/utils.ts +7 -14
  104. package/src/entrypoints/client/lazy/utils.ts +8 -14
  105. package/src/entrypoints/pxe_creation_options.ts +2 -1
  106. package/src/entrypoints/server/utils.ts +15 -19
  107. package/src/events/event_service.ts +4 -6
  108. package/src/job_coordinator/job_coordinator.ts +4 -3
  109. package/src/logs/log_service.ts +12 -12
  110. package/src/notes/note_service.ts +5 -7
  111. package/src/oracle_version.ts +2 -2
  112. package/src/private_kernel/private_kernel_execution_prover.ts +6 -3
  113. package/src/private_kernel/private_kernel_oracle.ts +2 -2
  114. package/src/pxe.ts +15 -7
  115. package/src/storage/address_store/address_store.ts +15 -15
  116. package/src/storage/anchor_block_store/anchor_block_store.ts +8 -0
  117. package/src/storage/capsule_store/capsule_store.ts +8 -8
  118. package/src/storage/contract_store/contract_store.ts +22 -11
  119. package/src/storage/metadata.ts +1 -1
  120. package/src/storage/note_store/note_store.ts +159 -129
  121. package/src/storage/private_event_store/private_event_store.ts +102 -81
  122. package/src/storage/private_event_store/stored_private_event.ts +3 -3
  123. package/src/storage/tagging_store/recipient_tagging_store.ts +31 -21
  124. package/src/storage/tagging_store/sender_address_book_store.ts +20 -14
  125. package/src/storage/tagging_store/sender_tagging_store.ts +210 -126
  126. package/src/tagging/get_all_logs_by_tags.ts +3 -3
  127. package/src/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.ts +2 -2
  128. package/src/tagging/recipient_sync/utils/load_logs_for_range.ts +2 -2
  129. package/src/tagging/sender_sync/sync_sender_tagging_indexes.ts +2 -2
  130. package/src/tagging/sender_sync/utils/load_and_store_new_tagging_indexes.ts +3 -3
@@ -30,18 +30,19 @@ export class AddressStore {
30
30
  }
31
31
  });
32
32
  }
33
- async #getCompleteAddress(address) {
34
- const index = await this.#completeAddressIndex.getAsync(address.toString());
35
- if (index === undefined) {
36
- return undefined;
37
- }
38
- const value = await this.#completeAddresses.atAsync(index);
39
- return value ? await CompleteAddress.fromBuffer(value) : undefined;
40
- }
41
33
  getCompleteAddress(account) {
42
- return this.#getCompleteAddress(account);
34
+ return this.#store.transactionAsync(async ()=>{
35
+ const index = await this.#completeAddressIndex.getAsync(account.toString());
36
+ if (index === undefined) {
37
+ return undefined;
38
+ }
39
+ const value = await this.#completeAddresses.atAsync(index);
40
+ return value ? await CompleteAddress.fromBuffer(value) : undefined;
41
+ });
43
42
  }
44
- async getCompleteAddresses() {
45
- return await Promise.all((await toArray(this.#completeAddresses.valuesAsync())).map((v)=>CompleteAddress.fromBuffer(v)));
43
+ getCompleteAddresses() {
44
+ return this.#store.transactionAsync(async ()=>{
45
+ return await Promise.all((await toArray(this.#completeAddresses.valuesAsync())).map((v)=>CompleteAddress.fromBuffer(v)));
46
+ });
46
47
  }
47
48
  }
@@ -3,7 +3,15 @@ import { BlockHeader } from '@aztec/stdlib/tx';
3
3
  export declare class AnchorBlockStore {
4
4
  #private;
5
5
  constructor(store: AztecAsyncKVStore);
6
+ /**
7
+ * Sets the currently synchronized block
8
+ *
9
+ * Important: this method is only called from BlockSynchronizer, and since we need it to run atomically with other
10
+ * stores in the case of a reorg, it MUST NOT be wrapped in a `transactionAsync` call. Doing so would result in a
11
+ * deadlock when the backend is IndexedDB, because `transactionAsync` is not designed to support reentrancy.
12
+ *
13
+ */
6
14
  setHeader(header: BlockHeader): Promise<void>;
7
15
  getBlockHeader(): Promise<BlockHeader>;
8
16
  }
9
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYW5jaG9yX2Jsb2NrX3N0b3JlLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvc3RvcmFnZS9hbmNob3JfYmxvY2tfc3RvcmUvYW5jaG9yX2Jsb2NrX3N0b3JlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxFQUFFLGlCQUFpQixFQUF1QixNQUFNLGlCQUFpQixDQUFDO0FBQzlFLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUUvQyxxQkFBYSxnQkFBZ0I7O0lBSTNCLFlBQVksS0FBSyxFQUFFLGlCQUFpQixFQUduQztJQUVLLFNBQVMsQ0FBQyxNQUFNLEVBQUUsV0FBVyxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FFbEQ7SUFFSyxjQUFjLElBQUksT0FBTyxDQUFDLFdBQVcsQ0FBQyxDQU8zQztDQUNGIn0=
17
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYW5jaG9yX2Jsb2NrX3N0b3JlLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvc3RvcmFnZS9hbmNob3JfYmxvY2tfc3RvcmUvYW5jaG9yX2Jsb2NrX3N0b3JlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxFQUFFLGlCQUFpQixFQUF1QixNQUFNLGlCQUFpQixDQUFDO0FBQzlFLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUUvQyxxQkFBYSxnQkFBZ0I7O0lBSTNCLFlBQVksS0FBSyxFQUFFLGlCQUFpQixFQUduQztJQUVEOzs7Ozs7O09BT0c7SUFDRyxTQUFTLENBQUMsTUFBTSxFQUFFLFdBQVcsR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLENBRWxEO0lBRUssY0FBYyxJQUFJLE9BQU8sQ0FBQyxXQUFXLENBQUMsQ0FPM0M7Q0FDRiJ9
@@ -1 +1 @@
1
- {"version":3,"file":"anchor_block_store.d.ts","sourceRoot":"","sources":["../../../src/storage/anchor_block_store/anchor_block_store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAuB,MAAM,iBAAiB,CAAC;AAC9E,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,qBAAa,gBAAgB;;IAI3B,YAAY,KAAK,EAAE,iBAAiB,EAGnC;IAEK,SAAS,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAElD;IAEK,cAAc,IAAI,OAAO,CAAC,WAAW,CAAC,CAO3C;CACF"}
1
+ {"version":3,"file":"anchor_block_store.d.ts","sourceRoot":"","sources":["../../../src/storage/anchor_block_store/anchor_block_store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAuB,MAAM,iBAAiB,CAAC;AAC9E,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,qBAAa,gBAAgB;;IAI3B,YAAY,KAAK,EAAE,iBAAiB,EAGnC;IAED;;;;;;;OAOG;IACG,SAAS,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAElD;IAEK,cAAc,IAAI,OAAO,CAAC,WAAW,CAAC,CAO3C;CACF"}
@@ -6,7 +6,14 @@ export class AnchorBlockStore {
6
6
  this.#store = store;
7
7
  this.#synchronizedHeader = this.#store.openSingleton('header');
8
8
  }
9
- async setHeader(header) {
9
+ /**
10
+ * Sets the currently synchronized block
11
+ *
12
+ * Important: this method is only called from BlockSynchronizer, and since we need it to run atomically with other
13
+ * stores in the case of a reorg, it MUST NOT be wrapped in a `transactionAsync` call. Doing so would result in a
14
+ * deadlock when the backend is IndexedDB, because `transactionAsync` is not designed to support reentrancy.
15
+ *
16
+ */ async setHeader(header) {
10
17
  await this.#synchronizedHeader.set(header.toBuffer());
11
18
  }
12
19
  async getBlockHeader() {
@@ -40,14 +40,12 @@ export class CapsuleStore {
40
40
  * If it is not there, it reads it from the KV store.
41
41
  */ async #getFromStage(jobId, dbSlotKey) {
42
42
  const jobStagedCapsules = this.#getJobStagedCapsules(jobId);
43
- let staged = jobStagedCapsules.get(dbSlotKey);
44
- // Note that if staged === null, we marked it for deletion, so we don't want to
45
- // re-read it from DB
46
- if (staged === undefined) {
47
- // If we don't have a staged version of this dbSlotKey, first we check if there's one in DB
48
- staged = await this.#loadCapsuleFromDb(dbSlotKey);
49
- }
50
- return staged;
43
+ const staged = jobStagedCapsules.get(dbSlotKey);
44
+ // Always issue DB read to keep IndexedDB transaction alive, even if the value is in the job staged data. This
45
+ // keeps IndexedDB transactions alive (they auto-commit when a new micro-task starts and there are no pending read
46
+ // requests). The staged value still takes precedence if it exists (including null for deletions).
47
+ const dbValue = await this.#loadCapsuleFromDb(dbSlotKey);
48
+ return staged !== undefined ? staged : dbValue;
51
49
  }
52
50
  /**
53
51
  * Writes a capsule to the stage of a job.
@@ -63,4 +63,4 @@ export declare class ContractStore {
63
63
  getDebugFunctionName(contractAddress: AztecAddress, selector: FunctionSelector): Promise<string>;
64
64
  getFunctionCall(functionName: string, args: any[], to: AztecAddress): Promise<FunctionCall>;
65
65
  }
66
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29udHJhY3Rfc3RvcmUuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9zdG9yYWdlL2NvbnRyYWN0X3N0b3JlL2NvbnRyYWN0X3N0b3JlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDN0QsT0FBTyxLQUFLLEVBQUUsRUFBRSxFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFFekQsT0FBTyxLQUFLLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUNqRSxPQUFPLEtBQUssRUFBRSxpQkFBaUIsRUFBaUIsTUFBTSxpQkFBaUIsQ0FBQztBQUN4RSxPQUFPLEVBQ0wsS0FBSyxnQkFBZ0IsRUFDckIsS0FBSyxXQUFXLEVBRWhCLEtBQUssZ0NBQWdDLEVBQ3JDLFlBQVksRUFDWixLQUFLLHFCQUFxQixFQUMxQixnQkFBZ0IsRUFNakIsTUFBTSxtQkFBbUIsQ0FBQztBQUMzQixPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFDM0QsT0FBTyxFQUNMLEtBQUssYUFBYSxFQUNsQixLQUFLLDJCQUEyQixFQUdqQyxNQUFNLHdCQUF3QixDQUFDO0FBSWhDOzs7Ozs7R0FNRztBQUNILHFCQUFhLGFBQWE7O0lBV3hCLFlBQVksS0FBSyxFQUFFLGlCQUFpQixFQUduQztJQUlZLG1CQUFtQixDQUFDLEVBQUUsRUFBRSxFQUFFLEVBQUUsUUFBUSxFQUFFLGdCQUFnQixHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FrQmxGO0lBRUssbUJBQW1CLENBQUMsUUFBUSxFQUFFLDJCQUEyQixHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FPOUU7SUE0Q0sscUJBQXFCLElBQUksT0FBTyxDQUFDLFlBQVksRUFBRSxDQUFDLENBR3JEO0lBRUQsNEVBQTRFO0lBQy9ELG1CQUFtQixDQUFDLGVBQWUsRUFBRSxZQUFZLEdBQUcsT0FBTyxDQUFDLDJCQUEyQixHQUFHLFNBQVMsQ0FBQyxDQUdoSDtJQUVZLG1CQUFtQixDQUFDLGVBQWUsRUFBRSxFQUFFLEdBQUcsT0FBTyxDQUFDLGdCQUFnQixHQUFHLFNBQVMsQ0FBQyxDQUkzRjtJQUVELDBFQUEwRTtJQUM3RCxnQkFBZ0IsQ0FBQyxlQUFlLEVBQUUsRUFBRSxHQUFHLE9BQU8sQ0FBQyxhQUFhLEdBQUcsU0FBUyxDQUFDLENBR3JGO0lBRVksV0FBVyxDQUN0QixPQUFPLEVBQUUsWUFBWSxHQUNwQixPQUFPLENBQUMsQ0FBQywyQkFBMkIsR0FBRyxnQkFBZ0IsQ0FBQyxHQUFHLFNBQVMsQ0FBQyxDQVV2RTtJQUVEOzs7Ozs7OztPQVFHO0lBQ1UsbUJBQW1CLENBQzlCLGVBQWUsRUFBRSxZQUFZLEVBQzdCLFFBQVEsRUFBRSxnQkFBZ0IsR0FDekIsT0FBTyxDQUFDLGdDQUFnQyxHQUFHLFNBQVMsQ0FBQyxDQUl2RDtJQUVZLG9DQUFvQyxDQUMvQyxlQUFlLEVBQUUsWUFBWSxFQUM3QixRQUFRLEVBQUUsZ0JBQWdCLEdBQ3pCLE9BQU8sQ0FBQyxnQ0FBZ0MsQ0FBQyxDQVUzQztJQUVZLHlCQUF5QixDQUNwQyxlQUFlLEVBQUUsWUFBWSxHQUM1QixPQUFPLENBQUMsZ0NBQWdDLEdBQUcsU0FBUyxDQUFDLENBSXZEO0lBRVksY0FBYyxDQUN6QixlQUFlLEVBQUUsWUFBWSxFQUM3QixRQUFRLEVBQUUsZ0JBQWdCLEdBQ3pCLE9BQU8sQ0FBQyxXQUFXLEdBQUcsU0FBUyxDQUFDLENBR2xDO0lBRUQ7Ozs7Ozs7OztPQVNHO0lBQ1Usd0JBQXdCLENBQ25DLGVBQWUsRUFBRSxZQUFZLEVBQzdCLFFBQVEsRUFBRSxnQkFBZ0IsR0FDekIsT0FBTyxDQUFDLHFCQUFxQixHQUFHLFNBQVMsQ0FBQyxDQUk1QztJQUVZLDhCQUE4QixDQUN6QyxlQUFlLEVBQUUsWUFBWSxHQUM1QixPQUFPLENBQUMscUJBQXFCLEdBQUcsU0FBUyxDQUFDLENBSTVDO0lBRUQ7Ozs7Ozs7O09BUUc7SUFDVSw0QkFBNEIsQ0FDdkMsZUFBZSxFQUFFLEVBQUUsRUFDbkIsUUFBUSxFQUFFLGdCQUFnQixHQUN6QixPQUFPLENBQUMsaUJBQWlCLENBQUMsT0FBTyxvQkFBb0IsQ0FBQyxHQUFHLFNBQVMsQ0FBQyxDQUdyRTtJQUVZLG9CQUFvQixDQUFDLGVBQWUsRUFBRSxZQUFZLCtCQUc5RDtJQUVZLG9CQUFvQixDQUFDLGVBQWUsRUFBRSxZQUFZLEVBQUUsUUFBUSxFQUFFLGdCQUFnQixtQkFJMUY7SUE4QlksZUFBZSxDQUFDLFlBQVksRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLEdBQUcsRUFBRSxFQUFFLEVBQUUsRUFBRSxZQUFZLEdBQUcsT0FBTyxDQUFDLFlBQVksQ0FBQyxDQXVCdkc7Q0FDRiJ9
66
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29udHJhY3Rfc3RvcmUuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9zdG9yYWdlL2NvbnRyYWN0X3N0b3JlL2NvbnRyYWN0X3N0b3JlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDN0QsT0FBTyxLQUFLLEVBQUUsRUFBRSxFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFFekQsT0FBTyxLQUFLLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUNqRSxPQUFPLEtBQUssRUFBRSxpQkFBaUIsRUFBaUIsTUFBTSxpQkFBaUIsQ0FBQztBQUN4RSxPQUFPLEVBQ0wsS0FBSyxnQkFBZ0IsRUFDckIsS0FBSyxXQUFXLEVBRWhCLEtBQUssZ0NBQWdDLEVBQ3JDLFlBQVksRUFDWixLQUFLLHFCQUFxQixFQUMxQixnQkFBZ0IsRUFNakIsTUFBTSxtQkFBbUIsQ0FBQztBQUMzQixPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFDM0QsT0FBTyxFQUNMLEtBQUssYUFBYSxFQUNsQixLQUFLLDJCQUEyQixFQUdqQyxNQUFNLHdCQUF3QixDQUFDO0FBSWhDOzs7Ozs7R0FNRztBQUNILHFCQUFhLGFBQWE7O0lBWXhCLFlBQVksS0FBSyxFQUFFLGlCQUFpQixFQUluQztJQUlZLG1CQUFtQixDQUFDLEVBQUUsRUFBRSxFQUFFLEVBQUUsUUFBUSxFQUFFLGdCQUFnQixHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FxQmxGO0lBRUssbUJBQW1CLENBQUMsUUFBUSxFQUFFLDJCQUEyQixHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FPOUU7SUE0Q0QscUJBQXFCLElBQUksT0FBTyxDQUFDLFlBQVksRUFBRSxDQUFDLENBSy9DO0lBRUQsNEVBQTRFO0lBQ3JFLG1CQUFtQixDQUFDLGVBQWUsRUFBRSxZQUFZLEdBQUcsT0FBTyxDQUFDLDJCQUEyQixHQUFHLFNBQVMsQ0FBQyxDQUsxRztJQUVNLG1CQUFtQixDQUFDLGVBQWUsRUFBRSxFQUFFLEdBQUcsT0FBTyxDQUFDLGdCQUFnQixHQUFHLFNBQVMsQ0FBQyxDQU1yRjtJQUVELDBFQUEwRTtJQUM3RCxnQkFBZ0IsQ0FBQyxlQUFlLEVBQUUsRUFBRSxHQUFHLE9BQU8sQ0FBQyxhQUFhLEdBQUcsU0FBUyxDQUFDLENBR3JGO0lBRVksV0FBVyxDQUN0QixPQUFPLEVBQUUsWUFBWSxHQUNwQixPQUFPLENBQUMsQ0FBQywyQkFBMkIsR0FBRyxnQkFBZ0IsQ0FBQyxHQUFHLFNBQVMsQ0FBQyxDQVV2RTtJQUVEOzs7Ozs7OztPQVFHO0lBQ1UsbUJBQW1CLENBQzlCLGVBQWUsRUFBRSxZQUFZLEVBQzdCLFFBQVEsRUFBRSxnQkFBZ0IsR0FDekIsT0FBTyxDQUFDLGdDQUFnQyxHQUFHLFNBQVMsQ0FBQyxDQUl2RDtJQUVZLG9DQUFvQyxDQUMvQyxlQUFlLEVBQUUsWUFBWSxFQUM3QixRQUFRLEVBQUUsZ0JBQWdCLEdBQ3pCLE9BQU8sQ0FBQyxnQ0FBZ0MsQ0FBQyxDQVUzQztJQUVZLHlCQUF5QixDQUNwQyxlQUFlLEVBQUUsWUFBWSxHQUM1QixPQUFPLENBQUMsZ0NBQWdDLEdBQUcsU0FBUyxDQUFDLENBSXZEO0lBRVksY0FBYyxDQUN6QixlQUFlLEVBQUUsWUFBWSxFQUM3QixRQUFRLEVBQUUsZ0JBQWdCLEdBQ3pCLE9BQU8sQ0FBQyxXQUFXLEdBQUcsU0FBUyxDQUFDLENBR2xDO0lBRUQ7Ozs7Ozs7OztPQVNHO0lBQ1Usd0JBQXdCLENBQ25DLGVBQWUsRUFBRSxZQUFZLEVBQzdCLFFBQVEsRUFBRSxnQkFBZ0IsR0FDekIsT0FBTyxDQUFDLHFCQUFxQixHQUFHLFNBQVMsQ0FBQyxDQUk1QztJQUVZLDhCQUE4QixDQUN6QyxlQUFlLEVBQUUsWUFBWSxHQUM1QixPQUFPLENBQUMscUJBQXFCLEdBQUcsU0FBUyxDQUFDLENBSTVDO0lBRUQ7Ozs7Ozs7O09BUUc7SUFDVSw0QkFBNEIsQ0FDdkMsZUFBZSxFQUFFLEVBQUUsRUFDbkIsUUFBUSxFQUFFLGdCQUFnQixHQUN6QixPQUFPLENBQUMsaUJBQWlCLENBQUMsT0FBTyxvQkFBb0IsQ0FBQyxHQUFHLFNBQVMsQ0FBQyxDQUdyRTtJQUVZLG9CQUFvQixDQUFDLGVBQWUsRUFBRSxZQUFZLCtCQUc5RDtJQUVZLG9CQUFvQixDQUFDLGVBQWUsRUFBRSxZQUFZLEVBQUUsUUFBUSxFQUFFLGdCQUFnQixtQkFJMUY7SUE4QlksZUFBZSxDQUFDLFlBQVksRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLEdBQUcsRUFBRSxFQUFFLEVBQUUsRUFBRSxZQUFZLEdBQUcsT0FBTyxDQUFDLFlBQVksQ0FBQyxDQXVCdkc7Q0FDRiJ9
@@ -1 +1 @@
1
- {"version":3,"file":"contract_store.d.ts","sourceRoot":"","sources":["../../../src/storage/contract_store/contract_store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAC7D,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,gCAAgC,CAAC;AAEzD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,KAAK,EAAE,iBAAiB,EAAiB,MAAM,iBAAiB,CAAC;AACxE,OAAO,EACL,KAAK,gBAAgB,EACrB,KAAK,WAAW,EAEhB,KAAK,gCAAgC,EACrC,YAAY,EACZ,KAAK,qBAAqB,EAC1B,gBAAgB,EAMjB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,2BAA2B,EAGjC,MAAM,wBAAwB,CAAC;AAIhC;;;;;;GAMG;AACH,qBAAa,aAAa;;IAWxB,YAAY,KAAK,EAAE,iBAAiB,EAGnC;IAIY,mBAAmB,CAAC,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAkBlF;IAEK,mBAAmB,CAAC,QAAQ,EAAE,2BAA2B,GAAG,OAAO,CAAC,IAAI,CAAC,CAO9E;IA4CK,qBAAqB,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC,CAGrD;IAED,4EAA4E;IAC/D,mBAAmB,CAAC,eAAe,EAAE,YAAY,GAAG,OAAO,CAAC,2BAA2B,GAAG,SAAS,CAAC,CAGhH;IAEY,mBAAmB,CAAC,eAAe,EAAE,EAAE,GAAG,OAAO,CAAC,gBAAgB,GAAG,SAAS,CAAC,CAI3F;IAED,0EAA0E;IAC7D,gBAAgB,CAAC,eAAe,EAAE,EAAE,GAAG,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC,CAGrF;IAEY,WAAW,CACtB,OAAO,EAAE,YAAY,GACpB,OAAO,CAAC,CAAC,2BAA2B,GAAG,gBAAgB,CAAC,GAAG,SAAS,CAAC,CAUvE;IAED;;;;;;;;OAQG;IACU,mBAAmB,CAC9B,eAAe,EAAE,YAAY,EAC7B,QAAQ,EAAE,gBAAgB,GACzB,OAAO,CAAC,gCAAgC,GAAG,SAAS,CAAC,CAIvD;IAEY,oCAAoC,CAC/C,eAAe,EAAE,YAAY,EAC7B,QAAQ,EAAE,gBAAgB,GACzB,OAAO,CAAC,gCAAgC,CAAC,CAU3C;IAEY,yBAAyB,CACpC,eAAe,EAAE,YAAY,GAC5B,OAAO,CAAC,gCAAgC,GAAG,SAAS,CAAC,CAIvD;IAEY,cAAc,CACzB,eAAe,EAAE,YAAY,EAC7B,QAAQ,EAAE,gBAAgB,GACzB,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC,CAGlC;IAED;;;;;;;;;OASG;IACU,wBAAwB,CACnC,eAAe,EAAE,YAAY,EAC7B,QAAQ,EAAE,gBAAgB,GACzB,OAAO,CAAC,qBAAqB,GAAG,SAAS,CAAC,CAI5C;IAEY,8BAA8B,CACzC,eAAe,EAAE,YAAY,GAC5B,OAAO,CAAC,qBAAqB,GAAG,SAAS,CAAC,CAI5C;IAED;;;;;;;;OAQG;IACU,4BAA4B,CACvC,eAAe,EAAE,EAAE,EACnB,QAAQ,EAAE,gBAAgB,GACzB,OAAO,CAAC,iBAAiB,CAAC,OAAO,oBAAoB,CAAC,GAAG,SAAS,CAAC,CAGrE;IAEY,oBAAoB,CAAC,eAAe,EAAE,YAAY,+BAG9D;IAEY,oBAAoB,CAAC,eAAe,EAAE,YAAY,EAAE,QAAQ,EAAE,gBAAgB,mBAI1F;IA8BY,eAAe,CAAC,YAAY,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,CAuBvG;CACF"}
1
+ {"version":3,"file":"contract_store.d.ts","sourceRoot":"","sources":["../../../src/storage/contract_store/contract_store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAC7D,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,gCAAgC,CAAC;AAEzD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,KAAK,EAAE,iBAAiB,EAAiB,MAAM,iBAAiB,CAAC;AACxE,OAAO,EACL,KAAK,gBAAgB,EACrB,KAAK,WAAW,EAEhB,KAAK,gCAAgC,EACrC,YAAY,EACZ,KAAK,qBAAqB,EAC1B,gBAAgB,EAMjB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,2BAA2B,EAGjC,MAAM,wBAAwB,CAAC;AAIhC;;;;;;GAMG;AACH,qBAAa,aAAa;;IAYxB,YAAY,KAAK,EAAE,iBAAiB,EAInC;IAIY,mBAAmB,CAAC,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAqBlF;IAEK,mBAAmB,CAAC,QAAQ,EAAE,2BAA2B,GAAG,OAAO,CAAC,IAAI,CAAC,CAO9E;IA4CD,qBAAqB,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC,CAK/C;IAED,4EAA4E;IACrE,mBAAmB,CAAC,eAAe,EAAE,YAAY,GAAG,OAAO,CAAC,2BAA2B,GAAG,SAAS,CAAC,CAK1G;IAEM,mBAAmB,CAAC,eAAe,EAAE,EAAE,GAAG,OAAO,CAAC,gBAAgB,GAAG,SAAS,CAAC,CAMrF;IAED,0EAA0E;IAC7D,gBAAgB,CAAC,eAAe,EAAE,EAAE,GAAG,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC,CAGrF;IAEY,WAAW,CACtB,OAAO,EAAE,YAAY,GACpB,OAAO,CAAC,CAAC,2BAA2B,GAAG,gBAAgB,CAAC,GAAG,SAAS,CAAC,CAUvE;IAED;;;;;;;;OAQG;IACU,mBAAmB,CAC9B,eAAe,EAAE,YAAY,EAC7B,QAAQ,EAAE,gBAAgB,GACzB,OAAO,CAAC,gCAAgC,GAAG,SAAS,CAAC,CAIvD;IAEY,oCAAoC,CAC/C,eAAe,EAAE,YAAY,EAC7B,QAAQ,EAAE,gBAAgB,GACzB,OAAO,CAAC,gCAAgC,CAAC,CAU3C;IAEY,yBAAyB,CACpC,eAAe,EAAE,YAAY,GAC5B,OAAO,CAAC,gCAAgC,GAAG,SAAS,CAAC,CAIvD;IAEY,cAAc,CACzB,eAAe,EAAE,YAAY,EAC7B,QAAQ,EAAE,gBAAgB,GACzB,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC,CAGlC;IAED;;;;;;;;;OASG;IACU,wBAAwB,CACnC,eAAe,EAAE,YAAY,EAC7B,QAAQ,EAAE,gBAAgB,GACzB,OAAO,CAAC,qBAAqB,GAAG,SAAS,CAAC,CAI5C;IAEY,8BAA8B,CACzC,eAAe,EAAE,YAAY,GAC5B,OAAO,CAAC,qBAAqB,GAAG,SAAS,CAAC,CAI5C;IAED;;;;;;;;OAQG;IACU,4BAA4B,CACvC,eAAe,EAAE,EAAE,EACnB,QAAQ,EAAE,gBAAgB,GACzB,OAAO,CAAC,iBAAiB,CAAC,OAAO,oBAAoB,CAAC,GAAG,SAAS,CAAC,CAGrE;IAEY,oBAAoB,CAAC,eAAe,EAAE,YAAY,+BAG9D;IAEY,oBAAoB,CAAC,eAAe,EAAE,YAAY,EAAE,QAAQ,EAAE,gBAAgB,mBAI1F;IA8BY,eAAe,CAAC,YAAY,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,CAuBvG;CACF"}
@@ -13,20 +13,23 @@ import { PrivateFunctionsTree } from './private_functions_tree.js';
13
13
  /** Map from contract class id to private function tree. */ // TODO: Update it to be LRU cache so that it doesn't keep all the data all the time.
14
14
  #privateFunctionTrees = new Map();
15
15
  /** Map from contract address to contract class id */ #contractClassIdMap = new Map();
16
+ #store;
16
17
  #contractArtifacts;
17
18
  #contractInstances;
18
19
  constructor(store){
20
+ this.#store = store;
19
21
  this.#contractArtifacts = store.openMap('contract_artifacts');
20
22
  this.#contractInstances = store.openMap('contracts_instances');
21
23
  }
22
24
  // Setters
23
25
  async addContractArtifact(id, contract) {
26
+ // Validation outside transactionAsync - these are not DB operations
24
27
  const privateFunctions = contract.functions.filter((functionArtifact)=>functionArtifact.functionType === FunctionType.PRIVATE);
25
28
  const privateSelectors = await Promise.all(privateFunctions.map(async (privateFunctionArtifact)=>(await FunctionSelector.fromNameAndParameters(privateFunctionArtifact.name, privateFunctionArtifact.parameters)).toString()));
26
29
  if (privateSelectors.length !== new Set(privateSelectors).size) {
27
30
  throw new Error('Repeated function selectors of private functions');
28
31
  }
29
- await this.#contractArtifacts.set(id.toString(), contractArtifactToBuffer(contract));
32
+ await this.#store.transactionAsync(()=>this.#contractArtifacts.set(id.toString(), contractArtifactToBuffer(contract)));
30
33
  }
31
34
  async addContractInstance(contract) {
32
35
  this.#contractClassIdMap.set(contract.address.toString(), contract.currentContractClassId);
@@ -68,18 +71,24 @@ import { PrivateFunctionsTree } from './private_functions_tree.js';
68
71
  return contractClassId && this.getContractArtifact(contractClassId);
69
72
  }
70
73
  // Public getters
71
- async getContractsAddresses() {
72
- const keys = await toArray(this.#contractInstances.keysAsync());
73
- return keys.map(AztecAddress.fromString);
74
- }
75
- /** Returns a contract instance for a given address. Throws if not found. */ async getContractInstance(contractAddress) {
76
- const contract = await this.#contractInstances.getAsync(contractAddress.toString());
77
- return contract && SerializableContractInstance.fromBuffer(contract).withAddress(contractAddress);
78
- }
79
- async getContractArtifact(contractClassId) {
80
- const contract = await this.#contractArtifacts.getAsync(contractClassId.toString());
81
- // TODO(@spalladino): AztecAsyncMap lies and returns Uint8Arrays instead of Buffers, hence the extra Buffer.from.
82
- return contract && contractArtifactFromBuffer(Buffer.from(contract));
74
+ getContractsAddresses() {
75
+ return this.#store.transactionAsync(async ()=>{
76
+ const keys = await toArray(this.#contractInstances.keysAsync());
77
+ return keys.map(AztecAddress.fromString);
78
+ });
79
+ }
80
+ /** Returns a contract instance for a given address. Throws if not found. */ getContractInstance(contractAddress) {
81
+ return this.#store.transactionAsync(async ()=>{
82
+ const contract = await this.#contractInstances.getAsync(contractAddress.toString());
83
+ return contract && SerializableContractInstance.fromBuffer(contract).withAddress(contractAddress);
84
+ });
85
+ }
86
+ getContractArtifact(contractClassId) {
87
+ return this.#store.transactionAsync(async ()=>{
88
+ const contract = await this.#contractArtifacts.getAsync(contractClassId.toString());
89
+ // TODO(@spalladino): AztecAsyncMap lies and returns Uint8Arrays instead of Buffers, hence the extra Buffer.from.
90
+ return contract && contractArtifactFromBuffer(Buffer.from(contract));
91
+ });
83
92
  }
84
93
  /** Returns a contract class for a given class id. Throws if not found. */ async getContractClass(contractClassId) {
85
94
  const artifact = await this.getContractArtifact(contractClassId);
@@ -1,2 +1,2 @@
1
- export declare const PXE_DATA_SCHEMA_VERSION = 2;
1
+ export declare const PXE_DATA_SCHEMA_VERSION = 3;
2
2
  //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWV0YWRhdGEuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9zdG9yYWdlL21ldGFkYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLGVBQU8sTUFBTSx1QkFBdUIsSUFBSSxDQUFDIn0=
@@ -1 +1 @@
1
- export const PXE_DATA_SCHEMA_VERSION = 2;
1
+ export const PXE_DATA_SCHEMA_VERSION = 3;
@@ -67,7 +67,17 @@ export declare class NoteStore implements StagedStore {
67
67
  * @param synchedBlockNumber - The block number up to which PXE managed to sync before the reorg happened.
68
68
  */
69
69
  rollback(blockNumber: number, synchedBlockNumber: number): Promise<void>;
70
+ /**
71
+ * Commits in memory job data to persistent storage.
72
+ *
73
+ * Called by JobCoordinator when a job completes successfully.
74
+ *
75
+ * Note: JobCoordinator wraps all commits in a single transaction, so we don't need our own transactionAsync here
76
+ * (and using one would throw on IndexedDB as it does not support nested txs).
77
+ *
78
+ * @param jobId - The jobId identifying which staged data to commit
79
+ */
70
80
  commit(jobId: string): Promise<void>;
71
81
  discardStaged(jobId: string): Promise<void>;
72
82
  }
73
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm90ZV9zdG9yZS5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3N0b3JhZ2Uvbm90ZV9zdG9yZS9ub3RlX3N0b3JlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUVBLE9BQU8sS0FBSyxFQUFFLEVBQUUsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQ3BELE9BQU8sS0FBSyxFQUFFLGlCQUFpQixFQUFxQyxNQUFNLGlCQUFpQixDQUFDO0FBQzVGLE9BQU8sS0FBSyxFQUFFLFlBQVksRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBQ2hFLE9BQU8sS0FBSyxFQUFFLFdBQVcsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ3ZELE9BQU8sRUFBRSxPQUFPLEVBQWMsS0FBSyxXQUFXLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUUzRSxPQUFPLEtBQUssRUFBRSxXQUFXLEVBQUUsTUFBTSwwQ0FBMEMsQ0FBQztBQUc1RTs7Ozs7SUFLSTtBQUNKLHFCQUFhLFNBQVUsWUFBVyxXQUFXOztJQUMzQyxRQUFRLENBQUMsU0FBUyxFQUFFLE1BQU0sQ0FBVTtJQStCcEMsWUFBWSxLQUFLLEVBQUUsaUJBQWlCLEVBUW5DO0lBRUQ7Ozs7Ozs7OztPQVNHO0lBQ0ksUUFBUSxDQUFDLEtBQUssRUFBRSxPQUFPLEVBQUUsRUFBRSxLQUFLLEVBQUUsWUFBWSxFQUFFLEtBQUssRUFBRSxNQUFNLEdBQUcsT0FBTyxDQUFDLElBQUksRUFBRSxDQUFDLENBRXJGO0lBK0JEOzs7Ozs7Ozs7OztPQVdHO0lBQ0csUUFBUSxDQUFDLE1BQU0sRUFBRSxXQUFXLEVBQUUsS0FBSyxFQUFFLE1BQU0sR0FBRyxPQUFPLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FvRHJFO0lBRUQ7Ozs7Ozs7Ozs7Ozs7O09BY0c7SUFDSCxlQUFlLENBQUMsVUFBVSxFQUFFLFdBQVcsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLEtBQUssRUFBRSxNQUFNLEdBQUcsT0FBTyxDQUFDLE9BQU8sRUFBRSxDQUFDLENBc0NoRjtJQUVEOzs7Ozs7Ozs7OztPQVdHO0lBQ1UsUUFBUSxDQUFDLFdBQVcsRUFBRSxNQUFNLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FNcEY7SUEwRUQsTUFBTSxDQUFDLEtBQUssRUFBRSxNQUFNLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxDQVluQztJQUVELGFBQWEsQ0FBQyxLQUFLLEVBQUUsTUFBTSxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FFMUM7Q0FpREYifQ==
83
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm90ZV9zdG9yZS5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3N0b3JhZ2Uvbm90ZV9zdG9yZS9ub3RlX3N0b3JlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sS0FBSyxFQUFFLEVBQUUsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQ3BELE9BQU8sS0FBSyxFQUFFLGlCQUFpQixFQUFxQyxNQUFNLGlCQUFpQixDQUFDO0FBQzVGLE9BQU8sS0FBSyxFQUFFLFlBQVksRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBQ2hFLE9BQU8sS0FBSyxFQUFFLFdBQVcsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ3ZELE9BQU8sRUFBRSxPQUFPLEVBQWMsS0FBSyxXQUFXLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUUzRSxPQUFPLEtBQUssRUFBRSxXQUFXLEVBQUUsTUFBTSwwQ0FBMEMsQ0FBQztBQUc1RTs7Ozs7SUFLSTtBQUNKLHFCQUFhLFNBQVUsWUFBVyxXQUFXOztJQUMzQyxRQUFRLENBQUMsU0FBUyxFQUFFLE1BQU0sQ0FBVTtJQStCcEMsWUFBWSxLQUFLLEVBQUUsaUJBQWlCLEVBUW5DO0lBRUQ7Ozs7Ozs7OztPQVNHO0lBQ0ksUUFBUSxDQUFDLEtBQUssRUFBRSxPQUFPLEVBQUUsRUFBRSxLQUFLLEVBQUUsWUFBWSxFQUFFLEtBQUssRUFBRSxNQUFNLEdBQUcsT0FBTyxDQUFDLElBQUksRUFBRSxDQUFDLENBYXJGO0lBY0Q7Ozs7Ozs7Ozs7O09BV0c7SUFDSCxRQUFRLENBQUMsTUFBTSxFQUFFLFdBQVcsRUFBRSxLQUFLLEVBQUUsTUFBTSxHQUFHLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQTZGL0Q7SUFFRDs7Ozs7Ozs7Ozs7Ozs7T0FjRztJQUNILGVBQWUsQ0FBQyxVQUFVLEVBQUUsV0FBVyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsS0FBSyxFQUFFLE1BQU0sR0FBRyxPQUFPLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FxQ2hGO0lBRUQ7Ozs7Ozs7Ozs7O09BV0c7SUFDVSxRQUFRLENBQUMsV0FBVyxFQUFFLE1BQU0sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxDQU1wRjtJQTZFRDs7Ozs7Ozs7O09BU0c7SUFDRyxNQUFNLENBQUMsS0FBSyxFQUFFLE1BQU0sR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLENBVXpDO0lBRUQsYUFBYSxDQUFDLEtBQUssRUFBRSxNQUFNLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUcxQztDQWtDRiJ9
@@ -1 +1 @@
1
- {"version":3,"file":"note_store.d.ts","sourceRoot":"","sources":["../../../src/storage/note_store/note_store.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,2BAA2B,CAAC;AACpD,OAAO,KAAK,EAAE,iBAAiB,EAAqC,MAAM,iBAAiB,CAAC;AAC5F,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,OAAO,EAAc,KAAK,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAE3E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0CAA0C,CAAC;AAG5E;;;;;IAKI;AACJ,qBAAa,SAAU,YAAW,WAAW;;IAC3C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAU;IA+BpC,YAAY,KAAK,EAAE,iBAAiB,EAQnC;IAED;;;;;;;;;OASG;IACI,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,CAErF;IA+BD;;;;;;;;;;;OAWG;IACG,QAAQ,CAAC,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAoDrE;IAED;;;;;;;;;;;;;;OAcG;IACH,eAAe,CAAC,UAAU,EAAE,WAAW,CAAC,EAAE,CAAC,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAsChF;IAED;;;;;;;;;;;OAWG;IACU,QAAQ,CAAC,WAAW,EAAE,MAAM,EAAE,kBAAkB,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAMpF;IA0ED,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAYnC;IAED,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE1C;CAiDF"}
1
+ {"version":3,"file":"note_store.d.ts","sourceRoot":"","sources":["../../../src/storage/note_store/note_store.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,2BAA2B,CAAC;AACpD,OAAO,KAAK,EAAE,iBAAiB,EAAqC,MAAM,iBAAiB,CAAC;AAC5F,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,OAAO,EAAc,KAAK,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAE3E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0CAA0C,CAAC;AAG5E;;;;;IAKI;AACJ,qBAAa,SAAU,YAAW,WAAW;;IAC3C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAU;IA+BpC,YAAY,KAAK,EAAE,iBAAiB,EAQnC;IAED;;;;;;;;;OASG;IACI,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,CAarF;IAcD;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CA6F/D;IAED;;;;;;;;;;;;;;OAcG;IACH,eAAe,CAAC,UAAU,EAAE,WAAW,CAAC,EAAE,CAAC,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAqChF;IAED;;;;;;;;;;;OAWG;IACU,QAAQ,CAAC,WAAW,EAAE,MAAM,EAAE,kBAAkB,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAMpF;IA6ED;;;;;;;;;OASG;IACG,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAUzC;IAED,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAG1C;CAkCF"}
@@ -1,4 +1,3 @@
1
- import { toArray } from '@aztec/foundation/iterable';
2
1
  import { Semaphore } from '@aztec/foundation/queue';
3
2
  import { NoteStatus } from '@aztec/stdlib/note';
4
3
  import { StoredNote } from './stored_note.js';
@@ -49,26 +48,18 @@ import { StoredNote } from './stored_note.js';
49
48
  * @param scope - The scope (user/account) under which to store the notes
50
49
  * @param jobId - The job context for staged writes
51
50
  */ addNotes(notes, scope, jobId) {
52
- return this.#withJobLock(jobId, ()=>Promise.all(notes.map((noteDao)=>this.#addNote(noteDao, scope, jobId))));
53
- }
54
- async #addNote(note, scope, jobId) {
55
- const noteForJob = await this.#readNote(note.siloedNullifier.toString(), jobId) ?? new StoredNote(note, new Set());
56
- // Make sure the note is linked to the scope and staged for this job
57
- noteForJob.addScope(scope.toString());
58
- this.#writeNote(noteForJob, jobId);
51
+ return this.#withJobLock(jobId, ()=>this.#store.transactionAsync(()=>Promise.all(notes.map(async (note)=>{
52
+ const noteForJob = await this.#readNote(note.siloedNullifier.toString(), jobId) ?? new StoredNote(note, new Set());
53
+ noteForJob.addScope(scope.toString());
54
+ this.#writeNote(noteForJob, jobId);
55
+ }))));
59
56
  }
60
57
  async #readNote(nullifier, jobId) {
61
- // First check staged notes for this job
62
- const noteForJob = this.#getNotesForJob(jobId).get(nullifier);
63
- if (noteForJob) {
64
- return noteForJob;
65
- }
66
- // Then check persistent storage
58
+ // Always issue DB read to keep IndexedDB transaction alive (they auto-commit when a new micro-task starts and there
59
+ // are no pending read requests). The staged value still takes precedence if it exists.
67
60
  const noteBuffer = await this.#notes.getAsync(nullifier);
68
- if (noteBuffer) {
69
- return StoredNote.fromBuffer(noteBuffer);
70
- }
71
- return undefined;
61
+ const noteForJob = this.#getNotesForJob(jobId).get(nullifier);
62
+ return noteForJob ?? (noteBuffer ? StoredNote.fromBuffer(noteBuffer) : undefined);
72
63
  }
73
64
  #writeNote(note, jobId) {
74
65
  this.#getNotesForJob(jobId).set(note.noteDao.siloedNullifier.toString(), note);
@@ -84,48 +75,84 @@ import { StoredNote } from './stored_note.js';
84
75
  * @returns Filtered and deduplicated notes (a note might be present in multiple scopes - we ensure it is only
85
76
  * returned once if this is the case)
86
77
  * @throws If filtering by an empty scopes array. Scopes have to be set to undefined or to a non-empty array.
87
- */ async getNotes(filter, jobId) {
78
+ */ getNotes(filter, jobId) {
88
79
  if (filter.scopes !== undefined && filter.scopes.length === 0) {
89
- throw new Error('Trying to get notes with an empty scopes array');
80
+ return Promise.reject(new Error('Trying to get notes with an empty scopes array'));
90
81
  }
91
- const targetStatus = filter.status ?? NoteStatus.ACTIVE;
92
- const foundNotes = new Map();
93
- const nullifiersOfContract = await this.#nullifiersOfContract(filter.contractAddress, jobId);
94
- for (const nullifier of nullifiersOfContract){
95
- const note = await this.#readNote(nullifier, jobId);
96
- // Defensive: hitting this case means we're mishandling contract indices or in-memory job data
97
- if (!note) {
98
- throw new Error('PXE note database is corrupted.');
99
- }
100
- // Apply filters
101
- if (targetStatus === NoteStatus.ACTIVE && note.isNullified()) {
102
- continue;
103
- }
104
- if (filter.owner && !note.noteDao.owner.equals(filter.owner)) {
105
- continue;
106
- }
107
- if (filter.storageSlot && !note.noteDao.storageSlot.equals(filter.storageSlot)) {
108
- continue;
109
- }
110
- if (filter.siloedNullifier && !note.noteDao.siloedNullifier.equals(filter.siloedNullifier)) {
111
- continue;
112
- }
113
- if (filter.scopes && note.scopes.intersection(new Set(filter.scopes.map((s)=>s.toString()))).size === 0) {
114
- continue;
82
+ return this.#store.transactionAsync(async ()=>{
83
+ const targetStatus = filter.status ?? NoteStatus.ACTIVE;
84
+ // The code below might read a bit unnatural, the reason is that we need to be careful in how we use `await` inside
85
+ // `transactionAsync`, otherwise browsers might choose to auto-commit the IndexedDB transaction forcing us to
86
+ // explicitly handle that condition. The rule we need to honor is: do not await unless you generate a database
87
+ // read or write or you're done using the DB for the remainder of the transaction. The following sequence is
88
+ // unsafe in IndexedDB:
89
+ //
90
+ // 1. start transactionAsync()
91
+ // 2. await readDb() <-- OK, transaction alive because we issued DB ops
92
+ // 3. run a bunch of computations (no await involved) <-- OK, tx alive because we are in the same microtask
93
+ // 4. await doSthNotInDb() <-- no DB ops issued in this task, browser's free to decide to commit the tx
94
+ // 5. await readDb() <-- BOOM, TransactionInactiveError
95
+ //
96
+ // Note that the real issue is in step number 5: we try to continue using a transaction that the browser might
97
+ // have already committed.
98
+ //
99
+ // We need to read candidate notes which are either indexed by contract address in the DB (in
100
+ // #nullifiersByContractAddress), or lie in memory for the not yet committed `jobId`.
101
+ // So we collect promises based on both sources without awaiting for them.
102
+ const noteReadPromises = new Map();
103
+ // Awaiting the getValuesAsync iterator is fine because it's reading from the DB
104
+ for await (const nullifier of this.#nullifiersByContractAddress.getValuesAsync(filter.contractAddress.toString())){
105
+ // Each #readNote will perform a DB read
106
+ noteReadPromises.set(nullifier, this.#readNote(nullifier, jobId));
115
107
  }
116
- foundNotes.set(note.noteDao.siloedNullifier.toString(), note.noteDao);
117
- }
118
- // Sort by block number, then by tx index within block, then by note index within tx
119
- return [
120
- ...foundNotes.values()
121
- ].sort((a, b)=>{
122
- if (a.l2BlockNumber !== b.l2BlockNumber) {
123
- return a.l2BlockNumber - b.l2BlockNumber;
108
+ // Add staged nullifiers from job, no awaits involved, so we are fine
109
+ for (const storedNote of this.#getNotesForJob(jobId).values()){
110
+ if (storedNote.noteDao.contractAddress.equals(filter.contractAddress)) {
111
+ const nullifier = storedNote.noteDao.siloedNullifier.toString();
112
+ if (!noteReadPromises.has(nullifier)) {
113
+ noteReadPromises.set(nullifier, Promise.resolve(storedNote));
114
+ }
115
+ }
124
116
  }
125
- if (a.txIndexInBlock !== b.txIndexInBlock) {
126
- return a.txIndexInBlock - b.txIndexInBlock;
117
+ // By now we have pending DB requests from all the #readNote calls. Await them all together.
118
+ const notes = await Promise.all(noteReadPromises.values());
119
+ // The rest of the function is await-free, and just deals with filtering and sorting our findings.
120
+ const foundNotes = new Map();
121
+ for (const note of notes){
122
+ // Defensive: hitting this case means we're mishandling contract indices or in-memory job data
123
+ if (!note) {
124
+ throw new Error('PXE note database is corrupted.');
125
+ }
126
+ // Apply filters
127
+ if (targetStatus === NoteStatus.ACTIVE && note.isNullified()) {
128
+ continue;
129
+ }
130
+ if (filter.owner && !note.noteDao.owner.equals(filter.owner)) {
131
+ continue;
132
+ }
133
+ if (filter.storageSlot && !note.noteDao.storageSlot.equals(filter.storageSlot)) {
134
+ continue;
135
+ }
136
+ if (filter.siloedNullifier && !note.noteDao.siloedNullifier.equals(filter.siloedNullifier)) {
137
+ continue;
138
+ }
139
+ if (filter.scopes && note.scopes.intersection(new Set(filter.scopes.map((s)=>s.toString()))).size === 0) {
140
+ continue;
141
+ }
142
+ foundNotes.set(note.noteDao.siloedNullifier.toString(), note.noteDao);
127
143
  }
128
- return a.noteIndexInTx - b.noteIndexInTx;
144
+ // Sort by block number, then by tx index within block, then by note index within tx
145
+ return [
146
+ ...foundNotes.values()
147
+ ].sort((a, b)=>{
148
+ if (a.l2BlockNumber !== b.l2BlockNumber) {
149
+ return a.l2BlockNumber - b.l2BlockNumber;
150
+ }
151
+ if (a.txIndexInBlock !== b.txIndexInBlock) {
152
+ return a.txIndexInBlock - b.txIndexInBlock;
153
+ }
154
+ return a.noteIndexInTx - b.noteIndexInTx;
155
+ });
129
156
  });
130
157
  }
131
158
  /**
@@ -143,10 +170,10 @@ import { StoredNote } from './stored_note.js';
143
170
  * @returns Array of NoteDao objects that were nullified
144
171
  * @throws Error if any nullifier is not found in this notes store
145
172
  */ applyNullifiers(nullifiers, jobId) {
173
+ if (nullifiers.length === 0) {
174
+ return Promise.resolve([]);
175
+ }
146
176
  return this.#withJobLock(jobId, ()=>this.#store.transactionAsync(async ()=>{
147
- if (nullifiers.length === 0) {
148
- return [];
149
- }
150
177
  const notesToNullify = await Promise.all(nullifiers.map(async (nullifierInBlock)=>{
151
178
  const nullifier = nullifierInBlock.data.toString();
152
179
  const storedNote = await this.#readNote(nullifier, jobId);
@@ -154,13 +181,12 @@ import { StoredNote } from './stored_note.js';
154
181
  throw new Error(`Attempted to mark a note as nullified which does not exist in PXE DB`);
155
182
  }
156
183
  return {
157
- storedNote: await this.#readNote(nullifier, jobId),
184
+ storedNote,
158
185
  blockNumber: nullifierInBlock.l2BlockNumber
159
186
  };
160
187
  }));
161
188
  const notesNullifiedInThisCall = new Map();
162
189
  for (const noteToNullify of notesToNullify){
163
- // Safe to coerce (!) because we throw if we find any undefined above
164
190
  const note = noteToNullify.storedNote;
165
191
  // Skip already nullified notes
166
192
  if (note.isNullified()) {
@@ -200,15 +226,22 @@ import { StoredNote } from './stored_note.js';
200
226
  *
201
227
  * @param blockNumber - Notes created after this block number will be deleted
202
228
  */ async #deleteActiveNotesAfterBlock(blockNumber) {
203
- const notes = await toArray(this.#notes.valuesAsync());
204
- for (const noteBuffer of notes){
229
+ // Collect notes to delete during iteration to keep IndexedDB transaction alive.
230
+ const notesToDelete = [];
231
+ for await (const noteBuffer of this.#notes.valuesAsync()){
205
232
  const storedNote = StoredNote.fromBuffer(noteBuffer);
206
233
  if (storedNote.noteDao.l2BlockNumber > blockNumber) {
207
- const noteNullifier = storedNote.noteDao.siloedNullifier.toString();
208
- await this.#notes.delete(noteNullifier);
209
- await this.#nullifiersByContractAddress.deleteValue(storedNote.noteDao.contractAddress.toString(), noteNullifier);
234
+ notesToDelete.push({
235
+ nullifier: storedNote.noteDao.siloedNullifier.toString(),
236
+ contractAddress: storedNote.noteDao.contractAddress.toString()
237
+ });
210
238
  }
211
239
  }
240
+ // Delete all collected notes. Each delete is a DB operation that keeps the transaction alive.
241
+ for (const { nullifier, contractAddress } of notesToDelete){
242
+ await this.#notes.delete(nullifier);
243
+ await this.#nullifiersByContractAddress.deleteValue(contractAddress, nullifier);
244
+ }
212
245
  }
213
246
  /**
214
247
  * Rewinds nullifications after a given block number.
@@ -219,47 +252,62 @@ import { StoredNote } from './stored_note.js';
219
252
  * @param blockNumber - Revert nullifications that occurred after this block
220
253
  * @param anchorBlockNumber - Upper bound for the block range to process
221
254
  */ async #rewindNullifiedNotesAfterBlock(blockNumber, anchorBlockNumber) {
222
- const currentBlockNumber = blockNumber + 1;
223
- for(let i = currentBlockNumber; i <= anchorBlockNumber; i++){
224
- const noteNullifiersToReinsert = await toArray(this.#nullifiersByNullificationBlockNumber.getValuesAsync(i));
225
- const nullifiedNoteBuffers = await Promise.all(noteNullifiersToReinsert.map(async (noteNullifier)=>{
226
- const note = await this.#notes.getAsync(noteNullifier);
227
- if (!note) {
228
- throw new Error(`PXE DB integrity error: no note found with nullifier ${noteNullifier}`);
255
+ // First pass: collect all nullifiers for all blocks, starting reads during iteration to keep tx alive.
256
+ const nullifiersByBlock = new Map();
257
+ for(let i = blockNumber + 1; i <= anchorBlockNumber; i++){
258
+ const blockNullifiers = [];
259
+ for await (const nullifier of this.#nullifiersByNullificationBlockNumber.getValuesAsync(i)){
260
+ // Start read immediately during iteration to keep IndexedDB transaction alive
261
+ blockNullifiers.push({
262
+ nullifier,
263
+ noteReadPromise: this.#notes.getAsync(nullifier)
264
+ });
265
+ }
266
+ if (blockNullifiers.length > 0) {
267
+ nullifiersByBlock.set(i, blockNullifiers);
268
+ }
269
+ }
270
+ // Second pass: await reads and perform writes
271
+ for (const [block, nullifiers] of nullifiersByBlock){
272
+ for (const { nullifier, noteReadPromise } of nullifiers){
273
+ const noteBuffer = await noteReadPromise;
274
+ if (!noteBuffer) {
275
+ throw new Error(`PXE DB integrity error: no note found with nullifier ${nullifier}`);
229
276
  }
230
- return note;
231
- }));
232
- const storedNotes = nullifiedNoteBuffers.map((buffer)=>StoredNote.fromBuffer(buffer));
233
- for (const storedNote of storedNotes){
234
- const noteNullifier = storedNote.noteDao.siloedNullifier.toString();
235
- const scopes = storedNote.scopes;
236
- if (scopes.size === 0) {
237
- // We should never run into this error because notes always have a scope assigned to them - either on initial
238
- // insertion via `addNotes` or when removing their nullifiers.
239
- throw new Error(`No scopes found for nullified note with nullifier ${noteNullifier}`);
277
+ const storedNote = StoredNote.fromBuffer(noteBuffer);
278
+ if (storedNote.scopes.size === 0) {
279
+ throw new Error(`No scopes found for nullified note with nullifier ${nullifier}`);
240
280
  }
241
281
  storedNote.markAsActive();
242
282
  await Promise.all([
243
- this.#notes.set(noteNullifier, storedNote.toBuffer()),
244
- this.#nullifiersByNullificationBlockNumber.deleteValue(i, noteNullifier)
283
+ this.#notes.set(nullifier, storedNote.toBuffer()),
284
+ this.#nullifiersByNullificationBlockNumber.deleteValue(block, nullifier)
245
285
  ]);
246
286
  }
247
287
  }
248
288
  }
249
- commit(jobId) {
250
- return this.#withJobLock(jobId, async ()=>{
251
- for (const [nullifier, storedNote] of this.#getNotesForJob(jobId)){
252
- await this.#notes.set(nullifier, storedNote.toBuffer());
253
- await this.#nullifiersByContractAddress.set(storedNote.noteDao.contractAddress.toString(), nullifier);
254
- if (storedNote.nullifiedAt !== undefined) {
255
- await this.#nullifiersByNullificationBlockNumber.set(storedNote.nullifiedAt, nullifier);
256
- }
289
+ /**
290
+ * Commits in memory job data to persistent storage.
291
+ *
292
+ * Called by JobCoordinator when a job completes successfully.
293
+ *
294
+ * Note: JobCoordinator wraps all commits in a single transaction, so we don't need our own transactionAsync here
295
+ * (and using one would throw on IndexedDB as it does not support nested txs).
296
+ *
297
+ * @param jobId - The jobId identifying which staged data to commit
298
+ */ async commit(jobId) {
299
+ for (const [nullifier, storedNote] of this.#getNotesForJob(jobId)){
300
+ await this.#notes.set(nullifier, storedNote.toBuffer());
301
+ await this.#nullifiersByContractAddress.set(storedNote.noteDao.contractAddress.toString(), nullifier);
302
+ if (storedNote.nullifiedAt !== undefined) {
303
+ await this.#nullifiersByNullificationBlockNumber.set(storedNote.nullifiedAt, nullifier);
257
304
  }
258
- this.#clearJobData(jobId);
259
- });
305
+ }
306
+ this.#clearJobData(jobId);
260
307
  }
261
308
  discardStaged(jobId) {
262
- return this.#withJobLock(jobId, ()=>Promise.resolve(this.#clearJobData(jobId)));
309
+ this.#clearJobData(jobId);
310
+ return Promise.resolve();
263
311
  }
264
312
  #clearJobData(jobId) {
265
313
  this.#notesForJob.delete(jobId);
@@ -290,14 +338,4 @@ import { StoredNote } from './stored_note.js';
290
338
  }
291
339
  return notesForJob;
292
340
  }
293
- async #nullifiersOfContract(contractAddress, jobId) {
294
- // Collect persisted nullifiers for this contract
295
- const persistedNullifiers = await toArray(this.#nullifiersByContractAddress.getValuesAsync(contractAddress.toString()));
296
- // Collect staged nullifiers from the job where the note's contract matches
297
- const stagedNullifiers = this.#getNotesForJob(jobId).values().filter((storedNote)=>storedNote.noteDao.contractAddress.equals(contractAddress)).map((storedNote)=>storedNote.noteDao.siloedNullifier.toString());
298
- return new Set([
299
- ...persistedNullifiers,
300
- ...stagedNullifiers
301
- ]);
302
- }
303
341
  }
@@ -88,4 +88,4 @@ export declare class PrivateEventStore implements StagedStore {
88
88
  discardStaged(jobId: string): Promise<void>;
89
89
  }
90
90
  export {};
91
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJpdmF0ZV9ldmVudF9zdG9yZS5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3N0b3JhZ2UvcHJpdmF0ZV9ldmVudF9zdG9yZS9wcml2YXRlX2V2ZW50X3N0b3JlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sRUFBRSxFQUFFLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUlwRCxPQUFPLEtBQUssRUFBRSxpQkFBaUIsRUFBcUMsTUFBTSxpQkFBaUIsQ0FBQztBQUM1RixPQUFPLEtBQUssRUFBRSxhQUFhLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUN2RCxPQUFPLEtBQUssRUFBRSxZQUFZLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUNoRSxPQUFPLEtBQUssRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFFckQsT0FBTyxLQUFLLEVBQUUsV0FBVyxFQUFFLE1BQU0sMENBQTBDLENBQUM7QUFDNUUsT0FBTyxLQUFLLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFHdkQsTUFBTSxNQUFNLHVCQUF1QixHQUFHO0lBQ3BDLGVBQWUsRUFBRSxZQUFZLENBQUM7SUFDOUIsU0FBUyxFQUFFLE1BQU0sQ0FBQztJQUNsQixPQUFPLEVBQUUsTUFBTSxDQUFDO0lBQ2hCLE1BQU0sRUFBRSxZQUFZLEVBQUUsQ0FBQztJQUN2QixNQUFNLENBQUMsRUFBRSxNQUFNLENBQUM7Q0FDakIsQ0FBQztBQUVGLEtBQUssb0JBQW9CLEdBQUcsSUFBSSxHQUFHO0lBQ2pDLGVBQWUsRUFBRSxZQUFZLENBQUM7SUFDOUIsS0FBSyxFQUFFLFlBQVksQ0FBQztJQUNwQiwyQ0FBMkM7SUFDM0MsY0FBYyxFQUFFLE1BQU0sQ0FBQztJQUN2Qix5RUFBeUU7SUFDekUsY0FBYyxFQUFFLE1BQU0sQ0FBQztDQUN4QixDQUFDO0FBRUY7O0dBRUc7QUFDSCxxQkFBYSxpQkFBa0IsWUFBVyxXQUFXOztJQUNuRCxRQUFRLENBQUMsU0FBUyxFQUFFLE1BQU0sQ0FBbUI7SUFnQjdDLE1BQU0seUNBQXVDO0lBRTdDLFlBQVksS0FBSyxFQUFFLGlCQUFpQixFQVFuQztJQUVEOzs7Ozs7Ozs7OztPQVdHO0lBQ0gsb0JBQW9CLENBQ2xCLGFBQWEsRUFBRSxhQUFhLEVBQzVCLFVBQVUsRUFBRSxFQUFFLEVBQ2QsVUFBVSxFQUFFLEVBQUUsRUFBRSxFQUNoQixxQkFBcUIsRUFBRSxFQUFFLEVBQ3pCLFFBQVEsRUFBRSxvQkFBb0IsRUFDOUIsS0FBSyxFQUFFLE1BQU0saUJBdUNkO0lBRUQ7Ozs7Ozs7Ozs7T0FVRztJQUNJLGdCQUFnQixDQUNyQixhQUFhLEVBQUUsYUFBYSxFQUM1QixNQUFNLEVBQUUsdUJBQXVCLEdBQzlCLE9BQU8sQ0FBQyxrQkFBa0IsRUFBRSxDQUFDLENBcUUvQjtJQUVEOzs7Ozs7Ozs7Ozs7Ozs7O09BZ0JHO0lBQ1UsUUFBUSxDQUFDLFdBQVcsRUFBRSxNQUFNLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0E0QnBGO0lBRUQ7Ozs7Ozs7OztPQVNHO0lBQ0gsTUFBTSxDQUFDLEtBQUssRUFBRSxNQUFNLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxDQWVuQztJQUVEOztPQUVHO0lBQ0gsYUFBYSxDQUFDLEtBQUssRUFBRSxNQUFNLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUUxQztDQTRFRiJ9
91
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJpdmF0ZV9ldmVudF9zdG9yZS5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3N0b3JhZ2UvcHJpdmF0ZV9ldmVudF9zdG9yZS9wcml2YXRlX2V2ZW50X3N0b3JlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sRUFBRSxFQUFFLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUdwRCxPQUFPLEtBQUssRUFBRSxpQkFBaUIsRUFBcUMsTUFBTSxpQkFBaUIsQ0FBQztBQUM1RixPQUFPLEtBQUssRUFBRSxhQUFhLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUN2RCxPQUFPLEtBQUssRUFBRSxZQUFZLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUNoRSxPQUFPLEtBQUssRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFFckQsT0FBTyxLQUFLLEVBQUUsV0FBVyxFQUFFLE1BQU0sMENBQTBDLENBQUM7QUFDNUUsT0FBTyxLQUFLLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFHdkQsTUFBTSxNQUFNLHVCQUF1QixHQUFHO0lBQ3BDLGVBQWUsRUFBRSxZQUFZLENBQUM7SUFDOUIsU0FBUyxFQUFFLE1BQU0sQ0FBQztJQUNsQixPQUFPLEVBQUUsTUFBTSxDQUFDO0lBQ2hCLE1BQU0sRUFBRSxZQUFZLEVBQUUsQ0FBQztJQUN2QixNQUFNLENBQUMsRUFBRSxNQUFNLENBQUM7Q0FDakIsQ0FBQztBQUVGLEtBQUssb0JBQW9CLEdBQUcsSUFBSSxHQUFHO0lBQ2pDLGVBQWUsRUFBRSxZQUFZLENBQUM7SUFDOUIsS0FBSyxFQUFFLFlBQVksQ0FBQztJQUNwQiwyQ0FBMkM7SUFDM0MsY0FBYyxFQUFFLE1BQU0sQ0FBQztJQUN2Qix5RUFBeUU7SUFDekUsY0FBYyxFQUFFLE1BQU0sQ0FBQztDQUN4QixDQUFDO0FBRUY7O0dBRUc7QUFDSCxxQkFBYSxpQkFBa0IsWUFBVyxXQUFXOztJQUNuRCxRQUFRLENBQUMsU0FBUyxFQUFFLE1BQU0sQ0FBbUI7SUFnQjdDLE1BQU0seUNBQXVDO0lBRTdDLFlBQVksS0FBSyxFQUFFLGlCQUFpQixFQVFuQztJQUVEOzs7Ozs7Ozs7OztPQVdHO0lBQ0gsb0JBQW9CLENBQ2xCLGFBQWEsRUFBRSxhQUFhLEVBQzVCLFVBQVUsRUFBRSxFQUFFLEVBQ2QsVUFBVSxFQUFFLEVBQUUsRUFBRSxFQUNoQixxQkFBcUIsRUFBRSxFQUFFLEVBQ3pCLFFBQVEsRUFBRSxvQkFBb0IsRUFDOUIsS0FBSyxFQUFFLE1BQU0saUJBeUNkO0lBRUQ7Ozs7Ozs7Ozs7T0FVRztJQUNJLGdCQUFnQixDQUNyQixhQUFhLEVBQUUsYUFBYSxFQUM1QixNQUFNLEVBQUUsdUJBQXVCLEdBQzlCLE9BQU8sQ0FBQyxrQkFBa0IsRUFBRSxDQUFDLENBK0UvQjtJQUVEOzs7Ozs7Ozs7Ozs7Ozs7O09BZ0JHO0lBQ1UsUUFBUSxDQUFDLFdBQVcsRUFBRSxNQUFNLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FzQ3BGO0lBRUQ7Ozs7Ozs7OztPQVNHO0lBQ0csTUFBTSxDQUFDLEtBQUssRUFBRSxNQUFNLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxDQWdCekM7SUFFRDs7T0FFRztJQUNILGFBQWEsQ0FBQyxLQUFLLEVBQUUsTUFBTSxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FHMUM7Q0EwRUYifQ==
@@ -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;AAIpD,OAAO,KAAK,EAAE,iBAAiB,EAAqC,MAAM,iBAAiB,CAAC;AAC5F,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAErD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0CAA0C,CAAC;AAC5E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAGvD,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;AAEF,KAAK,oBAAoB,GAAG,IAAI,GAAG;IACjC,eAAe,EAAE,YAAY,CAAC;IAC9B,KAAK,EAAE,YAAY,CAAC;IACpB,2CAA2C;IAC3C,cAAc,EAAE,MAAM,CAAC;IACvB,yEAAyE;IACzE,cAAc,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF;;GAEG;AACH,qBAAa,iBAAkB,YAAW,WAAW;;IACnD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAmB;IAgB7C,MAAM,yCAAuC;IAE7C,YAAY,KAAK,EAAE,iBAAiB,EAQnC;IAED;;;;;;;;;;;OAWG;IACH,oBAAoB,CAClB,aAAa,EAAE,aAAa,EAC5B,UAAU,EAAE,EAAE,EACd,UAAU,EAAE,EAAE,EAAE,EAChB,qBAAqB,EAAE,EAAE,EACzB,QAAQ,EAAE,oBAAoB,EAC9B,KAAK,EAAE,MAAM,iBAuCd;IAED;;;;;;;;;;OAUG;IACI,gBAAgB,CACrB,aAAa,EAAE,aAAa,EAC5B,MAAM,EAAE,uBAAuB,GAC9B,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAqE/B;IAED;;;;;;;;;;;;;;;;OAgBG;IACU,QAAQ,CAAC,WAAW,EAAE,MAAM,EAAE,kBAAkB,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA4BpF;IAED;;;;;;;;;OASG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAenC;IAED;;OAEG;IACH,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE1C;CA4EF"}
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,EAAqC,MAAM,iBAAiB,CAAC;AAC5F,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAErD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0CAA0C,CAAC;AAC5E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAGvD,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;AAEF,KAAK,oBAAoB,GAAG,IAAI,GAAG;IACjC,eAAe,EAAE,YAAY,CAAC;IAC9B,KAAK,EAAE,YAAY,CAAC;IACpB,2CAA2C;IAC3C,cAAc,EAAE,MAAM,CAAC;IACvB,yEAAyE;IACzE,cAAc,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF;;GAEG;AACH,qBAAa,iBAAkB,YAAW,WAAW;;IACnD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAmB;IAgB7C,MAAM,yCAAuC;IAE7C,YAAY,KAAK,EAAE,iBAAiB,EAQnC;IAED;;;;;;;;;;;OAWG;IACH,oBAAoB,CAClB,aAAa,EAAE,aAAa,EAC5B,UAAU,EAAE,EAAE,EACd,UAAU,EAAE,EAAE,EAAE,EAChB,qBAAqB,EAAE,EAAE,EACzB,QAAQ,EAAE,oBAAoB,EAC9B,KAAK,EAAE,MAAM,iBAyCd;IAED;;;;;;;;;;OAUG;IACI,gBAAgB,CACrB,aAAa,EAAE,aAAa,EAC5B,MAAM,EAAE,uBAAuB,GAC9B,OAAO,CAAC,kBAAkB,EAAE,CAAC,CA+E/B;IAED;;;;;;;;;;;;;;;;OAgBG;IACU,QAAQ,CAAC,WAAW,EAAE,MAAM,EAAE,kBAAkB,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAsCpF;IAED;;;;;;;;;OASG;IACG,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAgBzC;IAED;;OAEG;IACH,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAG1C;CA0EF"}