@aztec/pxe 0.69.1 → 0.70.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.
- package/dest/database/kv_pxe_database.d.ts +4 -0
- package/dest/database/kv_pxe_database.d.ts.map +1 -1
- package/dest/database/kv_pxe_database.js +26 -3
- package/dest/database/note_dao.d.ts +1 -1
- package/dest/database/note_dao.d.ts.map +1 -1
- package/dest/database/pxe_database.d.ts +16 -0
- package/dest/database/pxe_database.d.ts.map +1 -1
- package/dest/database/pxe_database_test_suite.d.ts.map +1 -1
- package/dest/database/pxe_database_test_suite.js +48 -1
- package/dest/kernel_oracle/index.js +2 -2
- package/dest/kernel_prover/hints/build_private_kernel_reset_private_inputs.d.ts +2 -2
- package/dest/kernel_prover/hints/build_private_kernel_reset_private_inputs.d.ts.map +1 -1
- package/dest/kernel_prover/hints/build_private_kernel_reset_private_inputs.js +1 -1
- package/dest/kernel_prover/index.d.ts +0 -1
- package/dest/kernel_prover/index.d.ts.map +1 -1
- package/dest/kernel_prover/index.js +1 -2
- package/dest/kernel_prover/kernel_prover.d.ts +8 -2
- package/dest/kernel_prover/kernel_prover.d.ts.map +1 -1
- package/dest/kernel_prover/kernel_prover.js +42 -18
- package/dest/note_decryption_utils/brute_force_note_info.d.ts +1 -1
- package/dest/note_decryption_utils/brute_force_note_info.d.ts.map +1 -1
- package/dest/note_decryption_utils/brute_force_note_info.js +2 -3
- package/dest/note_decryption_utils/produce_note_daos.d.ts +1 -1
- package/dest/note_decryption_utils/produce_note_daos.d.ts.map +1 -1
- package/dest/note_decryption_utils/produce_note_daos.js +3 -3
- package/dest/note_decryption_utils/produce_note_daos_for_key.d.ts +1 -1
- package/dest/note_decryption_utils/produce_note_daos_for_key.d.ts.map +1 -1
- package/dest/note_decryption_utils/produce_note_daos_for_key.js +3 -3
- package/dest/pxe_service/error_enriching.js +1 -1
- package/dest/pxe_service/pxe_service.d.ts +5 -1
- package/dest/pxe_service/pxe_service.d.ts.map +1 -1
- package/dest/pxe_service/pxe_service.js +30 -31
- package/dest/simulator/index.d.ts +2 -2
- package/dest/simulator/index.d.ts.map +1 -1
- package/dest/simulator/index.js +4 -4
- package/dest/simulator_oracle/index.d.ts +21 -6
- package/dest/simulator_oracle/index.d.ts.map +1 -1
- package/dest/simulator_oracle/index.js +53 -25
- package/dest/utils/create_pxe_service.d.ts.map +1 -1
- package/dest/utils/create_pxe_service.js +9 -12
- package/package.json +14 -15
- package/src/database/kv_pxe_database.ts +30 -0
- package/src/database/note_dao.ts +1 -1
- package/src/database/pxe_database.ts +18 -0
- package/src/database/pxe_database_test_suite.ts +61 -0
- package/src/kernel_oracle/index.ts +1 -1
- package/src/kernel_prover/hints/build_private_kernel_reset_private_inputs.ts +4 -4
- package/src/kernel_prover/index.ts +0 -2
- package/src/kernel_prover/kernel_prover.ts +58 -20
- package/src/note_decryption_utils/brute_force_note_info.ts +1 -1
- package/src/note_decryption_utils/produce_note_daos.ts +2 -0
- package/src/note_decryption_utils/produce_note_daos_for_key.ts +2 -0
- package/src/pxe_service/error_enriching.ts +1 -1
- package/src/pxe_service/pxe_service.ts +32 -44
- package/src/simulator/index.ts +4 -2
- package/src/simulator_oracle/index.ts +47 -11
- package/src/utils/create_pxe_service.ts +8 -13
- package/dest/kernel_prover/test/test_circuit_prover.d.ts +0 -20
- package/dest/kernel_prover/test/test_circuit_prover.d.ts.map +0 -1
- package/dest/kernel_prover/test/test_circuit_prover.js +0 -75
- package/src/kernel_prover/test/test_circuit_prover.ts +0 -122
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
type PrivateCallExecutionResult,
|
|
2
3
|
type PrivateExecutionResult,
|
|
3
4
|
type PrivateKernelProver,
|
|
4
5
|
type PrivateKernelSimulateOutput,
|
|
@@ -10,6 +11,7 @@ import {
|
|
|
10
11
|
} from '@aztec/circuit-types';
|
|
11
12
|
import {
|
|
12
13
|
CLIENT_IVC_VERIFICATION_KEY_LENGTH_IN_FIELDS,
|
|
14
|
+
ClientIvcProof,
|
|
13
15
|
Fr,
|
|
14
16
|
PROTOCOL_CONTRACT_TREE_HEIGHT,
|
|
15
17
|
PrivateCallData,
|
|
@@ -32,7 +34,7 @@ import { createLogger } from '@aztec/foundation/log';
|
|
|
32
34
|
import { assertLength } from '@aztec/foundation/serialize';
|
|
33
35
|
import { pushTestData } from '@aztec/foundation/testing';
|
|
34
36
|
import { Timer } from '@aztec/foundation/timer';
|
|
35
|
-
import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types/
|
|
37
|
+
import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types/vks';
|
|
36
38
|
import {
|
|
37
39
|
getProtocolContractSiblingPath,
|
|
38
40
|
isProtocolContract,
|
|
@@ -89,6 +91,12 @@ const NULL_PROVE_OUTPUT: PrivateKernelSimulateOutput<PrivateKernelCircuitPublicI
|
|
|
89
91
|
bytecode: Buffer.from([]),
|
|
90
92
|
};
|
|
91
93
|
|
|
94
|
+
export type ProvingConfig = {
|
|
95
|
+
simulate: boolean;
|
|
96
|
+
profile: boolean;
|
|
97
|
+
dryRun: boolean;
|
|
98
|
+
};
|
|
99
|
+
|
|
92
100
|
/**
|
|
93
101
|
* The KernelProver class is responsible for generating kernel proofs.
|
|
94
102
|
* It takes a transaction request, its signature, and the simulation result as inputs, and outputs a proof
|
|
@@ -98,7 +106,11 @@ const NULL_PROVE_OUTPUT: PrivateKernelSimulateOutput<PrivateKernelCircuitPublicI
|
|
|
98
106
|
export class KernelProver {
|
|
99
107
|
private log = createLogger('pxe:kernel-prover');
|
|
100
108
|
|
|
101
|
-
constructor(
|
|
109
|
+
constructor(
|
|
110
|
+
private oracle: ProvingDataOracle,
|
|
111
|
+
private proofCreator: PrivateKernelProver,
|
|
112
|
+
private fakeProofs = false,
|
|
113
|
+
) {}
|
|
102
114
|
|
|
103
115
|
/**
|
|
104
116
|
* Generate a proof for a given transaction request and execution result.
|
|
@@ -116,14 +128,19 @@ export class KernelProver {
|
|
|
116
128
|
async prove(
|
|
117
129
|
txRequest: TxRequest,
|
|
118
130
|
executionResult: PrivateExecutionResult,
|
|
119
|
-
profile:
|
|
120
|
-
dryRun: boolean = false,
|
|
131
|
+
{ simulate, profile, dryRun }: ProvingConfig = { simulate: false, profile: false, dryRun: false },
|
|
121
132
|
): Promise<PrivateKernelSimulateOutput<PrivateKernelTailCircuitPublicInputs>> {
|
|
133
|
+
if (simulate && profile) {
|
|
134
|
+
throw new Error('Cannot simulate and profile at the same time');
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
simulate = simulate || this.fakeProofs;
|
|
138
|
+
|
|
122
139
|
const timer = new Timer();
|
|
123
140
|
|
|
124
141
|
const isPrivateOnlyTx = this.isPrivateOnly(executionResult);
|
|
125
142
|
|
|
126
|
-
const executionStack = [executionResult];
|
|
143
|
+
const executionStack = [executionResult.entrypoint];
|
|
127
144
|
let firstIteration = true;
|
|
128
145
|
|
|
129
146
|
let output = NULL_PROVE_OUTPUT;
|
|
@@ -156,7 +173,9 @@ export class KernelProver {
|
|
|
156
173
|
);
|
|
157
174
|
while (resetBuilder.needsReset()) {
|
|
158
175
|
const privateInputs = await resetBuilder.build(this.oracle, noteHashLeafIndexMap);
|
|
159
|
-
output =
|
|
176
|
+
output = simulate
|
|
177
|
+
? await this.proofCreator.simulateReset(privateInputs)
|
|
178
|
+
: await this.proofCreator.generateResetOutput(privateInputs);
|
|
160
179
|
// TODO(#7368) consider refactoring this redundant bytecode pushing
|
|
161
180
|
acirs.push(output.bytecode);
|
|
162
181
|
witnessStack.push(output.outputWitness);
|
|
@@ -199,11 +218,17 @@ export class KernelProver {
|
|
|
199
218
|
protocolContractTreeRoot,
|
|
200
219
|
privateCallData,
|
|
201
220
|
isPrivateOnlyTx,
|
|
221
|
+
executionResult.firstNullifier,
|
|
222
|
+
);
|
|
223
|
+
this.log.debug(
|
|
224
|
+
`Calling private kernel init with isPrivateOnly ${isPrivateOnlyTx} and firstNullifierHint ${proofInput.firstNullifierHint}`,
|
|
202
225
|
);
|
|
203
226
|
|
|
204
227
|
pushTestData('private-kernel-inputs-init', proofInput);
|
|
205
228
|
|
|
206
|
-
output =
|
|
229
|
+
output = simulate
|
|
230
|
+
? await this.proofCreator.simulateInit(proofInput)
|
|
231
|
+
: await this.proofCreator.generateInitOutput(proofInput);
|
|
207
232
|
|
|
208
233
|
acirs.push(output.bytecode);
|
|
209
234
|
witnessStack.push(output.outputWitness);
|
|
@@ -222,7 +247,9 @@ export class KernelProver {
|
|
|
222
247
|
|
|
223
248
|
pushTestData('private-kernel-inputs-inner', proofInput);
|
|
224
249
|
|
|
225
|
-
output =
|
|
250
|
+
output = simulate
|
|
251
|
+
? await this.proofCreator.simulateInner(proofInput)
|
|
252
|
+
: await this.proofCreator.generateInnerOutput(proofInput);
|
|
226
253
|
|
|
227
254
|
acirs.push(output.bytecode);
|
|
228
255
|
witnessStack.push(output.outputWitness);
|
|
@@ -242,7 +269,9 @@ export class KernelProver {
|
|
|
242
269
|
);
|
|
243
270
|
while (resetBuilder.needsReset()) {
|
|
244
271
|
const privateInputs = await resetBuilder.build(this.oracle, noteHashLeafIndexMap);
|
|
245
|
-
output =
|
|
272
|
+
output = simulate
|
|
273
|
+
? await this.proofCreator.simulateReset(privateInputs)
|
|
274
|
+
: await this.proofCreator.generateResetOutput(privateInputs);
|
|
246
275
|
|
|
247
276
|
acirs.push(output.bytecode);
|
|
248
277
|
witnessStack.push(output.outputWitness);
|
|
@@ -275,7 +304,9 @@ export class KernelProver {
|
|
|
275
304
|
|
|
276
305
|
pushTestData('private-kernel-inputs-ordering', privateInputs);
|
|
277
306
|
|
|
278
|
-
const tailOutput =
|
|
307
|
+
const tailOutput = simulate
|
|
308
|
+
? await this.proofCreator.simulateTail(privateInputs)
|
|
309
|
+
: await this.proofCreator.generateTailOutput(privateInputs);
|
|
279
310
|
if (tailOutput.publicInputs.forPublic) {
|
|
280
311
|
const privateLogs = privateInputs.previousKernel.publicInputs.end.privateLogs;
|
|
281
312
|
const nonRevertiblePrivateLogs = tailOutput.publicInputs.forPublic.nonRevertibleAccumulatedData.privateLogs;
|
|
@@ -290,18 +321,22 @@ export class KernelProver {
|
|
|
290
321
|
tailOutput.profileResult = { gateCounts };
|
|
291
322
|
}
|
|
292
323
|
|
|
293
|
-
|
|
324
|
+
if (!simulate) {
|
|
325
|
+
this.log.info(`Private kernel witness generation took ${timer.ms()}ms`);
|
|
326
|
+
}
|
|
294
327
|
|
|
295
328
|
// TODO(#7368) how do we 'bincode' encode these inputs?
|
|
296
|
-
if (!dryRun) {
|
|
329
|
+
if (!dryRun && !simulate) {
|
|
297
330
|
const ivcProof = await this.proofCreator.createClientIvcProof(acirs, witnessStack);
|
|
298
331
|
tailOutput.clientIvcProof = ivcProof;
|
|
332
|
+
} else {
|
|
333
|
+
tailOutput.clientIvcProof = ClientIvcProof.empty();
|
|
299
334
|
}
|
|
300
335
|
|
|
301
336
|
return tailOutput;
|
|
302
337
|
}
|
|
303
338
|
|
|
304
|
-
private async createPrivateCallData({ publicInputs, vk: vkAsBuffer }:
|
|
339
|
+
private async createPrivateCallData({ publicInputs, vk: vkAsBuffer }: PrivateCallExecutionResult) {
|
|
305
340
|
const { contractAddress, functionSelector } = publicInputs.callContext;
|
|
306
341
|
|
|
307
342
|
const vkAsFields = vkAsFieldsMegaHonk(vkAsBuffer);
|
|
@@ -339,12 +374,15 @@ export class KernelProver {
|
|
|
339
374
|
}
|
|
340
375
|
|
|
341
376
|
private isPrivateOnly(executionResult: PrivateExecutionResult): boolean {
|
|
342
|
-
const
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
377
|
+
const isPrivateOnlyRecursive = (callResult: PrivateCallExecutionResult): boolean => {
|
|
378
|
+
const makesPublicCalls =
|
|
379
|
+
callResult.enqueuedPublicFunctionCalls.some(enqueuedCall => !enqueuedCall.isEmpty()) ||
|
|
380
|
+
!callResult.publicTeardownFunctionCall.isEmpty();
|
|
381
|
+
return (
|
|
382
|
+
!makesPublicCalls &&
|
|
383
|
+
callResult.nestedExecutions.every(nestedExecution => isPrivateOnlyRecursive(nestedExecution))
|
|
384
|
+
);
|
|
385
|
+
};
|
|
386
|
+
return isPrivateOnlyRecursive(executionResult.entrypoint);
|
|
349
387
|
}
|
|
350
388
|
}
|
|
@@ -34,6 +34,7 @@ export async function bruteForceNoteInfo(
|
|
|
34
34
|
simulator: AcirSimulator,
|
|
35
35
|
uniqueNoteHashes: Fr[],
|
|
36
36
|
txHash: TxHash,
|
|
37
|
+
firstNullifier: Fr,
|
|
37
38
|
contractAddress: AztecAddress,
|
|
38
39
|
storageSlot: Fr,
|
|
39
40
|
noteTypeId: NoteSelector,
|
|
@@ -46,7 +47,6 @@ export async function bruteForceNoteInfo(
|
|
|
46
47
|
let noteHash: Fr | undefined;
|
|
47
48
|
let uniqueNoteHash: Fr | undefined;
|
|
48
49
|
let innerNullifier: Fr | undefined;
|
|
49
|
-
const firstNullifier = Fr.fromBuffer(txHash.toBuffer());
|
|
50
50
|
|
|
51
51
|
for (; noteHashIndex < uniqueNoteHashes.length; ++noteHashIndex) {
|
|
52
52
|
if (excludedIndices.has(noteHashIndex)) {
|
|
@@ -31,6 +31,7 @@ export async function produceNoteDaos(
|
|
|
31
31
|
addressPoint: PublicKey | undefined,
|
|
32
32
|
payload: L1NotePayload,
|
|
33
33
|
txHash: TxHash,
|
|
34
|
+
firstNullifier: Fr,
|
|
34
35
|
l2BlockNumber: number,
|
|
35
36
|
l2BlockHash: string,
|
|
36
37
|
noteHashes: Fr[],
|
|
@@ -51,6 +52,7 @@ export async function produceNoteDaos(
|
|
|
51
52
|
addressPoint,
|
|
52
53
|
payload,
|
|
53
54
|
txHash,
|
|
55
|
+
firstNullifier,
|
|
54
56
|
l2BlockNumber,
|
|
55
57
|
l2BlockHash,
|
|
56
58
|
noteHashes,
|
|
@@ -13,6 +13,7 @@ export async function produceNoteDaosForKey<T>(
|
|
|
13
13
|
pkM: PublicKey,
|
|
14
14
|
payload: L1NotePayload,
|
|
15
15
|
txHash: TxHash,
|
|
16
|
+
firstNullifier: Fr,
|
|
16
17
|
l2BlockNumber: number,
|
|
17
18
|
l2BlockHash: string,
|
|
18
19
|
noteHashes: Fr[],
|
|
@@ -39,6 +40,7 @@ export async function produceNoteDaosForKey<T>(
|
|
|
39
40
|
simulator,
|
|
40
41
|
noteHashes,
|
|
41
42
|
txHash,
|
|
43
|
+
firstNullifier,
|
|
42
44
|
payload.contractAddress,
|
|
43
45
|
payload.storageSlot,
|
|
44
46
|
payload.noteTypeId,
|
|
@@ -4,7 +4,7 @@ import { FunctionSelector } from '@aztec/foundation/abi';
|
|
|
4
4
|
import { AztecAddress } from '@aztec/foundation/aztec-address';
|
|
5
5
|
import { Fr } from '@aztec/foundation/fields';
|
|
6
6
|
import { type Logger } from '@aztec/foundation/log';
|
|
7
|
-
import { resolveAssertionMessageFromRevertData, resolveOpcodeLocations } from '@aztec/simulator/
|
|
7
|
+
import { resolveAssertionMessageFromRevertData, resolveOpcodeLocations } from '@aztec/simulator/client';
|
|
8
8
|
|
|
9
9
|
import { type ContractDataOracle, type PxeDatabase } from '../index.js';
|
|
10
10
|
|
|
@@ -65,7 +65,7 @@ import { type KeyStore } from '@aztec/key-store';
|
|
|
65
65
|
import { type L2TipsStore } from '@aztec/kv-store/stores';
|
|
66
66
|
import { ProtocolContractAddress, protocolContractNames } from '@aztec/protocol-contracts';
|
|
67
67
|
import { getCanonicalProtocolContract } from '@aztec/protocol-contracts/bundle';
|
|
68
|
-
import { type AcirSimulator } from '@aztec/simulator/client';
|
|
68
|
+
import { type AcirSimulator, type SimulationProvider } from '@aztec/simulator/client';
|
|
69
69
|
|
|
70
70
|
import { inspect } from 'util';
|
|
71
71
|
|
|
@@ -75,8 +75,7 @@ import { ContractDataOracle } from '../contract_data_oracle/index.js';
|
|
|
75
75
|
import { type PxeDatabase } from '../database/index.js';
|
|
76
76
|
import { NoteDao } from '../database/note_dao.js';
|
|
77
77
|
import { KernelOracle } from '../kernel_oracle/index.js';
|
|
78
|
-
import { KernelProver } from '../kernel_prover/kernel_prover.js';
|
|
79
|
-
import { TestPrivateKernelProver } from '../kernel_prover/test/test_circuit_prover.js';
|
|
78
|
+
import { KernelProver, type ProvingConfig } from '../kernel_prover/kernel_prover.js';
|
|
80
79
|
import { getAcirSimulator } from '../simulator/index.js';
|
|
81
80
|
import { Synchronizer } from '../synchronizer/index.js';
|
|
82
81
|
import { enrichPublicSimulationError, enrichSimulationError } from './error_enriching.js';
|
|
@@ -90,6 +89,7 @@ export class PXEService implements PXE {
|
|
|
90
89
|
private simulator: AcirSimulator;
|
|
91
90
|
private log: Logger;
|
|
92
91
|
private packageVersion: string;
|
|
92
|
+
private proverEnabled: boolean;
|
|
93
93
|
|
|
94
94
|
constructor(
|
|
95
95
|
private keyStore: KeyStore,
|
|
@@ -97,14 +97,16 @@ export class PXEService implements PXE {
|
|
|
97
97
|
private db: PxeDatabase,
|
|
98
98
|
tipsStore: L2TipsStore,
|
|
99
99
|
private proofCreator: PrivateKernelProver,
|
|
100
|
+
private simulationProvider: SimulationProvider,
|
|
100
101
|
config: PXEServiceConfig,
|
|
101
102
|
logSuffix?: string,
|
|
102
103
|
) {
|
|
103
104
|
this.log = createLogger(logSuffix ? `pxe:service:${logSuffix}` : `pxe:service`);
|
|
104
105
|
this.synchronizer = new Synchronizer(node, db, tipsStore, config, logSuffix);
|
|
105
106
|
this.contractDataOracle = new ContractDataOracle(db);
|
|
106
|
-
this.simulator = getAcirSimulator(db, node, keyStore, this.contractDataOracle);
|
|
107
|
+
this.simulator = getAcirSimulator(db, node, keyStore, this.simulationProvider, this.contractDataOracle);
|
|
107
108
|
this.packageVersion = getPackageInfo().version;
|
|
109
|
+
this.proverEnabled = !!config.proverEnabled;
|
|
108
110
|
}
|
|
109
111
|
|
|
110
112
|
/**
|
|
@@ -305,6 +307,10 @@ export class PXEService implements PXE {
|
|
|
305
307
|
return await getNonNullifiedL1ToL2MessageWitness(this.node, contractAddress, messageHash, secret);
|
|
306
308
|
}
|
|
307
309
|
|
|
310
|
+
public getL2ToL1MembershipWitness(blockNumber: number, l2Tol1Message: Fr): Promise<[bigint, SiblingPath<number>]> {
|
|
311
|
+
return this.node.getL2ToL1MessageMembershipWitness(blockNumber, l2Tol1Message);
|
|
312
|
+
}
|
|
313
|
+
|
|
308
314
|
public async addNote(note: ExtendedNote, scope?: AztecAddress) {
|
|
309
315
|
const owner = await this.db.getCompleteAddress(note.owner);
|
|
310
316
|
if (!owner) {
|
|
@@ -453,20 +459,16 @@ export class PXEService implements PXE {
|
|
|
453
459
|
return await this.node.getCurrentBaseFees();
|
|
454
460
|
}
|
|
455
461
|
|
|
456
|
-
async #simulateKernels(
|
|
457
|
-
txRequest: TxExecutionRequest,
|
|
458
|
-
privateExecutionResult: PrivateExecutionResult,
|
|
459
|
-
): Promise<PrivateKernelTailCircuitPublicInputs> {
|
|
460
|
-
const result = await this.#prove(txRequest, new TestPrivateKernelProver(), privateExecutionResult);
|
|
461
|
-
return result.publicInputs;
|
|
462
|
-
}
|
|
463
|
-
|
|
464
462
|
public async proveTx(
|
|
465
463
|
txRequest: TxExecutionRequest,
|
|
466
464
|
privateExecutionResult: PrivateExecutionResult,
|
|
467
465
|
): Promise<TxProvingResult> {
|
|
468
466
|
try {
|
|
469
|
-
const { publicInputs, clientIvcProof } = await this.#prove(txRequest, this.proofCreator, privateExecutionResult
|
|
467
|
+
const { publicInputs, clientIvcProof } = await this.#prove(txRequest, this.proofCreator, privateExecutionResult, {
|
|
468
|
+
simulate: false,
|
|
469
|
+
profile: false,
|
|
470
|
+
dryRun: false,
|
|
471
|
+
});
|
|
470
472
|
return new TxProvingResult(privateExecutionResult, publicInputs, clientIvcProof!);
|
|
471
473
|
} catch (err: any) {
|
|
472
474
|
throw this.contextualizeError(err, inspect(txRequest), inspect(privateExecutionResult));
|
|
@@ -501,17 +503,11 @@ export class PXEService implements PXE {
|
|
|
501
503
|
await this.synchronizer.sync();
|
|
502
504
|
const privateExecutionResult = await this.#executePrivate(txRequest, msgSender, scopes);
|
|
503
505
|
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
this.proofCreator,
|
|
510
|
-
privateExecutionResult,
|
|
511
|
-
));
|
|
512
|
-
} else {
|
|
513
|
-
publicInputs = await this.#simulateKernels(txRequest, privateExecutionResult);
|
|
514
|
-
}
|
|
506
|
+
const { publicInputs, profileResult } = await this.#prove(txRequest, this.proofCreator, privateExecutionResult, {
|
|
507
|
+
simulate: !profile,
|
|
508
|
+
profile,
|
|
509
|
+
dryRun: true,
|
|
510
|
+
});
|
|
515
511
|
|
|
516
512
|
const privateSimulationResult = new PrivateSimulationResult(privateExecutionResult, publicInputs);
|
|
517
513
|
const simulatedTx = privateSimulationResult.toSimulatedTx();
|
|
@@ -526,8 +522,8 @@ export class PXEService implements PXE {
|
|
|
526
522
|
}
|
|
527
523
|
}
|
|
528
524
|
|
|
529
|
-
this.log.info(`Simulation completed for ${simulatedTx.
|
|
530
|
-
txHash: simulatedTx.
|
|
525
|
+
this.log.info(`Simulation completed for ${simulatedTx.getTxHash()} in ${timer.ms()}ms`, {
|
|
526
|
+
txHash: simulatedTx.getTxHash(),
|
|
531
527
|
...txInfo,
|
|
532
528
|
...(profileResult ? { gateCounts: profileResult.gateCounts } : {}),
|
|
533
529
|
...(publicOutput
|
|
@@ -795,20 +791,6 @@ export class PXEService implements PXE {
|
|
|
795
791
|
}
|
|
796
792
|
}
|
|
797
793
|
|
|
798
|
-
async #profileKernelProver(
|
|
799
|
-
txExecutionRequest: TxExecutionRequest,
|
|
800
|
-
proofCreator: PrivateKernelProver,
|
|
801
|
-
privateExecutionResult: PrivateExecutionResult,
|
|
802
|
-
): Promise<PrivateKernelSimulateOutput<PrivateKernelTailCircuitPublicInputs>> {
|
|
803
|
-
const block = privateExecutionResult.publicInputs.historicalHeader.globalVariables.blockNumber.toNumber();
|
|
804
|
-
const kernelOracle = new KernelOracle(this.contractDataOracle, this.keyStore, this.node, block);
|
|
805
|
-
const kernelProver = new KernelProver(kernelOracle, proofCreator);
|
|
806
|
-
|
|
807
|
-
// Dry run the prover with profiler enabled
|
|
808
|
-
const result = await kernelProver.prove(txExecutionRequest.toTxRequest(), privateExecutionResult, true, true);
|
|
809
|
-
return result;
|
|
810
|
-
}
|
|
811
|
-
|
|
812
794
|
/**
|
|
813
795
|
* Generate a kernel proof, and create a private kernel output.
|
|
814
796
|
* The function takes in a transaction execution request, and the result of private execution
|
|
@@ -823,13 +805,19 @@ export class PXEService implements PXE {
|
|
|
823
805
|
txExecutionRequest: TxExecutionRequest,
|
|
824
806
|
proofCreator: PrivateKernelProver,
|
|
825
807
|
privateExecutionResult: PrivateExecutionResult,
|
|
808
|
+
{ simulate, profile, dryRun }: ProvingConfig,
|
|
826
809
|
): Promise<PrivateKernelSimulateOutput<PrivateKernelTailCircuitPublicInputs>> {
|
|
827
810
|
// use the block the tx was simulated against
|
|
828
|
-
const block =
|
|
811
|
+
const block =
|
|
812
|
+
privateExecutionResult.entrypoint.publicInputs.historicalHeader.globalVariables.blockNumber.toNumber();
|
|
829
813
|
const kernelOracle = new KernelOracle(this.contractDataOracle, this.keyStore, this.node, block);
|
|
830
|
-
const kernelProver = new KernelProver(kernelOracle, proofCreator);
|
|
831
|
-
this.log.debug(`Executing kernel prover...`);
|
|
832
|
-
return await kernelProver.prove(txExecutionRequest.toTxRequest(), privateExecutionResult
|
|
814
|
+
const kernelProver = new KernelProver(kernelOracle, proofCreator, !this.proverEnabled);
|
|
815
|
+
this.log.debug(`Executing kernel prover (simulate: ${simulate}, profile: ${profile}, dryRun: ${dryRun})...`);
|
|
816
|
+
return await kernelProver.prove(txExecutionRequest.toTxRequest(), privateExecutionResult, {
|
|
817
|
+
simulate,
|
|
818
|
+
profile,
|
|
819
|
+
dryRun,
|
|
820
|
+
});
|
|
833
821
|
}
|
|
834
822
|
|
|
835
823
|
public async isContractClassPubliclyRegistered(id: Fr): Promise<boolean> {
|
package/src/simulator/index.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type AztecNode } from '@aztec/circuit-types';
|
|
2
2
|
import { type KeyStore } from '@aztec/key-store';
|
|
3
|
-
import { AcirSimulator } from '@aztec/simulator/client';
|
|
3
|
+
import { AcirSimulator, type SimulationProvider } from '@aztec/simulator/client';
|
|
4
4
|
|
|
5
5
|
import { ContractDataOracle } from '../contract_data_oracle/index.js';
|
|
6
6
|
import { type PxeDatabase } from '../database/pxe_database.js';
|
|
@@ -13,6 +13,7 @@ export function getAcirSimulator(
|
|
|
13
13
|
db: PxeDatabase,
|
|
14
14
|
aztecNode: AztecNode,
|
|
15
15
|
keyStore: KeyStore,
|
|
16
|
+
simulationProvider: SimulationProvider,
|
|
16
17
|
contractDataOracle?: ContractDataOracle,
|
|
17
18
|
) {
|
|
18
19
|
const simulatorOracle = new SimulatorOracle(
|
|
@@ -20,6 +21,7 @@ export function getAcirSimulator(
|
|
|
20
21
|
db,
|
|
21
22
|
keyStore,
|
|
22
23
|
aztecNode,
|
|
24
|
+
simulationProvider,
|
|
23
25
|
);
|
|
24
|
-
return new AcirSimulator(simulatorOracle, aztecNode);
|
|
26
|
+
return new AcirSimulator(simulatorOracle, aztecNode, simulationProvider);
|
|
25
27
|
}
|
|
@@ -30,8 +30,12 @@ import { type FunctionArtifact, getFunctionArtifact } from '@aztec/foundation/ab
|
|
|
30
30
|
import { poseidon2Hash } from '@aztec/foundation/crypto';
|
|
31
31
|
import { createLogger } from '@aztec/foundation/log';
|
|
32
32
|
import { type KeyStore } from '@aztec/key-store';
|
|
33
|
-
import {
|
|
34
|
-
|
|
33
|
+
import {
|
|
34
|
+
type AcirSimulator,
|
|
35
|
+
type DBOracle,
|
|
36
|
+
MessageLoadOracleInputs,
|
|
37
|
+
type SimulationProvider,
|
|
38
|
+
} from '@aztec/simulator/client';
|
|
35
39
|
|
|
36
40
|
import { type ContractDataOracle } from '../contract_data_oracle/index.js';
|
|
37
41
|
import { type PxeDatabase } from '../database/index.js';
|
|
@@ -49,6 +53,7 @@ export class SimulatorOracle implements DBOracle {
|
|
|
49
53
|
private db: PxeDatabase,
|
|
50
54
|
private keyStore: KeyStore,
|
|
51
55
|
private aztecNode: AztecNode,
|
|
56
|
+
private simulationProvider: SimulationProvider,
|
|
52
57
|
private log = createLogger('pxe:simulator_oracle'),
|
|
53
58
|
) {}
|
|
54
59
|
|
|
@@ -163,7 +168,7 @@ export class SimulatorOracle implements DBOracle {
|
|
|
163
168
|
* @returns - The index of the commitment. Undefined if it does not exist in the tree.
|
|
164
169
|
*/
|
|
165
170
|
async getCommitmentIndex(commitment: Fr) {
|
|
166
|
-
return await this
|
|
171
|
+
return await this.#findLeafIndex('latest', MerkleTreeId.NOTE_HASH_TREE, commitment);
|
|
167
172
|
}
|
|
168
173
|
|
|
169
174
|
// We need this in public as part of the EXISTS calls - but isn't used in private
|
|
@@ -172,19 +177,26 @@ export class SimulatorOracle implements DBOracle {
|
|
|
172
177
|
}
|
|
173
178
|
|
|
174
179
|
async getNullifierIndex(nullifier: Fr) {
|
|
175
|
-
return await this
|
|
180
|
+
return await this.#findLeafIndex('latest', MerkleTreeId.NULLIFIER_TREE, nullifier);
|
|
176
181
|
}
|
|
177
182
|
|
|
178
|
-
|
|
179
|
-
blockNumber: L2BlockNumber,
|
|
180
|
-
treeId: MerkleTreeId,
|
|
181
|
-
leafValue: Fr,
|
|
182
|
-
): Promise<bigint | undefined> {
|
|
183
|
+
async #findLeafIndex(blockNumber: L2BlockNumber, treeId: MerkleTreeId, leafValue: Fr): Promise<bigint | undefined> {
|
|
183
184
|
const [leafIndex] = await this.aztecNode.findLeavesIndexes(blockNumber, treeId, [leafValue]);
|
|
184
185
|
return leafIndex;
|
|
185
186
|
}
|
|
186
187
|
|
|
187
|
-
public async
|
|
188
|
+
public async getMembershipWitness(blockNumber: number, treeId: MerkleTreeId, leafValue: Fr): Promise<Fr[]> {
|
|
189
|
+
const leafIndex = await this.#findLeafIndex(blockNumber, treeId, leafValue);
|
|
190
|
+
if (!leafIndex) {
|
|
191
|
+
throw new Error(`Leaf value: ${leafValue} not found in ${MerkleTreeId[treeId]}`);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
const siblingPath = await this.#getSiblingPath(blockNumber, treeId, leafIndex);
|
|
195
|
+
|
|
196
|
+
return [new Fr(leafIndex), ...siblingPath];
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
async #getSiblingPath(blockNumber: number, treeId: MerkleTreeId, leafIndex: bigint): Promise<Fr[]> {
|
|
188
200
|
switch (treeId) {
|
|
189
201
|
case MerkleTreeId.NULLIFIER_TREE:
|
|
190
202
|
return (await this.aztecNode.getNullifierSiblingPath(blockNumber, leafIndex)).toFields();
|
|
@@ -598,11 +610,13 @@ export class SimulatorOracle implements DBOracle {
|
|
|
598
610
|
// I don't like this at all, but we need a simulator to run `computeNoteHashAndOptionallyANullifier`. This generates
|
|
599
611
|
// a chicken-and-egg problem due to this oracle requiring a simulator, which in turn requires this oracle. Furthermore, since jest doesn't allow
|
|
600
612
|
// mocking ESM exports, we have to pollute the method even more by providing a simulator parameter so tests can inject a fake one.
|
|
601
|
-
simulator ??
|
|
613
|
+
simulator ??
|
|
614
|
+
getAcirSimulator(this.db, this.aztecNode, this.keyStore, this.simulationProvider, this.contractDataOracle),
|
|
602
615
|
this.db,
|
|
603
616
|
notePayload ? recipient.toAddressPoint() : undefined,
|
|
604
617
|
payload!,
|
|
605
618
|
txEffect.data.txHash,
|
|
619
|
+
txEffect.data.nullifiers[0],
|
|
606
620
|
txEffect.l2BlockNumber,
|
|
607
621
|
txEffect.l2BlockHash,
|
|
608
622
|
txEffect.data.noteHashes,
|
|
@@ -666,4 +680,26 @@ export class SimulatorOracle implements DBOracle {
|
|
|
666
680
|
});
|
|
667
681
|
}
|
|
668
682
|
}
|
|
683
|
+
|
|
684
|
+
/**
|
|
685
|
+
* Used by contracts during execution to store arbitrary data in the local PXE database. The data is siloed/scoped
|
|
686
|
+
* to a specific `contract`.
|
|
687
|
+
* @param contract - An address of a contract that is requesting to store the data.
|
|
688
|
+
* @param key - A field element representing the key to store the data under.
|
|
689
|
+
* @param values - An array of field elements representing the data to store.
|
|
690
|
+
*/
|
|
691
|
+
store(contract: AztecAddress, key: Fr, values: Fr[]): Promise<void> {
|
|
692
|
+
return this.db.store(contract, key, values);
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
/**
|
|
696
|
+
* Used by contracts during execution to load arbitrary data from the local PXE database. The data is siloed/scoped
|
|
697
|
+
* to a specific `contract`.
|
|
698
|
+
* @param contract - An address of a contract that is requesting to load the data.
|
|
699
|
+
* @param key - A field element representing the key under which to load the data..
|
|
700
|
+
* @returns An array of field elements representing the stored data or `null` if no data is stored under the key.
|
|
701
|
+
*/
|
|
702
|
+
load(contract: AztecAddress, key: Fr): Promise<Fr[] | null> {
|
|
703
|
+
return this.db.load(contract, key);
|
|
704
|
+
}
|
|
669
705
|
}
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import { BBNativePrivateKernelProver } from '@aztec/bb-prover';
|
|
2
|
-
import {
|
|
2
|
+
import { BBWASMBundlePrivateKernelProver } from '@aztec/bb-prover/wasm/bundle';
|
|
3
3
|
import { type AztecNode, type PrivateKernelProver } from '@aztec/circuit-types';
|
|
4
4
|
import { randomBytes } from '@aztec/foundation/crypto';
|
|
5
5
|
import { createLogger } from '@aztec/foundation/log';
|
|
6
6
|
import { KeyStore } from '@aztec/key-store';
|
|
7
7
|
import { createStore } from '@aztec/kv-store/lmdb';
|
|
8
8
|
import { L2TipsStore } from '@aztec/kv-store/stores';
|
|
9
|
+
import { type SimulationProvider, WASMSimulator } from '@aztec/simulator/client';
|
|
9
10
|
|
|
10
11
|
import { type PXEServiceConfig } from '../config/index.js';
|
|
11
12
|
import { KVPxeDatabase } from '../database/kv_pxe_database.js';
|
|
12
|
-
import { TestPrivateKernelProver } from '../kernel_prover/test/test_circuit_prover.js';
|
|
13
13
|
import { PXEService } from '../pxe_service/pxe_service.js';
|
|
14
14
|
|
|
15
15
|
/**
|
|
@@ -46,25 +46,20 @@ export async function createPXEService(
|
|
|
46
46
|
|
|
47
47
|
const db = await KVPxeDatabase.create(store);
|
|
48
48
|
const tips = new L2TipsStore(store, 'pxe');
|
|
49
|
-
|
|
50
|
-
const prover = proofCreator ?? (await createProver(config, logSuffix));
|
|
51
|
-
const pxe = new PXEService(keyStore, aztecNode, db, tips, prover, config, logSuffix);
|
|
49
|
+
const simulationProvider = new WASMSimulator();
|
|
50
|
+
const prover = proofCreator ?? (await createProver(config, simulationProvider, logSuffix));
|
|
51
|
+
const pxe = new PXEService(keyStore, aztecNode, db, tips, prover, simulationProvider, config, logSuffix);
|
|
52
52
|
await pxe.init();
|
|
53
53
|
return pxe;
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
-
function createProver(config: PXEServiceConfig, logSuffix?: string) {
|
|
57
|
-
if (!config.proverEnabled) {
|
|
58
|
-
return new TestPrivateKernelProver();
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// (@PhilWindle) Temporary validation until WASM is implemented
|
|
56
|
+
function createProver(config: PXEServiceConfig, simulationProvider: SimulationProvider, logSuffix?: string) {
|
|
62
57
|
if (!config.bbBinaryPath || !config.bbWorkingDirectory) {
|
|
63
|
-
return new
|
|
58
|
+
return new BBWASMBundlePrivateKernelProver(simulationProvider, 16);
|
|
64
59
|
} else {
|
|
65
60
|
const bbConfig = config as Required<Pick<PXEServiceConfig, 'bbBinaryPath' | 'bbWorkingDirectory'>> &
|
|
66
61
|
PXEServiceConfig;
|
|
67
62
|
const log = createLogger('pxe:bb-native-prover' + (logSuffix ? `:${logSuffix}` : ''));
|
|
68
|
-
return BBNativePrivateKernelProver.new({ bbSkipCleanup: false, ...bbConfig }, log);
|
|
63
|
+
return BBNativePrivateKernelProver.new({ bbSkipCleanup: false, ...bbConfig }, simulationProvider, log);
|
|
69
64
|
}
|
|
70
65
|
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
/// <reference types="node" resolution-mode="require"/>
|
|
2
|
-
/// <reference types="node" resolution-mode="require"/>
|
|
3
|
-
import { type PrivateKernelProver, type PrivateKernelSimulateOutput } from '@aztec/circuit-types';
|
|
4
|
-
import { ClientIvcProof, type PrivateKernelCircuitPublicInputs, type PrivateKernelInitCircuitPrivateInputs, type PrivateKernelInnerCircuitPrivateInputs, type PrivateKernelResetCircuitPrivateInputs, type PrivateKernelTailCircuitPrivateInputs, type PrivateKernelTailCircuitPublicInputs } from '@aztec/circuits.js';
|
|
5
|
-
import { type WitnessMap } from '@noir-lang/types';
|
|
6
|
-
/**
|
|
7
|
-
* Test Proof Creator executes circuit simulations and provides fake proofs.
|
|
8
|
-
*/
|
|
9
|
-
export declare class TestPrivateKernelProver implements PrivateKernelProver {
|
|
10
|
-
private log;
|
|
11
|
-
constructor(log?: import("@aztec/foundation/log").Logger);
|
|
12
|
-
createClientIvcProof(_acirs: Buffer[], _witnessStack: WitnessMap[]): Promise<ClientIvcProof>;
|
|
13
|
-
simulateProofInit(privateInputs: PrivateKernelInitCircuitPrivateInputs): Promise<PrivateKernelSimulateOutput<PrivateKernelCircuitPublicInputs>>;
|
|
14
|
-
simulateProofInner(privateInputs: PrivateKernelInnerCircuitPrivateInputs): Promise<PrivateKernelSimulateOutput<PrivateKernelCircuitPublicInputs>>;
|
|
15
|
-
simulateProofReset(privateInputs: PrivateKernelResetCircuitPrivateInputs): Promise<PrivateKernelSimulateOutput<PrivateKernelCircuitPublicInputs>>;
|
|
16
|
-
simulateProofTail(privateInputs: PrivateKernelTailCircuitPrivateInputs): Promise<PrivateKernelSimulateOutput<PrivateKernelTailCircuitPublicInputs>>;
|
|
17
|
-
computeGateCountForCircuit(_bytecode: Buffer, _circuitName: string): Promise<number>;
|
|
18
|
-
private makeEmptyKernelSimulateOutput;
|
|
19
|
-
}
|
|
20
|
-
//# sourceMappingURL=test_circuit_prover.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"test_circuit_prover.d.ts","sourceRoot":"","sources":["../../../src/kernel_prover/test/test_circuit_prover.ts"],"names":[],"mappings":";;AAAA,OAAO,EAAE,KAAK,mBAAmB,EAAE,KAAK,2BAA2B,EAAE,MAAM,sBAAsB,CAAC;AAElG,OAAO,EACL,cAAc,EACd,KAAK,gCAAgC,EACrC,KAAK,qCAAqC,EAC1C,KAAK,sCAAsC,EAC3C,KAAK,sCAAsC,EAC3C,KAAK,qCAAqC,EAC1C,KAAK,oCAAoC,EAC1C,MAAM,oBAAoB,CAAC;AAe5B,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD;;GAEG;AACH,qBAAa,uBAAwB,YAAW,mBAAmB;IACrD,OAAO,CAAC,GAAG;gBAAH,GAAG,yCAAyC;IAEhE,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,aAAa,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC,cAAc,CAAC;IAI/E,iBAAiB,CAC5B,aAAa,EAAE,qCAAqC,GACnD,OAAO,CAAC,2BAA2B,CAAC,gCAAgC,CAAC,CAAC;IAY5D,kBAAkB,CAC7B,aAAa,EAAE,sCAAsC,GACpD,OAAO,CAAC,2BAA2B,CAAC,gCAAgC,CAAC,CAAC;IAY5D,kBAAkB,CAC7B,aAAa,EAAE,sCAAsC,GACpD,OAAO,CAAC,2BAA2B,CAAC,gCAAgC,CAAC,CAAC;IAkB5D,iBAAiB,CAC5B,aAAa,EAAE,qCAAqC,GACnD,OAAO,CAAC,2BAA2B,CAAC,oCAAoC,CAAC,CAAC;IAkBtE,0BAA0B,CAAC,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAK3F,OAAO,CAAC,6BAA6B;CAWtC"}
|