@aztec/pxe 0.36.0 → 0.38.0

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 (51) hide show
  1. package/dest/config/index.d.ts +17 -2
  2. package/dest/config/index.d.ts.map +1 -1
  3. package/dest/config/index.js +1 -1
  4. package/dest/index.d.ts +1 -0
  5. package/dest/index.d.ts.map +1 -1
  6. package/dest/index.js +3 -1
  7. package/dest/kernel_oracle/index.d.ts +1 -1
  8. package/dest/kernel_oracle/index.d.ts.map +1 -1
  9. package/dest/kernel_oracle/index.js +2 -2
  10. package/dest/kernel_prover/bb_prover/bb_native_proof_creator.d.ts +95 -0
  11. package/dest/kernel_prover/bb_prover/bb_native_proof_creator.d.ts.map +1 -0
  12. package/dest/kernel_prover/bb_prover/bb_native_proof_creator.js +437 -0
  13. package/dest/kernel_prover/{proof_creator.d.ts → interface/proof_creator.d.ts} +16 -35
  14. package/dest/kernel_prover/interface/proof_creator.d.ts.map +1 -0
  15. package/dest/kernel_prover/interface/proof_creator.js +2 -0
  16. package/dest/kernel_prover/kernel_prover.d.ts +4 -4
  17. package/dest/kernel_prover/kernel_prover.d.ts.map +1 -1
  18. package/dest/kernel_prover/kernel_prover.js +10 -37
  19. package/dest/kernel_prover/private_inputs_builders/build_private_kernel_tail_hints.d.ts +1 -1
  20. package/dest/kernel_prover/private_inputs_builders/build_private_kernel_tail_hints.d.ts.map +1 -1
  21. package/dest/kernel_prover/private_inputs_builders/build_private_kernel_tail_hints.js +4 -33
  22. package/dest/kernel_prover/proving_data_oracle.d.ts +1 -1
  23. package/dest/kernel_prover/proving_data_oracle.d.ts.map +1 -1
  24. package/dest/kernel_prover/test/test_circuit_prover.d.ts +16 -0
  25. package/dest/kernel_prover/test/test_circuit_prover.d.ts.map +1 -0
  26. package/dest/kernel_prover/test/test_circuit_prover.js +67 -0
  27. package/dest/pxe_service/create_pxe_service.d.ts +3 -1
  28. package/dest/pxe_service/create_pxe_service.d.ts.map +1 -1
  29. package/dest/pxe_service/create_pxe_service.js +16 -3
  30. package/dest/pxe_service/pxe_service.d.ts +5 -4
  31. package/dest/pxe_service/pxe_service.d.ts.map +1 -1
  32. package/dest/pxe_service/pxe_service.js +16 -57
  33. package/dest/simulator_oracle/index.d.ts +5 -4
  34. package/dest/simulator_oracle/index.d.ts.map +1 -1
  35. package/dest/simulator_oracle/index.js +12 -3
  36. package/package.json +14 -12
  37. package/src/config/index.ts +19 -2
  38. package/src/index.ts +3 -0
  39. package/src/kernel_oracle/index.ts +1 -1
  40. package/src/kernel_prover/bb_prover/bb_native_proof_creator.ts +713 -0
  41. package/src/kernel_prover/interface/proof_creator.ts +79 -0
  42. package/src/kernel_prover/kernel_prover.ts +19 -48
  43. package/src/kernel_prover/private_inputs_builders/build_private_kernel_tail_hints.ts +5 -40
  44. package/src/kernel_prover/proving_data_oracle.ts +1 -1
  45. package/src/kernel_prover/test/test_circuit_prover.ts +96 -0
  46. package/src/pxe_service/create_pxe_service.ts +17 -1
  47. package/src/pxe_service/pxe_service.ts +31 -68
  48. package/src/simulator_oracle/index.ts +16 -7
  49. package/dest/kernel_prover/proof_creator.d.ts.map +0 -1
  50. package/dest/kernel_prover/proof_creator.js +0 -68
  51. package/src/kernel_prover/proof_creator.ts +0 -157
