@aztec/pxe 0.0.1-commit.59e663cd → 0.0.1-commit.5cf06de3

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 (110) 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 +3 -3
  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 +4 -4
  10. package/dest/contract_function_simulator/oracle/oracle.d.ts.map +1 -1
  11. package/dest/contract_function_simulator/oracle/oracle.js +29 -17
  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 +6 -6
  15. package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts +18 -15
  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 +28 -33
  18. package/dest/contract_sync/index.d.ts +4 -3
  19. package/dest/contract_sync/index.d.ts.map +1 -1
  20. package/dest/contract_sync/index.js +11 -4
  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 +6 -5
  39. package/dest/logs/log_service.d.ts.map +1 -1
  40. package/dest/logs/log_service.js +10 -15
  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/pxe.d.ts +1 -1
  51. package/dest/pxe.d.ts.map +1 -1
  52. package/dest/pxe.js +9 -7
  53. package/dest/storage/address_store/address_store.d.ts +1 -1
  54. package/dest/storage/address_store/address_store.d.ts.map +1 -1
  55. package/dest/storage/address_store/address_store.js +12 -11
  56. package/dest/storage/anchor_block_store/anchor_block_store.d.ts +9 -1
  57. package/dest/storage/anchor_block_store/anchor_block_store.d.ts.map +1 -1
  58. package/dest/storage/anchor_block_store/anchor_block_store.js +8 -1
  59. package/dest/storage/capsule_store/capsule_store.js +6 -8
  60. package/dest/storage/contract_store/contract_store.d.ts +1 -1
  61. package/dest/storage/contract_store/contract_store.d.ts.map +1 -1
  62. package/dest/storage/contract_store/contract_store.js +22 -13
  63. package/dest/storage/metadata.d.ts +1 -1
  64. package/dest/storage/metadata.js +1 -1
  65. package/dest/storage/note_store/note_store.d.ts +11 -1
  66. package/dest/storage/note_store/note_store.d.ts.map +1 -1
  67. package/dest/storage/note_store/note_store.js +143 -105
  68. package/dest/storage/private_event_store/private_event_store.d.ts +1 -1
  69. package/dest/storage/private_event_store/private_event_store.d.ts.map +1 -1
  70. package/dest/storage/private_event_store/private_event_store.js +84 -61
  71. package/dest/storage/private_event_store/stored_private_event.js +1 -1
  72. package/dest/storage/tagging_store/recipient_tagging_store.d.ts +1 -1
  73. package/dest/storage/tagging_store/recipient_tagging_store.d.ts.map +1 -1
  74. package/dest/storage/tagging_store/recipient_tagging_store.js +31 -19
  75. package/dest/storage/tagging_store/sender_address_book_store.d.ts +1 -1
  76. package/dest/storage/tagging_store/sender_address_book_store.d.ts.map +1 -1
  77. package/dest/storage/tagging_store/sender_address_book_store.js +20 -14
  78. package/dest/storage/tagging_store/sender_tagging_store.d.ts +1 -1
  79. package/dest/storage/tagging_store/sender_tagging_store.d.ts.map +1 -1
  80. package/dest/storage/tagging_store/sender_tagging_store.js +183 -113
  81. package/package.json +16 -16
  82. package/src/block_synchronizer/block_synchronizer.ts +15 -12
  83. package/src/contract_function_simulator/contract_function_simulator.ts +6 -6
  84. package/src/contract_function_simulator/oracle/interfaces.ts +9 -9
  85. package/src/contract_function_simulator/oracle/oracle.ts +32 -15
  86. package/src/contract_function_simulator/oracle/private_execution_oracle.ts +4 -6
  87. package/src/contract_function_simulator/oracle/utility_execution_oracle.ts +31 -35
  88. package/src/contract_sync/index.ts +23 -2
  89. package/src/entrypoints/client/bundle/utils.ts +7 -14
  90. package/src/entrypoints/client/lazy/utils.ts +8 -14
  91. package/src/entrypoints/pxe_creation_options.ts +2 -1
  92. package/src/entrypoints/server/utils.ts +15 -19
  93. package/src/events/event_service.ts +4 -6
  94. package/src/job_coordinator/job_coordinator.ts +4 -3
  95. package/src/logs/log_service.ts +14 -14
  96. package/src/notes/note_service.ts +5 -7
  97. package/src/oracle_version.ts +2 -2
  98. package/src/private_kernel/private_kernel_execution_prover.ts +6 -3
  99. package/src/pxe.ts +19 -5
  100. package/src/storage/address_store/address_store.ts +15 -15
  101. package/src/storage/anchor_block_store/anchor_block_store.ts +8 -0
  102. package/src/storage/capsule_store/capsule_store.ts +8 -8
  103. package/src/storage/contract_store/contract_store.ts +22 -11
  104. package/src/storage/metadata.ts +1 -1
  105. package/src/storage/note_store/note_store.ts +159 -129
  106. package/src/storage/private_event_store/private_event_store.ts +102 -81
  107. package/src/storage/private_event_store/stored_private_event.ts +1 -1
  108. package/src/storage/tagging_store/recipient_tagging_store.ts +31 -21
  109. package/src/storage/tagging_store/sender_address_book_store.ts +20 -14
  110. package/src/storage/tagging_store/sender_tagging_store.ts +210 -126
