@aztec/pxe 0.69.1 → 0.71.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/config/index.d.ts.map +1 -1
- package/dest/config/index.js +3 -3
- package/dest/database/kv_pxe_database.d.ts +6 -0
- package/dest/database/kv_pxe_database.d.ts.map +1 -1
- package/dest/database/kv_pxe_database.js +48 -3
- package/dest/database/note_dao.d.ts +2 -4
- package/dest/database/note_dao.d.ts.map +1 -1
- package/dest/database/note_dao.js +1 -5
- package/dest/database/outgoing_note_dao.d.ts +1 -3
- package/dest/database/outgoing_note_dao.d.ts.map +1 -1
- package/dest/database/outgoing_note_dao.js +1 -5
- package/dest/database/pxe_database.d.ts +33 -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 +121 -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/add_public_values_to_payload.js +2 -2
- 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 +16 -9
- package/dest/simulator_oracle/index.d.ts.map +1 -1
- package/dest/simulator_oracle/index.js +131 -63
- 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/config/index.ts +2 -1
- package/src/database/kv_pxe_database.ts +62 -0
- package/src/database/note_dao.ts +2 -30
- package/src/database/outgoing_note_dao.ts +1 -28
- package/src/database/pxe_database.ts +37 -0
- package/src/database/pxe_database_test_suite.ts +160 -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/add_public_values_to_payload.ts +1 -1
- 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 +224 -67
- 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/dest/note_decryption_utils/brute_force_note_info.d.ts +0 -31
- package/dest/note_decryption_utils/brute_force_note_info.d.ts.map +0 -1
- package/dest/note_decryption_utils/brute_force_note_info.js +0 -55
- package/dest/note_decryption_utils/index.d.ts +0 -3
- package/dest/note_decryption_utils/index.d.ts.map +0 -1
- package/dest/note_decryption_utils/index.js +0 -2
- package/dest/note_decryption_utils/produce_note_daos.d.ts +0 -28
- package/dest/note_decryption_utils/produce_note_daos.d.ts.map +0 -1
- package/dest/note_decryption_utils/produce_note_daos.js +0 -33
- package/dest/note_decryption_utils/produce_note_daos_for_key.d.ts +0 -8
- package/dest/note_decryption_utils/produce_note_daos_for_key.d.ts.map +0 -1
- package/dest/note_decryption_utils/produce_note_daos_for_key.js +0 -17
- package/src/kernel_prover/test/test_circuit_prover.ts +0 -122
- package/src/note_decryption_utils/brute_force_note_info.ts +0 -90
- package/src/note_decryption_utils/index.ts +0 -2
- package/src/note_decryption_utils/produce_note_daos.ts +0 -67
- package/src/note_decryption_utils/produce_note_daos_for_key.ts +0 -57
|
@@ -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
|
}
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
2
|
type AztecNode,
|
|
3
|
+
type FunctionCall,
|
|
3
4
|
type InBlock,
|
|
4
5
|
L1NotePayload,
|
|
5
6
|
type L2Block,
|
|
6
7
|
type L2BlockNumber,
|
|
7
8
|
MerkleTreeId,
|
|
9
|
+
Note,
|
|
8
10
|
type NoteStatus,
|
|
9
11
|
type NullifierMembershipWitness,
|
|
10
12
|
type PublicDataWitness,
|
|
11
|
-
|
|
13
|
+
TxHash,
|
|
12
14
|
type TxScopedL2Log,
|
|
13
15
|
getNonNullifiedL1ToL2MessageWitness,
|
|
14
16
|
} from '@aztec/circuit-types';
|
|
@@ -18,25 +20,38 @@ import {
|
|
|
18
20
|
type CompleteAddress,
|
|
19
21
|
type ContractInstance,
|
|
20
22
|
Fr,
|
|
21
|
-
|
|
23
|
+
FunctionSelector,
|
|
22
24
|
IndexedTaggingSecret,
|
|
23
25
|
type KeyValidationRequest,
|
|
24
26
|
type L1_TO_L2_MSG_TREE_HEIGHT,
|
|
27
|
+
MAX_NOTE_HASHES_PER_TX,
|
|
28
|
+
PRIVATE_LOG_SIZE_IN_FIELDS,
|
|
25
29
|
PrivateLog,
|
|
26
30
|
computeAddressSecret,
|
|
27
31
|
computeTaggingSecretPoint,
|
|
28
32
|
} from '@aztec/circuits.js';
|
|
29
|
-
import {
|
|
33
|
+
import { computeUniqueNoteHash, siloNoteHash, siloNullifier } from '@aztec/circuits.js/hash';
|
|
34
|
+
import {
|
|
35
|
+
type FunctionArtifact,
|
|
36
|
+
FunctionType,
|
|
37
|
+
NoteSelector,
|
|
38
|
+
encodeArguments,
|
|
39
|
+
getFunctionArtifact,
|
|
40
|
+
} from '@aztec/foundation/abi';
|
|
30
41
|
import { poseidon2Hash } from '@aztec/foundation/crypto';
|
|
31
42
|
import { createLogger } from '@aztec/foundation/log';
|
|
32
43
|
import { type KeyStore } from '@aztec/key-store';
|
|
33
|
-
import {
|
|
34
|
-
|
|
44
|
+
import {
|
|
45
|
+
type AcirSimulator,
|
|
46
|
+
type DBOracle,
|
|
47
|
+
MessageLoadOracleInputs,
|
|
48
|
+
type SimulationProvider,
|
|
49
|
+
} from '@aztec/simulator/client';
|
|
35
50
|
|
|
36
|
-
import {
|
|
51
|
+
import { ContractDataOracle } from '../contract_data_oracle/index.js';
|
|
37
52
|
import { type PxeDatabase } from '../database/index.js';
|
|
38
|
-
import {
|
|
39
|
-
import {
|
|
53
|
+
import { NoteDao } from '../database/note_dao.js';
|
|
54
|
+
import { getOrderedNoteItems } from '../note_decryption_utils/add_public_values_to_payload.js';
|
|
40
55
|
import { getAcirSimulator } from '../simulator/index.js';
|
|
41
56
|
import { WINDOW_HALF_SIZE, getIndexedTaggingSecretsForTheWindow, getInitialIndexesMap } from './tagging_utils.js';
|
|
42
57
|
|
|
@@ -49,6 +64,7 @@ export class SimulatorOracle implements DBOracle {
|
|
|
49
64
|
private db: PxeDatabase,
|
|
50
65
|
private keyStore: KeyStore,
|
|
51
66
|
private aztecNode: AztecNode,
|
|
67
|
+
private simulationProvider: SimulationProvider,
|
|
52
68
|
private log = createLogger('pxe:simulator_oracle'),
|
|
53
69
|
) {}
|
|
54
70
|
|
|
@@ -163,7 +179,7 @@ export class SimulatorOracle implements DBOracle {
|
|
|
163
179
|
* @returns - The index of the commitment. Undefined if it does not exist in the tree.
|
|
164
180
|
*/
|
|
165
181
|
async getCommitmentIndex(commitment: Fr) {
|
|
166
|
-
return await this
|
|
182
|
+
return await this.#findLeafIndex('latest', MerkleTreeId.NOTE_HASH_TREE, commitment);
|
|
167
183
|
}
|
|
168
184
|
|
|
169
185
|
// We need this in public as part of the EXISTS calls - but isn't used in private
|
|
@@ -172,19 +188,26 @@ export class SimulatorOracle implements DBOracle {
|
|
|
172
188
|
}
|
|
173
189
|
|
|
174
190
|
async getNullifierIndex(nullifier: Fr) {
|
|
175
|
-
return await this
|
|
191
|
+
return await this.#findLeafIndex('latest', MerkleTreeId.NULLIFIER_TREE, nullifier);
|
|
176
192
|
}
|
|
177
193
|
|
|
178
|
-
|
|
179
|
-
blockNumber: L2BlockNumber,
|
|
180
|
-
treeId: MerkleTreeId,
|
|
181
|
-
leafValue: Fr,
|
|
182
|
-
): Promise<bigint | undefined> {
|
|
194
|
+
async #findLeafIndex(blockNumber: L2BlockNumber, treeId: MerkleTreeId, leafValue: Fr): Promise<bigint | undefined> {
|
|
183
195
|
const [leafIndex] = await this.aztecNode.findLeavesIndexes(blockNumber, treeId, [leafValue]);
|
|
184
196
|
return leafIndex;
|
|
185
197
|
}
|
|
186
198
|
|
|
187
|
-
public async
|
|
199
|
+
public async getMembershipWitness(blockNumber: number, treeId: MerkleTreeId, leafValue: Fr): Promise<Fr[]> {
|
|
200
|
+
const leafIndex = await this.#findLeafIndex(blockNumber, treeId, leafValue);
|
|
201
|
+
if (!leafIndex) {
|
|
202
|
+
throw new Error(`Leaf value: ${leafValue} not found in ${MerkleTreeId[treeId]}`);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
const siblingPath = await this.#getSiblingPath(blockNumber, treeId, leafIndex);
|
|
206
|
+
|
|
207
|
+
return [new Fr(leafIndex), ...siblingPath];
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
async #getSiblingPath(blockNumber: number, treeId: MerkleTreeId, leafIndex: bigint): Promise<Fr[]> {
|
|
188
211
|
switch (treeId) {
|
|
189
212
|
case MerkleTreeId.NULLIFIER_TREE:
|
|
190
213
|
return (await this.aztecNode.getNullifierSiblingPath(blockNumber, leafIndex)).toFields();
|
|
@@ -419,6 +442,8 @@ export class SimulatorOracle implements DBOracle {
|
|
|
419
442
|
maxBlockNumber: number,
|
|
420
443
|
scopes?: AztecAddress[],
|
|
421
444
|
): Promise<Map<string, TxScopedL2Log[]>> {
|
|
445
|
+
this.log.verbose('Searching for tagged logs', { contract: contractAddress });
|
|
446
|
+
|
|
422
447
|
// Ideally this algorithm would be implemented in noir, exposing its building blocks as oracles.
|
|
423
448
|
// However it is impossible at the moment due to the language not supporting nested slices.
|
|
424
449
|
// This nesting is necessary because for a given set of tags we don't
|
|
@@ -556,10 +581,9 @@ export class SimulatorOracle implements DBOracle {
|
|
|
556
581
|
* Decrypts logs tagged for a recipient and returns them.
|
|
557
582
|
* @param scopedLogs - The logs to decrypt.
|
|
558
583
|
* @param recipient - The recipient of the logs.
|
|
559
|
-
* @param simulator - The simulator to use for decryption.
|
|
560
584
|
* @returns The decrypted notes.
|
|
561
585
|
*/
|
|
562
|
-
async #decryptTaggedLogs(scopedLogs: TxScopedL2Log[], recipient: AztecAddress
|
|
586
|
+
async #decryptTaggedLogs(scopedLogs: TxScopedL2Log[], recipient: AztecAddress) {
|
|
563
587
|
const recipientCompleteAddress = await this.getCompleteAddress(recipient);
|
|
564
588
|
const ivskM = await this.keyStore.getMasterSecretKey(
|
|
565
589
|
recipientCompleteAddress.publicKeys.masterIncomingViewingPublicKey,
|
|
@@ -569,54 +593,29 @@ export class SimulatorOracle implements DBOracle {
|
|
|
569
593
|
// Since we could have notes with the same index for different txs, we need
|
|
570
594
|
// to keep track of them scoping by txHash
|
|
571
595
|
const excludedIndices: Map<string, Set<number>> = new Map();
|
|
572
|
-
const
|
|
573
|
-
|
|
574
|
-
const txEffectsCache = new Map<string, InBlock<TxEffect> | undefined>();
|
|
596
|
+
const decrypted = [];
|
|
575
597
|
|
|
576
598
|
for (const scopedLog of scopedLogs) {
|
|
577
|
-
const
|
|
599
|
+
const payload = scopedLog.isFromPublic
|
|
578
600
|
? L1NotePayload.decryptAsIncomingFromPublic(scopedLog.logData, addressSecret)
|
|
579
601
|
: L1NotePayload.decryptAsIncoming(PrivateLog.fromBuffer(scopedLog.logData), addressSecret);
|
|
580
602
|
|
|
581
|
-
if (
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
txEffectsCache.get(scopedLog.txHash.toString()) ?? (await this.aztecNode.getTxEffect(scopedLog.txHash));
|
|
586
|
-
|
|
587
|
-
if (!txEffect) {
|
|
588
|
-
this.log.warn(`No tx effect found for ${scopedLog.txHash} while decrypting tagged logs`);
|
|
589
|
-
continue;
|
|
590
|
-
}
|
|
603
|
+
if (!payload) {
|
|
604
|
+
this.log.verbose('Unable to decrypt log');
|
|
605
|
+
continue;
|
|
606
|
+
}
|
|
591
607
|
|
|
592
|
-
|
|
608
|
+
if (!excludedIndices.has(scopedLog.txHash.toString())) {
|
|
609
|
+
excludedIndices.set(scopedLog.txHash.toString(), new Set());
|
|
610
|
+
}
|
|
593
611
|
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
}
|
|
597
|
-
const { note } = await produceNoteDaos(
|
|
598
|
-
// I don't like this at all, but we need a simulator to run `computeNoteHashAndOptionallyANullifier`. This generates
|
|
599
|
-
// 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
|
-
// 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 ?? getAcirSimulator(this.db, this.aztecNode, this.keyStore, this.contractDataOracle),
|
|
602
|
-
this.db,
|
|
603
|
-
notePayload ? recipient.toAddressPoint() : undefined,
|
|
604
|
-
payload!,
|
|
605
|
-
txEffect.data.txHash,
|
|
606
|
-
txEffect.l2BlockNumber,
|
|
607
|
-
txEffect.l2BlockHash,
|
|
608
|
-
txEffect.data.noteHashes,
|
|
609
|
-
scopedLog.dataStartIndexForTx,
|
|
610
|
-
excludedIndices.get(scopedLog.txHash.toString())!,
|
|
611
|
-
this.log,
|
|
612
|
-
);
|
|
612
|
+
const note = await getOrderedNoteItems(this.db, payload);
|
|
613
|
+
const plaintext = [payload.storageSlot, payload.noteTypeId.toField(), ...note.items];
|
|
613
614
|
|
|
614
|
-
|
|
615
|
-
notes.push(note);
|
|
616
|
-
}
|
|
617
|
-
}
|
|
615
|
+
decrypted.push({ plaintext, txHash: scopedLog.txHash, contractAddress: payload.contractAddress });
|
|
618
616
|
}
|
|
619
|
-
|
|
617
|
+
|
|
618
|
+
return decrypted;
|
|
620
619
|
}
|
|
621
620
|
|
|
622
621
|
/**
|
|
@@ -629,20 +628,68 @@ export class SimulatorOracle implements DBOracle {
|
|
|
629
628
|
recipient: AztecAddress,
|
|
630
629
|
simulator?: AcirSimulator,
|
|
631
630
|
): Promise<void> {
|
|
632
|
-
const
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
631
|
+
const decryptedLogs = await this.#decryptTaggedLogs(logs, recipient);
|
|
632
|
+
|
|
633
|
+
// We've produced the full NoteDao, which we'd be able to simply insert into the database. However, this is
|
|
634
|
+
// only a temporary measure as we migrate from the PXE-driven discovery into the new contract-driven approach. We
|
|
635
|
+
// discard most of the work done up to this point and reconstruct the note plaintext to then hand over to the
|
|
636
|
+
// contract for further processing.
|
|
637
|
+
for (const decryptedLog of decryptedLogs) {
|
|
638
|
+
// Log processing requires the note hashes in the tx in which the note was created. We are now assuming that the
|
|
639
|
+
// note was included in the same block in which the log was delivered - note that partial notes will not work this
|
|
640
|
+
// way.
|
|
641
|
+
const txEffect = await this.aztecNode.getTxEffect(decryptedLog.txHash);
|
|
642
|
+
if (!txEffect) {
|
|
643
|
+
throw new Error(`Could not find tx effect for tx hash ${decryptedLog.txHash}`);
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
// This will trigger calls to the deliverNote oracle
|
|
647
|
+
await this.callProcessLog(
|
|
648
|
+
decryptedLog.contractAddress,
|
|
649
|
+
decryptedLog.plaintext,
|
|
650
|
+
decryptedLog.txHash,
|
|
651
|
+
txEffect.data.noteHashes,
|
|
652
|
+
txEffect.data.nullifiers[0],
|
|
653
|
+
recipient,
|
|
654
|
+
simulator,
|
|
655
|
+
);
|
|
642
656
|
}
|
|
657
|
+
return;
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
// Called when notes are delivered, usually as a result to a call to the process_log contract function
|
|
661
|
+
public async deliverNote(
|
|
662
|
+
contractAddress: AztecAddress,
|
|
663
|
+
storageSlot: Fr,
|
|
664
|
+
nonce: Fr,
|
|
665
|
+
content: Fr[],
|
|
666
|
+
noteHash: Fr,
|
|
667
|
+
nullifier: Fr,
|
|
668
|
+
txHash: Fr,
|
|
669
|
+
recipient: AztecAddress,
|
|
670
|
+
): Promise<void> {
|
|
671
|
+
const noteDao = await this.produceNoteDao(
|
|
672
|
+
contractAddress,
|
|
673
|
+
storageSlot,
|
|
674
|
+
nonce,
|
|
675
|
+
content,
|
|
676
|
+
noteHash,
|
|
677
|
+
nullifier,
|
|
678
|
+
txHash,
|
|
679
|
+
recipient,
|
|
680
|
+
);
|
|
681
|
+
|
|
682
|
+
await this.db.addNotes([noteDao], recipient);
|
|
683
|
+
this.log.verbose('Added note', {
|
|
684
|
+
contract: noteDao.contractAddress,
|
|
685
|
+
slot: noteDao.storageSlot,
|
|
686
|
+
nullifier: noteDao.siloedNullifier.toString,
|
|
687
|
+
});
|
|
643
688
|
}
|
|
644
689
|
|
|
645
690
|
public async removeNullifiedNotes(contractAddress: AztecAddress) {
|
|
691
|
+
this.log.verbose('Removing nullified notes', { contract: contractAddress });
|
|
692
|
+
|
|
646
693
|
for (const recipient of await this.keyStore.getAccounts()) {
|
|
647
694
|
const currentNotesForRecipient = await this.db.getNotes({ contractAddress, owner: recipient });
|
|
648
695
|
const nullifiersToCheck = currentNotesForRecipient.map(note => note.siloedNullifier);
|
|
@@ -666,4 +713,114 @@ export class SimulatorOracle implements DBOracle {
|
|
|
666
713
|
});
|
|
667
714
|
}
|
|
668
715
|
}
|
|
716
|
+
|
|
717
|
+
async produceNoteDao(
|
|
718
|
+
contractAddress: AztecAddress,
|
|
719
|
+
storageSlot: Fr,
|
|
720
|
+
nonce: Fr,
|
|
721
|
+
content: Fr[],
|
|
722
|
+
noteHash: Fr,
|
|
723
|
+
nullifier: Fr,
|
|
724
|
+
txHash: Fr,
|
|
725
|
+
recipient: AztecAddress,
|
|
726
|
+
): Promise<NoteDao> {
|
|
727
|
+
const receipt = await this.aztecNode.getTxReceipt(new TxHash(txHash));
|
|
728
|
+
if (receipt === undefined) {
|
|
729
|
+
throw new Error(`Failed to fetch tx receipt for tx hash ${txHash} when searching for note hashes`);
|
|
730
|
+
}
|
|
731
|
+
const { blockNumber, blockHash } = receipt;
|
|
732
|
+
|
|
733
|
+
const uniqueNoteHash = computeUniqueNoteHash(nonce, siloNoteHash(contractAddress, noteHash));
|
|
734
|
+
const siloedNullifier = siloNullifier(contractAddress, nullifier);
|
|
735
|
+
|
|
736
|
+
const uniqueNoteHashTreeIndex = (
|
|
737
|
+
await this.aztecNode.findLeavesIndexes(blockNumber!, MerkleTreeId.NOTE_HASH_TREE, [uniqueNoteHash])
|
|
738
|
+
)[0];
|
|
739
|
+
if (uniqueNoteHashTreeIndex === undefined) {
|
|
740
|
+
throw new Error(
|
|
741
|
+
`Note hash ${noteHash} (uniqued as ${uniqueNoteHash}) is not present on the tree at block ${blockNumber} (from tx ${txHash})`,
|
|
742
|
+
);
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
return new NoteDao(
|
|
746
|
+
new Note(content),
|
|
747
|
+
contractAddress,
|
|
748
|
+
storageSlot,
|
|
749
|
+
nonce,
|
|
750
|
+
noteHash,
|
|
751
|
+
siloedNullifier,
|
|
752
|
+
new TxHash(txHash),
|
|
753
|
+
blockNumber!,
|
|
754
|
+
blockHash!.toString(),
|
|
755
|
+
uniqueNoteHashTreeIndex,
|
|
756
|
+
recipient.toAddressPoint(),
|
|
757
|
+
NoteSelector.empty(), // todo: remove
|
|
758
|
+
);
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
async callProcessLog(
|
|
762
|
+
contractAddress: AztecAddress,
|
|
763
|
+
logPlaintext: Fr[],
|
|
764
|
+
txHash: TxHash,
|
|
765
|
+
noteHashes: Fr[],
|
|
766
|
+
firstNullifier: Fr,
|
|
767
|
+
recipient: AztecAddress,
|
|
768
|
+
simulator?: AcirSimulator,
|
|
769
|
+
) {
|
|
770
|
+
const artifact: FunctionArtifact | undefined = await new ContractDataOracle(this.db).getFunctionArtifactByName(
|
|
771
|
+
contractAddress,
|
|
772
|
+
'process_log',
|
|
773
|
+
);
|
|
774
|
+
if (!artifact) {
|
|
775
|
+
throw new Error(
|
|
776
|
+
`Mandatory implementation of "process_log" missing in noir contract ${contractAddress.toString()}.`,
|
|
777
|
+
);
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
const execRequest: FunctionCall = {
|
|
781
|
+
name: artifact.name,
|
|
782
|
+
to: contractAddress,
|
|
783
|
+
selector: FunctionSelector.fromNameAndParameters(artifact),
|
|
784
|
+
type: FunctionType.UNCONSTRAINED,
|
|
785
|
+
isStatic: artifact.isStatic,
|
|
786
|
+
args: encodeArguments(artifact, [
|
|
787
|
+
toBoundedVec(logPlaintext, PRIVATE_LOG_SIZE_IN_FIELDS),
|
|
788
|
+
txHash.toString(),
|
|
789
|
+
toBoundedVec(noteHashes, MAX_NOTE_HASHES_PER_TX),
|
|
790
|
+
firstNullifier,
|
|
791
|
+
recipient,
|
|
792
|
+
]),
|
|
793
|
+
returnTypes: artifact.returnTypes,
|
|
794
|
+
};
|
|
795
|
+
|
|
796
|
+
await (
|
|
797
|
+
simulator ??
|
|
798
|
+
getAcirSimulator(this.db, this.aztecNode, this.keyStore, this.simulationProvider, this.contractDataOracle)
|
|
799
|
+
).runUnconstrained(
|
|
800
|
+
execRequest,
|
|
801
|
+
artifact,
|
|
802
|
+
contractAddress,
|
|
803
|
+
[], // empty scope as this call should not require access to private information
|
|
804
|
+
);
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
dbStore(contractAddress: AztecAddress, slot: Fr, values: Fr[]): Promise<void> {
|
|
808
|
+
return this.db.dbStore(contractAddress, slot, values);
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
dbLoad(contractAddress: AztecAddress, slot: Fr): Promise<Fr[] | null> {
|
|
812
|
+
return this.db.dbLoad(contractAddress, slot);
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
dbDelete(contractAddress: AztecAddress, slot: Fr): Promise<void> {
|
|
816
|
+
return this.db.dbDelete(contractAddress, slot);
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
dbCopy(contractAddress: AztecAddress, srcSlot: Fr, dstSlot: Fr, numEntries: number): Promise<void> {
|
|
820
|
+
return this.db.dbCopy(contractAddress, srcSlot, dstSlot, numEntries);
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
function toBoundedVec(array: Fr[], maxLength: number) {
|
|
825
|
+
return { storage: array.concat(Array(maxLength - array.length).fill(new Fr(0))), len: array.length };
|
|
669
826
|
}
|
|
@@ -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"}
|