@@ -0,0 +1,79 @@
1
+ import {
2
+ type PrivateCircuitPublicInputs,
3
+ type PrivateKernelCircuitPublicInputs,
4
+ type PrivateKernelInitCircuitPrivateInputs,
5
+ type PrivateKernelInnerCircuitPrivateInputs,
6
+ type PrivateKernelTailCircuitPrivateInputs,
7
+ type PrivateKernelTailCircuitPublicInputs,
8
+ type Proof,
9
+ } from '@aztec/circuits.js';
10
+ import { type Fr } from '@aztec/foundation/fields';
11
+ import { type ACVMField } from '@aztec/simulator';
12
+
13
+ /**
14
+ * Represents the output of the proof creation process for init and inner private kernel circuit.
15
+ * Contains the public inputs required for the init and inner private kernel circuit and the generated proof.
16
+ */
17
+ export type ProofOutput<PublicInputsType> = {
18
+ /**
19
+ * The public inputs required for the proof generation process.
20
+ */
21
+ publicInputs: PublicInputsType;
22
+ /**
23
+ * The zk-SNARK proof for the kernel execution.
24
+ */
25
+ proof: Proof;
26
+ };
27
+
28
+ /**
29
+ * ProofCreator provides functionality to create and validate proofs, and retrieve
30
+ * siloed commitments necessary for maintaining transaction privacy and security on the network.
31
+ */
32
+ export interface ProofCreator {
33
+ /**
34
+ * Computes the siloed commitments for a given set of public inputs.
35
+ *
36
+ * @param publicInputs - The public inputs containing the contract address and new note hashes to be used in generating siloed note hashes.
37
+ * @returns An array of Fr (finite field) elements representing the siloed commitments.
38
+ */
39
+ getSiloedCommitments(publicInputs: PrivateCircuitPublicInputs): Promise<Fr[]>;
40
+
41
+ /**
42
+ * Creates a proof output for a given signed transaction request and private call data for the first iteration.
43
+ *
44
+ * @param privateKernelInputsInit - The private data structure for the initial iteration.
45
+ * @returns A Promise resolving to a ProofOutput object containing public inputs and the kernel proof.
46
+ */
47
+ createProofInit(
48
+ privateKernelInputsInit: PrivateKernelInitCircuitPrivateInputs,
49
+ ): Promise<ProofOutput<PrivateKernelCircuitPublicInputs>>;
50
+
51
+ /**
52
+ * Creates a proof output for a given previous kernel data and private call data for an inner iteration.
53
+ *
54
+ * @param privateKernelInputsInner - The private input data structure for the inner iteration.
55
+ * @returns A Promise resolving to a ProofOutput object containing public inputs and the kernel proof.
56
+ */
57
+ createProofInner(
58
+ privateKernelInputsInner: PrivateKernelInnerCircuitPrivateInputs,
59
+ ): Promise<ProofOutput<PrivateKernelCircuitPublicInputs>>;
60
+
61
+ /**
62
+ * Creates a proof output based on the last inner kernel iteration kernel data for the final ordering iteration.
63
+ *
64
+ * @param privateKernelInputsTail - The private input data structure for the final ordering iteration.
65
+ * @returns A Promise resolving to a ProofOutput object containing public inputs and the kernel proof.
66
+ */
67
+ createProofTail(
68
+ privateKernelInputsTail: PrivateKernelTailCircuitPrivateInputs,
69
+ ): Promise<ProofOutput<PrivateKernelTailCircuitPublicInputs>>;
70
+
71
+ /**
72
+ * Creates a proof for an app circuit.
73
+ *
74
+ * @param partialWitness - The witness produced via circuit simulation
75
+ * @param bytecode - The circuit bytecode in gzipped bincode format
76
+ * @returns A Promise resolving to a Proof object
77
+ */
78
+ createAppCircuitProof(partialWitness: Map<number, ACVMField>, bytecode: Buffer): Promise<Proof>;
79
+ }
@@ -1,34 +1,33 @@
1
1
  import {
2
2
  CallRequest,
3
3
  Fr,
4
- MAX_NOTE_HASH_READ_REQUESTS_PER_CALL,
5
4
  MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL,
6
5
  MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL,
7
- NoteHashReadRequestMembershipWitness,
8
6
  PrivateCallData,
9
7
  PrivateKernelCircuitPublicInputs,
10
8
  PrivateKernelData,
11
9
  PrivateKernelInitCircuitPrivateInputs,
12
10
  PrivateKernelInnerCircuitPrivateInputs,
13
11
  PrivateKernelTailCircuitPrivateInputs,
12
+ type PrivateKernelTailCircuitPublicInputs,
13
+ type Proof,
14
14
  type TxRequest,
15
15
  VK_TREE_HEIGHT,
16
16
  VerificationKey,
17
17
  makeEmptyProof,
18
18
  } from '@aztec/circuits.js';
19
- import { makeTuple } from '@aztec/foundation/array';
20
19
  import { padArrayEnd } from '@aztec/foundation/collection';
21
20
  import { createDebugLogger } from '@aztec/foundation/log';
22
21
  import { assertLength } from '@aztec/foundation/serialize';
23
22
  import { pushTestData } from '@aztec/foundation/testing';
24
- import { type ExecutionResult, collectNullifiedNoteHashCounters } from '@aztec/simulator';
23
+ import { type ExecutionResult, collectNoteHashLeafIndexMap, collectNullifiedNoteHashCounters } from '@aztec/simulator';
25
24
 
25
+ import { type ProofCreator, type ProofOutput } from './interface/proof_creator.js';
26
26
  import {
27
27
  buildPrivateKernelInnerHints,
28
28
  buildPrivateKernelTailHints,
29
29
  buildPrivateKernelTailOutputs,
30
30
  } from './private_inputs_builders/index.js';
