@aztec/pxe 0.0.1-commit.6c91f13 → 0.0.1-commit.7d4e6cd

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 (93) hide show
  1. package/dest/block_synchronizer/block_synchronizer.d.ts +4 -2
  2. package/dest/block_synchronizer/block_synchronizer.d.ts.map +1 -1
  3. package/dest/block_synchronizer/block_synchronizer.js +6 -3
  4. package/dest/config/package_info.js +1 -1
  5. package/dest/contract_function_simulator/contract_function_simulator.d.ts +4 -3
  6. package/dest/contract_function_simulator/contract_function_simulator.d.ts.map +1 -1
  7. package/dest/contract_function_simulator/contract_function_simulator.js +7 -6
  8. package/dest/contract_function_simulator/noir-structs/event_validation_request.d.ts +3 -2
  9. package/dest/contract_function_simulator/noir-structs/event_validation_request.d.ts.map +1 -1
  10. package/dest/contract_function_simulator/noir-structs/event_validation_request.js +5 -2
  11. package/dest/contract_function_simulator/oracle/private_execution.d.ts +1 -1
  12. package/dest/contract_function_simulator/oracle/private_execution.d.ts.map +1 -1
  13. package/dest/contract_function_simulator/oracle/private_execution.js +1 -2
  14. package/dest/contract_function_simulator/oracle/private_execution_oracle.d.ts +2 -17
  15. package/dest/contract_function_simulator/oracle/private_execution_oracle.d.ts.map +1 -1
  16. package/dest/contract_function_simulator/oracle/private_execution_oracle.js +4 -32
  17. package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts +3 -2
  18. package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts.map +1 -1
  19. package/dest/contract_function_simulator/oracle/utility_execution_oracle.js +4 -2
  20. package/dest/entrypoints/client/bundle/utils.d.ts +1 -1
  21. package/dest/entrypoints/client/bundle/utils.d.ts.map +1 -1
  22. package/dest/entrypoints/client/bundle/utils.js +10 -1
  23. package/dest/entrypoints/client/lazy/utils.d.ts +1 -1
  24. package/dest/entrypoints/client/lazy/utils.d.ts.map +1 -1
  25. package/dest/entrypoints/client/lazy/utils.js +10 -1
  26. package/dest/entrypoints/pxe_creation_options.d.ts +3 -2
  27. package/dest/entrypoints/pxe_creation_options.d.ts.map +1 -1
  28. package/dest/entrypoints/server/utils.d.ts +1 -1
  29. package/dest/entrypoints/server/utils.d.ts.map +1 -1
  30. package/dest/entrypoints/server/utils.js +11 -7
  31. package/dest/events/event_service.d.ts +2 -2
  32. package/dest/events/event_service.d.ts.map +1 -1
  33. package/dest/events/event_service.js +2 -2
  34. package/dest/job_coordinator/job_coordinator.d.ts +74 -0
  35. package/dest/job_coordinator/job_coordinator.d.ts.map +1 -0
  36. package/dest/job_coordinator/job_coordinator.js +93 -0
  37. package/dest/private_kernel/hints/build_private_kernel_reset_private_inputs.d.ts +2 -2
  38. package/dest/private_kernel/hints/build_private_kernel_reset_private_inputs.d.ts.map +1 -1
  39. package/dest/private_kernel/hints/build_private_kernel_reset_private_inputs.js +2 -2
  40. package/dest/private_kernel/private_kernel_execution_prover.d.ts +1 -1
  41. package/dest/private_kernel/private_kernel_execution_prover.d.ts.map +1 -1
  42. package/dest/private_kernel/private_kernel_execution_prover.js +3 -4
  43. package/dest/private_kernel/private_kernel_oracle.d.ts +3 -2
  44. package/dest/private_kernel/private_kernel_oracle.d.ts.map +1 -1
  45. package/dest/private_kernel/private_kernel_oracle_impl.d.ts +2 -2
  46. package/dest/private_kernel/private_kernel_oracle_impl.d.ts.map +1 -1
  47. package/dest/private_kernel/private_kernel_oracle_impl.js +2 -3
  48. package/dest/pxe.d.ts +2 -1
  49. package/dest/pxe.d.ts.map +1 -1
  50. package/dest/pxe.js +39 -20
  51. package/dest/storage/private_event_store/private_event_store.d.ts +7 -2
  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 +57 -14
  54. package/dest/storage/tagging_store/sender_tagging_store.js +1 -1
  55. package/dest/tagging/constants.d.ts +2 -0
  56. package/dest/tagging/constants.d.ts.map +1 -0
  57. package/dest/tagging/constants.js +10 -0
  58. package/dest/tagging/index.d.ts +2 -2
  59. package/dest/tagging/index.d.ts.map +1 -1
  60. package/dest/tagging/index.js +1 -10
  61. package/dest/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.d.ts +1 -1
  62. package/dest/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.d.ts.map +1 -1
  63. package/dest/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.js +2 -2
  64. package/dest/tagging/sender_sync/sync_sender_tagging_indexes.js +1 -1
  65. package/dest/tagging/sender_sync/utils/get_status_change_of_pending.d.ts +1 -1
  66. package/dest/tagging/sender_sync/utils/get_status_change_of_pending.d.ts.map +1 -1
  67. package/dest/tagging/sender_sync/utils/get_status_change_of_pending.js +2 -2
  68. package/package.json +16 -16
  69. package/src/block_synchronizer/block_synchronizer.ts +5 -2
  70. package/src/config/package_info.ts +1 -1
  71. package/src/contract_function_simulator/contract_function_simulator.ts +10 -5
  72. package/src/contract_function_simulator/noir-structs/event_validation_request.ts +4 -0
  73. package/src/contract_function_simulator/oracle/private_execution.ts +0 -2
  74. package/src/contract_function_simulator/oracle/private_execution_oracle.ts +4 -36
  75. package/src/contract_function_simulator/oracle/utility_execution_oracle.ts +2 -0
  76. package/src/entrypoints/client/bundle/utils.ts +7 -1
  77. package/src/entrypoints/client/lazy/utils.ts +7 -2
  78. package/src/entrypoints/pxe_creation_options.ts +2 -1
  79. package/src/entrypoints/server/utils.ts +11 -15
  80. package/src/events/event_service.ts +2 -0
  81. package/src/job_coordinator/job_coordinator.ts +149 -0
  82. package/src/private_kernel/hints/build_private_kernel_reset_private_inputs.ts +1 -2
  83. package/src/private_kernel/private_kernel_execution_prover.ts +2 -4
  84. package/src/private_kernel/private_kernel_oracle.ts +2 -1
  85. package/src/private_kernel/private_kernel_oracle_impl.ts +2 -8
  86. package/src/pxe.ts +64 -19
  87. package/src/storage/private_event_store/private_event_store.ts +68 -14
  88. package/src/storage/tagging_store/sender_tagging_store.ts +1 -1
  89. package/src/tagging/constants.ts +10 -0
  90. package/src/tagging/index.ts +1 -11
  91. package/src/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.ts +5 -2
  92. package/src/tagging/sender_sync/sync_sender_tagging_indexes.ts +1 -1
  93. package/src/tagging/sender_sync/utils/get_status_change_of_pending.ts +6 -2
