@aztec/pxe 0.75.0-commit.c03ba01a2a4122e43e90d5133ba017e54b90e9d2 → 0.75.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.d.ts +3 -0
- package/dest/bin/index.d.ts.map +1 -0
- package/dest/bin/index.js +5 -3
- package/dest/config/index.d.ts +46 -0
- package/dest/config/index.d.ts.map +1 -0
- package/dest/config/index.js +21 -18
- 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 +2 -4
- package/dest/contract_data_oracle/index.d.ts +104 -0
- package/dest/contract_data_oracle/index.d.ts.map +1 -0
- package/dest/contract_data_oracle/index.js +79 -69
- package/dest/contract_data_oracle/private_functions_tree.d.ts +65 -0
- package/dest/contract_data_oracle/private_functions_tree.d.ts.map +1 -0
- package/dest/contract_data_oracle/private_functions_tree.js +50 -44
- package/dest/database/contracts/contract_artifact_db.d.ts +20 -0
- package/dest/database/contracts/contract_artifact_db.d.ts.map +1 -0
- package/dest/database/contracts/contract_artifact_db.js +2 -3
- package/dest/database/contracts/contract_instance_db.d.ts +19 -0
- package/dest/database/contracts/contract_instance_db.d.ts.map +1 -0
- package/dest/database/contracts/contract_instance_db.js +2 -3
- package/dest/database/index.d.ts +3 -0
- package/dest/database/index.d.ts.map +1 -0
- package/dest/database/index.js +1 -0
- package/dest/database/kv_pxe_database.d.ts +55 -0
- package/dest/database/kv_pxe_database.d.ts.map +1 -0
- package/dest/database/kv_pxe_database.js +259 -243
- package/dest/database/note_dao.d.ts +103 -0
- package/dest/database/note_dao.d.ts.map +1 -0
- package/dest/database/note_dao.js +43 -28
- package/dest/database/outgoing_note_dao.d.ts +73 -0
- package/dest/database/outgoing_note_dao.d.ts.map +1 -0
- package/dest/database/outgoing_note_dao.js +34 -20
- package/dest/database/pxe_database.d.ts +216 -0
- package/dest/database/pxe_database.d.ts.map +1 -0
- package/dest/database/pxe_database.js +2 -4
- package/dest/database/pxe_database_test_suite.d.ts +7 -0
- package/dest/database/pxe_database_test_suite.d.ts.map +1 -0
- package/dest/database/pxe_database_test_suite.js +151 -296
- package/dest/index.d.ts +15 -0
- package/dest/index.d.ts.map +1 -0
- package/dest/index.js +1 -0
- package/dest/kernel_oracle/index.d.ts +34 -0
- package/dest/kernel_oracle/index.d.ts.map +1 -0
- package/dest/kernel_oracle/index.js +6 -9
- package/dest/kernel_prover/hints/build_private_kernel_reset_private_inputs.d.ts +28 -0
- package/dest/kernel_prover/hints/build_private_kernel_reset_private_inputs.d.ts.map +1 -0
- package/dest/kernel_prover/hints/build_private_kernel_reset_private_inputs.js +66 -68
- package/dest/kernel_prover/hints/index.d.ts +2 -0
- package/dest/kernel_prover/hints/index.d.ts.map +1 -0
- package/dest/kernel_prover/hints/index.js +1 -0
- package/dest/kernel_prover/index.d.ts +3 -0
- package/dest/kernel_prover/index.d.ts.map +1 -0
- package/dest/kernel_prover/index.js +1 -0
- package/dest/kernel_prover/kernel_prover.d.ts +38 -0
- package/dest/kernel_prover/kernel_prover.d.ts.map +1 -0
- package/dest/kernel_prover/kernel_prover.js +65 -60
- package/dest/kernel_prover/proving_data_oracle.d.ts +65 -0
- package/dest/kernel_prover/proving_data_oracle.d.ts.map +1 -0
- package/dest/kernel_prover/proving_data_oracle.js +2 -4
- package/dest/note_decryption_utils/add_public_values_to_payload.d.ts +10 -0
- package/dest/note_decryption_utils/add_public_values_to_payload.d.ts.map +1 -0
- package/dest/note_decryption_utils/add_public_values_to_payload.js +9 -8
- package/dest/pxe_http/index.d.ts +2 -0
- package/dest/pxe_http/index.d.ts.map +1 -0
- package/dest/pxe_http/index.js +1 -0
- package/dest/pxe_http/pxe_http_server.d.ts +16 -0
- package/dest/pxe_http/pxe_http_server.d.ts.map +1 -0
- package/dest/pxe_http/pxe_http_server.js +6 -8
- package/dest/pxe_service/error_enriching.d.ts +11 -0
- package/dest/pxe_service/error_enriching.d.ts.map +1 -0
- package/dest/pxe_service/error_enriching.js +13 -10
- package/dest/pxe_service/index.d.ts +4 -0
- package/dest/pxe_service/index.d.ts.map +1 -0
- package/dest/pxe_service/index.js +1 -0
- package/dest/pxe_service/pxe_service.d.ts +98 -0
- package/dest/pxe_service/pxe_service.d.ts.map +1 -0
- package/dest/pxe_service/pxe_service.js +290 -282
- package/dest/pxe_service/test/pxe_test_suite.d.ts +3 -0
- package/dest/pxe_service/test/pxe_test_suite.d.ts.map +1 -0
- package/dest/pxe_service/test/pxe_test_suite.js +27 -40
- package/dest/simulator/index.d.ts +10 -0
- package/dest/simulator/index.d.ts.map +1 -0
- package/dest/simulator/index.js +3 -1
- package/dest/simulator_oracle/index.d.ts +129 -0
- package/dest/simulator_oracle/index.d.ts.map +1 -0
- package/dest/simulator_oracle/index.js +231 -266
- package/dest/simulator_oracle/tagging_utils.d.ts +16 -0
- package/dest/simulator_oracle/tagging_utils.d.ts.map +1 -0
- package/dest/simulator_oracle/tagging_utils.js +6 -4
- package/dest/synchronizer/index.d.ts +2 -0
- package/dest/synchronizer/index.d.ts.map +1 -0
- package/dest/synchronizer/index.js +1 -0
- package/dest/synchronizer/synchronizer.d.ts +30 -0
- package/dest/synchronizer/synchronizer.d.ts.map +1 -0
- package/dest/synchronizer/synchronizer.js +42 -42
- package/dest/utils/create_pxe_service.d.ts +16 -0
- package/dest/utils/create_pxe_service.d.ts.map +1 -0
- package/dest/utils/create_pxe_service.js +9 -9
- package/package.json +15 -15
- package/src/pxe_service/pxe_service.ts +10 -5
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
1
|
+
var _PXEService_instances, _PXEService_getNoteNonces, _PXEService_getFunctionCall, _PXEService_registerProtocolContracts, _PXEService_getSimulationParameters, _PXEService_executePrivate, _PXEService_simulateUnconstrained, _PXEService_simulatePublicCalls, _PXEService_prove, _PXEService_isContractClassPubliclyRegistered, _PXEService_isContractPubliclyDeployed, _PXEService_isContractInitialized;
|
|
2
|
+
import { __classPrivateFieldGet } from "tslib";
|
|
3
|
+
import { EventMetadata, L1EventPayload, MerkleTreeId, PrivateSimulationResult, SimulationError, TxProvingResult, TxSimulationResult, UniqueNote, getNonNullifiedL1ToL2MessageWitness, } from '@aztec/circuit-types';
|
|
4
|
+
import { computeContractAddressFromInstance, computeContractClassId, getContractClassFromArtifact, } from '@aztec/circuits.js/contract';
|
|
3
5
|
import { computeNoteHashNonce, siloNullifier } from '@aztec/circuits.js/hash';
|
|
4
6
|
import { computeAddressSecret } from '@aztec/circuits.js/keys';
|
|
5
|
-
import { EventSelector, FunctionSelector, FunctionType, decodeFunctionSignature, encodeArguments } from '@aztec/foundation/abi';
|
|
7
|
+
import { EventSelector, FunctionSelector, FunctionType, decodeFunctionSignature, encodeArguments, } from '@aztec/foundation/abi';
|
|
6
8
|
import { Fr } from '@aztec/foundation/fields';
|
|
7
9
|
import { createLogger } from '@aztec/foundation/log';
|
|
8
10
|
import { Timer } from '@aztec/foundation/timer';
|
|
@@ -19,25 +21,19 @@ import { Synchronizer } from '../synchronizer/index.js';
|
|
|
19
21
|
import { enrichPublicSimulationError, enrichSimulationError } from './error_enriching.js';
|
|
20
22
|
/**
|
|
21
23
|
* A Private eXecution Environment (PXE) implementation.
|
|
22
|
-
*/
|
|
23
|
-
|
|
24
|
-
node
|
|
25
|
-
|
|
26
|
-
proofCreator;
|
|
27
|
-
simulationProvider;
|
|
28
|
-
synchronizer;
|
|
29
|
-
contractDataOracle;
|
|
30
|
-
simulator;
|
|
31
|
-
log;
|
|
32
|
-
packageVersion;
|
|
33
|
-
proverEnabled;
|
|
34
|
-
constructor(keyStore, node, db, tipsStore, proofCreator, simulationProvider, config, loggerOrSuffix){
|
|
24
|
+
*/
|
|
25
|
+
export class PXEService {
|
|
26
|
+
constructor(keyStore, node, db, tipsStore, proofCreator, simulationProvider, config, loggerOrSuffix) {
|
|
27
|
+
_PXEService_instances.add(this);
|
|
35
28
|
this.keyStore = keyStore;
|
|
36
29
|
this.node = node;
|
|
37
30
|
this.db = db;
|
|
38
31
|
this.proofCreator = proofCreator;
|
|
39
32
|
this.simulationProvider = simulationProvider;
|
|
40
|
-
this.log =
|
|
33
|
+
this.log =
|
|
34
|
+
!loggerOrSuffix || typeof loggerOrSuffix === 'string'
|
|
35
|
+
? createLogger(loggerOrSuffix ? `pxe:service:${loggerOrSuffix}` : `pxe:service`)
|
|
36
|
+
: loggerOrSuffix;
|
|
41
37
|
this.synchronizer = new Synchronizer(node, db, tipsStore, config, loggerOrSuffix);
|
|
42
38
|
this.contractDataOracle = new ContractDataOracle(db);
|
|
43
39
|
this.simulator = getAcirSimulator(db, node, keyStore, this.simulationProvider, this.contractDataOracle);
|
|
@@ -45,18 +41,20 @@ import { enrichPublicSimulationError, enrichSimulationError } from './error_enri
|
|
|
45
41
|
this.proverEnabled = !!config.proverEnabled;
|
|
46
42
|
}
|
|
47
43
|
/**
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
44
|
+
* Starts the PXE Service by beginning the synchronization process between the Aztec node and the database.
|
|
45
|
+
*
|
|
46
|
+
* @returns A promise that resolves when the server has started successfully.
|
|
47
|
+
*/
|
|
48
|
+
async init() {
|
|
49
|
+
await __classPrivateFieldGet(this, _PXEService_instances, "m", _PXEService_registerProtocolContracts).call(this);
|
|
53
50
|
const info = await this.getNodeInfo();
|
|
54
51
|
this.log.info(`Started PXE connected to chain ${info.l1ChainId} version ${info.protocolVersion}`);
|
|
55
52
|
}
|
|
56
53
|
isL1ToL2MessageSynced(l1ToL2Message) {
|
|
57
54
|
return this.node.isL1ToL2MessageSynced(l1ToL2Message);
|
|
58
55
|
}
|
|
59
|
-
/** Returns an estimate of the db size in bytes. */
|
|
56
|
+
/** Returns an estimate of the db size in bytes. */
|
|
57
|
+
estimateDbSize() {
|
|
60
58
|
return this.db.estimateSize();
|
|
61
59
|
}
|
|
62
60
|
addAuthWitness(witness) {
|
|
@@ -74,16 +72,16 @@ import { enrichPublicSimulationError, enrichSimulationError } from './error_enri
|
|
|
74
72
|
async getContractClassMetadata(id, includeArtifact = false) {
|
|
75
73
|
const artifact = await this.db.getContractArtifact(id);
|
|
76
74
|
return {
|
|
77
|
-
contractClass: artifact && await getContractClassFromArtifact(artifact),
|
|
78
|
-
isContractClassPubliclyRegistered: await this
|
|
79
|
-
artifact: includeArtifact ? artifact : undefined
|
|
75
|
+
contractClass: artifact && (await getContractClassFromArtifact(artifact)),
|
|
76
|
+
isContractClassPubliclyRegistered: await __classPrivateFieldGet(this, _PXEService_instances, "m", _PXEService_isContractClassPubliclyRegistered).call(this, id),
|
|
77
|
+
artifact: includeArtifact ? artifact : undefined,
|
|
80
78
|
};
|
|
81
79
|
}
|
|
82
80
|
async getContractMetadata(address) {
|
|
83
81
|
return {
|
|
84
82
|
contractInstance: await this.db.getContractInstance(address),
|
|
85
|
-
isContractInitialized: await this
|
|
86
|
-
isContractPubliclyDeployed: await this
|
|
83
|
+
isContractInitialized: await __classPrivateFieldGet(this, _PXEService_instances, "m", _PXEService_isContractInitialized).call(this, address),
|
|
84
|
+
isContractPubliclyDeployed: await __classPrivateFieldGet(this, _PXEService_instances, "m", _PXEService_isContractPubliclyDeployed).call(this, address),
|
|
87
85
|
};
|
|
88
86
|
}
|
|
89
87
|
async registerAccount(secretKey, partialAddress) {
|
|
@@ -92,7 +90,8 @@ import { enrichPublicSimulationError, enrichSimulationError } from './error_enri
|
|
|
92
90
|
if (accounts.includes(accountCompleteAddress.address)) {
|
|
93
91
|
this.log.info(`Account:\n "${accountCompleteAddress.address.toString()}"\n already registered.`);
|
|
94
92
|
return accountCompleteAddress;
|
|
95
|
-
}
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
96
95
|
this.log.info(`Registered account ${accountCompleteAddress.address.toString()}`);
|
|
97
96
|
this.log.debug(`Registered account\n ${accountCompleteAddress.toReadableString()}`);
|
|
98
97
|
}
|
|
@@ -108,7 +107,8 @@ import { enrichPublicSimulationError, enrichSimulationError } from './error_enri
|
|
|
108
107
|
const wasAdded = await this.db.addSenderAddress(address);
|
|
109
108
|
if (wasAdded) {
|
|
110
109
|
this.log.info(`Added sender:\n ${address.toString()}`);
|
|
111
|
-
}
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
112
|
this.log.info(`Sender:\n "${address.toString()}"\n already registered.`);
|
|
113
113
|
}
|
|
114
114
|
return address;
|
|
@@ -121,7 +121,8 @@ import { enrichPublicSimulationError, enrichSimulationError } from './error_enri
|
|
|
121
121
|
const wasRemoved = await this.db.removeSenderAddress(address);
|
|
122
122
|
if (wasRemoved) {
|
|
123
123
|
this.log.info(`Removed sender:\n ${address.toString()}`);
|
|
124
|
-
}
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
125
126
|
this.log.info(`Sender:\n "${address.toString()}"\n not in address book.`);
|
|
126
127
|
}
|
|
127
128
|
return Promise.resolve();
|
|
@@ -131,10 +132,10 @@ import { enrichPublicSimulationError, enrichSimulationError } from './error_enri
|
|
|
131
132
|
const completeAddresses = await this.db.getCompleteAddresses();
|
|
132
133
|
// Filter out the addresses not corresponding to accounts
|
|
133
134
|
const accounts = await this.keyStore.getAccounts();
|
|
134
|
-
return completeAddresses.filter(
|
|
135
|
+
return completeAddresses.filter(completeAddress => accounts.find(address => address.equals(completeAddress.address)));
|
|
135
136
|
}
|
|
136
137
|
async registerContractClass(artifact) {
|
|
137
|
-
const
|
|
138
|
+
const contractClassId = await computeContractClassId(await getContractClassFromArtifact(artifact));
|
|
138
139
|
await this.db.addContractArtifact(contractClassId, artifact);
|
|
139
140
|
this.log.info(`Added contract class ${artifact.name} with id ${contractClassId}`);
|
|
140
141
|
}
|
|
@@ -144,23 +145,23 @@ import { enrichPublicSimulationError, enrichSimulationError } from './error_enri
|
|
|
144
145
|
if (artifact) {
|
|
145
146
|
// If the user provides an artifact, validate it against the expected class id and register it
|
|
146
147
|
const contractClass = await getContractClassFromArtifact(artifact);
|
|
147
|
-
|
|
148
|
-
|
|
148
|
+
const contractClassId = await computeContractClassId(contractClass);
|
|
149
|
+
if (!contractClassId.equals(instance.contractClassId)) {
|
|
150
|
+
throw new Error(`Artifact does not match expected class id (computed ${contractClassId} but instance refers to ${instance.contractClassId})`);
|
|
149
151
|
}
|
|
150
152
|
const computedAddress = await computeContractAddressFromInstance(instance);
|
|
151
153
|
if (!computedAddress.equals(instance.address)) {
|
|
152
154
|
throw new Error('Added a contract in which the address does not match the contract instance.');
|
|
153
155
|
}
|
|
154
|
-
await this.db.addContractArtifact(
|
|
155
|
-
const publicFunctionSignatures = artifact.functions
|
|
156
|
+
await this.db.addContractArtifact(contractClassId, artifact);
|
|
157
|
+
const publicFunctionSignatures = artifact.functions
|
|
158
|
+
.filter(fn => fn.functionType === FunctionType.PUBLIC)
|
|
159
|
+
.map(fn => decodeFunctionSignature(fn.name, fn.parameters));
|
|
156
160
|
await this.node.registerContractFunctionSignatures(instance.address, publicFunctionSignatures);
|
|
157
161
|
// TODO(#10007): Node should get public contract class from the registration event, not from PXE registration
|
|
158
|
-
await this.node.addContractClass({
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
unconstrainedFunctions: []
|
|
162
|
-
});
|
|
163
|
-
} else {
|
|
162
|
+
await this.node.addContractClass({ ...contractClass, privateFunctions: [], unconstrainedFunctions: [] });
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
164
165
|
// Otherwise, make sure there is an artifact already registered for that class id
|
|
165
166
|
artifact = await this.db.getContractArtifact(instance.contractClassId);
|
|
166
167
|
if (!artifact) {
|
|
@@ -174,18 +175,18 @@ import { enrichPublicSimulationError, enrichSimulationError } from './error_enri
|
|
|
174
175
|
return this.db.getContractsAddresses();
|
|
175
176
|
}
|
|
176
177
|
async getPublicStorageAt(contract, slot) {
|
|
177
|
-
if (!await this.getContractInstance(contract)) {
|
|
178
|
+
if (!(await this.getContractInstance(contract))) {
|
|
178
179
|
throw new Error(`Contract ${contract.toString()} is not deployed`);
|
|
179
180
|
}
|
|
180
181
|
return await this.node.getPublicStorageAt(contract, slot, 'latest');
|
|
181
182
|
}
|
|
182
183
|
async getNotes(filter) {
|
|
183
184
|
const noteDaos = await this.db.getNotes(filter);
|
|
184
|
-
const extendedNotes = noteDaos.map(async (dao)=>{
|
|
185
|
+
const extendedNotes = noteDaos.map(async (dao) => {
|
|
185
186
|
let owner = filter.owner;
|
|
186
187
|
if (owner === undefined) {
|
|
187
188
|
const completeAddresses = await this.db.getCompleteAddresses();
|
|
188
|
-
const completeAddressIndex = (await Promise.all(completeAddresses.map(
|
|
189
|
+
const completeAddressIndex = (await Promise.all(completeAddresses.map(completeAddresses => completeAddresses.address.toAddressPoint()))).findIndex(addressPoint => addressPoint.equals(dao.addressPoint));
|
|
189
190
|
const completeAddress = completeAddresses[completeAddressIndex];
|
|
190
191
|
if (completeAddress === undefined) {
|
|
191
192
|
throw new Error(`Cannot find complete address for addressPoint ${dao.addressPoint.toString()}`);
|
|
@@ -207,21 +208,19 @@ import { enrichPublicSimulationError, enrichSimulationError } from './error_enri
|
|
|
207
208
|
if (!owner) {
|
|
208
209
|
throw new Error(`Unknown account: ${note.owner.toString()}`);
|
|
209
210
|
}
|
|
210
|
-
const { data: nonces, l2BlockNumber, l2BlockHash } = await this
|
|
211
|
+
const { data: nonces, l2BlockNumber, l2BlockHash } = await __classPrivateFieldGet(this, _PXEService_instances, "m", _PXEService_getNoteNonces).call(this, note);
|
|
211
212
|
if (nonces.length === 0) {
|
|
212
213
|
throw new Error(`Cannot find the note in tx: ${note.txHash}.`);
|
|
213
214
|
}
|
|
214
|
-
for (const nonce of nonces){
|
|
215
|
+
for (const nonce of nonces) {
|
|
215
216
|
const { noteHash, uniqueNoteHash, innerNullifier } = await this.simulator.computeNoteHashAndOptionallyANullifier(note.contractAddress, nonce, note.storageSlot, note.noteTypeId, true, note.note);
|
|
216
|
-
const [index] = await this.node.findLeavesIndexes('latest', MerkleTreeId.NOTE_HASH_TREE, [
|
|
217
|
-
uniqueNoteHash
|
|
218
|
-
]);
|
|
217
|
+
const [index] = await this.node.findLeavesIndexes('latest', MerkleTreeId.NOTE_HASH_TREE, [uniqueNoteHash]);
|
|
219
218
|
if (index === undefined) {
|
|
220
219
|
throw new Error('Note does not exist.');
|
|
221
220
|
}
|
|
222
221
|
const siloedNullifier = await siloNullifier(note.contractAddress, innerNullifier);
|
|
223
222
|
const [nullifierIndex] = await this.node.findLeavesIndexes('latest', MerkleTreeId.NULLIFIER_TREE, [
|
|
224
|
-
siloedNullifier
|
|
223
|
+
siloedNullifier,
|
|
225
224
|
]);
|
|
226
225
|
if (nullifierIndex !== undefined) {
|
|
227
226
|
throw new Error('The note has been destroyed.');
|
|
@@ -230,54 +229,23 @@ import { enrichPublicSimulationError, enrichSimulationError } from './error_enri
|
|
|
230
229
|
}
|
|
231
230
|
}
|
|
232
231
|
async addNullifiedNote(note) {
|
|
233
|
-
const { data: nonces, l2BlockHash, l2BlockNumber } = await this
|
|
232
|
+
const { data: nonces, l2BlockHash, l2BlockNumber } = await __classPrivateFieldGet(this, _PXEService_instances, "m", _PXEService_getNoteNonces).call(this, note);
|
|
234
233
|
if (nonces.length === 0) {
|
|
235
234
|
throw new Error(`Cannot find the note in tx: ${note.txHash}.`);
|
|
236
235
|
}
|
|
237
|
-
for (const nonce of nonces){
|
|
236
|
+
for (const nonce of nonces) {
|
|
238
237
|
const { noteHash, uniqueNoteHash, innerNullifier } = await this.simulator.computeNoteHashAndOptionallyANullifier(note.contractAddress, nonce, note.storageSlot, note.noteTypeId, false, note.note);
|
|
239
238
|
if (!innerNullifier.equals(Fr.ZERO)) {
|
|
240
239
|
throw new Error('Unexpectedly received non-zero nullifier.');
|
|
241
240
|
}
|
|
242
|
-
const [index] = await this.node.findLeavesIndexes('latest', MerkleTreeId.NOTE_HASH_TREE, [
|
|
243
|
-
uniqueNoteHash
|
|
244
|
-
]);
|
|
241
|
+
const [index] = await this.node.findLeavesIndexes('latest', MerkleTreeId.NOTE_HASH_TREE, [uniqueNoteHash]);
|
|
245
242
|
if (index === undefined) {
|
|
246
243
|
throw new Error('Note does not exist.');
|
|
247
244
|
}
|
|
248
|
-
await this.db.addNullifiedNote(new NoteDao(note.note, note.contractAddress, note.storageSlot, nonce, noteHash, Fr.ZERO,
|
|
245
|
+
await this.db.addNullifiedNote(new NoteDao(note.note, note.contractAddress, note.storageSlot, nonce, noteHash, Fr.ZERO, // We are not able to derive
|
|
246
|
+
note.txHash, l2BlockNumber, l2BlockHash, index, await note.owner.toAddressPoint(), note.noteTypeId));
|
|
249
247
|
}
|
|
250
248
|
}
|
|
251
|
-
/**
|
|
252
|
-
* Finds the nonce(s) for a given note.
|
|
253
|
-
* @param note - The note to find the nonces for.
|
|
254
|
-
* @returns The nonces of the note.
|
|
255
|
-
* @remarks More than a single nonce may be returned since there might be more than one nonce for a given note.
|
|
256
|
-
*/ async #getNoteNonces(note) {
|
|
257
|
-
const tx = await this.node.getTxEffect(note.txHash);
|
|
258
|
-
if (!tx) {
|
|
259
|
-
throw new Error(`Unknown tx: ${note.txHash}`);
|
|
260
|
-
}
|
|
261
|
-
const nonces = [];
|
|
262
|
-
const firstNullifier = tx.data.nullifiers[0];
|
|
263
|
-
const hashes = tx.data.noteHashes;
|
|
264
|
-
for(let i = 0; i < hashes.length; ++i){
|
|
265
|
-
const hash = hashes[i];
|
|
266
|
-
if (hash.equals(Fr.ZERO)) {
|
|
267
|
-
break;
|
|
268
|
-
}
|
|
269
|
-
const nonce = await computeNoteHashNonce(firstNullifier, i);
|
|
270
|
-
const { uniqueNoteHash } = await this.simulator.computeNoteHashAndOptionallyANullifier(note.contractAddress, nonce, note.storageSlot, note.noteTypeId, false, note.note);
|
|
271
|
-
if (hash.equals(uniqueNoteHash)) {
|
|
272
|
-
nonces.push(nonce);
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
return {
|
|
276
|
-
l2BlockHash: tx.l2BlockHash,
|
|
277
|
-
l2BlockNumber: tx.l2BlockNumber,
|
|
278
|
-
data: nonces
|
|
279
|
-
};
|
|
280
|
-
}
|
|
281
249
|
async getBlock(blockNumber) {
|
|
282
250
|
// If a negative block number is provided the current block number is fetched.
|
|
283
251
|
if (blockNumber < 0) {
|
|
@@ -290,13 +258,14 @@ import { enrichPublicSimulationError, enrichSimulationError } from './error_enri
|
|
|
290
258
|
}
|
|
291
259
|
async proveTx(txRequest, privateExecutionResult) {
|
|
292
260
|
try {
|
|
293
|
-
const { publicInputs, clientIvcProof } = await this
|
|
261
|
+
const { publicInputs, clientIvcProof } = await __classPrivateFieldGet(this, _PXEService_instances, "m", _PXEService_prove).call(this, txRequest, this.proofCreator, privateExecutionResult, {
|
|
294
262
|
simulate: false,
|
|
295
263
|
profile: false,
|
|
296
|
-
dryRun: false
|
|
264
|
+
dryRun: false,
|
|
297
265
|
});
|
|
298
266
|
return new TxProvingResult(privateExecutionResult, publicInputs, clientIvcProof);
|
|
299
|
-
}
|
|
267
|
+
}
|
|
268
|
+
catch (err) {
|
|
300
269
|
throw this.contextualizeError(err, inspect(txRequest), inspect(privateExecutionResult));
|
|
301
270
|
}
|
|
302
271
|
}
|
|
@@ -310,25 +279,25 @@ import { enrichPublicSimulationError, enrichSimulationError } from './error_enri
|
|
|
310
279
|
msgSender,
|
|
311
280
|
chainId: txRequest.txContext.chainId,
|
|
312
281
|
version: txRequest.txContext.version,
|
|
313
|
-
authWitnesses: txRequest.authWitnesses.map(
|
|
282
|
+
authWitnesses: txRequest.authWitnesses.map(w => w.requestHash),
|
|
314
283
|
};
|
|
315
284
|
this.log.info(`Simulating transaction execution request to ${txRequest.functionSelector} at ${txRequest.origin}`, txInfo);
|
|
316
285
|
const timer = new Timer();
|
|
317
286
|
await this.synchronizer.sync();
|
|
318
|
-
const privateExecutionResult = await this
|
|
319
|
-
const { publicInputs, profileResult } = await this
|
|
287
|
+
const privateExecutionResult = await __classPrivateFieldGet(this, _PXEService_instances, "m", _PXEService_executePrivate).call(this, txRequest, msgSender, scopes);
|
|
288
|
+
const { publicInputs, profileResult } = await __classPrivateFieldGet(this, _PXEService_instances, "m", _PXEService_prove).call(this, txRequest, this.proofCreator, privateExecutionResult, {
|
|
320
289
|
simulate: !profile,
|
|
321
290
|
profile,
|
|
322
|
-
dryRun: true
|
|
291
|
+
dryRun: true,
|
|
323
292
|
});
|
|
324
293
|
const privateSimulationResult = new PrivateSimulationResult(privateExecutionResult, publicInputs);
|
|
325
294
|
const simulatedTx = privateSimulationResult.toSimulatedTx();
|
|
326
295
|
let publicOutput;
|
|
327
296
|
if (simulatePublic) {
|
|
328
|
-
publicOutput = await this
|
|
297
|
+
publicOutput = await __classPrivateFieldGet(this, _PXEService_instances, "m", _PXEService_simulatePublicCalls).call(this, simulatedTx, enforceFeePayment);
|
|
329
298
|
}
|
|
330
299
|
if (!skipTxValidation) {
|
|
331
|
-
if (!await this.node.isValidTx(simulatedTx, true)) {
|
|
300
|
+
if (!(await this.node.isValidTx(simulatedTx, true))) {
|
|
332
301
|
throw new Error('The simulated transaction is unable to be added to state and is invalid.');
|
|
333
302
|
}
|
|
334
303
|
}
|
|
@@ -336,18 +305,19 @@ import { enrichPublicSimulationError, enrichSimulationError } from './error_enri
|
|
|
336
305
|
this.log.info(`Simulation completed for ${txHash.toString()} in ${timer.ms()}ms`, {
|
|
337
306
|
txHash,
|
|
338
307
|
...txInfo,
|
|
339
|
-
...profileResult ? {
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
308
|
+
...(profileResult ? { gateCounts: profileResult.gateCounts } : {}),
|
|
309
|
+
...(publicOutput
|
|
310
|
+
? {
|
|
311
|
+
gasUsed: publicOutput.gasUsed,
|
|
312
|
+
revertCode: publicOutput.txEffect.revertCode.getCode(),
|
|
313
|
+
revertReason: publicOutput.revertReason,
|
|
314
|
+
}
|
|
315
|
+
: {}),
|
|
347
316
|
});
|
|
348
317
|
return TxSimulationResult.fromPrivateSimulationResultAndPublicOutput(privateSimulationResult, publicOutput, profileResult);
|
|
349
|
-
}
|
|
350
|
-
|
|
318
|
+
}
|
|
319
|
+
catch (err) {
|
|
320
|
+
throw this.contextualizeError(err, inspect(txRequest), `simulatePublic=${simulatePublic}`, `msgSender=${msgSender?.toString() ?? 'undefined'}`, `skipTxValidation=${skipTxValidation}`, `profile=${profile}`, `scopes=${scopes?.map(s => s.toString()).join(', ') ?? 'undefined'}`);
|
|
351
321
|
}
|
|
352
322
|
}
|
|
353
323
|
async sendTx(tx) {
|
|
@@ -356,7 +326,7 @@ import { enrichPublicSimulationError, enrichSimulationError } from './error_enri
|
|
|
356
326
|
throw new Error(`A settled tx with equal hash ${txHash.toString()} exists.`);
|
|
357
327
|
}
|
|
358
328
|
this.log.debug(`Sending transaction ${txHash}`);
|
|
359
|
-
await this.node.sendTx(tx).catch(
|
|
329
|
+
await this.node.sendTx(tx).catch(err => {
|
|
360
330
|
throw this.contextualizeError(err, inspect(tx));
|
|
361
331
|
});
|
|
362
332
|
this.log.info(`Sent transaction ${txHash}`);
|
|
@@ -366,13 +336,14 @@ import { enrichPublicSimulationError, enrichSimulationError } from './error_enri
|
|
|
366
336
|
try {
|
|
367
337
|
await this.synchronizer.sync();
|
|
368
338
|
// TODO - Should check if `from` has the permission to call the view function.
|
|
369
|
-
const functionCall = await this
|
|
370
|
-
const executionResult = await this
|
|
339
|
+
const functionCall = await __classPrivateFieldGet(this, _PXEService_instances, "m", _PXEService_getFunctionCall).call(this, functionName, args, to);
|
|
340
|
+
const executionResult = await __classPrivateFieldGet(this, _PXEService_instances, "m", _PXEService_simulateUnconstrained).call(this, functionCall, scopes);
|
|
371
341
|
// TODO - Return typed result based on the function artifact.
|
|
372
342
|
return executionResult;
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
|
|
343
|
+
}
|
|
344
|
+
catch (err) {
|
|
345
|
+
const stringifiedArgs = args.map(arg => arg.toString()).join(', ');
|
|
346
|
+
throw this.contextualizeError(err, `simulateUnconstrained ${to}:${functionName}(${stringifiedArgs})`, `scopes=${scopes?.map(s => s.toString()).join(', ') ?? 'undefined'}`);
|
|
376
347
|
}
|
|
377
348
|
}
|
|
378
349
|
getTxReceipt(txHash) {
|
|
@@ -388,38 +359,21 @@ import { enrichPublicSimulationError, enrichSimulationError } from './error_enri
|
|
|
388
359
|
return await this.node.getProvenBlockNumber();
|
|
389
360
|
}
|
|
390
361
|
/**
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
362
|
+
* Gets public logs based on the provided filter.
|
|
363
|
+
* @param filter - The filter to apply to the logs.
|
|
364
|
+
* @returns The requested logs.
|
|
365
|
+
*/
|
|
366
|
+
getPublicLogs(filter) {
|
|
395
367
|
return this.node.getPublicLogs(filter);
|
|
396
368
|
}
|
|
397
369
|
/**
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
370
|
+
* Gets contract class logs based on the provided filter.
|
|
371
|
+
* @param filter - The filter to apply to the logs.
|
|
372
|
+
* @returns The requested logs.
|
|
373
|
+
*/
|
|
374
|
+
getContractClassLogs(filter) {
|
|
402
375
|
return this.node.getContractClassLogs(filter);
|
|
403
376
|
}
|
|
404
|
-
async #getFunctionCall(functionName, args, to) {
|
|
405
|
-
const contract = await this.db.getContract(to);
|
|
406
|
-
if (!contract) {
|
|
407
|
-
throw new Error(`Unknown contract ${to}: add it to PXE Service by calling server.addContracts(...).\nSee docs for context: https://docs.aztec.network/developers/reference/debugging/aztecnr-errors#unknown-contract-0x0-add-it-to-pxe-by-calling-serveraddcontracts`);
|
|
408
|
-
}
|
|
409
|
-
const functionDao = contract.functions.find((f)=>f.name === functionName);
|
|
410
|
-
if (!functionDao) {
|
|
411
|
-
throw new Error(`Unknown function ${functionName} in contract ${contract.name}.`);
|
|
412
|
-
}
|
|
413
|
-
return {
|
|
414
|
-
name: functionDao.name,
|
|
415
|
-
args: encodeArguments(functionDao, args),
|
|
416
|
-
selector: await FunctionSelector.fromNameAndParameters(functionDao.name, functionDao.parameters),
|
|
417
|
-
type: functionDao.functionType,
|
|
418
|
-
to,
|
|
419
|
-
isStatic: functionDao.isStatic,
|
|
420
|
-
returnTypes: functionDao.returnTypes
|
|
421
|
-
};
|
|
422
|
-
}
|
|
423
377
|
async getNodeInfo() {
|
|
424
378
|
const [nodeVersion, protocolVersion, chainId, enr, contractAddresses, protocolContractAddresses] = await Promise.all([
|
|
425
379
|
this.node.getNodeVersion(),
|
|
@@ -427,7 +381,7 @@ import { enrichPublicSimulationError, enrichSimulationError } from './error_enri
|
|
|
427
381
|
this.node.getChainId(),
|
|
428
382
|
this.node.getEncodedEnr(),
|
|
429
383
|
this.node.getL1ContractAddresses(),
|
|
430
|
-
this.node.getProtocolContractAddresses()
|
|
384
|
+
this.node.getProtocolContractAddresses(),
|
|
431
385
|
]);
|
|
432
386
|
const nodeInfo = {
|
|
433
387
|
nodeVersion,
|
|
@@ -435,7 +389,7 @@ import { enrichPublicSimulationError, enrichSimulationError } from './error_enri
|
|
|
435
389
|
protocolVersion,
|
|
436
390
|
enr,
|
|
437
391
|
l1ContractAddresses: contractAddresses,
|
|
438
|
-
protocolContractAddresses: protocolContractAddresses
|
|
392
|
+
protocolContractAddresses: protocolContractAddresses,
|
|
439
393
|
};
|
|
440
394
|
return nodeInfo;
|
|
441
395
|
}
|
|
@@ -446,145 +400,25 @@ import { enrichPublicSimulationError, enrichSimulationError } from './error_enri
|
|
|
446
400
|
classRegisterer: ProtocolContractAddress.ContractClassRegisterer,
|
|
447
401
|
feeJuice: ProtocolContractAddress.FeeJuice,
|
|
448
402
|
instanceDeployer: ProtocolContractAddress.ContractInstanceDeployer,
|
|
449
|
-
multiCallEntrypoint: ProtocolContractAddress.MultiCallEntrypoint
|
|
450
|
-
}
|
|
451
|
-
});
|
|
452
|
-
}
|
|
453
|
-
async #registerProtocolContracts() {
|
|
454
|
-
const registered = {};
|
|
455
|
-
for (const name of protocolContractNames){
|
|
456
|
-
const { address, contractClass, instance, artifact } = await getCanonicalProtocolContract(name);
|
|
457
|
-
await this.db.addContractArtifact(contractClass.id, artifact);
|
|
458
|
-
await this.db.addContractInstance(instance);
|
|
459
|
-
registered[name] = address.toString();
|
|
460
|
-
}
|
|
461
|
-
this.log.verbose(`Registered protocol contracts in pxe`, registered);
|
|
462
|
-
}
|
|
463
|
-
/**
|
|
464
|
-
* Retrieves the simulation parameters required to run an ACIR simulation.
|
|
465
|
-
* This includes the contract address, function artifact, and historical tree roots.
|
|
466
|
-
*
|
|
467
|
-
* @param execRequest - The transaction request object containing details of the contract call.
|
|
468
|
-
* @returns An object containing the contract address, function artifact, and historical tree roots.
|
|
469
|
-
*/ async #getSimulationParameters(execRequest) {
|
|
470
|
-
const contractAddress = execRequest.to ?? execRequest.origin;
|
|
471
|
-
const functionSelector = execRequest.selector ?? execRequest.functionSelector;
|
|
472
|
-
const functionArtifact = await this.contractDataOracle.getFunctionArtifact(contractAddress, functionSelector);
|
|
473
|
-
const debug = await this.contractDataOracle.getFunctionDebugMetadata(contractAddress, functionSelector);
|
|
474
|
-
return {
|
|
475
|
-
contractAddress,
|
|
476
|
-
functionArtifact: {
|
|
477
|
-
...functionArtifact,
|
|
478
|
-
debug
|
|
479
|
-
}
|
|
480
|
-
};
|
|
481
|
-
}
|
|
482
|
-
async #executePrivate(txRequest, msgSender, scopes) {
|
|
483
|
-
// TODO - Pause syncing while simulating.
|
|
484
|
-
const { contractAddress, functionArtifact } = await this.#getSimulationParameters(txRequest);
|
|
485
|
-
try {
|
|
486
|
-
const result = await this.simulator.run(txRequest, functionArtifact, contractAddress, msgSender, scopes);
|
|
487
|
-
this.log.debug(`Private simulation completed for ${contractAddress.toString()}:${functionArtifact.name}`);
|
|
488
|
-
return result;
|
|
489
|
-
} catch (err) {
|
|
490
|
-
if (err instanceof SimulationError) {
|
|
491
|
-
await enrichSimulationError(err, this.db, this.log);
|
|
492
|
-
}
|
|
493
|
-
throw err;
|
|
494
|
-
}
|
|
495
|
-
}
|
|
496
|
-
/**
|
|
497
|
-
* Simulate an unconstrained transaction on the given contract, without considering constraints set by ACIR.
|
|
498
|
-
* The simulation parameters are fetched using ContractDataOracle and executed using AcirSimulator.
|
|
499
|
-
* Returns the simulation result containing the outputs of the unconstrained function.
|
|
500
|
-
*
|
|
501
|
-
* @param execRequest - The transaction request object containing the target contract and function data.
|
|
502
|
-
* @param scopes - The accounts whose notes we can access in this call. Currently optional and will default to all.
|
|
503
|
-
* @returns The simulation result containing the outputs of the unconstrained function.
|
|
504
|
-
*/ async #simulateUnconstrained(execRequest, scopes) {
|
|
505
|
-
const { contractAddress, functionArtifact } = await this.#getSimulationParameters(execRequest);
|
|
506
|
-
this.log.debug('Executing unconstrained simulator...');
|
|
507
|
-
try {
|
|
508
|
-
const result = await this.simulator.runUnconstrained(execRequest, functionArtifact, contractAddress, scopes);
|
|
509
|
-
this.log.verbose(`Unconstrained simulation for ${contractAddress}.${functionArtifact.name} completed`);
|
|
510
|
-
return result;
|
|
511
|
-
} catch (err) {
|
|
512
|
-
if (err instanceof SimulationError) {
|
|
513
|
-
await enrichSimulationError(err, this.db, this.log);
|
|
514
|
-
}
|
|
515
|
-
throw err;
|
|
516
|
-
}
|
|
517
|
-
}
|
|
518
|
-
/**
|
|
519
|
-
* Simulate the public part of a transaction.
|
|
520
|
-
* This allows to catch public execution errors before submitting the transaction.
|
|
521
|
-
* It can also be used for estimating gas in the future.
|
|
522
|
-
* @param tx - The transaction to be simulated.
|
|
523
|
-
*/ async #simulatePublicCalls(tx, enforceFeePayment) {
|
|
524
|
-
// Simulating public calls can throw if the TX fails in a phase that doesn't allow reverts (setup)
|
|
525
|
-
// Or return as reverted if it fails in a phase that allows reverts (app logic, teardown)
|
|
526
|
-
try {
|
|
527
|
-
const result = await this.node.simulatePublicCalls(tx, enforceFeePayment);
|
|
528
|
-
if (result.revertReason) {
|
|
529
|
-
throw result.revertReason;
|
|
530
|
-
}
|
|
531
|
-
return result;
|
|
532
|
-
} catch (err) {
|
|
533
|
-
if (err instanceof SimulationError) {
|
|
534
|
-
try {
|
|
535
|
-
await enrichPublicSimulationError(err, this.contractDataOracle, this.db, this.log);
|
|
536
|
-
} catch (enrichErr) {
|
|
537
|
-
this.log.error(`Failed to enrich public simulation error: ${enrichErr}`);
|
|
538
|
-
}
|
|
539
|
-
}
|
|
540
|
-
throw err;
|
|
541
|
-
}
|
|
542
|
-
}
|
|
543
|
-
/**
|
|
544
|
-
* Generate a kernel proof, and create a private kernel output.
|
|
545
|
-
* The function takes in a transaction execution request, and the result of private execution
|
|
546
|
-
* and then generates a kernel proof.
|
|
547
|
-
*
|
|
548
|
-
* @param txExecutionRequest - The transaction request to be simulated and proved.
|
|
549
|
-
* @param proofCreator - The proof creator to use for proving the execution.
|
|
550
|
-
* @param privateExecutionResult - The result of the private execution
|
|
551
|
-
* @returns An object that contains the output of the kernel execution, including the ClientIvcProof if proving is enabled.
|
|
552
|
-
*/ async #prove(txExecutionRequest, proofCreator, privateExecutionResult, { simulate, profile, dryRun }) {
|
|
553
|
-
// use the block the tx was simulated against
|
|
554
|
-
const block = privateExecutionResult.entrypoint.publicInputs.historicalHeader.globalVariables.blockNumber.toNumber();
|
|
555
|
-
const kernelOracle = new KernelOracle(this.contractDataOracle, this.keyStore, this.node, block);
|
|
556
|
-
const kernelProver = new KernelProver(kernelOracle, proofCreator, !this.proverEnabled);
|
|
557
|
-
this.log.debug(`Executing kernel prover (simulate: ${simulate}, profile: ${profile}, dryRun: ${dryRun})...`);
|
|
558
|
-
return await kernelProver.prove(txExecutionRequest.toTxRequest(), privateExecutionResult, {
|
|
559
|
-
simulate,
|
|
560
|
-
profile,
|
|
561
|
-
dryRun
|
|
403
|
+
multiCallEntrypoint: ProtocolContractAddress.MultiCallEntrypoint,
|
|
404
|
+
},
|
|
562
405
|
});
|
|
563
406
|
}
|
|
564
|
-
async
|
|
565
|
-
|
|
566
|
-
}
|
|
567
|
-
async #isContractPubliclyDeployed(address) {
|
|
568
|
-
return !!await this.node.getContract(address);
|
|
569
|
-
}
|
|
570
|
-
async #isContractInitialized(address) {
|
|
571
|
-
const initNullifier = await siloNullifier(address, address.toField());
|
|
572
|
-
return !!await this.node.getNullifierMembershipWitness('latest', initNullifier);
|
|
573
|
-
}
|
|
574
|
-
async getPrivateEvents(eventMetadataDef, from, limit, // TODO (#9272): Make this better, we should be able to only pass an address now
|
|
407
|
+
async getPrivateEvents(eventMetadataDef, from, limit,
|
|
408
|
+
// TODO (#9272): Make this better, we should be able to only pass an address now
|
|
575
409
|
vpks) {
|
|
576
410
|
const eventMetadata = new EventMetadata(eventMetadataDef);
|
|
577
411
|
if (vpks.length === 0) {
|
|
578
412
|
throw new Error('Tried to get encrypted events without supplying any viewing public keys');
|
|
579
413
|
}
|
|
580
414
|
const blocks = await this.node.getBlocks(from, limit);
|
|
581
|
-
const txEffects = blocks.flatMap(
|
|
582
|
-
const privateLogs = txEffects.flatMap(
|
|
583
|
-
const vsks = await Promise.all(vpks.map(async (vpk)=>{
|
|
415
|
+
const txEffects = blocks.flatMap(block => block.body.txEffects);
|
|
416
|
+
const privateLogs = txEffects.flatMap(txEffect => txEffect.privateLogs);
|
|
417
|
+
const vsks = await Promise.all(vpks.map(async (vpk) => {
|
|
584
418
|
const [keyPrefix, account] = await this.keyStore.getKeyPrefixAndAccount(vpk);
|
|
585
419
|
let secretKey = await this.keyStore.getMasterSecretKey(vpk);
|
|
586
420
|
if (keyPrefix === 'iv') {
|
|
587
|
-
const registeredAccount = (await this.getRegisteredAccounts()).find(
|
|
421
|
+
const registeredAccount = (await this.getRegisteredAccounts()).find(completeAddress => completeAddress.address.equals(account));
|
|
588
422
|
if (!registeredAccount) {
|
|
589
423
|
throw new Error('No registered account');
|
|
590
424
|
}
|
|
@@ -593,20 +427,19 @@ import { enrichPublicSimulationError, enrichSimulationError } from './error_enri
|
|
|
593
427
|
}
|
|
594
428
|
return secretKey;
|
|
595
429
|
}));
|
|
596
|
-
const visibleEvents = (await Promise.all(privateLogs.map(async (log)=>{
|
|
597
|
-
for (const sk of vsks){
|
|
430
|
+
const visibleEvents = (await Promise.all(privateLogs.map(async (log) => {
|
|
431
|
+
for (const sk of vsks) {
|
|
598
432
|
// TODO: Verify that the first field of the log is the tag siloed with contract address.
|
|
599
433
|
// Or use tags to query logs, like we do with notes.
|
|
600
434
|
const decryptedEvent = await L1EventPayload.decryptAsIncoming(log, sk);
|
|
601
435
|
if (decryptedEvent !== undefined) {
|
|
602
|
-
return [
|
|
603
|
-
decryptedEvent
|
|
604
|
-
];
|
|
436
|
+
return [decryptedEvent];
|
|
605
437
|
}
|
|
606
438
|
}
|
|
607
439
|
return [];
|
|
608
440
|
}))).flat();
|
|
609
|
-
const decodedEvents = visibleEvents
|
|
441
|
+
const decodedEvents = visibleEvents
|
|
442
|
+
.map(visibleEvent => {
|
|
610
443
|
if (visibleEvent === undefined) {
|
|
611
444
|
return undefined;
|
|
612
445
|
}
|
|
@@ -614,16 +447,18 @@ import { enrichPublicSimulationError, enrichSimulationError } from './error_enri
|
|
|
614
447
|
return undefined;
|
|
615
448
|
}
|
|
616
449
|
return eventMetadata.decode(visibleEvent);
|
|
617
|
-
})
|
|
450
|
+
})
|
|
451
|
+
.filter(visibleEvent => visibleEvent !== undefined);
|
|
618
452
|
return decodedEvents;
|
|
619
453
|
}
|
|
620
454
|
async getPublicEvents(eventMetadataDef, from, limit) {
|
|
621
455
|
const eventMetadata = new EventMetadata(eventMetadataDef);
|
|
622
456
|
const { logs } = await this.node.getPublicLogs({
|
|
623
457
|
fromBlock: from,
|
|
624
|
-
toBlock: from + limit
|
|
458
|
+
toBlock: from + limit,
|
|
625
459
|
});
|
|
626
|
-
const decodedEvents = logs
|
|
460
|
+
const decodedEvents = logs
|
|
461
|
+
.map(log => {
|
|
627
462
|
// +1 for the event selector
|
|
628
463
|
const expectedLength = eventMetadata.fieldNames.length + 1;
|
|
629
464
|
const logFields = log.log.log.slice(0, expectedLength);
|
|
@@ -632,11 +467,12 @@ import { enrichPublicSimulationError, enrichSimulationError } from './error_enri
|
|
|
632
467
|
return undefined;
|
|
633
468
|
}
|
|
634
469
|
// If any of the remaining fields, are non-zero, the payload does match expected:
|
|
635
|
-
if (log.log.log.slice(expectedLength + 1).find(
|
|
470
|
+
if (log.log.log.slice(expectedLength + 1).find(f => !f.isZero())) {
|
|
636
471
|
throw new Error('Something is weird here, we have matching EventSelectors, but the actual payload has mismatched length');
|
|
637
472
|
}
|
|
638
473
|
return eventMetadata.decode(log.log);
|
|
639
|
-
})
|
|
474
|
+
})
|
|
475
|
+
.filter(log => log !== undefined);
|
|
640
476
|
return decodedEvents;
|
|
641
477
|
}
|
|
642
478
|
async resetNoteSyncData() {
|
|
@@ -649,10 +485,182 @@ import { enrichPublicSimulationError, enrichSimulationError } from './error_enri
|
|
|
649
485
|
}
|
|
650
486
|
if (err instanceof SimulationError) {
|
|
651
487
|
err.setAztecContext(contextStr);
|
|
652
|
-
}
|
|
488
|
+
}
|
|
489
|
+
else {
|
|
653
490
|
this.log.error(err.name, err);
|
|
654
491
|
this.log.debug(contextStr);
|
|
655
492
|
}
|
|
656
493
|
return err;
|
|
657
494
|
}
|
|
658
495
|
}
|
|
496
|
+
_PXEService_instances = new WeakSet(), _PXEService_getNoteNonces =
|
|
497
|
+
/**
|
|
498
|
+
* Finds the nonce(s) for a given note.
|
|
499
|
+
* @param note - The note to find the nonces for.
|
|
500
|
+
* @returns The nonces of the note.
|
|
501
|
+
* @remarks More than a single nonce may be returned since there might be more than one nonce for a given note.
|
|
502
|
+
*/
|
|
503
|
+
async function _PXEService_getNoteNonces(note) {
|
|
504
|
+
const tx = await this.node.getTxEffect(note.txHash);
|
|
505
|
+
if (!tx) {
|
|
506
|
+
throw new Error(`Unknown tx: ${note.txHash}`);
|
|
507
|
+
}
|
|
508
|
+
const nonces = [];
|
|
509
|
+
const firstNullifier = tx.data.nullifiers[0];
|
|
510
|
+
const hashes = tx.data.noteHashes;
|
|
511
|
+
for (let i = 0; i < hashes.length; ++i) {
|
|
512
|
+
const hash = hashes[i];
|
|
513
|
+
if (hash.equals(Fr.ZERO)) {
|
|
514
|
+
break;
|
|
515
|
+
}
|
|
516
|
+
const nonce = await computeNoteHashNonce(firstNullifier, i);
|
|
517
|
+
const { uniqueNoteHash } = await this.simulator.computeNoteHashAndOptionallyANullifier(note.contractAddress, nonce, note.storageSlot, note.noteTypeId, false, note.note);
|
|
518
|
+
if (hash.equals(uniqueNoteHash)) {
|
|
519
|
+
nonces.push(nonce);
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
return { l2BlockHash: tx.l2BlockHash, l2BlockNumber: tx.l2BlockNumber, data: nonces };
|
|
523
|
+
}, _PXEService_getFunctionCall = async function _PXEService_getFunctionCall(functionName, args, to) {
|
|
524
|
+
const contract = await this.db.getContract(to);
|
|
525
|
+
if (!contract) {
|
|
526
|
+
throw new Error(`Unknown contract ${to}: add it to PXE Service by calling server.addContracts(...).\nSee docs for context: https://docs.aztec.network/developers/reference/debugging/aztecnr-errors#unknown-contract-0x0-add-it-to-pxe-by-calling-serveraddcontracts`);
|
|
527
|
+
}
|
|
528
|
+
const functionDao = contract.functions.find(f => f.name === functionName);
|
|
529
|
+
if (!functionDao) {
|
|
530
|
+
throw new Error(`Unknown function ${functionName} in contract ${contract.name}.`);
|
|
531
|
+
}
|
|
532
|
+
return {
|
|
533
|
+
name: functionDao.name,
|
|
534
|
+
args: encodeArguments(functionDao, args),
|
|
535
|
+
selector: await FunctionSelector.fromNameAndParameters(functionDao.name, functionDao.parameters),
|
|
536
|
+
type: functionDao.functionType,
|
|
537
|
+
to,
|
|
538
|
+
isStatic: functionDao.isStatic,
|
|
539
|
+
returnTypes: functionDao.returnTypes,
|
|
540
|
+
};
|
|
541
|
+
}, _PXEService_registerProtocolContracts = async function _PXEService_registerProtocolContracts() {
|
|
542
|
+
const registered = {};
|
|
543
|
+
for (const name of protocolContractNames) {
|
|
544
|
+
const { address, contractClass, instance, artifact } = await getCanonicalProtocolContract(name);
|
|
545
|
+
await this.db.addContractArtifact(contractClass.id, artifact);
|
|
546
|
+
await this.db.addContractInstance(instance);
|
|
547
|
+
registered[name] = address.toString();
|
|
548
|
+
}
|
|
549
|
+
this.log.verbose(`Registered protocol contracts in pxe`, registered);
|
|
550
|
+
}, _PXEService_getSimulationParameters =
|
|
551
|
+
/**
|
|
552
|
+
* Retrieves the simulation parameters required to run an ACIR simulation.
|
|
553
|
+
* This includes the contract address, function artifact, and historical tree roots.
|
|
554
|
+
*
|
|
555
|
+
* @param execRequest - The transaction request object containing details of the contract call.
|
|
556
|
+
* @returns An object containing the contract address, function artifact, and historical tree roots.
|
|
557
|
+
*/
|
|
558
|
+
async function _PXEService_getSimulationParameters(execRequest) {
|
|
559
|
+
const contractAddress = execRequest.to ?? execRequest.origin;
|
|
560
|
+
const functionSelector = execRequest.selector ?? execRequest.functionSelector;
|
|
561
|
+
const functionArtifact = await this.contractDataOracle.getFunctionArtifact(contractAddress, functionSelector);
|
|
562
|
+
const debug = await this.contractDataOracle.getFunctionDebugMetadata(contractAddress, functionSelector);
|
|
563
|
+
return {
|
|
564
|
+
contractAddress,
|
|
565
|
+
functionArtifact: {
|
|
566
|
+
...functionArtifact,
|
|
567
|
+
debug,
|
|
568
|
+
},
|
|
569
|
+
};
|
|
570
|
+
}, _PXEService_executePrivate = async function _PXEService_executePrivate(txRequest, msgSender, scopes) {
|
|
571
|
+
// TODO - Pause syncing while simulating.
|
|
572
|
+
const { contractAddress, functionArtifact } = await __classPrivateFieldGet(this, _PXEService_instances, "m", _PXEService_getSimulationParameters).call(this, txRequest);
|
|
573
|
+
try {
|
|
574
|
+
const result = await this.simulator.run(txRequest, functionArtifact, contractAddress, msgSender, scopes);
|
|
575
|
+
this.log.debug(`Private simulation completed for ${contractAddress.toString()}:${functionArtifact.name}`);
|
|
576
|
+
return result;
|
|
577
|
+
}
|
|
578
|
+
catch (err) {
|
|
579
|
+
if (err instanceof SimulationError) {
|
|
580
|
+
await enrichSimulationError(err, this.db, this.log);
|
|
581
|
+
}
|
|
582
|
+
throw err;
|
|
583
|
+
}
|
|
584
|
+
}, _PXEService_simulateUnconstrained =
|
|
585
|
+
/**
|
|
586
|
+
* Simulate an unconstrained transaction on the given contract, without considering constraints set by ACIR.
|
|
587
|
+
* The simulation parameters are fetched using ContractDataOracle and executed using AcirSimulator.
|
|
588
|
+
* Returns the simulation result containing the outputs of the unconstrained function.
|
|
589
|
+
*
|
|
590
|
+
* @param execRequest - The transaction request object containing the target contract and function data.
|
|
591
|
+
* @param scopes - The accounts whose notes we can access in this call. Currently optional and will default to all.
|
|
592
|
+
* @returns The simulation result containing the outputs of the unconstrained function.
|
|
593
|
+
*/
|
|
594
|
+
async function _PXEService_simulateUnconstrained(execRequest, scopes) {
|
|
595
|
+
const { contractAddress, functionArtifact } = await __classPrivateFieldGet(this, _PXEService_instances, "m", _PXEService_getSimulationParameters).call(this, execRequest);
|
|
596
|
+
this.log.debug('Executing unconstrained simulator...');
|
|
597
|
+
try {
|
|
598
|
+
const result = await this.simulator.runUnconstrained(execRequest, functionArtifact, contractAddress, scopes);
|
|
599
|
+
this.log.verbose(`Unconstrained simulation for ${contractAddress}.${functionArtifact.name} completed`);
|
|
600
|
+
return result;
|
|
601
|
+
}
|
|
602
|
+
catch (err) {
|
|
603
|
+
if (err instanceof SimulationError) {
|
|
604
|
+
await enrichSimulationError(err, this.db, this.log);
|
|
605
|
+
}
|
|
606
|
+
throw err;
|
|
607
|
+
}
|
|
608
|
+
}, _PXEService_simulatePublicCalls =
|
|
609
|
+
/**
|
|
610
|
+
* Simulate the public part of a transaction.
|
|
611
|
+
* This allows to catch public execution errors before submitting the transaction.
|
|
612
|
+
* It can also be used for estimating gas in the future.
|
|
613
|
+
* @param tx - The transaction to be simulated.
|
|
614
|
+
*/
|
|
615
|
+
async function _PXEService_simulatePublicCalls(tx, enforceFeePayment) {
|
|
616
|
+
// Simulating public calls can throw if the TX fails in a phase that doesn't allow reverts (setup)
|
|
617
|
+
// Or return as reverted if it fails in a phase that allows reverts (app logic, teardown)
|
|
618
|
+
try {
|
|
619
|
+
const result = await this.node.simulatePublicCalls(tx, enforceFeePayment);
|
|
620
|
+
if (result.revertReason) {
|
|
621
|
+
throw result.revertReason;
|
|
622
|
+
}
|
|
623
|
+
return result;
|
|
624
|
+
}
|
|
625
|
+
catch (err) {
|
|
626
|
+
if (err instanceof SimulationError) {
|
|
627
|
+
try {
|
|
628
|
+
await enrichPublicSimulationError(err, this.contractDataOracle, this.db, this.log);
|
|
629
|
+
}
|
|
630
|
+
catch (enrichErr) {
|
|
631
|
+
this.log.error(`Failed to enrich public simulation error: ${enrichErr}`);
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
throw err;
|
|
635
|
+
}
|
|
636
|
+
}, _PXEService_prove =
|
|
637
|
+
/**
|
|
638
|
+
* Generate a kernel proof, and create a private kernel output.
|
|
639
|
+
* The function takes in a transaction execution request, and the result of private execution
|
|
640
|
+
* and then generates a kernel proof.
|
|
641
|
+
*
|
|
642
|
+
* @param txExecutionRequest - The transaction request to be simulated and proved.
|
|
643
|
+
* @param proofCreator - The proof creator to use for proving the execution.
|
|
644
|
+
* @param privateExecutionResult - The result of the private execution
|
|
645
|
+
* @returns An object that contains the output of the kernel execution, including the ClientIvcProof if proving is enabled.
|
|
646
|
+
*/
|
|
647
|
+
async function _PXEService_prove(txExecutionRequest, proofCreator, privateExecutionResult, { simulate, profile, dryRun }) {
|
|
648
|
+
// use the block the tx was simulated against
|
|
649
|
+
const block = privateExecutionResult.entrypoint.publicInputs.historicalHeader.globalVariables.blockNumber.toNumber();
|
|
650
|
+
const kernelOracle = new KernelOracle(this.contractDataOracle, this.keyStore, this.node, block);
|
|
651
|
+
const kernelProver = new KernelProver(kernelOracle, proofCreator, !this.proverEnabled);
|
|
652
|
+
this.log.debug(`Executing kernel prover (simulate: ${simulate}, profile: ${profile}, dryRun: ${dryRun})...`);
|
|
653
|
+
return await kernelProver.prove(txExecutionRequest.toTxRequest(), privateExecutionResult, {
|
|
654
|
+
simulate,
|
|
655
|
+
profile,
|
|
656
|
+
dryRun,
|
|
657
|
+
});
|
|
658
|
+
}, _PXEService_isContractClassPubliclyRegistered = async function _PXEService_isContractClassPubliclyRegistered(id) {
|
|
659
|
+
return !!(await this.node.getContractClass(id));
|
|
660
|
+
}, _PXEService_isContractPubliclyDeployed = async function _PXEService_isContractPubliclyDeployed(address) {
|
|
661
|
+
return !!(await this.node.getContract(address));
|
|
662
|
+
}, _PXEService_isContractInitialized = async function _PXEService_isContractInitialized(address) {
|
|
663
|
+
const initNullifier = await siloNullifier(address, address.toField());
|
|
664
|
+
return !!(await this.node.getNullifierMembershipWitness('latest', initNullifier));
|
|
665
|
+
};
|
|
666
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHhlX3NlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcHhlX3NlcnZpY2UvcHhlX3NlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSxPQUFPLEVBR0wsYUFBYSxFQU9iLGNBQWMsRUFHZCxZQUFZLEVBT1osdUJBQXVCLEVBR3ZCLGVBQWUsRUFLZixlQUFlLEVBRWYsa0JBQWtCLEVBQ2xCLFVBQVUsRUFDVixtQ0FBbUMsR0FDcEMsTUFBTSxzQkFBc0IsQ0FBQztBQVc5QixPQUFPLEVBQ0wsa0NBQWtDLEVBQ2xDLHNCQUFzQixFQUN0Qiw0QkFBNEIsR0FDN0IsTUFBTSw2QkFBNkIsQ0FBQztBQUNyQyxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsYUFBYSxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDOUUsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDL0QsT0FBTyxFQUdMLGFBQWEsRUFDYixnQkFBZ0IsRUFDaEIsWUFBWSxFQUNaLHVCQUF1QixFQUN2QixlQUFlLEdBQ2hCLE1BQU0sdUJBQXVCLENBQUM7QUFFL0IsT0FBTyxFQUFFLEVBQUUsRUFBYyxNQUFNLDBCQUEwQixDQUFDO0FBQzFELE9BQU8sRUFBZSxZQUFZLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUNsRSxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFHaEQsT0FBTyxFQUFFLHVCQUF1QixFQUFFLHFCQUFxQixFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDM0YsT0FBTyxFQUFFLDRCQUE0QixFQUFFLE1BQU0sa0NBQWtDLENBQUM7QUFHaEYsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUcvQixPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDM0QsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sa0NBQWtDLENBQUM7QUFFdEUsT0FBTyxFQUFFLE9B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
|