@@ -1,15 +1,15 @@
1
1
  import type { Fr } from '@aztec/foundation/curves/bn254';
2
- import { createLogger } from '@aztec/foundation/log';
2
+ import { type Logger, type LoggerBindings, createLogger } from '@aztec/foundation/log';
3
3
  import type { KeyStore } from '@aztec/key-store';
4
4
  import { AztecAddress } from '@aztec/stdlib/aztec-address';
5
5
  import type { CompleteAddress } from '@aztec/stdlib/contract';
6
6
  import type { AztecNode } from '@aztec/stdlib/interfaces/server';
7
7
  import { DirectionalAppTaggingSecret, PendingTaggedLog, SiloedTag, Tag, TxScopedL2Log } from '@aztec/stdlib/logs';
8
+ import type { BlockHeader } from '@aztec/stdlib/tx';
8
9
 
9
10
  import type { LogRetrievalRequest } from '../contract_function_simulator/noir-structs/log_retrieval_request.js';
10
11
  import { LogRetrievalResponse } from '../contract_function_simulator/noir-structs/log_retrieval_response.js';
11
12
  import { AddressStore } from '../storage/address_store/address_store.js';
12
- import { AnchorBlockStore } from '../storage/anchor_block_store/anchor_block_store.js';
13
13
  import { CapsuleStore } from '../storage/capsule_store/capsule_store.js';
14
14
  import type { RecipientTaggingStore } from '../storage/tagging_store/recipient_tagging_store.js';
15
15
  import type { SenderAddressBookStore } from '../storage/tagging_store/sender_address_book_store.js';
@@ -20,18 +20,21 @@ import {
20
20
  } from '../tagging/index.js';
21
21
 
22
22
  export class LogService {
23
- private log = createLogger('log_service');
23
+ private log: Logger;
24
24
 
25
25
  constructor(
26
26
  private readonly aztecNode: AztecNode,
27
- private readonly anchorBlockStore: AnchorBlockStore,
27
+ private readonly anchorBlockHeader: BlockHeader,
28
28
  private readonly keyStore: KeyStore,
29
29
  private readonly capsuleStore: CapsuleStore,
30
30
  private readonly recipientTaggingStore: RecipientTaggingStore,
31
31
  private readonly senderAddressBookStore: SenderAddressBookStore,
32
32
  private readonly addressStore: AddressStore,
33
33
  private readonly jobId: string,
34
- ) {}
34
+ bindings?: LoggerBindings,
35
+ ) {
36
+ this.log = createLogger('pxe:log_service', bindings);
37
+ }
35
38
 