@@ -7,6 +7,7 @@ import type { AztecNode } from '@aztec/stdlib/interfaces/client';
7
7
  import type { PXEConfig } from '../config/index.js';
8
8
  import type { AnchorBlockStore } from '../storage/anchor_block_store/anchor_block_store.js';
9
9
  import type { NoteStore } from '../storage/note_store/note_store.js';
10
+ import type { PrivateEventStore } from '../storage/private_event_store/private_event_store.js';
10
11
 
11
12
  /**
12
13
  * The BlockSynchronizer class orchestrates synchronization between PXE and Aztec node, maintaining an up-to-date
@@ -22,6 +23,7 @@ export class BlockSynchronizer implements L2BlockStreamEventHandler {
22
23
  private node: AztecNode,
23
24
  private anchorBlockStore: AnchorBlockStore,
24
25
  private noteStore: NoteStore,
26
+ private privateEventStore: PrivateEventStore,
25
27
  private l2TipsStore: L2TipsKVStore,
26
28
  config: Partial<Pick<PXEConfig, 'l2BlockBatchSize'>> = {},
27
29
  loggerOrSuffix?: string | Logger,
@@ -48,13 +50,13 @@ export class BlockSynchronizer implements L2BlockStreamEventHandler {
48
50
 
49
51
  switch (event.type) {
50
52
  case 'blocks-added': {
51
- const lastBlock = event.blocks.at(-1)!.block;
53
+ const lastBlock = event.blocks.at(-1)!;
52
54
  this.log.verbose(`Updated pxe last block to ${lastBlock.number}`, {
53
55
  blockHash: lastBlock.hash(),
54
56
  archive: lastBlock.archive.root.toString(),
55
57
  header: lastBlock.header.toInspect(),
56
58
  });
57
- await this.anchorBlockStore.setHeader(lastBlock.getBlockHeader());
59
+ await this.anchorBlockStore.setHeader(lastBlock.header);
58
60
  break;
59
61
  }
60
62
  case 'chain-pruned': {
@@ -62,6 +64,7 @@ export class BlockSynchronizer implements L2BlockStreamEventHandler {
62
64
  // We first unnullify and then remove so that unnullified notes that were created after the block number end up deleted.
63
65
  const lastSynchedBlockNumber = (await this.anchorBlockStore.getBlockHeader()).getBlockNumber();
64
66
  await this.noteStore.rollbackNotesAndNullifiers(event.block.number, lastSynchedBlockNumber);
67
+ await this.privateEventStore.rollbackEventsAfterBlock(event.block.number, lastSynchedBlockNumber);
65
68
  // Update the header to the last block.
66
69
  const newHeader = await this.node.getBlockHeader(event.block.number);
67
70
  if (!newHeader) {
@@ -1,3 +1,3 @@
1
1
  export function getPackageInfo() {
2
- return { version: '3.0.0', name: '@aztec/pxe' };
2
+ return { version: '4.0.0', name: '@aztec/pxe' };
3
3
  }
@@ -123,6 +123,7 @@ export class ContractFunctionSimulator {
123
123
  * @param senderForTags - The address that is used as a tagging sender when emitting private logs. Returned from
124
124
  * the `privateGetSenderForTags` oracle.
125
125
  * @param scopes - The accounts whose notes we can access in this call. Currently optional and will default to all.
126
+ * @param jobId - The job ID for staged writes.
126
127
  * @returns The result of the execution.
127
128
  */