31
- import { KernelProofCreator, type ProofCreator, type ProofOutput, type ProofOutputFinal } from './proof_creator.js';
32
31
  import { type ProvingDataOracle } from './proving_data_oracle.js';
33
32
 
34
33
  /**
@@ -39,7 +38,8 @@ import { type ProvingDataOracle } from './proving_data_oracle.js';
39
38
  */
40
39
  export class KernelProver {
41
40
  private log = createDebugLogger('aztec:kernel-prover');
42
- constructor(private oracle: ProvingDataOracle, private proofCreator: ProofCreator = new KernelProofCreator()) {}
41
+
42
+ constructor(private oracle: ProvingDataOracle, private proofCreator: ProofCreator) {}
43
43
 
44
44
  /**
45
45
  * Generate a proof for a given transaction request and execution result.
@@ -51,20 +51,21 @@ export class KernelProver {
51
51
  * @param executionResult - The execution result object containing nested executions and preimages.
52
52
  * @returns A Promise that resolves to a KernelProverOutput object containing proof, public inputs, and output notes.
53
53
  */
54
- async prove(txRequest: TxRequest, executionResult: ExecutionResult): Promise<ProofOutputFinal> {
54
+ async prove(
55
+ txRequest: TxRequest,
56
+ executionResult: ExecutionResult,
57
+ ): Promise<ProofOutput<PrivateKernelTailCircuitPublicInputs>> {
55
58
  const executionStack = [executionResult];
56
59
  let firstIteration = true;
57
60
  let previousVerificationKey = VerificationKey.makeFake();
58
61
 
59
- let output: ProofOutput = {
62
+ let output: ProofOutput<PrivateKernelCircuitPublicInputs> = {
60
63
  publicInputs: PrivateKernelCircuitPublicInputs.empty(),
61
64
  proof: makeEmptyProof(),
62
65
  };
63
66
 
64
- const noteHashNullifierCounterMap = new Map();
65
- collectNullifiedNoteHashCounters(executionResult).forEach(({ noteHashCounter, nullifierCounter }) =>
66
- noteHashNullifierCounterMap.set(noteHashCounter, nullifierCounter),
67
- );
67
+ const noteHashLeafIndexMap = collectNoteHashLeafIndexMap(executionResult);
68
+ const noteHashNullifierCounterMap = collectNullifiedNoteHashCounters(executionResult);
68
69
 
69
70
  while (executionStack.length) {
70
71
  const currentExecution = executionStack.pop()!;
@@ -75,38 +76,16 @@ export class KernelProver {
75
76
  );
76
77
  const publicCallRequests = currentExecution.enqueuedPublicFunctionCalls.map(result => result.toCallRequest());
77
78
 
78
- // Start with the partially filled in read request witnesses from the simulator
79
- // and fill the non-transient ones in with sibling paths via oracle.
80
- const noteHashReadRequestMembershipWitnesses = currentExecution.noteHashReadRequestPartialWitnesses;
81
- for (let rr = 0; rr < noteHashReadRequestMembershipWitnesses.length; rr++) {
82
- // Pretty sure this check was forever broken. I made some changes to Fr and this started triggering.
83
- // The conditional makes no sense to me anyway.
84
- // if (currentExecution.callStackItem.publicInputs.readRequests[rr] == Fr.ZERO) {
85
- // throw new Error(
86
- // 'Number of read requests output from Noir circuit does not match number of read request commitment indices output from simulator.',
87
- // );
88
- // }
89
- const rrWitness = noteHashReadRequestMembershipWitnesses[rr];
90
- if (!rrWitness.isTransient) {
91
- // Non-transient reads must contain full membership witness with sibling path from commitment to root.
92
- // Get regular membership witness to fill in sibling path in the read request witness.
93
- const membershipWitness = await this.oracle.getNoteMembershipWitness(rrWitness.leafIndex.toBigInt());
94
- rrWitness.siblingPath = membershipWitness.siblingPath;
95
- }
96
- }
97
-
98
- // fill in witnesses for remaining/empty read requests
99
- noteHashReadRequestMembershipWitnesses.push(
100
- ...Array(MAX_NOTE_HASH_READ_REQUESTS_PER_CALL - noteHashReadRequestMembershipWitnesses.length)
101
- .fill(0)
102
- .map(() => NoteHashReadRequestMembershipWitness.empty(BigInt(0))),
79
+ const proof = await this.proofCreator.createAppCircuitProof(
80
+ currentExecution.partialWitness,
81
+ currentExecution.acir,
103
82
  );
104
83
 
105
84
  const privateCallData = await this.createPrivateCallData(
106
85
  currentExecution,
107
86
  privateCallRequests,
108
87
  publicCallRequests,
109
- noteHashReadRequestMembershipWitnesses,
88
+ proof,
110
89
  );
111
90
 
112
91
  const hints = buildPrivateKernelInnerHints(
@@ -148,7 +127,7 @@ export class KernelProver {
148
127
  `Calling private kernel tail with hwm ${previousKernelData.publicInputs.minRevertibleSideEffectCounter}`,
149
128
  );
150
129
 
151
- const hints = await buildPrivateKernelTailHints(output.publicInputs, this.oracle);
130
+ const hints = await buildPrivateKernelTailHints(output.publicInputs, noteHashLeafIndexMap, this.oracle);
152
131
 
153
132
  const expectedOutputs = buildPrivateKernelTailOutputs(hints.sortedNewNoteHashes, hints.sortedNewNullifiers);
154
133
 
@@ -162,7 +141,7 @@ export class KernelProver {
162
141
  { callStackItem, vk }: ExecutionResult,
163
142
  privateCallRequests: CallRequest[],
164
143
  publicCallRequests: CallRequest[],
165
- noteHashReadRequestMembershipWitnesses: NoteHashReadRequestMembershipWitness[],
144
+ proof: Proof,
166
145
  ) {
167
146
  const { contractAddress, functionData } = callStackItem;
168
147
 
@@ -188,9 +167,6 @@ export class KernelProver {
188
167
  // const acirHash = keccak256(Buffer.from(bytecode, 'hex'));
189
168
  const acirHash = Fr.fromBuffer(Buffer.alloc(32, 0));
190
169
 
191
- // TODO
192
- const proof = makeEmptyProof();
193
-
194
170
  return PrivateCallData.from({
195
171
  callStackItem,
196
172
  privateCallStack,
@@ -202,11 +178,6 @@ export class KernelProver {
202
178
  contractClassPublicBytecodeCommitment,
203
179
  saltedInitializationHash,
204
180
  functionLeafMembershipWitness,
205
- noteHashReadRequestMembershipWitnesses: makeTuple(
206
- MAX_NOTE_HASH_READ_REQUESTS_PER_CALL,
207
- i => noteHashReadRequestMembershipWitnesses[i],
208
- 0,
209
- ),
210
181
  acirHash,
211
182
  });
212
183
  }
@@ -4,13 +4,11 @@ import {
4
4
  type MAX_ENCRYPTED_LOGS_PER_TX,
5
5
  MAX_NEW_NOTE_HASHES_PER_TX,
6
6
  MAX_NEW_NULLIFIERS_PER_TX,
7
- MAX_NOTE_HASH_READ_REQUESTS_PER_TX,
8
7
  MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX,
9
8
  type MAX_NULLIFIER_READ_REQUESTS_PER_TX,
10
9
  type MAX_UNENCRYPTED_LOGS_PER_TX,
11
10
  MembershipWitness,
12
11
  NULLIFIER_TREE_HEIGHT,
13
- type NoteHashContext,
14
12
  type Nullifier,
15
13
  type NullifierKeyValidationRequestContext,
16
14
  type PrivateKernelCircuitPublicInputs,
@@ -18,9 +16,9 @@ import {
18
16
  type ReadRequestContext,
19
17
  type SideEffect,
20
18
  type SideEffectType,
19
+ buildNoteHashReadRequestHints,
21
20
  buildNullifierReadRequestHints,
22
21
  buildTransientDataHints,
23
- countAccumulatedItems,
24
22
  sortByCounterGetSortedHints,
25
23
  } from '@aztec/circuits.js';
26
24
  import { makeTuple } from '@aztec/foundation/array';
@@ -50,42 +48,6 @@ function sortSideEffects<T extends SideEffectType, K extends number>(
50
48
  return [sorted.map(({ sideEffect }) => sideEffect) as Tuple<T, K>, originalToSorted as Tuple<number, K>];
51
49
  }
52
50
 
53
- function isValidNoteHashReadRequest(readRequest: SideEffect, noteHash: NoteHashContext) {
54
- return (
55
- noteHash.value.equals(readRequest.value) &&
56
- noteHash.counter < readRequest.counter.toNumber() &&
57
- (noteHash.nullifierCounter === 0 || noteHash.nullifierCounter > readRequest.counter.toNumber())
58
- );
59
- }
60
-
61
- /**
62
- * Performs the matching between an array of read request and an array of note hashes. This produces
63
- * hints for the private kernel tail circuit to efficiently match a read request with the corresponding
64
- * note hash. Several read requests might be pointing to the same note hash. It is therefore valid
65
- * to return more than one hint with the same index.
66
- *
67
- * @param noteHashReadRequests - The array of read requests.
68
- * @param noteHashes - The array of note hashes.
69
- * @returns An array of hints where each element is the index of the note hash in note hashes array
70
- * corresponding to the read request. In other words we have readRequests[i] == noteHashes[hints[i]].
71
- */
72
- function getNoteHashReadRequestHints(
73
- noteHashReadRequests: Tuple<SideEffect, typeof MAX_NOTE_HASH_READ_REQUESTS_PER_TX>,
74
- noteHashes: Tuple<NoteHashContext, typeof MAX_NEW_NOTE_HASHES_PER_TX>,
75
- ): Tuple<number, typeof MAX_NOTE_HASH_READ_REQUESTS_PER_TX> {
76
- const hints = makeTuple(MAX_NOTE_HASH_READ_REQUESTS_PER_TX, () => 0);
77
- const numReadRequests = countAccumulatedItems(noteHashReadRequests);
78
- for (let i = 0; i < numReadRequests; i++) {
79
- const readRequest = noteHashReadRequests[i];
80
- const noteHashIndex = noteHashes.findIndex((n: NoteHashContext) => isValidNoteHashReadRequest(readRequest, n));
81
- if (noteHashIndex === -1) {
82
- throw new Error(`The read request at index ${i} ${readRequest} does not match to any note hash.`);
83
- }
84
- hints[i] = noteHashIndex;
85
- }
86
- return hints;
87
- }
88
-
89
51
  function getNullifierReadRequestHints(
90
52
  nullifierReadRequests: Tuple<ReadRequestContext, typeof MAX_NULLIFIER_READ_REQUESTS_PER_TX>,
91
53
  nullifiers: Tuple<Nullifier, typeof MAX_NEW_NULLIFIERS_PER_TX>,
@@ -131,11 +93,14 @@ async function getMasterNullifierSecretKeys(
131
93
 
132
94
  export async function buildPrivateKernelTailHints(
133
95
  publicInputs: PrivateKernelCircuitPublicInputs,
96
+ noteHashLeafIndexMap: Map<bigint, bigint>,
134
97
  oracle: ProvingDataOracle,
135
98
  ) {
136
- const noteHashReadRequestHints = getNoteHashReadRequestHints(
99
+ const noteHashReadRequestHints = await buildNoteHashReadRequestHints(
100
+ oracle,
137
101
  publicInputs.validationRequests.noteHashReadRequests,
138
102
  publicInputs.end.newNoteHashes,
103
+ noteHashLeafIndexMap,
139
104
  );
140
105
 
141
106
  const nullifierReadRequestHints = await getNullifierReadRequestHints(
@@ -58,7 +58,7 @@ export interface ProvingDataOracle {
58
58
  * @param leafIndex - The leaf index of the note in the note hash tree.
59
59
  * @returns the MembershipWitness for the note.
60
60
  */
61
- getNoteMembershipWitness(leafIndex: bigint): Promise<MembershipWitness<typeof NOTE_HASH_TREE_HEIGHT>>;
61
+ getNoteHashMembershipWitness(leafIndex: bigint): Promise<MembershipWitness<typeof NOTE_HASH_TREE_HEIGHT>>;
62
62
 
63
63
  getNullifierMembershipWitness(nullifier: Fr): Promise<NullifierMembershipWitness | undefined>;
64
64
 
@@ -0,0 +1,96 @@
1
+ import { type CircuitSimulationStats } from '@aztec/circuit-types/stats';
2
+ import {
3
+ type PrivateCircuitPublicInputs,
4
+ type PrivateKernelCircuitPublicInputs,
5
+ type PrivateKernelInitCircuitPrivateInputs,
6
+ type PrivateKernelInnerCircuitPrivateInputs,
7
+ type PrivateKernelTailCircuitPrivateInputs,
8
+ type PrivateKernelTailCircuitPublicInputs,
9
+ Proof,
10
+ makeEmptyProof,
11
+ } from '@aztec/circuits.js';
12
+ import { siloNoteHash } from '@aztec/circuits.js/hash';
13
+ import { createDebugLogger } from '@aztec/foundation/log';
14
+ import { elapsed } from '@aztec/foundation/timer';
15
+ import { executeInit, executeInner, executeTail, executeTailForPublic } from '@aztec/noir-protocol-circuits-types';
16
+
17
+ import { type ProofCreator, type ProofOutput } from '../interface/proof_creator.js';
18
+
19
+ /**
20
+ * Test Proof Creator executes circuit simulations and provides fake proofs.
21
+ */
22
+ export class TestProofCreator implements ProofCreator {
23
+ constructor(private log = createDebugLogger('aztec:test_proof_creator')) {}
24
+
25
+ public getSiloedCommitments(publicInputs: PrivateCircuitPublicInputs) {
26
+ const contractAddress = publicInputs.callContext.storageContractAddress;
27
+
28
+ return Promise.resolve(
29
+ publicInputs.newNoteHashes.map(commitment => siloNoteHash(contractAddress, commitment.value)),
30
+ );
31
+ }
32
+
33
+ public async createProofInit(
34
+ privateInputs: PrivateKernelInitCircuitPrivateInputs,
35
+ ): Promise<ProofOutput<PrivateKernelCircuitPublicInputs>> {
36
+ const [duration, result] = await elapsed(() => executeInit(privateInputs));
37
+ this.log.debug(`Simulated private kernel init`, {
38
+ eventName: 'circuit-simulation',
39
+ circuitName: 'private-kernel-init',
40
+ duration,
41
+ inputSize: privateInputs.toBuffer().length,
42
+ outputSize: result.toBuffer().length,
43
+ } satisfies CircuitSimulationStats);
44
+ const proof = makeEmptyProof();
45
+
46
+ return {
47
+ publicInputs: result,
48
+ proof: proof,
49
+ };
50
+ }
51
+
52
+ public async createProofInner(
53
+ privateInputs: PrivateKernelInnerCircuitPrivateInputs,
54
+ ): Promise<ProofOutput<PrivateKernelCircuitPublicInputs>> {
55
+ const [duration, result] = await elapsed(() => executeInner(privateInputs));
56
+ this.log.debug(`Simulated private kernel inner`, {
57
+ eventName: 'circuit-simulation',
58
+ circuitName: 'private-kernel-inner',
59
+ duration,
60
+ inputSize: privateInputs.toBuffer().length,
61
+ outputSize: result.toBuffer().length,
62
+ } satisfies CircuitSimulationStats);
63
+ const proof = makeEmptyProof();
64
+
65
+ return {
66
+ publicInputs: result,
67
+ proof: proof,
68
+ };
69
+ }
70
+
71
+ public async createProofTail(
72
+ privateInputs: PrivateKernelTailCircuitPrivateInputs,
73
+ ): Promise<ProofOutput<PrivateKernelTailCircuitPublicInputs>> {
74
+ const isForPublic = privateInputs.isForPublic();
75
+ const [duration, result] = await elapsed(() =>
76
+ isForPublic ? executeTailForPublic(privateInputs) : executeTail(privateInputs),
77
+ );
78
+ this.log.debug(`Simulated private kernel ordering`, {
79
+ eventName: 'circuit-simulation',
80
+ circuitName: 'private-kernel-ordering',
81
+ duration,
82
+ inputSize: privateInputs.toBuffer().length,
83
+ outputSize: result.toBuffer().length,
84
+ } satisfies CircuitSimulationStats);
85
+ const proof = makeEmptyProof();
86
+
87
+ return {
88
+ publicInputs: result,
89
+ proof: proof,
90
+ };
91
+ }
92
+
93
+ createAppCircuitProof(_1: Map<number, string>, _2: Buffer): Promise<Proof> {
94
+ return Promise.resolve(new Proof(Buffer.alloc(0)));
95
+ }
96
+ }
@@ -13,6 +13,9 @@ import { join } from 'path';
13
13
 
14
14
  import { type PXEServiceConfig } from '../config/index.js';
15
15
  import { KVPxeDatabase } from '../database/kv_pxe_database.js';
16
+ import { BBNativeProofCreator } from '../kernel_prover/bb_prover/bb_native_proof_creator.js';
17
+ import { type ProofCreator } from '../kernel_prover/interface/proof_creator.js';
18
+ import { TestProofCreator } from '../kernel_prover/test/test_circuit_prover.js';
16
19
  import { PXEService } from './pxe_service.js';
17
20
 
18
21
  /**
@@ -23,12 +26,14 @@ import { PXEService } from './pxe_service.js';
23
26
  * @param aztecNode - The AztecNode instance to be used by the server.
24
27
  * @param config - The PXE Service Config to use
25
28
  * @param options - (Optional) Optional information for creating an PXEService.
29
+ * @param proofCreator - An optional proof creator to use in place of any other configuration
26
30
  * @returns A Promise that resolves to the started PXEService instance.
27
31
  */
28
32
  export async function createPXEService(
29
33
  aztecNode: AztecNode,
30
34
  config: PXEServiceConfig,
31
35
  useLogSuffix: string | boolean | undefined = undefined,
36
+ proofCreator?: ProofCreator,
32
37
  ) {
33
38
  const logSuffix =
34
39
  typeof useLogSuffix === 'boolean' ? (useLogSuffix ? randomBytes(3).toString('hex') : undefined) : useLogSuffix;
@@ -42,7 +47,18 @@ export async function createPXEService(
42
47
  );
43
48
  const db = new KVPxeDatabase(await initStoreForRollup(AztecLmdbStore.open(pxeDbPath), l1Contracts.rollupAddress));
44
49
 
45
- const server = new PXEService(keyStore, aztecNode, db, config, logSuffix);
50
+ // (@PhilWindle) Temporary validation until WASM is implemented
51
+ let prover: ProofCreator | undefined = proofCreator;
52
+ if (!prover) {
53
+ if (config.proverEnabled && (!config.bbBinaryPath || !config.bbWorkingDirectory)) {
54
+ throw new Error(`Prover must be configured with binary path and working directory`);
55
+ }
56
+ prover = !config.proverEnabled
57
+ ? new TestProofCreator()
58
+ : new BBNativeProofCreator(config.bbBinaryPath!, config.bbWorkingDirectory!);
59
+ }
60
+
61
+ const server = new PXEService(keyStore, aztecNode, db, prover, config, logSuffix);
46
62
  for (const contract of [
47
63
  getCanonicalClassRegisterer(),
48
64
  getCanonicalInstanceDeployer(),
@@ -1,8 +1,6 @@
1
1
  import {
2
2
  type AuthWitness,
3
3
  type AztecNode,
4
- EncryptedFunctionL2Logs,
5
- type EncryptedL2Log,
6
4
  EncryptedTxL2Logs,
7
5
  ExtendedNote,
8
6
  type FunctionCall,
@@ -20,8 +18,6 @@ import {
20
18
  type TxExecutionRequest,
21
19
  type TxHash,
22
20
  type TxReceipt,
23
- UnencryptedFunctionL2Logs,
24
- type UnencryptedL2Log,
25
21
  UnencryptedTxL2Logs,
26
22
  isNoirCallStackUnresolved,
27
23
  } from '@aztec/circuit-types';
@@ -34,24 +30,23 @@ import {
34
30
  MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX,
35
31
  type PartialAddress,
36
32
  type PrivateKernelTailCircuitPublicInputs,
37
- type PublicCallRequest,
38
- type SideEffect,
33
+ PublicCallRequest,
39
34
  computeContractClassId,
40
35
  getContractClassFromArtifact,
41
36
  } from '@aztec/circuits.js';
42
37
  import { computeCommitmentNonce, siloNullifier } from '@aztec/circuits.js/hash';
43
38
  import { type ContractArtifact, type DecodedReturn, FunctionSelector, encodeArguments } from '@aztec/foundation/abi';
44
39
  import { arrayNonEmptyLength, padArrayEnd } from '@aztec/foundation/collection';
45
- import { Fr } from '@aztec/foundation/fields';
40
+ import { Fr, type Point } from '@aztec/foundation/fields';
46
41
  import { SerialQueue } from '@aztec/foundation/fifo';
47
42
  import { type DebugLogger, createDebugLogger } from '@aztec/foundation/log';
48
43
  import { Timer } from '@aztec/foundation/timer';
49
44
  import {
50
45
  type AcirSimulator,
51
46
  type ExecutionResult,
52
- collectEncryptedLogs,
53
47
  collectEnqueuedPublicFunctionCalls,
54
- collectUnencryptedLogs,
48
+ collectSortedEncryptedLogs,
49
+ collectSortedUnencryptedLogs,
55
50
  resolveOpcodeLocations,
56
51
  } from '@aztec/simulator';
57
52
  import { type ContractClassWithId, type ContractInstanceWithAddress } from '@aztec/types/contracts';
@@ -62,6 +57,7 @@ import { ContractDataOracle } from '../contract_data_oracle/index.js';
62
57
  import { type PxeDatabase } from '../database/index.js';
63
58
  import { NoteDao } from '../database/note_dao.js';
64
59
  import { KernelOracle } from '../kernel_oracle/index.js';
60
+ import { type ProofCreator } from '../kernel_prover/interface/proof_creator.js';
65
61
  import { KernelProver } from '../kernel_prover/kernel_prover.js';
66
62
  import { getAcirSimulator } from '../simulator/index.js';
67
63
  import { Synchronizer } from '../synchronizer/index.js';
@@ -83,6 +79,7 @@ export class PXEService implements PXE {
83
79
  private keyStore: KeyStore,
84
80
  private node: AztecNode,
85
81
  private db: PxeDatabase,
82
+ private proofCreator: ProofCreator,
86
83
  private config: PXEServiceConfig,
87
84
  logSuffix?: string,
88
85
  ) {
@@ -216,8 +213,20 @@ export class PXEService implements PXE {
216
213
  return this.keyStore.getPublicKeysHash(address);
217
214
  }
218
215
 
219
- public async registerRecipient(recipient: CompleteAddress): Promise<void> {
216
+ public async registerRecipient(recipient: CompleteAddress, publicKeys: Point[] = []): Promise<void> {
220
217
  const wasAdded = await this.db.addCompleteAddress(recipient);
218
+
219
+ // TODO #5834: This should be refactored to be okay with only adding complete address
220
+ if (publicKeys.length !== 0) {
221
+ await this.keyStore.addPublicKeysForAccount(
222
+ recipient.address,
223
+ publicKeys[0],
224
+ publicKeys[1],
225
+ publicKeys[2],
226
+ publicKeys[3],
227
+ );
228
+ }
229
+
221
230
  if (wasAdded) {
222
231
  this.log.info(`Added recipient:\n ${recipient.toReadableString()}`);
223
232
  } else {
@@ -654,18 +663,27 @@ export class PXEService implements PXE {
654
663
  const executionResult = await this.#simulate(txExecutionRequest, msgSender);
655
664
 
656
665
  const kernelOracle = new KernelOracle(this.contractDataOracle, this.keyStore, this.node);
657
- const kernelProver = new KernelProver(kernelOracle);
666
+ const kernelProver = new KernelProver(kernelOracle, this.proofCreator);
658
667
  this.log.debug(`Executing kernel prover...`);
659
668
  const { proof, publicInputs } = await kernelProver.prove(txExecutionRequest.toTxRequest(), executionResult);
660
669
 
661
- const { encryptedLogs, unencryptedLogs } = this.patchLogsOrdering(executionResult);
670
+ const unencryptedLogs = new UnencryptedTxL2Logs([collectSortedUnencryptedLogs(executionResult)]);
671
+ const encryptedLogs = new EncryptedTxL2Logs([collectSortedEncryptedLogs(executionResult)]);
662
672
  const enqueuedPublicFunctions = collectEnqueuedPublicFunctionCalls(executionResult);
673
+ const teardownPublicFunction = PublicCallRequest.empty();
663
674
 
664
675
  // HACK(#1639): Manually patches the ordering of the public call stack
665
676
  // TODO(#757): Enforce proper ordering of enqueued public calls
666
677
  await this.patchPublicCallStackOrdering(publicInputs, enqueuedPublicFunctions);
667
678
 
668
- const tx = new Tx(publicInputs, proof, encryptedLogs, unencryptedLogs, enqueuedPublicFunctions);
679
+ const tx = new Tx(
680
+ publicInputs,
681
+ proof,
682
+ encryptedLogs,
683
+ unencryptedLogs,
684
+ enqueuedPublicFunctions,
685
+ teardownPublicFunction,
686
+ );
669
687
  return new SimulatedTx(tx, executionResult.returnValues);
670
688
  }
671
689
 
@@ -776,61 +794,6 @@ export class PXEService implements PXE {
776
794
  );
777
795
  }
778
796
 
779
- // As above, this is a hack for encrypted/unencrypted logs ordering, now they are sorted. Since the private kernel
780
- // cannot keep track of side effects that happen after or before a nested call, we override the gathered logs.
781
- // As a sanity check, we at least verify that the elements are the same, so we are only tweaking their ordering.
782
- // See yarn-project/end-to-end/src/e2e_ordering.test.ts
783
- // See https://github.com/AztecProtocol/aztec-packages/issues/1641
784
- // Added as part of resolving #5017
785
- private patchLogsOrdering(execResult: ExecutionResult) {
786
- const encLogs = collectEncryptedLogs(execResult).flatMap(l => l.logs);
787
- const unencLogs = collectUnencryptedLogs(execResult).flatMap(l => l.logs);
788
- const getLogs = (res: ExecutionResult, enc: boolean) => {
789
- const logs: SideEffect[] = enc
790
- ? res.callStackItem.publicInputs.encryptedLogsHashes.concat(res.nestedExecutions.flatMap(e => getLogs(e, true)))
791
- : res.callStackItem.publicInputs.unencryptedLogsHashes.concat(
792
- res.nestedExecutions.flatMap(e => getLogs(e, false)),
793
- );
794
-
795
- return logs;
796
- };
797
-
798
- const sortSEs = (a: SideEffect, b: SideEffect) => {
799
- if (a.isEmpty()) {
800
- return 1;
801
- } else if (b.isEmpty()) {
802
- return -1;
803
- } else {
804
- return Number(a.counter.toBigInt() - b.counter.toBigInt());
805
- }
806
- };
807
-
808
- const sortedEncLogs = getLogs(execResult, true).sort(sortSEs);
809
- const sortedUnencLogs = getLogs(execResult, false).sort(sortSEs);
810
-
811
- const finalEncLogs: EncryptedL2Log[] = [];
812
- sortedEncLogs.forEach((sideEffect: SideEffect) => {
813
- if (!sideEffect.isEmpty()) {
814
- const isLog = (log: EncryptedL2Log) => Fr.fromBuffer(log.hash()).equals(sideEffect.value);
815
- const thisLogIndex = encLogs.findIndex(isLog);
816
- finalEncLogs.push(encLogs[thisLogIndex]);
817
- }
818
- });
819
-
820
- const finalUnencLogs: UnencryptedL2Log[] = [];
821
- sortedUnencLogs.forEach((sideEffect: SideEffect) => {
822
- if (!sideEffect.isEmpty()) {
823
- const isLog = (log: UnencryptedL2Log) => Fr.fromBuffer(log.hash()).equals(sideEffect.value);
824
- const thisLogIndex = unencLogs.findIndex(isLog);
825
- finalUnencLogs.push(unencLogs[thisLogIndex]);
826
- }
827
- });
828
-
829
- const encryptedLogs = new EncryptedTxL2Logs([new EncryptedFunctionL2Logs(finalEncLogs)]);
830
- const unencryptedLogs = new UnencryptedTxL2Logs([new UnencryptedFunctionL2Logs(finalUnencLogs)]);
831
- return { encryptedLogs, unencryptedLogs };
832
- }
833
-
834
797
  public async isGlobalStateSynchronized() {
835
798
  return await this.synchronizer.isGlobalStateSynchronized();
836
799
  }