@aztec/pxe 0.48.0 → 0.50.1

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 (29) hide show
  1. package/dest/config/index.d.ts +1 -0
  2. package/dest/config/index.d.ts.map +1 -1
  3. package/dest/config/index.js +6 -1
  4. package/dest/kernel_prover/hints/build_private_kernel_reset_hints.d.ts +1 -1
  5. package/dest/kernel_prover/hints/build_private_kernel_reset_hints.d.ts.map +1 -1
  6. package/dest/kernel_prover/hints/build_private_kernel_reset_hints.js +20 -7
  7. package/dest/kernel_prover/hints/needs_reset.d.ts +1 -1
  8. package/dest/kernel_prover/hints/needs_reset.d.ts.map +1 -1
  9. package/dest/kernel_prover/hints/needs_reset.js +21 -18
  10. package/dest/kernel_prover/kernel_prover.d.ts.map +1 -1
  11. package/dest/kernel_prover/kernel_prover.js +7 -7
  12. package/dest/pxe_http/pxe_http_server.d.ts.map +1 -1
  13. package/dest/pxe_http/pxe_http_server.js +6 -4
  14. package/dest/pxe_service/create_pxe_service.d.ts.map +1 -1
  15. package/dest/pxe_service/create_pxe_service.js +17 -15
  16. package/dest/pxe_service/pxe_service.d.ts +7 -13
  17. package/dest/pxe_service/pxe_service.d.ts.map +1 -1
  18. package/dest/pxe_service/pxe_service.js +48 -38
  19. package/dest/simulator_oracle/index.d.ts.map +1 -1
  20. package/dest/simulator_oracle/index.js +3 -19
  21. package/package.json +14 -14
  22. package/src/config/index.ts +6 -0
  23. package/src/kernel_prover/hints/build_private_kernel_reset_hints.ts +29 -7
  24. package/src/kernel_prover/hints/needs_reset.ts +20 -17
  25. package/src/kernel_prover/kernel_prover.ts +6 -2
  26. package/src/pxe_http/pxe_http_server.ts +6 -2
  27. package/src/pxe_service/create_pxe_service.ts +18 -19
  28. package/src/pxe_service/pxe_service.ts +46 -10
  29. package/src/simulator_oracle/index.ts +7 -21
