@aztec/pxe 0.66.0 → 0.67.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/bin/index.js +5 -6
- package/dest/config/index.d.ts +0 -9
- package/dest/config/index.d.ts.map +1 -1
- package/dest/config/index.js +1 -17
- package/dest/config/package_info.d.ts +5 -0
- package/dest/config/package_info.d.ts.map +1 -0
- package/dest/config/package_info.js +4 -0
- package/dest/contract_data_oracle/index.js +2 -2
- package/dest/database/incoming_note_dao.d.ts +1 -1
- package/dest/database/incoming_note_dao.d.ts.map +1 -1
- package/dest/database/incoming_note_dao.js +2 -2
- package/dest/database/kv_pxe_database.d.ts +10 -13
- package/dest/database/kv_pxe_database.d.ts.map +1 -1
- package/dest/database/kv_pxe_database.js +153 -230
- package/dest/database/outgoing_note_dao.js +2 -2
- package/dest/database/pxe_database.d.ts +7 -25
- 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 +18 -59
- package/dest/index.d.ts +2 -0
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +3 -1
- package/dest/kernel_oracle/index.d.ts.map +1 -1
- package/dest/kernel_oracle/index.js +3 -3
- package/dest/kernel_prover/index.d.ts +1 -0
- package/dest/kernel_prover/index.d.ts.map +1 -1
- package/dest/kernel_prover/index.js +2 -1
- package/dest/kernel_prover/kernel_prover.d.ts +1 -0
- package/dest/kernel_prover/kernel_prover.d.ts.map +1 -1
- package/dest/kernel_prover/kernel_prover.js +38 -4
- package/dest/kernel_prover/test/test_circuit_prover.d.ts.map +1 -1
- package/dest/kernel_prover/test/test_circuit_prover.js +4 -4
- package/dest/note_decryption_utils/add_public_values_to_payload.js +2 -2
- package/dest/note_decryption_utils/brute_force_note_info.d.ts +3 -3
- package/dest/note_decryption_utils/brute_force_note_info.d.ts.map +1 -1
- package/dest/note_decryption_utils/brute_force_note_info.js +8 -8
- package/dest/note_decryption_utils/produce_note_daos.d.ts +3 -6
- package/dest/note_decryption_utils/produce_note_daos.d.ts.map +1 -1
- package/dest/note_decryption_utils/produce_note_daos.js +5 -19
- 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/pxe_service/error_enriching.d.ts +3 -3
- package/dest/pxe_service/error_enriching.d.ts.map +1 -1
- package/dest/pxe_service/error_enriching.js +10 -10
- package/dest/pxe_service/index.d.ts +0 -1
- package/dest/pxe_service/index.d.ts.map +1 -1
- package/dest/pxe_service/index.js +1 -2
- package/dest/pxe_service/pxe_service.d.ts +2 -16
- package/dest/pxe_service/pxe_service.d.ts.map +1 -1
- package/dest/pxe_service/pxe_service.js +70 -95
- package/dest/pxe_service/test/pxe_test_suite.d.ts.map +1 -1
- package/dest/pxe_service/test/pxe_test_suite.js +1 -3
- package/dest/simulator/index.d.ts +1 -1
- package/dest/simulator/index.d.ts.map +1 -1
- package/dest/simulator/index.js +2 -2
- package/dest/simulator_oracle/index.d.ts +7 -6
- package/dest/simulator_oracle/index.d.ts.map +1 -1
- package/dest/simulator_oracle/index.js +59 -42
- package/dest/synchronizer/synchronizer.d.ts +10 -40
- package/dest/synchronizer/synchronizer.d.ts.map +1 -1
- package/dest/synchronizer/synchronizer.js +35 -69
- package/dest/{pxe_service → utils}/create_pxe_service.d.ts +1 -1
- package/dest/utils/create_pxe_service.d.ts.map +1 -0
- package/dest/utils/create_pxe_service.js +49 -0
- package/package.json +31 -19
- package/src/bin/index.ts +4 -5
- package/src/config/index.ts +0 -21
- package/src/config/package_info.ts +3 -0
- package/src/contract_data_oracle/index.ts +1 -1
- package/src/database/incoming_note_dao.ts +2 -2
- package/src/database/kv_pxe_database.ts +212 -309
- package/src/database/outgoing_note_dao.ts +1 -1
- package/src/database/pxe_database.ts +7 -28
- package/src/database/pxe_database_test_suite.ts +20 -75
- package/src/index.ts +2 -0
- package/src/kernel_oracle/index.ts +2 -2
- package/src/kernel_prover/index.ts +2 -0
- package/src/kernel_prover/kernel_prover.ts +61 -2
- package/src/kernel_prover/test/test_circuit_prover.ts +5 -3
- package/src/note_decryption_utils/add_public_values_to_payload.ts +1 -1
- package/src/note_decryption_utils/brute_force_note_info.ts +9 -9
- package/src/note_decryption_utils/produce_note_daos.ts +5 -48
- package/src/note_decryption_utils/produce_note_daos_for_key.ts +1 -1
- package/src/pxe_service/error_enriching.ts +14 -12
- package/src/pxe_service/index.ts +0 -1
- package/src/pxe_service/pxe_service.ts +123 -169
- package/src/pxe_service/test/pxe_test_suite.ts +0 -3
- package/src/simulator/index.ts +1 -1
- package/src/simulator_oracle/index.ts +63 -70
- package/src/synchronizer/synchronizer.ts +37 -77
- package/src/{pxe_service → utils}/create_pxe_service.ts +10 -10
- package/dest/pxe_service/create_pxe_service.d.ts.map +0 -1
- package/dest/pxe_service/create_pxe_service.js +0 -49
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type SimulationError, isNoirCallStackUnresolved } from '@aztec/circuit-types';
|
|
2
2
|
import { AztecAddress, Fr, FunctionSelector, PUBLIC_DISPATCH_SELECTOR } from '@aztec/circuits.js';
|
|
3
|
-
import { type
|
|
4
|
-
import { resolveAssertionMessageFromRevertData, resolveOpcodeLocations } from '@aztec/simulator';
|
|
3
|
+
import { type Logger } from '@aztec/foundation/log';
|
|
4
|
+
import { resolveAssertionMessageFromRevertData, resolveOpcodeLocations } from '@aztec/simulator/errors';
|
|
5
5
|
|
|
6
6
|
import { type ContractDataOracle, type PxeDatabase } from '../index.js';
|
|
7
7
|
|
|
@@ -10,27 +10,27 @@ import { type ContractDataOracle, type PxeDatabase } from '../index.js';
|
|
|
10
10
|
* can be found in the PXE database
|
|
11
11
|
* @param err - The error to enrich.
|
|
12
12
|
*/
|
|
13
|
-
export async function enrichSimulationError(err: SimulationError, db: PxeDatabase, logger:
|
|
14
|
-
// Maps contract addresses to the set of
|
|
13
|
+
export async function enrichSimulationError(err: SimulationError, db: PxeDatabase, logger: Logger) {
|
|
14
|
+
// Maps contract addresses to the set of function names that were in error.
|
|
15
15
|
// Map and Set do reference equality for their keys instead of value equality, so we store the string
|
|
16
16
|
// representation to get e.g. different contract address objects with the same address value to match.
|
|
17
17
|
const mentionedFunctions: Map<string, Set<string>> = new Map();
|
|
18
18
|
|
|
19
|
-
err.getCallStack().forEach(({ contractAddress,
|
|
19
|
+
err.getCallStack().forEach(({ contractAddress, functionName }) => {
|
|
20
20
|
if (!mentionedFunctions.has(contractAddress.toString())) {
|
|
21
21
|
mentionedFunctions.set(contractAddress.toString(), new Set());
|
|
22
22
|
}
|
|
23
|
-
mentionedFunctions.get(contractAddress.toString())!.add(
|
|
23
|
+
mentionedFunctions.get(contractAddress.toString())!.add(functionName?.toString() ?? '');
|
|
24
24
|
});
|
|
25
25
|
|
|
26
26
|
await Promise.all(
|
|
27
|
-
[...mentionedFunctions.entries()].map(async ([contractAddress,
|
|
27
|
+
[...mentionedFunctions.entries()].map(async ([contractAddress, fnNames]) => {
|
|
28
28
|
const parsedContractAddress = AztecAddress.fromString(contractAddress);
|
|
29
29
|
const contract = await db.getContract(parsedContractAddress);
|
|
30
30
|
if (contract) {
|
|
31
31
|
err.enrichWithContractName(parsedContractAddress, contract.name);
|
|
32
|
-
|
|
33
|
-
const functionArtifact = contract.functions.find(f =>
|
|
32
|
+
fnNames.forEach(fnName => {
|
|
33
|
+
const functionArtifact = contract.functions.find(f => fnName === f.name);
|
|
34
34
|
if (functionArtifact) {
|
|
35
35
|
err.enrichWithFunctionName(
|
|
36
36
|
parsedContractAddress,
|
|
@@ -39,7 +39,7 @@ export async function enrichSimulationError(err: SimulationError, db: PxeDatabas
|
|
|
39
39
|
);
|
|
40
40
|
} else {
|
|
41
41
|
logger.warn(
|
|
42
|
-
`Could not function artifact in contract ${contract.name} for
|
|
42
|
+
`Could not function artifact in contract ${contract.name} for function '${fnName}' when enriching error callstack`,
|
|
43
43
|
);
|
|
44
44
|
}
|
|
45
45
|
});
|
|
@@ -56,7 +56,7 @@ export async function enrichPublicSimulationError(
|
|
|
56
56
|
err: SimulationError,
|
|
57
57
|
contractDataOracle: ContractDataOracle,
|
|
58
58
|
db: PxeDatabase,
|
|
59
|
-
logger:
|
|
59
|
+
logger: Logger,
|
|
60
60
|
) {
|
|
61
61
|
const callStack = err.getCallStack();
|
|
62
62
|
const originalFailingFunction = callStack[callStack.length - 1];
|
|
@@ -89,7 +89,9 @@ export async function enrichPublicSimulationError(
|
|
|
89
89
|
err.setNoirCallStack(parsedCallStack);
|
|
90
90
|
} catch (err) {
|
|
91
91
|
logger.warn(
|
|
92
|
-
`Could not resolve noir call stack for ${originalFailingFunction.contractAddress.toString()}:${
|
|
92
|
+
`Could not resolve noir call stack for ${originalFailingFunction.contractAddress.toString()}:${
|
|
93
|
+
originalFailingFunction.functionName?.toString() ?? ''
|
|
94
|
+
}: ${err}`,
|
|
93
95
|
);
|
|
94
96
|
}
|
|
95
97
|
}
|
package/src/pxe_service/index.ts
CHANGED
|
@@ -12,7 +12,6 @@ import {
|
|
|
12
12
|
type L2Block,
|
|
13
13
|
type LogFilter,
|
|
14
14
|
MerkleTreeId,
|
|
15
|
-
type OutgoingNotesFilter,
|
|
16
15
|
type PXE,
|
|
17
16
|
type PXEInfo,
|
|
18
17
|
type PrivateExecutionResult,
|
|
@@ -56,8 +55,7 @@ import {
|
|
|
56
55
|
encodeArguments,
|
|
57
56
|
} from '@aztec/foundation/abi';
|
|
58
57
|
import { Fr, type Point } from '@aztec/foundation/fields';
|
|
59
|
-
import { type
|
|
60
|
-
import { SerialQueue } from '@aztec/foundation/queue';
|
|
58
|
+
import { type Logger, createLogger } from '@aztec/foundation/log';
|
|
61
59
|
import { type KeyStore } from '@aztec/key-store';
|
|
62
60
|
import { type L2TipsStore } from '@aztec/kv-store/stores';
|
|
63
61
|
import {
|
|
@@ -65,11 +63,12 @@ import {
|
|
|
65
63
|
getCanonicalProtocolContract,
|
|
66
64
|
protocolContractNames,
|
|
67
65
|
} from '@aztec/protocol-contracts';
|
|
68
|
-
import { type AcirSimulator } from '@aztec/simulator';
|
|
66
|
+
import { type AcirSimulator } from '@aztec/simulator/client';
|
|
69
67
|
|
|
70
68
|
import { inspect } from 'util';
|
|
71
69
|
|
|
72
|
-
import { type PXEServiceConfig
|
|
70
|
+
import { type PXEServiceConfig } from '../config/index.js';
|
|
71
|
+
import { getPackageInfo } from '../config/package_info.js';
|
|
73
72
|
import { ContractDataOracle } from '../contract_data_oracle/index.js';
|
|
74
73
|
import { IncomingNoteDao } from '../database/incoming_note_dao.js';
|
|
75
74
|
import { type PxeDatabase } from '../database/index.js';
|
|
@@ -87,11 +86,8 @@ export class PXEService implements PXE {
|
|
|
87
86
|
private synchronizer: Synchronizer;
|
|
88
87
|
private contractDataOracle: ContractDataOracle;
|
|
89
88
|
private simulator: AcirSimulator;
|
|
90
|
-
private log:
|
|
89
|
+
private log: Logger;
|
|
91
90
|
private packageVersion: string;
|
|
92
|
-
// serialize synchronizer and calls to proveTx.
|
|
93
|
-
// ensures that state is not changed while simulating
|
|
94
|
-
private jobQueue = new SerialQueue();
|
|
95
91
|
|
|
96
92
|
constructor(
|
|
97
93
|
private keyStore: KeyStore,
|
|
@@ -102,13 +98,11 @@ export class PXEService implements PXE {
|
|
|
102
98
|
config: PXEServiceConfig,
|
|
103
99
|
logSuffix?: string,
|
|
104
100
|
) {
|
|
105
|
-
this.log =
|
|
101
|
+
this.log = createLogger(logSuffix ? `pxe:service:${logSuffix}` : `pxe:service`);
|
|
106
102
|
this.synchronizer = new Synchronizer(node, db, tipsStore, config, logSuffix);
|
|
107
103
|
this.contractDataOracle = new ContractDataOracle(db);
|
|
108
104
|
this.simulator = getAcirSimulator(db, node, keyStore, this.contractDataOracle);
|
|
109
105
|
this.packageVersion = getPackageInfo().version;
|
|
110
|
-
|
|
111
|
-
this.jobQueue.start();
|
|
112
106
|
}
|
|
113
107
|
|
|
114
108
|
/**
|
|
@@ -116,27 +110,12 @@ export class PXEService implements PXE {
|
|
|
116
110
|
*
|
|
117
111
|
* @returns A promise that resolves when the server has started successfully.
|
|
118
112
|
*/
|
|
119
|
-
public async
|
|
120
|
-
await this.synchronizer.start();
|
|
113
|
+
public async init() {
|
|
121
114
|
await this.#registerProtocolContracts();
|
|
122
115
|
const info = await this.getNodeInfo();
|
|
123
116
|
this.log.info(`Started PXE connected to chain ${info.l1ChainId} version ${info.protocolVersion}`);
|
|
124
117
|
}
|
|
125
118
|
|
|
126
|
-
/**
|
|
127
|
-
* Stops the PXE Service, halting processing of new transactions and shutting down the synchronizer.
|
|
128
|
-
* This function ensures that all ongoing tasks are completed before stopping the server.
|
|
129
|
-
* It is useful for gracefully shutting down the server during maintenance or restarts.
|
|
130
|
-
*
|
|
131
|
-
* @returns A Promise resolving once the server has been stopped successfully.
|
|
132
|
-
*/
|
|
133
|
-
public async stop() {
|
|
134
|
-
await this.jobQueue.cancel();
|
|
135
|
-
this.log.info('Cancelled Job Queue');
|
|
136
|
-
await this.synchronizer.stop();
|
|
137
|
-
this.log.info('Stopped Synchronizer');
|
|
138
|
-
}
|
|
139
|
-
|
|
140
119
|
isL1ToL2MessageSynced(l1ToL2Message: Fr): Promise<boolean> {
|
|
141
120
|
return this.node.isL1ToL2MessageSynced(l1ToL2Message);
|
|
142
121
|
}
|
|
@@ -320,33 +299,6 @@ export class PXEService implements PXE {
|
|
|
320
299
|
return Promise.all(extendedNotes);
|
|
321
300
|
}
|
|
322
301
|
|
|
323
|
-
public async getOutgoingNotes(filter: OutgoingNotesFilter): Promise<UniqueNote[]> {
|
|
324
|
-
const noteDaos = await this.db.getOutgoingNotes(filter);
|
|
325
|
-
|
|
326
|
-
const extendedNotes = noteDaos.map(async dao => {
|
|
327
|
-
let owner = filter.owner;
|
|
328
|
-
if (owner === undefined) {
|
|
329
|
-
const completeAddresses = (await this.db.getCompleteAddresses()).find(address =>
|
|
330
|
-
address.publicKeys.masterOutgoingViewingPublicKey.equals(dao.ovpkM),
|
|
331
|
-
);
|
|
332
|
-
if (completeAddresses === undefined) {
|
|
333
|
-
throw new Error(`Cannot find complete address for OvpkM ${dao.ovpkM.toString()}`);
|
|
334
|
-
}
|
|
335
|
-
owner = completeAddresses.address;
|
|
336
|
-
}
|
|
337
|
-
return new UniqueNote(
|
|
338
|
-
dao.note,
|
|
339
|
-
owner,
|
|
340
|
-
dao.contractAddress,
|
|
341
|
-
dao.storageSlot,
|
|
342
|
-
dao.noteTypeId,
|
|
343
|
-
dao.txHash,
|
|
344
|
-
dao.nonce,
|
|
345
|
-
);
|
|
346
|
-
});
|
|
347
|
-
return Promise.all(extendedNotes);
|
|
348
|
-
}
|
|
349
|
-
|
|
350
302
|
public async getL1ToL2MembershipWitness(
|
|
351
303
|
contractAddress: AztecAddress,
|
|
352
304
|
messageHash: Fr,
|
|
@@ -367,7 +319,7 @@ export class PXEService implements PXE {
|
|
|
367
319
|
}
|
|
368
320
|
|
|
369
321
|
for (const nonce of nonces) {
|
|
370
|
-
const { noteHash,
|
|
322
|
+
const { noteHash, uniqueNoteHash, innerNullifier } = await this.simulator.computeNoteHashAndOptionallyANullifier(
|
|
371
323
|
note.contractAddress,
|
|
372
324
|
nonce,
|
|
373
325
|
note.storageSlot,
|
|
@@ -376,7 +328,7 @@ export class PXEService implements PXE {
|
|
|
376
328
|
note.note,
|
|
377
329
|
);
|
|
378
330
|
|
|
379
|
-
const [index] = await this.node.findLeavesIndexes('latest', MerkleTreeId.NOTE_HASH_TREE, [
|
|
331
|
+
const [index] = await this.node.findLeavesIndexes('latest', MerkleTreeId.NOTE_HASH_TREE, [uniqueNoteHash]);
|
|
380
332
|
if (index === undefined) {
|
|
381
333
|
throw new Error('Note does not exist.');
|
|
382
334
|
}
|
|
@@ -416,7 +368,7 @@ export class PXEService implements PXE {
|
|
|
416
368
|
}
|
|
417
369
|
|
|
418
370
|
for (const nonce of nonces) {
|
|
419
|
-
const { noteHash,
|
|
371
|
+
const { noteHash, uniqueNoteHash, innerNullifier } = await this.simulator.computeNoteHashAndOptionallyANullifier(
|
|
420
372
|
note.contractAddress,
|
|
421
373
|
nonce,
|
|
422
374
|
note.storageSlot,
|
|
@@ -429,7 +381,7 @@ export class PXEService implements PXE {
|
|
|
429
381
|
throw new Error('Unexpectedly received non-zero nullifier.');
|
|
430
382
|
}
|
|
431
383
|
|
|
432
|
-
const [index] = await this.node.findLeavesIndexes('latest', MerkleTreeId.NOTE_HASH_TREE, [
|
|
384
|
+
const [index] = await this.node.findLeavesIndexes('latest', MerkleTreeId.NOTE_HASH_TREE, [uniqueNoteHash]);
|
|
433
385
|
if (index === undefined) {
|
|
434
386
|
throw new Error('Note does not exist.');
|
|
435
387
|
}
|
|
@@ -475,7 +427,7 @@ export class PXEService implements PXE {
|
|
|
475
427
|
}
|
|
476
428
|
|
|
477
429
|
const nonce = computeNoteHashNonce(firstNullifier, i);
|
|
478
|
-
const {
|
|
430
|
+
const { uniqueNoteHash } = await this.simulator.computeNoteHashAndOptionallyANullifier(
|
|
479
431
|
note.contractAddress,
|
|
480
432
|
nonce,
|
|
481
433
|
note.storageSlot,
|
|
@@ -483,7 +435,7 @@ export class PXEService implements PXE {
|
|
|
483
435
|
false,
|
|
484
436
|
note.note,
|
|
485
437
|
);
|
|
486
|
-
if (hash.equals(
|
|
438
|
+
if (hash.equals(uniqueNoteHash)) {
|
|
487
439
|
nonces.push(nonce);
|
|
488
440
|
}
|
|
489
441
|
}
|
|
@@ -511,22 +463,16 @@ export class PXEService implements PXE {
|
|
|
511
463
|
return result.publicInputs;
|
|
512
464
|
}
|
|
513
465
|
|
|
514
|
-
public proveTx(
|
|
466
|
+
public async proveTx(
|
|
515
467
|
txRequest: TxExecutionRequest,
|
|
516
468
|
privateExecutionResult: PrivateExecutionResult,
|
|
517
469
|
): Promise<TxProvingResult> {
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
);
|
|
525
|
-
return new TxProvingResult(privateExecutionResult, publicInputs, clientIvcProof!);
|
|
526
|
-
})
|
|
527
|
-
.catch(err => {
|
|
528
|
-
throw this.contextualizeError(err, inspect(txRequest), inspect(privateExecutionResult));
|
|
529
|
-
});
|
|
470
|
+
try {
|
|
471
|
+
const { publicInputs, clientIvcProof } = await this.#prove(txRequest, this.proofCreator, privateExecutionResult);
|
|
472
|
+
return new TxProvingResult(privateExecutionResult, publicInputs, clientIvcProof!);
|
|
473
|
+
} catch (err: any) {
|
|
474
|
+
throw this.contextualizeError(err, inspect(txRequest), inspect(privateExecutionResult));
|
|
475
|
+
}
|
|
530
476
|
}
|
|
531
477
|
|
|
532
478
|
// TODO(#7456) Prevent msgSender being defined here for the first call
|
|
@@ -538,59 +484,77 @@ export class PXEService implements PXE {
|
|
|
538
484
|
profile: boolean = false,
|
|
539
485
|
scopes?: AztecAddress[],
|
|
540
486
|
): Promise<TxSimulationResult> {
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
487
|
+
try {
|
|
488
|
+
const txInfo = {
|
|
489
|
+
origin: txRequest.origin,
|
|
490
|
+
functionSelector: txRequest.functionSelector,
|
|
491
|
+
simulatePublic,
|
|
492
|
+
msgSender,
|
|
493
|
+
chainId: txRequest.txContext.chainId,
|
|
494
|
+
version: txRequest.txContext.version,
|
|
495
|
+
authWitnesses: txRequest.authWitnesses.map(w => w.requestHash),
|
|
496
|
+
};
|
|
497
|
+
this.log.verbose(
|
|
498
|
+
`Simulating transaction execution request to ${txRequest.functionSelector} at ${txRequest.origin}`,
|
|
499
|
+
txInfo,
|
|
500
|
+
);
|
|
501
|
+
await this.synchronizer.sync();
|
|
502
|
+
const privateExecutionResult = await this.#executePrivate(txRequest, msgSender, scopes);
|
|
556
503
|
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
504
|
+
let publicInputs: PrivateKernelTailCircuitPublicInputs;
|
|
505
|
+
let profileResult;
|
|
506
|
+
if (profile) {
|
|
507
|
+
({ publicInputs, profileResult } = await this.#profileKernelProver(
|
|
508
|
+
txRequest,
|
|
509
|
+
this.proofCreator,
|
|
510
|
+
privateExecutionResult,
|
|
511
|
+
));
|
|
512
|
+
} else {
|
|
513
|
+
publicInputs = await this.#simulateKernels(txRequest, privateExecutionResult);
|
|
514
|
+
}
|
|
563
515
|
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
516
|
+
const privateSimulationResult = new PrivateSimulationResult(privateExecutionResult, publicInputs);
|
|
517
|
+
const simulatedTx = privateSimulationResult.toSimulatedTx();
|
|
518
|
+
let publicOutput: PublicSimulationOutput | undefined;
|
|
519
|
+
if (simulatePublic) {
|
|
520
|
+
publicOutput = await this.#simulatePublicCalls(simulatedTx);
|
|
521
|
+
}
|
|
569
522
|
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
// If we log, the `getTxHash` function will throw.
|
|
574
|
-
if (!msgSender) {
|
|
575
|
-
this.log.info(`Executed local simulation for ${simulatedTx.getTxHash()}`);
|
|
523
|
+
if (!skipTxValidation) {
|
|
524
|
+
if (!(await this.node.isValidTx(simulatedTx, true))) {
|
|
525
|
+
throw new Error('The simulated transaction is unable to be added to state and is invalid.');
|
|
576
526
|
}
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
`profile=${profile}`,
|
|
591
|
-
`scopes=${scopes?.map(s => s.toString()).join(', ') ?? 'undefined'}`,
|
|
592
|
-
);
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
this.log.info(`Simulation completed for ${simulatedTx.tryGetTxHash()}`, {
|
|
530
|
+
txHash: simulatedTx.tryGetTxHash(),
|
|
531
|
+
...txInfo,
|
|
532
|
+
...(profileResult ? { gateCounts: profileResult.gateCounts } : {}),
|
|
533
|
+
...(publicOutput
|
|
534
|
+
? {
|
|
535
|
+
gasUsed: publicOutput.gasUsed,
|
|
536
|
+
revertCode: publicOutput.txEffect.revertCode.getCode(),
|
|
537
|
+
revertReason: publicOutput.revertReason,
|
|
538
|
+
}
|
|
539
|
+
: {}),
|
|
593
540
|
});
|
|
541
|
+
|
|
542
|
+
return TxSimulationResult.fromPrivateSimulationResultAndPublicOutput(
|
|
543
|
+
privateSimulationResult,
|
|
544
|
+
publicOutput,
|
|
545
|
+
profileResult,
|
|
546
|
+
);
|
|
547
|
+
} catch (err: any) {
|
|
548
|
+
throw this.contextualizeError(
|
|
549
|
+
err,
|
|
550
|
+
inspect(txRequest),
|
|
551
|
+
`simulatePublic=${simulatePublic}`,
|
|
552
|
+
`msgSender=${msgSender?.toString() ?? 'undefined'}`,
|
|
553
|
+
`skipTxValidation=${skipTxValidation}`,
|
|
554
|
+
`profile=${profile}`,
|
|
555
|
+
`scopes=${scopes?.map(s => s.toString()).join(', ') ?? 'undefined'}`,
|
|
556
|
+
);
|
|
557
|
+
}
|
|
594
558
|
}
|
|
595
559
|
|
|
596
560
|
public async sendTx(tx: Tx): Promise<TxHash> {
|
|
@@ -598,7 +562,7 @@ export class PXEService implements PXE {
|
|
|
598
562
|
if (await this.node.getTxEffect(txHash)) {
|
|
599
563
|
throw new Error(`A settled tx with equal hash ${txHash.toString()} exists.`);
|
|
600
564
|
}
|
|
601
|
-
this.log.
|
|
565
|
+
this.log.debug(`Sending transaction ${txHash}`);
|
|
602
566
|
await this.node.sendTx(tx).catch(err => {
|
|
603
567
|
throw this.contextualizeError(err, inspect(tx));
|
|
604
568
|
});
|
|
@@ -613,24 +577,22 @@ export class PXEService implements PXE {
|
|
|
613
577
|
_from?: AztecAddress,
|
|
614
578
|
scopes?: AztecAddress[],
|
|
615
579
|
): Promise<AbiDecoded> {
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
.
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
);
|
|
633
|
-
});
|
|
580
|
+
try {
|
|
581
|
+
await this.synchronizer.sync();
|
|
582
|
+
// TODO - Should check if `from` has the permission to call the view function.
|
|
583
|
+
const functionCall = await this.#getFunctionCall(functionName, args, to);
|
|
584
|
+
const executionResult = await this.#simulateUnconstrained(functionCall, scopes);
|
|
585
|
+
|
|
586
|
+
// TODO - Return typed result based on the function artifact.
|
|
587
|
+
return executionResult;
|
|
588
|
+
} catch (err: any) {
|
|
589
|
+
const stringifiedArgs = args.map(arg => arg.toString()).join(', ');
|
|
590
|
+
throw this.contextualizeError(
|
|
591
|
+
err,
|
|
592
|
+
`simulateUnconstrained ${to}:${functionName}(${stringifiedArgs})`,
|
|
593
|
+
`scopes=${scopes?.map(s => s.toString()).join(', ') ?? 'undefined'}`,
|
|
594
|
+
);
|
|
595
|
+
}
|
|
634
596
|
}
|
|
635
597
|
|
|
636
598
|
public getTxReceipt(txHash: TxHash): Promise<TxReceipt> {
|
|
@@ -727,12 +689,14 @@ export class PXEService implements PXE {
|
|
|
727
689
|
}
|
|
728
690
|
|
|
729
691
|
async #registerProtocolContracts() {
|
|
692
|
+
const registered: Record<string, string> = {};
|
|
730
693
|
for (const name of protocolContractNames) {
|
|
731
694
|
const { address, contractClass, instance, artifact } = getCanonicalProtocolContract(name);
|
|
732
695
|
await this.db.addContractArtifact(contractClass.id, artifact);
|
|
733
696
|
await this.db.addContractInstance(instance);
|
|
734
|
-
|
|
697
|
+
registered[name] = address.toString();
|
|
735
698
|
}
|
|
699
|
+
this.log.verbose(`Registered protocol contracts in pxe`, registered);
|
|
736
700
|
}
|
|
737
701
|
|
|
738
702
|
/**
|
|
@@ -764,13 +728,11 @@ export class PXEService implements PXE {
|
|
|
764
728
|
scopes?: AztecAddress[],
|
|
765
729
|
): Promise<PrivateExecutionResult> {
|
|
766
730
|
// TODO - Pause syncing while simulating.
|
|
767
|
-
|
|
768
731
|
const { contractAddress, functionArtifact } = await this.#getSimulationParameters(txRequest);
|
|
769
732
|
|
|
770
|
-
this.log.debug('Executing simulator...');
|
|
771
733
|
try {
|
|
772
734
|
const result = await this.simulator.run(txRequest, functionArtifact, contractAddress, msgSender, scopes);
|
|
773
|
-
this.log.
|
|
735
|
+
this.log.debug(`Private simulation completed for ${contractAddress.toString()}:${functionArtifact.name}`);
|
|
774
736
|
return result;
|
|
775
737
|
} catch (err) {
|
|
776
738
|
if (err instanceof SimulationError) {
|
|
@@ -848,19 +810,14 @@ export class PXEService implements PXE {
|
|
|
848
810
|
}
|
|
849
811
|
|
|
850
812
|
/**
|
|
851
|
-
*
|
|
852
|
-
* The function takes in a transaction request,
|
|
853
|
-
*
|
|
854
|
-
* transaction object with the generated proof and public inputs. If a new contract address is provided,
|
|
855
|
-
* the function will also include the new contract's public functions in the transaction object.
|
|
813
|
+
* Generate a kernel proof, and create a private kernel output.
|
|
814
|
+
* The function takes in a transaction execution request, and the result of private execution
|
|
815
|
+
* and then generates a kernel proof.
|
|
856
816
|
*
|
|
857
817
|
* @param txExecutionRequest - The transaction request to be simulated and proved.
|
|
858
818
|
* @param proofCreator - The proof creator to use for proving the execution.
|
|
859
|
-
* @param
|
|
860
|
-
* @
|
|
861
|
-
* @returns An object that contains:
|
|
862
|
-
* A private transaction object containing the proof, public inputs, and encrypted logs.
|
|
863
|
-
* The return values of the private execution
|
|
819
|
+
* @param privateExecutionResult - The result of the private execution
|
|
820
|
+
* @returns An object that contains the output of the kernel execution, including the ClientIvcProof if proving is enabled.
|
|
864
821
|
*/
|
|
865
822
|
async #prove(
|
|
866
823
|
txExecutionRequest: TxExecutionRequest,
|
|
@@ -875,14 +832,6 @@ export class PXEService implements PXE {
|
|
|
875
832
|
return await kernelProver.prove(txExecutionRequest.toTxRequest(), privateExecutionResult);
|
|
876
833
|
}
|
|
877
834
|
|
|
878
|
-
public async isGlobalStateSynchronized() {
|
|
879
|
-
return await this.synchronizer.isGlobalStateSynchronized();
|
|
880
|
-
}
|
|
881
|
-
|
|
882
|
-
public getSyncStatus() {
|
|
883
|
-
return Promise.resolve(this.synchronizer.getSyncStatus());
|
|
884
|
-
}
|
|
885
|
-
|
|
886
835
|
public async isContractClassPubliclyRegistered(id: Fr): Promise<boolean> {
|
|
887
836
|
return !!(await this.node.getContractClass(id));
|
|
888
837
|
}
|
|
@@ -915,7 +864,7 @@ export class PXEService implements PXE {
|
|
|
915
864
|
|
|
916
865
|
const vsks = await Promise.all(
|
|
917
866
|
vpks.map(async vpk => {
|
|
918
|
-
const [keyPrefix, account] = this.keyStore.getKeyPrefixAndAccount(vpk);
|
|
867
|
+
const [keyPrefix, account] = await this.keyStore.getKeyPrefixAndAccount(vpk);
|
|
919
868
|
let secretKey = await this.keyStore.getMasterSecretKey(vpk);
|
|
920
869
|
if (keyPrefix === 'iv') {
|
|
921
870
|
const registeredAccount = await this.getRegisteredAccount(account);
|
|
@@ -936,7 +885,7 @@ export class PXEService implements PXE {
|
|
|
936
885
|
for (const sk of vsks) {
|
|
937
886
|
// TODO: Verify that the first field of the log is the tag siloed with contract address.
|
|
938
887
|
// Or use tags to query logs, like we do with notes.
|
|
939
|
-
const decryptedEvent = L1EventPayload.decryptAsIncoming(log, sk)
|
|
888
|
+
const decryptedEvent = L1EventPayload.decryptAsIncoming(log, sk);
|
|
940
889
|
if (decryptedEvent !== undefined) {
|
|
941
890
|
return [decryptedEvent];
|
|
942
891
|
}
|
|
@@ -1003,10 +952,15 @@ export class PXEService implements PXE {
|
|
|
1003
952
|
}
|
|
1004
953
|
|
|
1005
954
|
private contextualizeError(err: Error, ...context: string[]): Error {
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
955
|
+
let contextStr = '';
|
|
956
|
+
if (context.length > 0) {
|
|
957
|
+
contextStr = `\nContext:\n${context.join('\n')}`;
|
|
958
|
+
}
|
|
959
|
+
if (err instanceof SimulationError) {
|
|
960
|
+
err.setAztecContext(contextStr);
|
|
961
|
+
} else {
|
|
962
|
+
this.log.error(err.name, err);
|
|
963
|
+
this.log.debug(contextStr);
|
|
1010
964
|
}
|
|
1011
965
|
return err;
|
|
1012
966
|
}
|
|
@@ -115,8 +115,5 @@ export const pxeTestSuite = (testName: string, pxeSetup: () => Promise<PXE>) =>
|
|
|
115
115
|
expect(typeof nodeInfo.l1ChainId).toEqual('number');
|
|
116
116
|
expect(nodeInfo.l1ContractAddresses.rollupAddress.toString()).toMatch(/0x[a-fA-F0-9]+/);
|
|
117
117
|
});
|
|
118
|
-
|
|
119
|
-
// Note: Not testing `isGlobalStateSynchronized`, `isAccountStateSynchronized` and `getSyncStatus` as these methods
|
|
120
|
-
// only call synchronizer.
|
|
121
118
|
});
|
|
122
119
|
};
|
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';
|
|
3
|
+
import { AcirSimulator } 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';
|