128
129
  public async run(
@@ -131,13 +132,14 @@ export class ContractFunctionSimulator {
131
132
  selector: FunctionSelector,
132
133
  msgSender = AztecAddress.fromField(Fr.MAX_FIELD_VALUE),
133
134
  anchorBlockHeader: BlockHeader,
134
- senderForTags?: AztecAddress,
135
- scopes?: AztecAddress[],
135
+ senderForTags: AztecAddress | undefined,
136
+ scopes: AztecAddress[] | undefined,
137
+ jobId: string,
136
138
  ): Promise<PrivateExecutionResult> {
137
139
  const simulatorSetupTimer = new Timer();
138
140
 
139
141
  await this.contractStore.syncPrivateState(contractAddress, selector, privateSyncCall =>
140
- this.runUtility(privateSyncCall, [], anchorBlockHeader, scopes),
142
+ this.runUtility(privateSyncCall, [], anchorBlockHeader, scopes, jobId),
141
143
  );
142
144
 
143
145
  await verifyCurrentClassId(contractAddress, this.aztecNode, this.contractStore, anchorBlockHeader);
@@ -174,7 +176,7 @@ export class ContractFunctionSimulator {
174
176
  callContext,
175
177
  anchorBlockHeader,
176
178
  async call => {
177
- await this.runUtility(call, [], anchorBlockHeader, scopes);
179
+ await this.runUtility(call, [], anchorBlockHeader, scopes, jobId);
178
180
  },
179
181
  request.authWitnesses,
180
182
  request.capsules,
@@ -192,6 +194,7 @@ export class ContractFunctionSimulator {
192
194
  this.senderAddressBookStore,
193
195
  this.capsuleStore,
194
196
  this.privateEventStore,
197
+ jobId,
195
198
  0, // totalPublicArgsCount
196
199
  startSideEffectCounter,
197
200
  undefined, // log
@@ -261,7 +264,8 @@ export class ContractFunctionSimulator {
261
264
  call: FunctionCall,
262
265
  authwits: AuthWitness[],
263
266
  anchorBlockHeader: BlockHeader,
264
- scopes?: AztecAddress[],
267
+ scopes: AztecAddress[] | undefined,
268
+ jobId: string,
265
269
  ): Promise<Fr[]> {
266
270
  await verifyCurrentClassId(call.to, this.aztecNode, this.contractStore, anchorBlockHeader);
267
271
 
@@ -286,6 +290,7 @@ export class ContractFunctionSimulator {
286
290
  this.senderAddressBookStore,
287
291
  this.capsuleStore,
288
292
  this.privateEventStore,
293
+ jobId,
289
294
  undefined,
290
295
  scopes,
291
296
  );
@@ -15,6 +15,7 @@ export class EventValidationRequest {
15
15
  constructor(
16
16
  public contractAddress: AztecAddress,
17
17
  public eventTypeId: EventSelector,
18
+ public randomness: Fr,
18
19
  public serializedEvent: Fr[],
19
20
  public eventCommitment: Fr,
20
21
  public txHash: TxHash,
@@ -27,6 +28,8 @@ export class EventValidationRequest {
27
28
  const contractAddress = AztecAddress.fromField(reader.readField());
28
29
  const eventTypeId = EventSelector.fromField(reader.readField());
29
30
 
31
+ const randomness = reader.readField();
32
+
30
33
  const eventStorage = reader.readFieldArray(MAX_EVENT_SERIALIZED_LEN);
31
34
  const eventLen = reader.readField().toNumber();
32
35
  const serializedEvent = eventStorage.slice(0, eventLen);
@@ -38,6 +41,7 @@ export class EventValidationRequest {
38
41
  return new EventValidationRequest(
39
42
  contractAddress,
40
43
  eventTypeId,
44
+ randomness,
41
45
  serializedEvent,
42
46
  eventCommitment,
43
47
  txHash,
@@ -85,7 +85,6 @@ export async function executePrivateFunction(
85
85
 
86
86
  const rawReturnValues = await privateExecutionOracle.privateLoadFromExecutionCache(publicInputs.returnsHash);
87
87
 
88
- const noteHashLeafIndexMap = privateExecutionOracle.getNoteHashLeafIndexMap();
89
88
  const newNotes = privateExecutionOracle.getNewNotes();
90
89
  const noteHashNullifierCounterMap = privateExecutionOracle.getNoteHashNullifierCounterMap();
91
90
  const offchainEffects = privateExecutionOracle.getOffchainEffects();
@@ -108,7 +107,6 @@ export async function executePrivateFunction(
108
107
  Buffer.from(artifact.verificationKey!, 'base64'),
109
108
  partialWitness,
110
109
  publicInputs,
111
- noteHashLeafIndexMap,
112
110
  newNotes,
113
111
  noteHashNullifierCounterMap,
114
112
  rawReturnValues,
@@ -14,7 +14,7 @@ import {
14
14
  } from '@aztec/stdlib/abi';
15
15
  import type { AuthWitness } from '@aztec/stdlib/auth-witness';
16
16
  import { AztecAddress } from '@aztec/stdlib/aztec-address';
17
- import { computeUniqueNoteHash, siloNoteHash, siloNullifier } from '@aztec/stdlib/hash';
17
+ import { siloNullifier } from '@aztec/stdlib/hash';
18
18
  import type { AztecNode } from '@aztec/stdlib/interfaces/client';
19
19
  import { PrivateContextInputs } from '@aztec/stdlib/kernel';
20
20
  import { type ContractClassLog, DirectionalAppTaggingSecret, type PreTag } from '@aztec/stdlib/logs';
@@ -64,16 +64,6 @@ export class PrivateExecutionOracle extends UtilityExecutionOracle implements IP
64
64
  * Users can also use this to get a clearer idea of what's happened during a simulation.
65
65
  */
66
66
  private newNotes: NoteAndSlot[] = [];
67
- /**
68
- * Notes from previous transactions that are returned to the oracle call `getNotes` during this execution.
69
- * The mapping maps from the unique siloed note hash to the index for notes created in private executions.
70
- * It maps from siloed note hash to the index for notes created by public functions.
71
- *
72
- * They are not part of the ExecutionNoteCache and being forwarded to nested contexts via `extend()`
73
- * because these notes are meant to be maintained on a per-call basis
74
- * They should act as references for the read requests output by an app circuit via public inputs.
75
- */
76
- private noteHashLeafIndexMap: Map<bigint, bigint> = new Map();
77
67
  private noteHashNullifierCounterMap: Map<number, number> = new Map();
78
68
  private contractClassLogs: CountedContractClassLog[] = [];
79
69
  private offchainEffects: { data: Fr[] }[] = [];
@@ -104,6 +94,7 @@ export class PrivateExecutionOracle extends UtilityExecutionOracle implements IP
104
94
  senderAddressBookStore: SenderAddressBookStore,
105
95
  capsuleStore: CapsuleStore,
106
96
  privateEventStore: PrivateEventStore,
97
+ jobId: string,
107
98
  private totalPublicCalldataCount: number = 0,
108
99
  protected sideEffectCounter: number = 0,
109
100
  log = createLogger('simulator:client_execution_context'),
@@ -126,6 +117,7 @@ export class PrivateExecutionOracle extends UtilityExecutionOracle implements IP
126
117
  senderAddressBookStore,
127
118
  capsuleStore,
128
119
  privateEventStore,
120
+ jobId,
129
121
  log,
130
122
  scopes,
131
123
  );
@@ -160,14 +152,6 @@ export class PrivateExecutionOracle extends UtilityExecutionOracle implements IP
160
152
  return toACVMWitness(0, fields);
161
153
  }
162
154
 
163
- /**
164
- * The KernelProver will use this to fully populate witnesses and provide hints to the kernel circuit
165
- * regarding which note hash each settled read request corresponds to.
166
- */
167
- public getNoteHashLeafIndexMap() {
168
- return this.noteHashLeafIndexMap;
169
- }
170
-
171
155
  /**
172
156
  * Get the data for the newly created notes.
173
157
  */
@@ -402,23 +386,6 @@ export class PrivateExecutionOracle extends UtilityExecutionOracle implements IP
402
386
  .join(', ')}`,
403
387
  );
404
388
 
405
- const noteHashesAndIndexes = await Promise.all(
406
- notes.map(async n => {
407
- if (n.index !== undefined) {
408
- const siloedNoteHash = await siloNoteHash(n.contractAddress, n.noteHash);
409
- const uniqueNoteHash = await computeUniqueNoteHash(n.noteNonce, siloedNoteHash);
410
-
411
- return { hash: uniqueNoteHash, index: n.index };
412
- }
413
- }),
414
- );
415
-
416
- noteHashesAndIndexes
417
- .filter(n => n !== undefined)
418
- .forEach(n => {
419
- this.noteHashLeafIndexMap.set(n!.hash.toBigInt(), n!.index);
420
- });
421
-
422
389
  return notes;
423
390
  }
424
391
 
@@ -586,6 +553,7 @@ export class PrivateExecutionOracle extends UtilityExecutionOracle implements IP
586
553
  this.senderAddressBookStore,
587
554
  this.capsuleStore,
588
555
  this.privateEventStore,
556
+ this.jobId,
589
557
  this.totalPublicCalldataCount,
590
558
  sideEffectCounter,
591
559
  this.log,
@@ -64,6 +64,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
64
64
  protected readonly senderAddressBookStore: SenderAddressBookStore,
65
65
  protected readonly capsuleStore: CapsuleStore,
66
66
  protected readonly privateEventStore: PrivateEventStore,
67
+ protected readonly jobId: string,
67
68
  protected log = createLogger('simulator:client_view_context'),
68
69
  protected readonly scopes?: AztecAddress[],
69
70
  ) {}
@@ -412,6 +413,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
412
413
  eventService.deliverEvent(
413
414
  request.contractAddress,
414
415
  request.eventTypeId,
416
+ request.randomness,
415
417
  request.serializedEvent,
416
418
  request.eventCommitment,
417
419
  request.txHash,
@@ -1,3 +1,4 @@
1
+ import { BBPrivateKernelProver } from '@aztec/bb-prover/client';
1
2
  import { BBBundlePrivateKernelProver } from '@aztec/bb-prover/client/bundle';
2
3
  import { randomBytes } from '@aztec/foundation/crypto/random';
3
4
  import { createLogger } from '@aztec/foundation/log';
@@ -49,7 +50,12 @@ export async function createPXE(
49
50
  ? loggers.prover
50
51
  : createLogger('pxe:bb:wasm:bundle' + (logSuffix ? `:${logSuffix}` : ''));
51
52
 
52
- const prover = options.prover ?? new BBBundlePrivateKernelProver(simulator, proverLogger);
53
+ let prover;
54
+ if (options.proverOrOptions instanceof BBPrivateKernelProver) {
55
+ prover = options.proverOrOptions;
56
+ } else {
57
+ prover = new BBBundlePrivateKernelProver(simulator, { ...options.proverOrOptions, logger: proverLogger });
58
+ }
53
59
  const protocolContractsProvider = new BundledProtocolContractsProvider();
54
60
 
55
61
  const pxeLogger = loggers.pxe ? loggers.pxe : createLogger('pxe:service' + (logSuffix ? `:${logSuffix}` : ''));
@@ -1,3 +1,4 @@
1
+ import { BBPrivateKernelProver } from '@aztec/bb-prover/client';
1
2
  import { BBLazyPrivateKernelProver } from '@aztec/bb-prover/client/lazy';
2
3
  import { randomBytes } from '@aztec/foundation/crypto/random';
3
4
  import { createLogger } from '@aztec/foundation/log';
@@ -48,8 +49,12 @@ export async function createPXE(
48
49
  ? loggers.prover
49
50
  : createLogger('pxe:bb:wasm:bundle' + (logSuffix ? `:${logSuffix}` : ''));
50
51
 
51
- const prover = options.prover ?? new BBLazyPrivateKernelProver(simulator, proverLogger);
52
-
52
+ let prover;
53
+ if (options.proverOrOptions instanceof BBPrivateKernelProver) {
54
+ prover = options.proverOrOptions;
55
+ } else {
56
+ prover = new BBLazyPrivateKernelProver(simulator, { ...options.proverOrOptions, logger: proverLogger });
57
+ }
53
58
  const protocolContractsProvider = new LazyProtocolContractsProvider();
54
59
 
55
60
  const pxeLogger = loggers.pxe ? loggers.pxe : createLogger('pxe:service' + (logSuffix ? `:${logSuffix}` : ''));
@@ -1,3 +1,4 @@
1
+ import type { BBPrivateKernelProverOptions } from '@aztec/bb-prover/client';
1
2
  import type { Logger } from '@aztec/foundation/log';
2
3
  import type { AztecAsyncKVStore } from '@aztec/kv-store';
3
4
  import type { CircuitSimulator } from '@aztec/simulator/client';
@@ -6,7 +7,7 @@ import type { PrivateKernelProver } from '@aztec/stdlib/interfaces/client';
6
7
  export type PXECreationOptions = {
7
8
  loggers?: { store?: Logger; pxe?: Logger; prover?: Logger };
8
9
  useLogSuffix?: boolean | string;
9
- prover?: PrivateKernelProver;
10
+ proverOrOptions?: PrivateKernelProver | BBPrivateKernelProverOptions;
10
11
  store?: AztecAsyncKVStore;
11
12
  simulator?: CircuitSimulator;
12
13
  };
@@ -1,13 +1,10 @@
1
+ import { BBPrivateKernelProver } from '@aztec/bb-prover/client';
1
2
  import { BBBundlePrivateKernelProver } from '@aztec/bb-prover/client/bundle';
2
3
  import { randomBytes } from '@aztec/foundation/crypto/random';
3
- import { type Logger, createLogger } from '@aztec/foundation/log';
4
+ import { createLogger } from '@aztec/foundation/log';
5
+ import { createStore } from '@aztec/kv-store/lmdb-v2';
4
6
  import { BundledProtocolContractsProvider } from '@aztec/protocol-contracts/providers/bundle';
5
- import {
6
- type CircuitSimulator,
7
- MemoryCircuitRecorder,
8
- SimulatorRecorderWrapper,
9
- WASMSimulator,
10
- } from '@aztec/simulator/client';
7
+ import { MemoryCircuitRecorder, SimulatorRecorderWrapper, WASMSimulator } from '@aztec/simulator/client';
11
8
  import { FileCircuitRecorder } from '@aztec/simulator/testing';
12
9
  import type { AztecNode } from '@aztec/stdlib/interfaces/client';
13
10
 
@@ -46,9 +43,6 @@ export async function createPXE(
46
43
  };
47
44
 
48
45
  if (!options.store) {
49
- // TODO once https://github.com/AztecProtocol/aztec-packages/issues/13656 is fixed, we can remove this and always
50
- // import the lmdb-v2 version
51
- const { createStore } = await import('@aztec/kv-store/lmdb-v2');
52
46
  const storeLogger = loggers.store
53
47
  ? loggers.store
54
48
  : createLogger('pxe:data:lmdb' + (logSuffix ? `:${logSuffix}` : ''));
@@ -58,7 +52,13 @@ export async function createPXE(
58
52
  ? loggers.prover
59
53
  : createLogger('pxe:bb:native' + (logSuffix ? `:${logSuffix}` : ''));
60
54
 
61
- const prover = options.prover ?? createProver(simulator, proverLogger);
55
+ let prover;
56
+ if (options.proverOrOptions instanceof BBPrivateKernelProver) {
57
+ prover = options.proverOrOptions;
58
+ } else {
59
+ prover = new BBBundlePrivateKernelProver(simulator, { ...options.proverOrOptions, logger: proverLogger });
60
+ }
61
+
62
62
  const protocolContractsProvider = new BundledProtocolContractsProvider();
63
63
 
64
64
  const pxeLogger = loggers.pxe ? loggers.pxe : createLogger('pxe:service' + (logSuffix ? `:${logSuffix}` : ''));
@@ -73,7 +73,3 @@ export async function createPXE(
73
73
  );
74
74
  return pxe;
75
75
  }
76
-
77
- function createProver(simulator: CircuitSimulator, logger?: Logger) {
78
- return new BBBundlePrivateKernelProver(simulator, logger);
79
- }
@@ -19,6 +19,7 @@ export class EventService {
19
19
  public async deliverEvent(
20
20
  contractAddress: AztecAddress,
21
21
  selector: EventSelector,
22
+ randomness: Fr,
22
23
  content: Fr[],
23
24
  eventCommitment: Fr,
24
25
  txHash: TxHash,
@@ -63,6 +64,7 @@ export class EventService {
63
64
 
64
65
  return this.privateEventStore.storePrivateEventLog(
65
66
  selector,
67
+ randomness,
66
68
  content,
67
69
  Number(nullifierIndex.data), // Index of the event commitment in the nullifier tree
68
70
  {
@@ -0,0 +1,149 @@
1
+ import { randomBytes } from '@aztec/foundation/crypto/random';
2
+ import { createLogger } from '@aztec/foundation/log';
3
+ import type { AztecAsyncKVStore } from '@aztec/kv-store';
4
+
5
+ /**
6
+ * Interface that stores must implement to support staged writes.
7
+ */
8
+ export interface StagedStore {
9
+ /** Unique name identifying this store (used for tracking staged stores from JobCoordinator) */
10
+ readonly storeName: string;
11
+
12
+ /**
13
+ * Commits staged data to main storage.
14
+ * Should be called within a transaction for atomicity.
15
+ *
16
+ * @param jobId - The job identifier
17
+ */
18
+ commit(jobId: string): Promise<void>;
19
+
20
+ /**
21
+ * Discards staged data without committing.
22
+ * Called on abort.
23
+ *
24
+ * @param jobId - The job identifier
25
+ */
26
+ discardStaged(jobId: string): Promise<void>;
27
+ }
28
+
29
+ /**
30
+ * JobCoordinator manages job lifecycle and provides crash resilience for PXE operations.
31
+ *
32
+ * It uses a staged writes pattern:
33
+ * 1. When a job begins, a unique job ID is created
34
+ * 2. During the job, all writes go to staging (keyed by job ID)
35
+ * 3. On commit, staging is promoted to main storage
36
+ * 4. On abort, staged data is discarded
37
+ *
38
+ * Note: PXE should only rely on a single JobCoordinator instance, so it can eventually
39
+ * orchestrate concurrent jobs. Right now it doesn't make a difference because we're
40
+ * using a job queue with concurrency=1.
41
+ */
42
+ export class JobCoordinator {
43
+ private readonly log = createLogger('pxe:job_coordinator');
44
+
45
+ /** The underlying KV store */
46
+ kvStore: AztecAsyncKVStore;
47
+
48
+ #currentJobId: string | undefined;
49
+ #stores: Map<string, StagedStore> = new Map();
50
+
51
+ constructor(kvStore: AztecAsyncKVStore) {
52
+ this.kvStore = kvStore;
53
+ }
54
+
55
+ /**
56
+ * Registers a staged store.
57
+ * Must be called during initialization for all stores that need staging support.
58
+ */
59
+ registerStore(store: StagedStore): void {
60
+ if (this.#stores.has(store.storeName)) {
61
+ throw new Error(`Store "${store.storeName}" is already registered`);
62
+ }
63
+ this.#stores.set(store.storeName, store);
64
+ this.log.debug(`Registered staged store: ${store.storeName}`);
65
+ }
66
+
67
+ /**
68
+ * Registers multiple staged stores.
69
+ */
70
+ registerStores(stores: StagedStore[]): void {
71
+ for (const store of stores) {
72
+ this.registerStore(store);
73
+ }
74
+ }
75
+
76
+ /**
77
+ * Begins a new job and returns a job ID for staged writes.
78
+ *
79
+ * @returns Job ID to pass to store operations
80
+ */
81
+ beginJob(): string {
82
+ if (this.#currentJobId) {
83
+ throw new Error(
84
+ `Cannot begin job: job ${this.#currentJobId} is already in progress. ` +
85
+ `This should not happen - ensure jobs are properly committed or aborted.`,
86
+ );
87
+ }
88
+
89
+ const jobId = randomBytes(8).toString('hex');
90
+ this.#currentJobId = jobId;
91
+
92
+ this.log.debug(`Started job ${jobId}`);
93
+ return jobId;
94
+ }
95
+
96
+ /**
97
+ * Commits a job by promoting all staged data to main storage.
98
+ *
99
+ * @param jobId - The job ID returned from beginJob
100
+ */
101
+ async commitJob(jobId: string): Promise<void> {
102
+ if (!this.#currentJobId || this.#currentJobId !== jobId) {
103
+ throw new Error(
104
+ `Cannot commit job ${jobId}: no matching job in progress. ` + `Current job: ${this.#currentJobId ?? 'none'}`,
105
+ );
106
+ }
107
+
108
+ this.log.debug(`Committing job ${jobId}`);
109
+
110
+ // Commit all stores atomically in a single transaction.
111
+ // Each store's commit is a no-op if it has no staged data (but that's up to each store to handle).
112
+ await this.kvStore.transactionAsync(async () => {
113
+ for (const store of this.#stores.values()) {
114
+ await store.commit(jobId);
115
+ }
116
+ });
117
+
118
+ this.#currentJobId = undefined;
119
+ this.log.debug(`Job ${jobId} committed successfully`);
120
+ }
121
+
122
+ /**
123
+ * Aborts a job by discarding all staged data.
124
+ *
125
+ * @param jobId - The job ID returned from beginJob
126
+ */
127
+ async abortJob(jobId: string): Promise<void> {
128
+ if (!this.#currentJobId || this.#currentJobId !== jobId) {
129
+ // Job may have already been aborted or never started properly
130
+ this.log.warn(`Abort called for job ${jobId} but current job is ${this.#currentJobId ?? 'none'}`);
131
+ }
132
+
133
+ this.log.debug(`Aborting job ${jobId}`);
134
+
135
+ for (const store of this.#stores.values()) {
136
+ await store.discardStaged(jobId);
137
+ }
138
+
139
+ this.#currentJobId = undefined;
140
+ this.log.debug(`Job ${jobId} aborted`);
141
+ }
142
+
143
+ /**
144
+ * Checks if there's a job currently in progress.
145
+ */
146
+ hasJobInProgress(): boolean {
147
+ return this.#currentJobId !== undefined;
148
+ }
149
+ }
@@ -138,7 +138,7 @@ export class PrivateKernelResetPrivateInputsBuilder {
138
138
  }
139
139
  }
140
140
 
141
- async build(oracle: PrivateKernelOracle, noteHashLeafIndexMap: Map<bigint, bigint>) {
141
+ async build(oracle: PrivateKernelOracle) {
142
142
  if (privateKernelResetDimensionNames.every(name => !this.requestedDimensions[name])) {
143
143
  throw new Error('Reset is not required.');
144
144
  }
@@ -190,7 +190,6 @@ export class PrivateKernelResetPrivateInputsBuilder {
190
190
  this.previousKernel.validationRequests.noteHashReadRequests,
191
191
  this.previousKernel.end.noteHashes,
192
192
  this.noteHashResetActions,
193
- noteHashLeafIndexMap,
194
193
  ),
195
194
  await buildNullifierReadRequestHintsFromResetActions(
196
195
  { getNullifierMembershipWitness: getNullifierMembershipWitnessResolver(oracle) },
@@ -28,7 +28,6 @@ import {
28
28
  type PrivateCallExecutionResult,
29
29
  type PrivateExecutionResult,
30
30
  TxRequest,
31
- collectNoteHashLeafIndexMap,
32
31
  collectNoteHashNullifierCounterMap,
33
32
  getFinalMinRevertibleSideEffectCounter,
34
33
  } from '@aztec/stdlib/tx';
@@ -101,7 +100,6 @@ export class PrivateKernelExecutionProver {
101
100
 
102
101
  const executionSteps: PrivateExecutionStep[] = [];
103
102
 
104
- const noteHashLeafIndexMap = collectNoteHashLeafIndexMap(executionResult);
105
103
  const noteHashNullifierCounterMap = collectNoteHashNullifierCounterMap(executionResult);
106
104
  const minRevertibleSideEffectCounter = getFinalMinRevertibleSideEffectCounter(executionResult);
107
105
  const splitCounter = isPrivateOnlyTx ? 0 : minRevertibleSideEffectCounter;
@@ -116,7 +114,7 @@ export class PrivateKernelExecutionProver {
116
114
  );
117
115
  while (resetBuilder.needsReset()) {
118
116
  const witgenTimer = new Timer();
119
- const privateInputs = await resetBuilder.build(this.oracle, noteHashLeafIndexMap);
117
+ const privateInputs = await resetBuilder.build(this.oracle);
120
118
  output = generateWitnesses
121
119
  ? await this.proofCreator.generateResetOutput(privateInputs)
122
120
  : await this.proofCreator.simulateReset(privateInputs);
@@ -224,7 +222,7 @@ export class PrivateKernelExecutionProver {
224
222
  );
225
223
  while (resetBuilder.needsReset()) {
226
224
  const witgenTimer = new Timer();
227
- const privateInputs = await resetBuilder.build(this.oracle, noteHashLeafIndexMap);
225
+ const privateInputs = await resetBuilder.build(this.oracle);
228
226
  output = generateWitnesses
229
227
  ? await this.proofCreator.generateResetOutput(privateInputs)
230
228
  : await this.proofCreator.simulateReset(privateInputs);
@@ -43,7 +43,8 @@ export interface PrivateKernelOracle {
43
43
 
44
44
  /**
45
45
  * Returns a membership witness with the sibling path and leaf index in our private function indexed merkle tree.
46
- */ getNoteHashMembershipWitness(leafIndex: bigint): Promise<MembershipWitness<typeof NOTE_HASH_TREE_HEIGHT>>;
46
+ */
47
+ getNoteHashMembershipWitness(noteHash: Fr): Promise<MembershipWitness<typeof NOTE_HASH_TREE_HEIGHT> | undefined>;
47
48
 
48
49
  /**
49
50
  * Returns a membership witness with the sibling path and leaf index in our nullifier indexed merkle tree.
@@ -2,7 +2,6 @@ import { NOTE_HASH_TREE_HEIGHT, PUBLIC_DATA_TREE_HEIGHT, VK_TREE_HEIGHT } from '
2
2
  import type { Fr } from '@aztec/foundation/curves/bn254';
3
3
  import type { GrumpkinScalar, Point } from '@aztec/foundation/curves/grumpkin';
4
4
  import { createLogger } from '@aztec/foundation/log';
5
- import type { Tuple } from '@aztec/foundation/serialize';
6
5
  import { MembershipWitness } from '@aztec/foundation/trees';
7
6
  import type { KeyStore } from '@aztec/key-store';
8
7
  import { getVKIndex, getVKSiblingPath } from '@aztec/noir-protocol-circuits-types/vk-tree';
@@ -70,13 +69,8 @@ export class PrivateKernelOracleImpl implements PrivateKernelOracle {
70
69
  return Promise.resolve(new MembershipWitness(VK_TREE_HEIGHT, BigInt(leafIndex), getVKSiblingPath(leafIndex)));
71
70
  }
72
71
 
73
- async getNoteHashMembershipWitness(leafIndex: bigint): Promise<MembershipWitness<typeof NOTE_HASH_TREE_HEIGHT>> {
74
- const path = await this.node.getNoteHashSiblingPath(this.blockNumber, leafIndex);
75
- return new MembershipWitness<typeof NOTE_HASH_TREE_HEIGHT>(
76
- path.pathSize,
77
- leafIndex,
78
- path.toFields() as Tuple<Fr, typeof NOTE_HASH_TREE_HEIGHT>,
79
- );
72
+ getNoteHashMembershipWitness(noteHash: Fr): Promise<MembershipWitness<typeof NOTE_HASH_TREE_HEIGHT> | undefined> {
73
+ return this.node.getNoteHashMembershipWitness(this.blockNumber, noteHash);
80
74
  }
81
75
 
82
76
  getNullifierMembershipWitness(nullifier: Fr): Promise<NullifierMembershipWitness | undefined> {