36
39
  public async bulkRetrieveLogs(logRetrievalRequests: LogRetrievalRequest[]): Promise<(LogRetrievalResponse | null)[]> {
37
40
  return await Promise.all(
@@ -53,8 +56,7 @@ export class LogService {
53
56
  }
54
57
 
55
58
  async #getPublicLogByTag(tag: Tag, contractAddress: AztecAddress): Promise<LogRetrievalResponse | null> {
56
- const anchorBlockHeader = await this.anchorBlockStore.getBlockHeader();
57
- const anchorBlockHash = await anchorBlockHeader.hash();
59
+ const anchorBlockHash = await this.anchorBlockHeader.hash();
58
60
  const allLogsPerTag = await getAllPublicLogsByTagsFromContract(
59
61
  this.aztecNode,
60
62
  contractAddress,
@@ -83,8 +85,7 @@ export class LogService {
83
85
  }
84
86
 
85
87
  async #getPrivateLogByTag(siloedTag: SiloedTag): Promise<LogRetrievalResponse | null> {
86
- const anchorBlockHeader = await this.anchorBlockStore.getBlockHeader();
87
- const anchorBlockHash = await anchorBlockHeader.hash();
88
+ const anchorBlockHash = await this.anchorBlockHeader.hash();
88
89
  const allLogsPerTag = await getAllPrivateLogsByTags(this.aztecNode, [siloedTag], anchorBlockHash);
89
90
  const logsForTag = allLogsPerTag[0];
90
91
 
@@ -107,17 +108,16 @@ export class LogService {
107
108
  );
108
109
  }
109
110
 
110
- public async syncTaggedLogs(
111
+ public async fetchTaggedLogs(
111
112
  contractAddress: AztecAddress,
112
113
  pendingTaggedLogArrayBaseSlot: Fr,
113
114
  scopes?: AztecAddress[],
114
115
  ) {
115
- this.log.verbose('Searching for tagged logs', { contract: contractAddress });
116
+ this.log.verbose(`Fetching tagged logs for ${contractAddress.toString()}`);
116
117
 
117
118
  // We only load logs from block up to and including the anchor block number
118
- const anchorBlockHeader = await this.anchorBlockStore.getBlockHeader();
119
- const anchorBlockNumber = anchorBlockHeader.getBlockNumber();
120
- const anchorBlockHash = await anchorBlockHeader.hash();
119
+ const anchorBlockNumber = this.anchorBlockHeader.getBlockNumber();
120
+ const anchorBlockHash = await this.anchorBlockHeader.hash();
121
121
 
122
122
  // Determine recipients: use scopes if provided, otherwise get all accounts
123
123
  const recipients = scopes && scopes.length > 0 ? scopes : await this.keyStore.getAccounts();
@@ -5,16 +5,15 @@ import { computeUniqueNoteHash, siloNoteHash, siloNullifier } from '@aztec/stdli
5
5
  import { type AztecNode, MAX_RPC_LEN } from '@aztec/stdlib/interfaces/client';
6
6
  import { Note, NoteDao, NoteStatus } from '@aztec/stdlib/note';
7
7
  import { MerkleTreeId } from '@aztec/stdlib/trees';
8
- import type { TxHash } from '@aztec/stdlib/tx';
8
+ import type { BlockHeader, TxHash } from '@aztec/stdlib/tx';
9
9
 
10
- import type { AnchorBlockStore } from '../storage/anchor_block_store/anchor_block_store.js';
11
10
  import type { NoteStore } from '../storage/note_store/note_store.js';
12
11
 
13
12
  export class NoteService {
14
13
  constructor(
15
14
  private readonly noteStore: NoteStore,
16
15
  private readonly aztecNode: AztecNode,
17
- private readonly anchorBlockStore: AnchorBlockStore,
16
+ private readonly anchorBlockHeader: BlockHeader,
18
17
  private readonly jobId: string,
19
18
  ) {}
20
19
 
@@ -72,7 +71,7 @@ export class NoteService {
72
71
  * @param contractAddress - The contract whose notes should be checked and nullified.
73
72
  */
74
73
  public async syncNoteNullifiers(contractAddress: AztecAddress): Promise<void> {
75
- const anchorBlockHash = await (await this.anchorBlockStore.getBlockHeader()).hash();
74
+ const anchorBlockHash = await this.anchorBlockHeader.hash();
76
75
 
77
76
  const contractNotes = await this.noteStore.getNotes({ contractAddress }, this.jobId);
78
77
 
@@ -142,9 +141,8 @@ export class NoteService {
142
141
  // number which *should* be recent enough to be available, even for non-archive nodes.
143
142
  // Also note that the note should never be ahead of the synced block here since `fetchTaggedLogs` only processes
144
143
  // logs up to the synced block making this only an additional safety check.
145
- const anchorBlockHeader = await this.anchorBlockStore.getBlockHeader();
146
- const anchorBlockNumber = anchorBlockHeader.getBlockNumber();
147
- const anchorBlockHash = await anchorBlockHeader.hash();
144
+ const anchorBlockNumber = this.anchorBlockHeader.getBlockNumber();
145
+ const anchorBlockHash = await this.anchorBlockHeader.hash();
148
146
 
149
147
  // By computing siloed and unique note hashes ourselves we prevent contracts from interfering with the note storage
150
148
  // of other contracts, which would constitute a security breach.
@@ -4,9 +4,9 @@
4
4
  ///
5
5
  /// @dev Whenever a contract function or Noir test is run, the `utilityAssertCompatibleOracleVersion` oracle is called
6
6
  /// and if the oracle version is incompatible an error is thrown.
7
- export const ORACLE_VERSION = 9;
7
+ export const ORACLE_VERSION = 11;
8
8
 
9
9
  /// This hash is computed as by hashing the Oracle interface and it is used to detect when the Oracle interface changes,
10
10
  /// which in turn implies that you need to update the ORACLE_VERSION constant in this file and in
11
11
  /// `noir-projects/aztec-nr/aztec/src/oracle/version.nr`.
12
- export const ORACLE_INTERFACE_HASH = '9866cc52510acaef75a3d47a0ed501fd9ff92b9d53b2c8a88c8a3ffd04ced81f';
12
+ export const ORACLE_INTERFACE_HASH = '20c4d02d8cd5e448c11001a5f72ea2e0927630aeda75e537550872a9627bf40b';
@@ -1,6 +1,6 @@
1
1
  import { vkAsFieldsMegaHonk } from '@aztec/foundation/crypto/keys';
2
2
  import { Fr } from '@aztec/foundation/curves/bn254';
3
- import { createLogger } from '@aztec/foundation/log';
3
+ import { type Logger, type LoggerBindings, createLogger } from '@aztec/foundation/log';
4
4
  import { pushTestData } from '@aztec/foundation/testing';
5
5
  import { Timer } from '@aztec/foundation/timer';
6
6
  import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types/vk-tree';
@@ -56,13 +56,16 @@ export interface PrivateKernelExecutionProverConfig {
56
56
  * inform state tree updates.
57
57
  */
58
58
  export class PrivateKernelExecutionProver {
59
- private log = createLogger('pxe:private-kernel-execution-prover');
59
+ private log: Logger;
60
60
 
61
61
  constructor(
62
62
  private oracle: PrivateKernelOracle,
63
63
  private proofCreator: PrivateKernelProver,
64
64
  private fakeProofs = false,
65
- ) {}
65
+ bindings?: LoggerBindings,
66
+ ) {
67
+ this.log = createLogger('pxe:private-kernel-execution-prover', bindings);
68
+ }
66
69
 
67
70
  /**
68
71
  * Generate a proof for a given transaction request and execution result.
package/src/pxe.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import type { PrivateEventFilter } from '@aztec/aztec.js/wallet';
2
2
  import { BlockNumber } from '@aztec/foundation/branded-types';
3
3
  import { Fr } from '@aztec/foundation/curves/bn254';
4
- import { type Logger, createLogger } from '@aztec/foundation/log';
4
+ import { type Logger, type LoggerBindings, createLogger } from '@aztec/foundation/log';
5
5
  import { SerialQueue } from '@aztec/foundation/queue';
6
6
  import { Timer } from '@aztec/foundation/timer';
7
7
  import { KeyStore } from '@aztec/key-store';
@@ -128,6 +128,10 @@ export class PXE {
128
128
  config: PXEConfig,
129
129
  loggerOrSuffix?: string | Logger,
130
130
  ) {
131
+ // Extract bindings from the logger, or use empty bindings if a string suffix is provided.
132
+ const bindings: LoggerBindings | undefined =
133
+ loggerOrSuffix && typeof loggerOrSuffix !== 'string' ? loggerOrSuffix.getBindings() : undefined;
134
+
131
135
  const log =
132
136
  !loggerOrSuffix || typeof loggerOrSuffix === 'string'
133
137
  ? createLogger(loggerOrSuffix ? `pxe:service:${loggerOrSuffix}` : `pxe:service`)
@@ -153,10 +157,10 @@ export class PXE {
153
157
  privateEventStore,
154
158
  tipsStore,
155
159
  config,
156
- loggerOrSuffix,
160
+ bindings,
157
161
  );
158
162
 
159
- const jobCoordinator = new JobCoordinator(store);
163
+ const jobCoordinator = new JobCoordinator(store, bindings);
160
164
  jobCoordinator.registerStores([
161
165
  capsuleStore,
162
166
  senderTaggingStore,
@@ -213,7 +217,6 @@ export class PXE {
213
217
  this.keyStore,
214
218
  this.addressStore,
215
219
  BenchmarkedNodeFactory.create(this.node),
216
- this.anchorBlockStore,
217
220
  this.senderTaggingStore,
218
221
  this.recipientTaggingStore,
219
222
  this.senderAddressBookStore,
@@ -300,7 +303,9 @@ export class PXE {
300
303
  privateSyncCall => this.#simulateUtility(contractFunctionSimulator, privateSyncCall, [], undefined, jobId),
301
304
  this.node,
302
305
  this.contractStore,
306
+ this.noteStore,
303
307
  anchorBlockHeader,
308
+ jobId,
304
309
  );
305
310
 
306
311
  const result = await contractFunctionSimulator.run(
@@ -400,7 +405,12 @@ export class PXE {
400
405
  const anchorBlockHeader = await this.anchorBlockStore.getBlockHeader();
401
406
  const anchorBlockHash = await anchorBlockHeader.hash();
402
407
  const kernelOracle = new PrivateKernelOracle(this.contractStore, this.keyStore, this.node, anchorBlockHash);
403
- const kernelTraceProver = new PrivateKernelExecutionProver(kernelOracle, proofCreator, !this.proverEnabled);
408
+ const kernelTraceProver = new PrivateKernelExecutionProver(
409
+ kernelOracle,
410
+ proofCreator,
411
+ !this.proverEnabled,
412
+ this.log.getBindings(),
413
+ );
404
414
  this.log.debug(`Executing kernel trace prover (${JSON.stringify(config)})...`);
405
415
  return await kernelTraceProver.proveWithKernels(txExecutionRequest.toTxRequest(), privateExecutionResult, config);
406
416
  }
@@ -968,7 +978,9 @@ export class PXE {
968
978
  privateSyncCall => this.#simulateUtility(contractFunctionSimulator, privateSyncCall, [], undefined, jobId),
969
979
  this.node,
970
980
  this.contractStore,
981
+ this.noteStore,
971
982
  anchorBlockHeader,
983
+ jobId,
972
984
  );
973
985
 
974
986
  const executionResult = await this.#simulateUtility(
@@ -1039,7 +1051,9 @@ export class PXE {
1039
1051
  await this.#simulateUtility(contractFunctionSimulator, privateSyncCall, [], undefined, jobId),
1040
1052
  this.node,
1041
1053
  this.contractStore,
1054
+ this.noteStore,
1042
1055
  anchorBlockHeader,
1056
+ jobId,
1043
1057
  );
1044
1058
  });
1045
1059
 
@@ -43,23 +43,23 @@ export class AddressStore {
43
43
  });
44
44
  }
45
45
 
46
- async #getCompleteAddress(address: AztecAddress): Promise<CompleteAddress | undefined> {
47
- const index = await this.#completeAddressIndex.getAsync(address.toString());
48
- if (index === undefined) {
49
- return undefined;
50
- }
51
-
52
- const value = await this.#completeAddresses.atAsync(index);
53
- return value ? await CompleteAddress.fromBuffer(value) : undefined;
54
- }
55
-
56
46
  getCompleteAddress(account: AztecAddress): Promise<CompleteAddress | undefined> {
57
- return this.#getCompleteAddress(account);
47
+ return this.#store.transactionAsync(async () => {
48
+ const index = await this.#completeAddressIndex.getAsync(account.toString());
49
+ if (index === undefined) {
50
+ return undefined;
51
+ }
52
+
53
+ const value = await this.#completeAddresses.atAsync(index);
54
+ return value ? await CompleteAddress.fromBuffer(value) : undefined;
55
+ });
58
56
  }
59
57
 
60
- async getCompleteAddresses(): Promise<CompleteAddress[]> {
61
- return await Promise.all(
62
- (await toArray(this.#completeAddresses.valuesAsync())).map(v => CompleteAddress.fromBuffer(v)),
63
- );
58
+ getCompleteAddresses(): Promise<CompleteAddress[]> {
59
+ return this.#store.transactionAsync(async () => {
60
+ return await Promise.all(
61
+ (await toArray(this.#completeAddresses.valuesAsync())).map(v => CompleteAddress.fromBuffer(v)),
62
+ );
63
+ });
64
64
  }
65
65
  }
@@ -10,6 +10,14 @@ export class AnchorBlockStore {
10
10
  this.#synchronizedHeader = this.#store.openSingleton('header');
11
11
  }
12
12
 
13
+ /**
14
+ * Sets the currently synchronized block
15
+ *
16
+ * Important: this method is only called from BlockSynchronizer, and since we need it to run atomically with other
17
+ * stores in the case of a reorg, it MUST NOT be wrapped in a `transactionAsync` call. Doing so would result in a
18
+ * deadlock when the backend is IndexedDB, because `transactionAsync` is not designed to support reentrancy.
19
+ *
20
+ */
13
21
  async setHeader(header: BlockHeader): Promise<void> {
14
22
  await this.#synchronizedHeader.set(header.toBuffer());
15
23
  }
@@ -57,14 +57,14 @@ export class CapsuleStore implements StagedStore {
57
57
  */
58
58
  async #getFromStage(jobId: string, dbSlotKey: string): Promise<Buffer | null | undefined> {
59
59
  const jobStagedCapsules = this.#getJobStagedCapsules(jobId);
60
- let staged: Buffer | null | undefined = jobStagedCapsules.get(dbSlotKey);
61
- // Note that if staged === null, we marked it for deletion, so we don't want to
62
- // re-read it from DB
63
- if (staged === undefined) {
64
- // If we don't have a staged version of this dbSlotKey, first we check if there's one in DB
65
- staged = await this.#loadCapsuleFromDb(dbSlotKey);
66
- }
67
- return staged;
60
+ const staged: Buffer | null | undefined = jobStagedCapsules.get(dbSlotKey);
61
+
62
+ // Always issue DB read to keep IndexedDB transaction alive, even if the value is in the job staged data. This
63
+ // keeps IndexedDB transactions alive (they auto-commit when a new micro-task starts and there are no pending read
64
+ // requests). The staged value still takes precedence if it exists (including null for deletions).
65
+ const dbValue = await this.#loadCapsuleFromDb(dbSlotKey);
66
+
67
+ return staged !== undefined ? staged : dbValue;
68
68
  }
69
69
 
70
70
  /**
@@ -42,10 +42,12 @@ export class ContractStore {
42
42
  /** Map from contract address to contract class id */
43
43
  #contractClassIdMap: Map<string, Fr> = new Map();
44
44
 
45
+ #store: AztecAsyncKVStore;
45
46
  #contractArtifacts: AztecAsyncMap<string, Buffer>;
46
47
  #contractInstances: AztecAsyncMap<string, Buffer>;
47
48
 
48
49
  constructor(store: AztecAsyncKVStore) {
50
+ this.#store = store;
49
51
  this.#contractArtifacts = store.openMap('contract_artifacts');
50
52
  this.#contractInstances = store.openMap('contracts_instances');
51
53
  }
@@ -53,6 +55,7 @@ export class ContractStore {
53
55
  // Setters
54
56
 
55
57
  public async addContractArtifact(id: Fr, contract: ContractArtifact): Promise<void> {
58
+ // Validation outside transactionAsync - these are not DB operations
56
59
  const privateFunctions = contract.functions.filter(
57
60
  functionArtifact => functionArtifact.functionType === FunctionType.PRIVATE,
58
61
  );
@@ -69,7 +72,9 @@ export class ContractStore {
69
72
  throw new Error('Repeated function selectors of private functions');
70
73
  }
71
74
 
72
- await this.#contractArtifacts.set(id.toString(), contractArtifactToBuffer(contract));
75
+ await this.#store.transactionAsync(() =>
76
+ this.#contractArtifacts.set(id.toString(), contractArtifactToBuffer(contract)),
77
+ );
73
78
  }
74
79
 
75
80
  async addContractInstance(contract: ContractInstanceWithAddress): Promise<void> {
@@ -123,21 +128,27 @@ export class ContractStore {
123
128
 
124
129
  // Public getters
125
130
 
126
- async getContractsAddresses(): Promise<AztecAddress[]> {
127
- const keys = await toArray(this.#contractInstances.keysAsync());
128
- return keys.map(AztecAddress.fromString);
131
+ getContractsAddresses(): Promise<AztecAddress[]> {
132
+ return this.#store.transactionAsync(async () => {
133
+ const keys = await toArray(this.#contractInstances.keysAsync());
134
+ return keys.map(AztecAddress.fromString);
135
+ });
129
136
  }
130
137
 
131
138
  /** Returns a contract instance for a given address. Throws if not found. */
132
- public async getContractInstance(contractAddress: AztecAddress): Promise<ContractInstanceWithAddress | undefined> {
133
- const contract = await this.#contractInstances.getAsync(contractAddress.toString());
134
- return contract && SerializableContractInstance.fromBuffer(contract).withAddress(contractAddress);
139
+ public getContractInstance(contractAddress: AztecAddress): Promise<ContractInstanceWithAddress | undefined> {
140
+ return this.#store.transactionAsync(async () => {
141
+ const contract = await this.#contractInstances.getAsync(contractAddress.toString());
142
+ return contract && SerializableContractInstance.fromBuffer(contract).withAddress(contractAddress);
143
+ });
135
144
  }
136
145
 
137
- public async getContractArtifact(contractClassId: Fr): Promise<ContractArtifact | undefined> {
138
- const contract = await this.#contractArtifacts.getAsync(contractClassId.toString());
139
- // TODO(@spalladino): AztecAsyncMap lies and returns Uint8Arrays instead of Buffers, hence the extra Buffer.from.
140
- return contract && contractArtifactFromBuffer(Buffer.from(contract));
146
+ public getContractArtifact(contractClassId: Fr): Promise<ContractArtifact | undefined> {
147
+ return this.#store.transactionAsync(async () => {
148
+ const contract = await this.#contractArtifacts.getAsync(contractClassId.toString());
149
+ // TODO(@spalladino): AztecAsyncMap lies and returns Uint8Arrays instead of Buffers, hence the extra Buffer.from.
150
+ return contract && contractArtifactFromBuffer(Buffer.from(contract));
151
+ });
141
152
  }
142
153
 
143
154
  /** Returns a contract class for a given class id. Throws if not found. */
@@ -1 +1 @@
1
- export const PXE_DATA_SCHEMA_VERSION = 2;
1
+ export const PXE_DATA_SCHEMA_VERSION = 3;