@aztec/pxe 0.69.0-devnet → 0.69.1-devnet
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 +11 -7
- package/dest/database/kv_pxe_database.d.ts.map +1 -1
- package/dest/database/kv_pxe_database.js +36 -13
- package/dest/database/note_dao.d.ts +105 -0
- package/dest/database/note_dao.d.ts.map +1 -0
- package/dest/database/note_dao.js +123 -0
- package/dest/database/outgoing_note_dao.js +3 -3
- package/dest/database/pxe_database.d.ts +25 -9
- 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 +68 -21
- package/dest/kernel_oracle/index.js +2 -2
- package/dest/kernel_prover/hints/build_private_kernel_reset_private_inputs.js +2 -2
- 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 +32 -12
- 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 +3 -3
- package/dest/note_decryption_utils/produce_note_daos.d.ts.map +1 -1
- package/dest/note_decryption_utils/produce_note_daos.js +6 -6
- 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/pxe_service.d.ts +3 -2
- package/dest/pxe_service/pxe_service.d.ts.map +1 -1
- package/dest/pxe_service/pxe_service.js +34 -42
- package/dest/simulator_oracle/index.d.ts +18 -3
- package/dest/simulator_oracle/index.d.ts.map +1 -1
- package/dest/simulator_oracle/index.js +63 -37
- package/dest/utils/create_pxe_service.d.ts.map +1 -1
- package/dest/utils/create_pxe_service.js +3 -8
- package/package.json +14 -15
- package/src/database/kv_pxe_database.ts +46 -16
- package/src/database/{incoming_note_dao.ts → note_dao.ts} +65 -48
- package/src/database/outgoing_note_dao.ts +2 -2
- package/src/database/pxe_database.ts +27 -9
- package/src/database/pxe_database_test_suite.ts +86 -25
- package/src/kernel_oracle/index.ts +1 -1
- package/src/kernel_prover/hints/build_private_kernel_reset_private_inputs.ts +1 -1
- package/src/kernel_prover/index.ts +0 -2
- package/src/kernel_prover/kernel_prover.ts +41 -11
- package/src/note_decryption_utils/brute_force_note_info.ts +1 -1
- package/src/note_decryption_utils/produce_note_daos.ts +8 -6
- package/src/note_decryption_utils/produce_note_daos_for_key.ts +2 -0
- package/src/pxe_service/pxe_service.ts +42 -63
- package/src/simulator_oracle/index.ts +54 -24
- package/src/utils/create_pxe_service.ts +2 -8
- package/dest/database/incoming_note_dao.d.ts +0 -86
- package/dest/database/incoming_note_dao.d.ts.map +0 -1
- package/dest/database/incoming_note_dao.js +0 -110
- 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
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
} from '@aztec/circuit-types';
|
|
11
11
|
import {
|
|
12
12
|
CLIENT_IVC_VERIFICATION_KEY_LENGTH_IN_FIELDS,
|
|
13
|
+
ClientIvcProof,
|
|
13
14
|
Fr,
|
|
14
15
|
PROTOCOL_CONTRACT_TREE_HEIGHT,
|
|
15
16
|
PrivateCallData,
|
|
@@ -32,7 +33,7 @@ import { createLogger } from '@aztec/foundation/log';
|
|
|
32
33
|
import { assertLength } from '@aztec/foundation/serialize';
|
|
33
34
|
import { pushTestData } from '@aztec/foundation/testing';
|
|
34
35
|
import { Timer } from '@aztec/foundation/timer';
|
|
35
|
-
import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types/
|
|
36
|
+
import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types/vks';
|
|
36
37
|
import {
|
|
37
38
|
getProtocolContractSiblingPath,
|
|
38
39
|
isProtocolContract,
|
|
@@ -89,6 +90,12 @@ const NULL_PROVE_OUTPUT: PrivateKernelSimulateOutput<PrivateKernelCircuitPublicI
|
|
|
89
90
|
bytecode: Buffer.from([]),
|
|
90
91
|
};
|
|
91
92
|
|
|
93
|
+
export type ProvingConfig = {
|
|
94
|
+
simulate: boolean;
|
|
95
|
+
profile: boolean;
|
|
96
|
+
dryRun: boolean;
|
|
97
|
+
};
|
|
98
|
+
|
|
92
99
|
/**
|
|
93
100
|
* The KernelProver class is responsible for generating kernel proofs.
|
|
94
101
|
* It takes a transaction request, its signature, and the simulation result as inputs, and outputs a proof
|
|
@@ -98,7 +105,11 @@ const NULL_PROVE_OUTPUT: PrivateKernelSimulateOutput<PrivateKernelCircuitPublicI
|
|
|
98
105
|
export class KernelProver {
|
|
99
106
|
private log = createLogger('pxe:kernel-prover');
|
|
100
107
|
|
|
101
|
-
constructor(
|
|
108
|
+
constructor(
|
|
109
|
+
private oracle: ProvingDataOracle,
|
|
110
|
+
private proofCreator: PrivateKernelProver,
|
|
111
|
+
private fakeProofs = false,
|
|
112
|
+
) {}
|
|
102
113
|
|
|
103
114
|
/**
|
|
104
115
|
* Generate a proof for a given transaction request and execution result.
|
|
@@ -116,9 +127,14 @@ export class KernelProver {
|
|
|
116
127
|
async prove(
|
|
117
128
|
txRequest: TxRequest,
|
|
118
129
|
executionResult: PrivateExecutionResult,
|
|
119
|
-
profile:
|
|
120
|
-
dryRun: boolean = false,
|
|
130
|
+
{ simulate, profile, dryRun }: ProvingConfig = { simulate: false, profile: false, dryRun: false },
|
|
121
131
|
): Promise<PrivateKernelSimulateOutput<PrivateKernelTailCircuitPublicInputs>> {
|
|
132
|
+
if (simulate && profile) {
|
|
133
|
+
throw new Error('Cannot simulate and profile at the same time');
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
simulate = simulate || this.fakeProofs;
|
|
137
|
+
|
|
122
138
|
const timer = new Timer();
|
|
123
139
|
|
|
124
140
|
const isPrivateOnlyTx = this.isPrivateOnly(executionResult);
|
|
@@ -156,7 +172,9 @@ export class KernelProver {
|
|
|
156
172
|
);
|
|
157
173
|
while (resetBuilder.needsReset()) {
|
|
158
174
|
const privateInputs = await resetBuilder.build(this.oracle, noteHashLeafIndexMap);
|
|
159
|
-
output =
|
|
175
|
+
output = simulate
|
|
176
|
+
? await this.proofCreator.simulateReset(privateInputs)
|
|
177
|
+
: await this.proofCreator.generateResetOutput(privateInputs);
|
|
160
178
|
// TODO(#7368) consider refactoring this redundant bytecode pushing
|
|
161
179
|
acirs.push(output.bytecode);
|
|
162
180
|
witnessStack.push(output.outputWitness);
|
|
@@ -203,7 +221,9 @@ export class KernelProver {
|
|
|
203
221
|
|
|
204
222
|
pushTestData('private-kernel-inputs-init', proofInput);
|
|
205
223
|
|
|
206
|
-
output =
|
|
224
|
+
output = simulate
|
|
225
|
+
? await this.proofCreator.simulateInit(proofInput)
|
|
226
|
+
: await this.proofCreator.generateInitOutput(proofInput);
|
|
207
227
|
|
|
208
228
|
acirs.push(output.bytecode);
|
|
209
229
|
witnessStack.push(output.outputWitness);
|
|
@@ -222,7 +242,9 @@ export class KernelProver {
|
|
|
222
242
|
|
|
223
243
|
pushTestData('private-kernel-inputs-inner', proofInput);
|
|
224
244
|
|
|
225
|
-
output =
|
|
245
|
+
output = simulate
|
|
246
|
+
? await this.proofCreator.simulateInner(proofInput)
|
|
247
|
+
: await this.proofCreator.generateInnerOutput(proofInput);
|
|
226
248
|
|
|
227
249
|
acirs.push(output.bytecode);
|
|
228
250
|
witnessStack.push(output.outputWitness);
|
|
@@ -242,7 +264,9 @@ export class KernelProver {
|
|
|
242
264
|
);
|
|
243
265
|
while (resetBuilder.needsReset()) {
|
|
244
266
|
const privateInputs = await resetBuilder.build(this.oracle, noteHashLeafIndexMap);
|
|
245
|
-
output =
|
|
267
|
+
output = simulate
|
|
268
|
+
? await this.proofCreator.simulateReset(privateInputs)
|
|
269
|
+
: await this.proofCreator.generateResetOutput(privateInputs);
|
|
246
270
|
|
|
247
271
|
acirs.push(output.bytecode);
|
|
248
272
|
witnessStack.push(output.outputWitness);
|
|
@@ -275,7 +299,9 @@ export class KernelProver {
|
|
|
275
299
|
|
|
276
300
|
pushTestData('private-kernel-inputs-ordering', privateInputs);
|
|
277
301
|
|
|
278
|
-
const tailOutput =
|
|
302
|
+
const tailOutput = simulate
|
|
303
|
+
? await this.proofCreator.simulateTail(privateInputs)
|
|
304
|
+
: await this.proofCreator.generateTailOutput(privateInputs);
|
|
279
305
|
if (tailOutput.publicInputs.forPublic) {
|
|
280
306
|
const privateLogs = privateInputs.previousKernel.publicInputs.end.privateLogs;
|
|
281
307
|
const nonRevertiblePrivateLogs = tailOutput.publicInputs.forPublic.nonRevertibleAccumulatedData.privateLogs;
|
|
@@ -290,12 +316,16 @@ export class KernelProver {
|
|
|
290
316
|
tailOutput.profileResult = { gateCounts };
|
|
291
317
|
}
|
|
292
318
|
|
|
293
|
-
|
|
319
|
+
if (!simulate) {
|
|
320
|
+
this.log.info(`Private kernel witness generation took ${timer.ms()}ms`);
|
|
321
|
+
}
|
|
294
322
|
|
|
295
323
|
// TODO(#7368) how do we 'bincode' encode these inputs?
|
|
296
|
-
if (!dryRun) {
|
|
324
|
+
if (!dryRun && !simulate) {
|
|
297
325
|
const ivcProof = await this.proofCreator.createClientIvcProof(acirs, witnessStack);
|
|
298
326
|
tailOutput.clientIvcProof = ivcProof;
|
|
327
|
+
} else {
|
|
328
|
+
tailOutput.clientIvcProof = ClientIvcProof.empty();
|
|
299
329
|
}
|
|
300
330
|
|
|
301
331
|
return tailOutput;
|
|
@@ -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)) {
|
|
@@ -3,7 +3,7 @@ import { type Fr } from '@aztec/foundation/fields';
|
|
|
3
3
|
import { type Logger } from '@aztec/foundation/log';
|
|
4
4
|
import { type AcirSimulator } from '@aztec/simulator/client';
|
|
5
5
|
|
|
6
|
-
import {
|
|
6
|
+
import { NoteDao } from '../database/note_dao.js';
|
|
7
7
|
import { type PxeDatabase } from '../database/pxe_database.js';
|
|
8
8
|
import { produceNoteDaosForKey } from './produce_note_daos_for_key.js';
|
|
9
9
|
|
|
@@ -31,37 +31,39 @@ 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[],
|
|
37
38
|
dataStartIndexForTx: number,
|
|
38
39
|
excludedIndices: Set<number>,
|
|
39
40
|
logger: Logger,
|
|
40
|
-
): Promise<{
|
|
41
|
+
): Promise<{ note: NoteDao | undefined }> {
|
|
41
42
|
if (!addressPoint) {
|
|
42
43
|
throw new Error('addressPoint is undefined. Cannot create note.');
|
|
43
44
|
}
|
|
44
45
|
|
|
45
|
-
let
|
|
46
|
+
let note: NoteDao | undefined;
|
|
46
47
|
|
|
47
48
|
if (addressPoint) {
|
|
48
|
-
|
|
49
|
+
note = await produceNoteDaosForKey(
|
|
49
50
|
simulator,
|
|
50
51
|
db,
|
|
51
52
|
addressPoint,
|
|
52
53
|
payload,
|
|
53
54
|
txHash,
|
|
55
|
+
firstNullifier,
|
|
54
56
|
l2BlockNumber,
|
|
55
57
|
l2BlockHash,
|
|
56
58
|
noteHashes,
|
|
57
59
|
dataStartIndexForTx,
|
|
58
60
|
excludedIndices,
|
|
59
61
|
logger,
|
|
60
|
-
|
|
62
|
+
NoteDao.fromPayloadAndNoteInfo,
|
|
61
63
|
);
|
|
62
64
|
}
|
|
63
65
|
|
|
64
66
|
return {
|
|
65
|
-
|
|
67
|
+
note,
|
|
66
68
|
};
|
|
67
69
|
}
|
|
@@ -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,
|
|
@@ -7,11 +7,11 @@ import {
|
|
|
7
7
|
type FunctionCall,
|
|
8
8
|
type GetUnencryptedLogsResponse,
|
|
9
9
|
type InBlock,
|
|
10
|
-
type IncomingNotesFilter,
|
|
11
10
|
L1EventPayload,
|
|
12
11
|
type L2Block,
|
|
13
12
|
type LogFilter,
|
|
14
13
|
MerkleTreeId,
|
|
14
|
+
type NotesFilter,
|
|
15
15
|
type PXE,
|
|
16
16
|
type PXEInfo,
|
|
17
17
|
type PrivateExecutionResult,
|
|
@@ -54,6 +54,7 @@ import {
|
|
|
54
54
|
EventSelector,
|
|
55
55
|
FunctionSelector,
|
|
56
56
|
FunctionType,
|
|
57
|
+
decodeFunctionSignature,
|
|
57
58
|
encodeArguments,
|
|
58
59
|
} from '@aztec/foundation/abi';
|
|
59
60
|
import { type AztecAddress } from '@aztec/foundation/aztec-address';
|
|
@@ -71,11 +72,10 @@ import { inspect } from 'util';
|
|
|
71
72
|
import { type PXEServiceConfig } from '../config/index.js';
|
|
72
73
|
import { getPackageInfo } from '../config/package_info.js';
|
|
73
74
|
import { ContractDataOracle } from '../contract_data_oracle/index.js';
|
|
74
|
-
import { IncomingNoteDao } from '../database/incoming_note_dao.js';
|
|
75
75
|
import { type PxeDatabase } from '../database/index.js';
|
|
76
|
+
import { NoteDao } from '../database/note_dao.js';
|
|
76
77
|
import { KernelOracle } from '../kernel_oracle/index.js';
|
|
77
|
-
import { KernelProver } from '../kernel_prover/kernel_prover.js';
|
|
78
|
-
import { TestPrivateKernelProver } from '../kernel_prover/test/test_circuit_prover.js';
|
|
78
|
+
import { KernelProver, type ProvingConfig } from '../kernel_prover/kernel_prover.js';
|
|
79
79
|
import { getAcirSimulator } from '../simulator/index.js';
|
|
80
80
|
import { Synchronizer } from '../synchronizer/index.js';
|
|
81
81
|
import { enrichPublicSimulationError, enrichSimulationError } from './error_enriching.js';
|
|
@@ -89,6 +89,7 @@ export class PXEService implements PXE {
|
|
|
89
89
|
private simulator: AcirSimulator;
|
|
90
90
|
private log: Logger;
|
|
91
91
|
private packageVersion: string;
|
|
92
|
+
private proverEnabled: boolean;
|
|
92
93
|
|
|
93
94
|
constructor(
|
|
94
95
|
private keyStore: KeyStore,
|
|
@@ -104,6 +105,7 @@ export class PXEService implements PXE {
|
|
|
104
105
|
this.contractDataOracle = new ContractDataOracle(db);
|
|
105
106
|
this.simulator = getAcirSimulator(db, node, keyStore, this.contractDataOracle);
|
|
106
107
|
this.packageVersion = getPackageInfo().version;
|
|
108
|
+
this.proverEnabled = !!config.proverEnabled;
|
|
107
109
|
}
|
|
108
110
|
|
|
109
111
|
/**
|
|
@@ -237,14 +239,10 @@ export class PXEService implements PXE {
|
|
|
237
239
|
|
|
238
240
|
await this.db.addContractArtifact(contractClassId, artifact);
|
|
239
241
|
|
|
240
|
-
const
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
await this.node.registerContractFunctionNames(instance.address, functionNames);
|
|
242
|
+
const publicFunctionSignatures = artifact.functions
|
|
243
|
+
.filter(fn => fn.functionType === FunctionType.PUBLIC)
|
|
244
|
+
.map(fn => decodeFunctionSignature(fn.name, fn.parameters));
|
|
245
|
+
await this.node.registerContractFunctionSignatures(instance.address, publicFunctionSignatures);
|
|
248
246
|
|
|
249
247
|
// TODO(#10007): Node should get public contract class from the registration event, not from PXE registration
|
|
250
248
|
await this.node.addContractClass({ ...contractClass, privateFunctions: [], unconstrainedFunctions: [] });
|
|
@@ -273,8 +271,8 @@ export class PXEService implements PXE {
|
|
|
273
271
|
return await this.node.getPublicStorageAt(contract, slot, 'latest');
|
|
274
272
|
}
|
|
275
273
|
|
|
276
|
-
public async
|
|
277
|
-
const noteDaos = await this.db.
|
|
274
|
+
public async getNotes(filter: NotesFilter): Promise<UniqueNote[]> {
|
|
275
|
+
const noteDaos = await this.db.getNotes(filter);
|
|
278
276
|
|
|
279
277
|
const extendedNotes = noteDaos.map(async dao => {
|
|
280
278
|
let owner = filter.owner;
|
|
@@ -343,19 +341,19 @@ export class PXEService implements PXE {
|
|
|
343
341
|
}
|
|
344
342
|
|
|
345
343
|
await this.db.addNote(
|
|
346
|
-
new
|
|
344
|
+
new NoteDao(
|
|
347
345
|
note.note,
|
|
348
346
|
note.contractAddress,
|
|
349
347
|
note.storageSlot,
|
|
350
|
-
note.noteTypeId,
|
|
351
|
-
note.txHash,
|
|
352
|
-
l2BlockNumber,
|
|
353
|
-
l2BlockHash,
|
|
354
348
|
nonce,
|
|
355
349
|
noteHash,
|
|
356
350
|
siloedNullifier,
|
|
351
|
+
note.txHash,
|
|
352
|
+
l2BlockNumber,
|
|
353
|
+
l2BlockHash,
|
|
357
354
|
index,
|
|
358
355
|
owner.address.toAddressPoint(),
|
|
356
|
+
note.noteTypeId,
|
|
359
357
|
),
|
|
360
358
|
scope,
|
|
361
359
|
);
|
|
@@ -388,19 +386,19 @@ export class PXEService implements PXE {
|
|
|
388
386
|
}
|
|
389
387
|
|
|
390
388
|
await this.db.addNullifiedNote(
|
|
391
|
-
new
|
|
389
|
+
new NoteDao(
|
|
392
390
|
note.note,
|
|
393
391
|
note.contractAddress,
|
|
394
392
|
note.storageSlot,
|
|
395
|
-
note.noteTypeId,
|
|
396
|
-
note.txHash,
|
|
397
|
-
l2BlockNumber,
|
|
398
|
-
l2BlockHash,
|
|
399
393
|
nonce,
|
|
400
394
|
noteHash,
|
|
401
395
|
Fr.ZERO, // We are not able to derive
|
|
396
|
+
note.txHash,
|
|
397
|
+
l2BlockNumber,
|
|
398
|
+
l2BlockHash,
|
|
402
399
|
index,
|
|
403
400
|
note.owner.toAddressPoint(),
|
|
401
|
+
note.noteTypeId,
|
|
404
402
|
),
|
|
405
403
|
);
|
|
406
404
|
}
|
|
@@ -456,20 +454,16 @@ export class PXEService implements PXE {
|
|
|
456
454
|
return await this.node.getCurrentBaseFees();
|
|
457
455
|
}
|
|
458
456
|
|
|
459
|
-
async #simulateKernels(
|
|
460
|
-
txRequest: TxExecutionRequest,
|
|
461
|
-
privateExecutionResult: PrivateExecutionResult,
|
|
462
|
-
): Promise<PrivateKernelTailCircuitPublicInputs> {
|
|
463
|
-
const result = await this.#prove(txRequest, new TestPrivateKernelProver(), privateExecutionResult);
|
|
464
|
-
return result.publicInputs;
|
|
465
|
-
}
|
|
466
|
-
|
|
467
457
|
public async proveTx(
|
|
468
458
|
txRequest: TxExecutionRequest,
|
|
469
459
|
privateExecutionResult: PrivateExecutionResult,
|
|
470
460
|
): Promise<TxProvingResult> {
|
|
471
461
|
try {
|
|
472
|
-
const { publicInputs, clientIvcProof } = await this.#prove(txRequest, this.proofCreator, privateExecutionResult
|
|
462
|
+
const { publicInputs, clientIvcProof } = await this.#prove(txRequest, this.proofCreator, privateExecutionResult, {
|
|
463
|
+
simulate: false,
|
|
464
|
+
profile: false,
|
|
465
|
+
dryRun: false,
|
|
466
|
+
});
|
|
473
467
|
return new TxProvingResult(privateExecutionResult, publicInputs, clientIvcProof!);
|
|
474
468
|
} catch (err: any) {
|
|
475
469
|
throw this.contextualizeError(err, inspect(txRequest), inspect(privateExecutionResult));
|
|
@@ -504,17 +498,11 @@ export class PXEService implements PXE {
|
|
|
504
498
|
await this.synchronizer.sync();
|
|
505
499
|
const privateExecutionResult = await this.#executePrivate(txRequest, msgSender, scopes);
|
|
506
500
|
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
this.proofCreator,
|
|
513
|
-
privateExecutionResult,
|
|
514
|
-
));
|
|
515
|
-
} else {
|
|
516
|
-
publicInputs = await this.#simulateKernels(txRequest, privateExecutionResult);
|
|
517
|
-
}
|
|
501
|
+
const { publicInputs, profileResult } = await this.#prove(txRequest, this.proofCreator, privateExecutionResult, {
|
|
502
|
+
simulate: !profile,
|
|
503
|
+
profile,
|
|
504
|
+
dryRun: true,
|
|
505
|
+
});
|
|
518
506
|
|
|
519
507
|
const privateSimulationResult = new PrivateSimulationResult(privateExecutionResult, publicInputs);
|
|
520
508
|
const simulatedTx = privateSimulationResult.toSimulatedTx();
|
|
@@ -529,8 +517,8 @@ export class PXEService implements PXE {
|
|
|
529
517
|
}
|
|
530
518
|
}
|
|
531
519
|
|
|
532
|
-
this.log.info(`Simulation completed for ${simulatedTx.
|
|
533
|
-
txHash: simulatedTx.
|
|
520
|
+
this.log.info(`Simulation completed for ${simulatedTx.getTxHash()} in ${timer.ms()}ms`, {
|
|
521
|
+
txHash: simulatedTx.getTxHash(),
|
|
534
522
|
...txInfo,
|
|
535
523
|
...(profileResult ? { gateCounts: profileResult.gateCounts } : {}),
|
|
536
524
|
...(publicOutput
|
|
@@ -798,20 +786,6 @@ export class PXEService implements PXE {
|
|
|
798
786
|
}
|
|
799
787
|
}
|
|
800
788
|
|
|
801
|
-
async #profileKernelProver(
|
|
802
|
-
txExecutionRequest: TxExecutionRequest,
|
|
803
|
-
proofCreator: PrivateKernelProver,
|
|
804
|
-
privateExecutionResult: PrivateExecutionResult,
|
|
805
|
-
): Promise<PrivateKernelSimulateOutput<PrivateKernelTailCircuitPublicInputs>> {
|
|
806
|
-
const block = privateExecutionResult.publicInputs.historicalHeader.globalVariables.blockNumber.toNumber();
|
|
807
|
-
const kernelOracle = new KernelOracle(this.contractDataOracle, this.keyStore, this.node, block);
|
|
808
|
-
const kernelProver = new KernelProver(kernelOracle, proofCreator);
|
|
809
|
-
|
|
810
|
-
// Dry run the prover with profiler enabled
|
|
811
|
-
const result = await kernelProver.prove(txExecutionRequest.toTxRequest(), privateExecutionResult, true, true);
|
|
812
|
-
return result;
|
|
813
|
-
}
|
|
814
|
-
|
|
815
789
|
/**
|
|
816
790
|
* Generate a kernel proof, and create a private kernel output.
|
|
817
791
|
* The function takes in a transaction execution request, and the result of private execution
|
|
@@ -826,13 +800,18 @@ export class PXEService implements PXE {
|
|
|
826
800
|
txExecutionRequest: TxExecutionRequest,
|
|
827
801
|
proofCreator: PrivateKernelProver,
|
|
828
802
|
privateExecutionResult: PrivateExecutionResult,
|
|
803
|
+
{ simulate, profile, dryRun }: ProvingConfig,
|
|
829
804
|
): Promise<PrivateKernelSimulateOutput<PrivateKernelTailCircuitPublicInputs>> {
|
|
830
805
|
// use the block the tx was simulated against
|
|
831
806
|
const block = privateExecutionResult.publicInputs.historicalHeader.globalVariables.blockNumber.toNumber();
|
|
832
807
|
const kernelOracle = new KernelOracle(this.contractDataOracle, this.keyStore, this.node, block);
|
|
833
|
-
const kernelProver = new KernelProver(kernelOracle, proofCreator);
|
|
834
|
-
this.log.debug(`Executing kernel prover...`);
|
|
835
|
-
return await kernelProver.prove(txExecutionRequest.toTxRequest(), privateExecutionResult
|
|
808
|
+
const kernelProver = new KernelProver(kernelOracle, proofCreator, !this.proverEnabled);
|
|
809
|
+
this.log.debug(`Executing kernel prover (simulate: ${simulate}, profile: ${profile}, dryRun: ${dryRun})...`);
|
|
810
|
+
return await kernelProver.prove(txExecutionRequest.toTxRequest(), privateExecutionResult, {
|
|
811
|
+
simulate,
|
|
812
|
+
profile,
|
|
813
|
+
dryRun,
|
|
814
|
+
});
|
|
836
815
|
}
|
|
837
816
|
|
|
838
817
|
public async isContractClassPubliclyRegistered(id: Fr): Promise<boolean> {
|
|
@@ -34,8 +34,8 @@ import { MessageLoadOracleInputs } from '@aztec/simulator/acvm';
|
|
|
34
34
|
import { type AcirSimulator, type DBOracle } from '@aztec/simulator/client';
|
|
35
35
|
|
|
36
36
|
import { type ContractDataOracle } from '../contract_data_oracle/index.js';
|
|
37
|
-
import { type IncomingNoteDao } from '../database/incoming_note_dao.js';
|
|
38
37
|
import { type PxeDatabase } from '../database/index.js';
|
|
38
|
+
import { type NoteDao } from '../database/note_dao.js';
|
|
39
39
|
import { produceNoteDaos } from '../note_decryption_utils/produce_note_daos.js';
|
|
40
40
|
import { getAcirSimulator } from '../simulator/index.js';
|
|
41
41
|
import { WINDOW_HALF_SIZE, getIndexedTaggingSecretsForTheWindow, getInitialIndexesMap } from './tagging_utils.js';
|
|
@@ -92,7 +92,7 @@ export class SimulatorOracle implements DBOracle {
|
|
|
92
92
|
}
|
|
93
93
|
|
|
94
94
|
async getNotes(contractAddress: AztecAddress, storageSlot: Fr, status: NoteStatus, scopes?: AztecAddress[]) {
|
|
95
|
-
const noteDaos = await this.db.
|
|
95
|
+
const noteDaos = await this.db.getNotes({
|
|
96
96
|
contractAddress,
|
|
97
97
|
storageSlot,
|
|
98
98
|
status,
|
|
@@ -163,7 +163,7 @@ export class SimulatorOracle implements DBOracle {
|
|
|
163
163
|
* @returns - The index of the commitment. Undefined if it does not exist in the tree.
|
|
164
164
|
*/
|
|
165
165
|
async getCommitmentIndex(commitment: Fr) {
|
|
166
|
-
return await this
|
|
166
|
+
return await this.#findLeafIndex('latest', MerkleTreeId.NOTE_HASH_TREE, commitment);
|
|
167
167
|
}
|
|
168
168
|
|
|
169
169
|
// We need this in public as part of the EXISTS calls - but isn't used in private
|
|
@@ -172,19 +172,26 @@ export class SimulatorOracle implements DBOracle {
|
|
|
172
172
|
}
|
|
173
173
|
|
|
174
174
|
async getNullifierIndex(nullifier: Fr) {
|
|
175
|
-
return await this
|
|
175
|
+
return await this.#findLeafIndex('latest', MerkleTreeId.NULLIFIER_TREE, nullifier);
|
|
176
176
|
}
|
|
177
177
|
|
|
178
|
-
|
|
179
|
-
blockNumber: L2BlockNumber,
|
|
180
|
-
treeId: MerkleTreeId,
|
|
181
|
-
leafValue: Fr,
|
|
182
|
-
): Promise<bigint | undefined> {
|
|
178
|
+
async #findLeafIndex(blockNumber: L2BlockNumber, treeId: MerkleTreeId, leafValue: Fr): Promise<bigint | undefined> {
|
|
183
179
|
const [leafIndex] = await this.aztecNode.findLeavesIndexes(blockNumber, treeId, [leafValue]);
|
|
184
180
|
return leafIndex;
|
|
185
181
|
}
|
|
186
182
|
|
|
187
|
-
public async
|
|
183
|
+
public async getMembershipWitness(blockNumber: number, treeId: MerkleTreeId, leafValue: Fr): Promise<Fr[]> {
|
|
184
|
+
const leafIndex = await this.#findLeafIndex(blockNumber, treeId, leafValue);
|
|
185
|
+
if (!leafIndex) {
|
|
186
|
+
throw new Error(`Leaf value: ${leafValue} not found in ${MerkleTreeId[treeId]}`);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
const siblingPath = await this.#getSiblingPath(blockNumber, treeId, leafIndex);
|
|
190
|
+
|
|
191
|
+
return [new Fr(leafIndex), ...siblingPath];
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
async #getSiblingPath(blockNumber: number, treeId: MerkleTreeId, leafIndex: bigint): Promise<Fr[]> {
|
|
188
195
|
switch (treeId) {
|
|
189
196
|
case MerkleTreeId.NULLIFIER_TREE:
|
|
190
197
|
return (await this.aztecNode.getNullifierSiblingPath(blockNumber, leafIndex)).toFields();
|
|
@@ -569,17 +576,17 @@ export class SimulatorOracle implements DBOracle {
|
|
|
569
576
|
// Since we could have notes with the same index for different txs, we need
|
|
570
577
|
// to keep track of them scoping by txHash
|
|
571
578
|
const excludedIndices: Map<string, Set<number>> = new Map();
|
|
572
|
-
const
|
|
579
|
+
const notes: NoteDao[] = [];
|
|
573
580
|
|
|
574
581
|
const txEffectsCache = new Map<string, InBlock<TxEffect> | undefined>();
|
|
575
582
|
|
|
576
583
|
for (const scopedLog of scopedLogs) {
|
|
577
|
-
const
|
|
584
|
+
const notePayload = scopedLog.isFromPublic
|
|
578
585
|
? L1NotePayload.decryptAsIncomingFromPublic(scopedLog.logData, addressSecret)
|
|
579
586
|
: L1NotePayload.decryptAsIncoming(PrivateLog.fromBuffer(scopedLog.logData), addressSecret);
|
|
580
587
|
|
|
581
|
-
if (
|
|
582
|
-
const payload =
|
|
588
|
+
if (notePayload) {
|
|
589
|
+
const payload = notePayload;
|
|
583
590
|
|
|
584
591
|
const txEffect =
|
|
585
592
|
txEffectsCache.get(scopedLog.txHash.toString()) ?? (await this.aztecNode.getTxEffect(scopedLog.txHash));
|
|
@@ -594,15 +601,16 @@ export class SimulatorOracle implements DBOracle {
|
|
|
594
601
|
if (!excludedIndices.has(scopedLog.txHash.toString())) {
|
|
595
602
|
excludedIndices.set(scopedLog.txHash.toString(), new Set());
|
|
596
603
|
}
|
|
597
|
-
const {
|
|
604
|
+
const { note } = await produceNoteDaos(
|
|
598
605
|
// I don't like this at all, but we need a simulator to run `computeNoteHashAndOptionallyANullifier`. This generates
|
|
599
606
|
// 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
607
|
// mocking ESM exports, we have to pollute the method even more by providing a simulator parameter so tests can inject a fake one.
|
|
601
608
|
simulator ?? getAcirSimulator(this.db, this.aztecNode, this.keyStore, this.contractDataOracle),
|
|
602
609
|
this.db,
|
|
603
|
-
|
|
610
|
+
notePayload ? recipient.toAddressPoint() : undefined,
|
|
604
611
|
payload!,
|
|
605
612
|
txEffect.data.txHash,
|
|
613
|
+
txEffect.data.nullifiers[0],
|
|
606
614
|
txEffect.l2BlockNumber,
|
|
607
615
|
txEffect.l2BlockHash,
|
|
608
616
|
txEffect.data.noteHashes,
|
|
@@ -611,12 +619,12 @@ export class SimulatorOracle implements DBOracle {
|
|
|
611
619
|
this.log,
|
|
612
620
|
);
|
|
613
621
|
|
|
614
|
-
if (
|
|
615
|
-
|
|
622
|
+
if (note) {
|
|
623
|
+
notes.push(note);
|
|
616
624
|
}
|
|
617
625
|
}
|
|
618
626
|
}
|
|
619
|
-
return {
|
|
627
|
+
return { notes };
|
|
620
628
|
}
|
|
621
629
|
|
|
622
630
|
/**
|
|
@@ -629,10 +637,10 @@ export class SimulatorOracle implements DBOracle {
|
|
|
629
637
|
recipient: AztecAddress,
|
|
630
638
|
simulator?: AcirSimulator,
|
|
631
639
|
): Promise<void> {
|
|
632
|
-
const {
|
|
633
|
-
if (
|
|
634
|
-
await this.db.addNotes(
|
|
635
|
-
|
|
640
|
+
const { notes } = await this.#decryptTaggedLogs(logs, recipient, simulator);
|
|
641
|
+
if (notes.length) {
|
|
642
|
+
await this.db.addNotes(notes, recipient);
|
|
643
|
+
notes.forEach(noteDao => {
|
|
636
644
|
this.log.verbose(`Added incoming note for contract ${noteDao.contractAddress} at slot ${noteDao.storageSlot}`, {
|
|
637
645
|
contract: noteDao.contractAddress,
|
|
638
646
|
slot: noteDao.storageSlot,
|
|
@@ -644,7 +652,7 @@ export class SimulatorOracle implements DBOracle {
|
|
|
644
652
|
|
|
645
653
|
public async removeNullifiedNotes(contractAddress: AztecAddress) {
|
|
646
654
|
for (const recipient of await this.keyStore.getAccounts()) {
|
|
647
|
-
const currentNotesForRecipient = await this.db.
|
|
655
|
+
const currentNotesForRecipient = await this.db.getNotes({ contractAddress, owner: recipient });
|
|
648
656
|
const nullifiersToCheck = currentNotesForRecipient.map(note => note.siloedNullifier);
|
|
649
657
|
const nullifierIndexes = await this.aztecNode.findNullifiersIndexesWithBlock('latest', nullifiersToCheck);
|
|
650
658
|
|
|
@@ -666,4 +674,26 @@ export class SimulatorOracle implements DBOracle {
|
|
|
666
674
|
});
|
|
667
675
|
}
|
|
668
676
|
}
|
|
677
|
+
|
|
678
|
+
/**
|
|
679
|
+
* Used by contracts during execution to store arbitrary data in the local PXE database. The data is siloed/scoped
|
|
680
|
+
* to a specific `contract`.
|
|
681
|
+
* @param contract - An address of a contract that is requesting to store the data.
|
|
682
|
+
* @param key - A field element representing the key to store the data under.
|
|
683
|
+
* @param values - An array of field elements representing the data to store.
|
|
684
|
+
*/
|
|
685
|
+
store(contract: AztecAddress, key: Fr, values: Fr[]): Promise<void> {
|
|
686
|
+
return this.db.store(contract, key, values);
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
/**
|
|
690
|
+
* Used by contracts during execution to load arbitrary data from the local PXE database. The data is siloed/scoped
|
|
691
|
+
* to a specific `contract`.
|
|
692
|
+
* @param contract - An address of a contract that is requesting to load the data.
|
|
693
|
+
* @param key - A field element representing the key under which to load the data..
|
|
694
|
+
* @returns An array of field elements representing the stored data or `null` if no data is stored under the key.
|
|
695
|
+
*/
|
|
696
|
+
load(contract: AztecAddress, key: Fr): Promise<Fr[] | null> {
|
|
697
|
+
return this.db.load(contract, key);
|
|
698
|
+
}
|
|
669
699
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
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';
|
|
@@ -9,7 +9,6 @@ import { L2TipsStore } from '@aztec/kv-store/stores';
|
|
|
9
9
|
|
|
10
10
|
import { type PXEServiceConfig } from '../config/index.js';
|
|
11
11
|
import { KVPxeDatabase } from '../database/kv_pxe_database.js';
|
|
12
|
-
import { TestPrivateKernelProver } from '../kernel_prover/test/test_circuit_prover.js';
|
|
13
12
|
import { PXEService } from '../pxe_service/pxe_service.js';
|
|
14
13
|
|
|
15
14
|
/**
|
|
@@ -54,13 +53,8 @@ export async function createPXEService(
|
|
|
54
53
|
}
|
|
55
54
|
|
|
56
55
|
function createProver(config: PXEServiceConfig, logSuffix?: string) {
|
|
57
|
-
if (!config.proverEnabled) {
|
|
58
|
-
return new TestPrivateKernelProver();
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// (@PhilWindle) Temporary validation until WASM is implemented
|
|
62
56
|
if (!config.bbBinaryPath || !config.bbWorkingDirectory) {
|
|
63
|
-
return new
|
|
57
|
+
return new BBWASMBundlePrivateKernelProver(16);
|
|
64
58
|
} else {
|
|
65
59
|
const bbConfig = config as Required<Pick<PXEServiceConfig, 'bbBinaryPath' | 'bbWorkingDirectory'>> &
|
|
66
60
|
PXEServiceConfig;
|