@@ -31,7 +31,7 @@ import {
31
31
 
32
32
  import { type WitnessMap } from '@noir-lang/types';
33
33
 
34
- import { buildPrivateKernelResetInputs, needsReset, somethingToReset } from './hints/index.js';
34
+ import { buildPrivateKernelResetInputs, needsFinalReset, needsReset } from './hints/index.js';
35
35
  import { type ProvingDataOracle } from './proving_data_oracle.js';
36
36
 
37
37
  const NULL_PROVE_OUTPUT: PrivateKernelSimulateOutput<PrivateKernelCircuitPublicInputs> = {
@@ -88,6 +88,7 @@ export class KernelProver {
88
88
  noteHashLeafIndexMap,
89
89
  noteHashNullifierCounterMap,
90
90
  validationRequestsSplitCounter,
91
+ false,
91
92
  );
92
93
  output = await this.proofCreator.simulateProofReset(resetInputs);
93
94
  // TODO(#7368) consider refactoring this redundant bytecode pushing
@@ -135,13 +136,14 @@ export class KernelProver {
135
136
  firstIteration = false;
136
137
  }
137
138
 
138
- if (somethingToReset(output.publicInputs)) {
139
+ if (needsFinalReset(output.publicInputs)) {
139
140
  const resetInputs = await this.getPrivateKernelResetInputs(
140
141
  executionStack,
141
142
  output,
142
143
  noteHashLeafIndexMap,
143
144
  noteHashNullifierCounterMap,
144
145
  validationRequestsSplitCounter,
146
+ true,
145
147
  );
146
148
  output = await this.proofCreator.simulateProofReset(resetInputs);
147
149
  // TODO(#7368) consider refactoring this redundant bytecode pushing
@@ -188,6 +190,7 @@ export class KernelProver {
188
190
  noteHashLeafIndexMap: Map<bigint, bigint>,
189
191
  noteHashNullifierCounterMap: Map<number, number>,
190
192
  validationRequestsSplitCounter: number,
193
+ shouldSilo: boolean,
191
194
  ) {
192
195
  const previousVkMembershipWitness = await this.oracle.getVkMembershipWitness(output.verificationKey);
193
196
  const previousKernelData = new PrivateKernelData(
@@ -203,6 +206,7 @@ export class KernelProver {
203
206
  noteHashLeafIndexMap,
204
207
  noteHashNullifierCounterMap,
205
208
  validationRequestsSplitCounter,
209
+ shouldSilo,
206
210
  this.oracle,
207
211
  );
208
212
  }
@@ -9,6 +9,7 @@ import {
9
9
  Note,
10
10
  NullifierMembershipWitness,
11
11
  type PXE,
12
+ SiblingPath,
12
13
  SimulatedTx,
13
14
  Tx,
14
15
  TxEffect,
@@ -16,13 +17,14 @@ import {
16
17
  TxHash,
17
18
  TxReceipt,
18
19
  UnencryptedL2BlockL2Logs,
20
+ UniqueNote,
19
21
  } from '@aztec/circuit-types';
20
22
  import { FunctionSelector } from '@aztec/circuits.js';
21
23
  import { NoteSelector } from '@aztec/foundation/abi';
22
24
  import { AztecAddress } from '@aztec/foundation/aztec-address';
25
+ import { Buffer32 } from '@aztec/foundation/buffer';
23
26
  import { EthAddress } from '@aztec/foundation/eth-address';
24
27
  import { Fr, GrumpkinScalar, Point } from '@aztec/foundation/fields';
25
- import { BaseHashType } from '@aztec/foundation/hash';
26
28
  import { JsonRpcServer, createNamespacedJsonRpcServer } from '@aztec/foundation/json-rpc/server';
27
29
 
28
30
  import http from 'http';
@@ -41,13 +43,15 @@ export function createPXERpcServer(pxeService: PXE): JsonRpcServer {
41
43
  ExtendedUnencryptedL2Log,
42
44
  FunctionSelector,
43
45
  TxHash,
44
- BaseHashType,
46
+ Buffer32,
45
47
  EthAddress,
46
48
  Point,
47
49
  Fr,
48
50
  GrumpkinScalar,
49
51
  Note,
50
52
  ExtendedNote,
53
+ UniqueNote,
54
+ SiblingPath,
51
55
  AuthWitness,
52
56
  L2Block,
53
57
  TxEffect,
@@ -3,8 +3,7 @@ import { type AztecNode, type PrivateKernelProver } from '@aztec/circuit-types';
3
3
  import { randomBytes } from '@aztec/foundation/crypto';
4
4
  import { createDebugLogger } from '@aztec/foundation/log';
5
5
  import { KeyStore } from '@aztec/key-store';
6
- import { AztecLmdbStore } from '@aztec/kv-store/lmdb';
7
- import { initStoreForRollup } from '@aztec/kv-store/utils';
6
+ import { createStore } from '@aztec/kv-store/utils';
8
7
  import { getCanonicalAuthRegistry } from '@aztec/protocol-contracts/auth-registry';
9
8
  import { getCanonicalClassRegisterer } from '@aztec/protocol-contracts/class-registerer';
10
9
  import { getCanonicalFeeJuice } from '@aztec/protocol-contracts/fee-juice';
@@ -43,24 +42,10 @@ export async function createPXEService(
43
42
  const keyStorePath = config.dataDirectory ? join(config.dataDirectory, 'pxe_key_store') : undefined;
44
43
  const l1Contracts = await aztecNode.getL1ContractAddresses();
45
44
 
46
- const keyStore = new KeyStore(await initStoreForRollup(AztecLmdbStore.open(keyStorePath), l1Contracts.rollupAddress));
47
- const db = new KVPxeDatabase(await initStoreForRollup(AztecLmdbStore.open(pxeDbPath), l1Contracts.rollupAddress));
48
-
49
- // (@PhilWindle) Temporary validation until WASM is implemented
50
- let prover: PrivateKernelProver | undefined = proofCreator;
51
- if (!prover) {
52
- if (config.proverEnabled && (!config.bbBinaryPath || !config.bbWorkingDirectory)) {
53
- throw new Error(`Prover must be configured with binary path and working directory`);
54
- }
55
- prover = !config.proverEnabled
56
- ? new TestPrivateKernelProver()
57
- : new BBNativePrivateKernelProver(
58
- config.bbBinaryPath!,
59
- config.bbWorkingDirectory!,
60
- createDebugLogger('aztec:pxe:bb-native-prover' + (logSuffix ? `:${logSuffix}` : '')),
61
- );
62
- }
45
+ const keyStore = new KeyStore(await createStore(keyStorePath, l1Contracts.rollupAddress));
46
+ const db = new KVPxeDatabase(await createStore(pxeDbPath, l1Contracts.rollupAddress));
63
47
 
48
+ const prover = proofCreator ?? (await createProver(config, logSuffix));
64
49
  const server = new PXEService(keyStore, aztecNode, db, prover, config, logSuffix);
65
50
  for (const contract of [
66
51
  getCanonicalClassRegisterer(),
@@ -76,3 +61,17 @@ export async function createPXEService(
76
61
  await server.start();
77
62
  return server;
78
63
  }
64
+
65
+ function createProver(config: PXEServiceConfig, logSuffix?: string) {
66
+ if (!config.proverEnabled) {
67
+ return new TestPrivateKernelProver();
68
+ }
69
+
70
+ // (@PhilWindle) Temporary validation until WASM is implemented
71
+ if (!config.bbBinaryPath || !config.bbWorkingDirectory) {
72
+ throw new Error(`Prover must be configured with binary path and working directory`);
73
+ }
74
+ const bbConfig = config as Required<Pick<PXEServiceConfig, 'bbBinaryPath' | 'bbWorkingDirectory'>> & PXEServiceConfig;
75
+ const log = createDebugLogger('aztec:pxe:bb-native-prover' + (logSuffix ? `:${logSuffix}` : ''));
76
+ return BBNativePrivateKernelProver.new(bbConfig, log);
77
+ }
@@ -5,7 +5,7 @@ import {
5
5
  EncryptedTxL2Logs,
6
6
  type EventMetadata,
7
7
  EventType,
8
- ExtendedNote,
8
+ type ExtendedNote,
9
9
  type FunctionCall,
10
10
  type GetUnencryptedLogsResponse,
11
11
  type IncomingNotesFilter,
@@ -17,6 +17,7 @@ import {
17
17
  type PXE,
18
18
  type PXEInfo,
19
19
  type PrivateKernelProver,
20
+ type SiblingPath,
20
21
  SimulatedTx,
21
22
  SimulationError,
22
23
  TaggedLog,
@@ -26,11 +27,14 @@ import {
26
27
  type TxHash,
27
28
  type TxReceipt,
28
29
  UnencryptedTxL2Logs,
30
+ UniqueNote,
31
+ getNonNullifiedL1ToL2MessageWitness,
29
32
  isNoirCallStackUnresolved,
30
33
  } from '@aztec/circuit-types';
31
34
  import {
32
35
  AztecAddress,
33
36
  type CompleteAddress,
37
+ type L1_TO_L2_MSG_TREE_HEIGHT,
34
38
  type PartialAddress,
35
39
  computeContractClassId,
36
40
  getContractClassFromArtifact,
@@ -296,7 +300,7 @@ export class PXEService implements PXE {
296
300
  return await this.node.getPublicStorageAt(contract, slot, 'latest');
297
301
  }
298
302
 
299
- public async getIncomingNotes(filter: IncomingNotesFilter): Promise<ExtendedNote[]> {
303
+ public async getIncomingNotes(filter: IncomingNotesFilter): Promise<UniqueNote[]> {
300
304
  const noteDaos = await this.db.getIncomingNotes(filter);
301
305
 
302
306
  // TODO(#6531): Refactor --> This type conversion is ugly but I decided to keep it this way for now because
@@ -312,12 +316,20 @@ export class PXEService implements PXE {
312
316
  }
313
317
  owner = completeAddresses.address;
314
318
  }
315
- return new ExtendedNote(dao.note, owner, dao.contractAddress, dao.storageSlot, dao.noteTypeId, dao.txHash);
319
+ return new UniqueNote(
320
+ dao.note,
321
+ owner,
322
+ dao.contractAddress,
323
+ dao.storageSlot,
324
+ dao.noteTypeId,
325
+ dao.txHash,
326
+ dao.nonce,
327
+ );
316
328
  });
317
329
  return Promise.all(extendedNotes);
318
330
  }
319
331
 
320
- public async getOutgoingNotes(filter: OutgoingNotesFilter): Promise<ExtendedNote[]> {
332
+ public async getOutgoingNotes(filter: OutgoingNotesFilter): Promise<UniqueNote[]> {
321
333
  const noteDaos = await this.db.getOutgoingNotes(filter);
322
334
 
323
335
  // TODO(#6532): Refactor --> This type conversion is ugly but I decided to keep it this way for now because
@@ -333,18 +345,34 @@ export class PXEService implements PXE {
333
345
  }
334
346
  owner = completeAddresses.address;
335
347
  }
336
- return new ExtendedNote(dao.note, owner, dao.contractAddress, dao.storageSlot, dao.noteTypeId, dao.txHash);
348
+ return new UniqueNote(
349
+ dao.note,
350
+ owner,
351
+ dao.contractAddress,
352
+ dao.storageSlot,
353
+ dao.noteTypeId,
354
+ dao.txHash,
355
+ dao.nonce,
356
+ );
337
357
  });
338
358
  return Promise.all(extendedNotes);
339
359
  }
340
360
 
361
+ public async getL1ToL2MembershipWitness(
362
+ contractAddress: AztecAddress,
363
+ messageHash: Fr,
364
+ secret: Fr,
365
+ ): Promise<[bigint, SiblingPath<typeof L1_TO_L2_MSG_TREE_HEIGHT>]> {
366
+ return await getNonNullifiedL1ToL2MessageWitness(this.node, contractAddress, messageHash, secret);
367
+ }
368
+
341
369
  public async addNote(note: ExtendedNote, scope?: AztecAddress) {
342
370
  const owner = await this.db.getCompleteAddress(note.owner);
343
371
  if (!owner) {
344
372
  throw new Error(`Unknown account: ${note.owner.toString()}`);
345
373
  }
346
374
 
347
- const nonces = await this.getNoteNonces(note);
375
+ const nonces = await this.#getNoteNonces(note);
348
376
  if (nonces.length === 0) {
349
377
  throw new Error(`Cannot find the note in tx: ${note.txHash}.`);
350
378
  }
@@ -394,7 +422,7 @@ export class PXEService implements PXE {
394
422
  throw new Error(`Unknown account: ${note.owner.toString()}`);
395
423
  }
396
424
 
397
- const nonces = await this.getNoteNonces(note);
425
+ const nonces = await this.#getNoteNonces(note);
398
426
  if (nonces.length === 0) {
399
427
  throw new Error(`Cannot find the note in tx: ${note.txHash}.`);
400
428
  }
@@ -440,9 +468,8 @@ export class PXEService implements PXE {
440
468
  * @param note - The note to find the nonces for.
441
469
  * @returns The nonces of the note.
442
470
  * @remarks More than a single nonce may be returned since there might be more than one nonce for a given note.
443
- * TODO(#4956): Un-expose this
444
471
  */
445
- public async getNoteNonces(note: ExtendedNote): Promise<Fr[]> {
472
+ async #getNoteNonces(note: ExtendedNote): Promise<Fr[]> {
446
473
  const tx = await this.node.getTxEffect(note.txHash);
447
474
  if (!tx) {
448
475
  throw new Error(`Unknown tx: ${note.txHash}`);
@@ -497,6 +524,7 @@ export class PXEService implements PXE {
497
524
  txRequest: TxExecutionRequest,
498
525
  simulatePublic: boolean,
499
526
  msgSender: AztecAddress | undefined = undefined,
527
+ skipTxValidation: boolean = true, // TODO(#7956): make the default be false
500
528
  scopes?: AztecAddress[],
501
529
  ): Promise<SimulatedTx> {
502
530
  return await this.jobQueue.put(async () => {
@@ -505,6 +533,12 @@ export class PXEService implements PXE {
505
533
  simulatedTx.publicOutput = await this.#simulatePublicCalls(simulatedTx.tx);
506
534
  }
507
535
 
536
+ if (!skipTxValidation) {
537
+ if (!(await this.node.isValidTx(simulatedTx.tx))) {
538
+ throw new Error('The simulated transaction is unable to be added to state and is invalid.');
539
+ }
540
+ }
541
+
508
542
  // We log only if the msgSender is undefined, as simulating with a different msgSender
509
543
  // is unlikely to be a real transaction, and likely to be only used to read data.
510
544
  // Meaning that it will not necessarily have produced a nullifier (and thus have no TxHash)
@@ -718,7 +752,9 @@ export class PXEService implements PXE {
718
752
  const noirCallStack = err.getNoirCallStack();
719
753
  if (debugInfo && isNoirCallStackUnresolved(noirCallStack)) {
720
754
  try {
721
- const parsedCallStack = resolveOpcodeLocations(noirCallStack, debugInfo);
755
+ // Public functions are simulated as a single Brillig entry point.
756
+ // Thus, we can safely assume here that the Brillig function id is `0`.
757
+ const parsedCallStack = resolveOpcodeLocations(noirCallStack, debugInfo, 0);
722
758
  err.setNoirCallStack(parsedCallStack);
723
759
  } catch (err) {
724
760
  this.log.warn(
@@ -5,7 +5,7 @@ import {
5
5
  type NoteStatus,
6
6
  type NullifierMembershipWitness,
7
7
  type PublicDataWitness,
8
- type SiblingPath,
8
+ getNonNullifiedL1ToL2MessageWitness,
9
9
  } from '@aztec/circuit-types';
10
10
  import {
11
11
  type AztecAddress,
@@ -16,7 +16,6 @@ import {
16
16
  type KeyValidationRequest,
17
17
  type L1_TO_L2_MSG_TREE_HEIGHT,
18
18
  } from '@aztec/circuits.js';
19
- import { computeL1ToL2MessageNullifier } from '@aztec/circuits.js/hash';
20
19
  import { type FunctionArtifact, getFunctionArtifact } from '@aztec/foundation/abi';
21
20
  import { createDebugLogger } from '@aztec/foundation/log';
22
21
  import { type KeyStore } from '@aztec/key-store';
@@ -127,25 +126,12 @@ export class SimulatorOracle implements DBOracle {
127
126
  messageHash: Fr,
128
127
  secret: Fr,
129
128
  ): Promise<MessageLoadOracleInputs<typeof L1_TO_L2_MSG_TREE_HEIGHT>> {
130
- let nullifierIndex: bigint | undefined;
131
- let messageIndex = 0n;
132
- let startIndex = 0n;
133
- let siblingPath: SiblingPath<typeof L1_TO_L2_MSG_TREE_HEIGHT>;
134
-
135
- // We iterate over messages until we find one whose nullifier is not in the nullifier tree --> we need to check
136
- // for nullifiers because messages can have duplicates.
137
- do {
138
- const response = await this.aztecNode.getL1ToL2MessageMembershipWitness('latest', messageHash, startIndex);
139
- if (!response) {
140
- throw new Error(`No non-nullified L1 to L2 message found for message hash ${messageHash.toString()}`);
141
- }
142
- [messageIndex, siblingPath] = response;
143
-
144
- const messageNullifier = computeL1ToL2MessageNullifier(contractAddress, messageHash, secret, messageIndex);
145
- nullifierIndex = await this.getNullifierIndex(messageNullifier);
146
-
147
- startIndex = messageIndex + 1n;
148
- } while (nullifierIndex !== undefined);
129
+ const [messageIndex, siblingPath] = await getNonNullifiedL1ToL2MessageWitness(
130
+ this.aztecNode,
131
+ contractAddress,
132
+ messageHash,
133
+ secret,
134
+ );
149
135
 
150
136
  // Assuming messageIndex is what you intended to use for the index in MessageLoadOracleInputs
151
137
  return new MessageLoadOracleInputs(messageIndex, siblingPath);