@aztec/pxe 0.82.0 → 0.82.1
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.js +1 -1
- package/dest/private_kernel/private_kernel_execution_prover.d.ts +0 -1
- package/dest/private_kernel/private_kernel_execution_prover.d.ts.map +1 -1
- package/dest/private_kernel/private_kernel_execution_prover.js +3 -12
- package/dest/private_kernel/private_kernel_oracle_impl.d.ts +1 -1
- package/dest/private_kernel/private_kernel_oracle_impl.d.ts.map +1 -1
- package/dest/private_kernel/private_kernel_oracle_impl.js +11 -1
- package/dest/pxe_oracle_interface/pxe_oracle_interface.d.ts.map +1 -1
- package/dest/pxe_oracle_interface/pxe_oracle_interface.js +6 -0
- package/dest/pxe_service/error_enriching.d.ts.map +1 -1
- package/dest/pxe_service/error_enriching.js +5 -8
- package/dest/pxe_service/pxe_service.d.ts.map +1 -1
- package/dest/pxe_service/pxe_service.js +8 -4
- package/dest/storage/contract_data_provider/contract_data_provider.d.ts +10 -44
- package/dest/storage/contract_data_provider/contract_data_provider.d.ts.map +1 -1
- package/dest/storage/contract_data_provider/contract_data_provider.js +92 -72
- package/dest/storage/contract_data_provider/index.d.ts +0 -1
- package/dest/storage/contract_data_provider/index.d.ts.map +1 -1
- package/dest/storage/contract_data_provider/index.js +0 -1
- package/dest/storage/contract_data_provider/private_functions_tree.d.ts +3 -42
- package/dest/storage/contract_data_provider/private_functions_tree.d.ts.map +1 -1
- package/dest/storage/contract_data_provider/private_functions_tree.js +9 -61
- package/dest/test/pxe_test_suite.d.ts.map +1 -1
- package/dest/test/pxe_test_suite.js +1 -1
- package/package.json +15 -15
- package/src/config/index.ts +1 -1
- package/src/private_kernel/private_kernel_execution_prover.ts +4 -20
- package/src/private_kernel/private_kernel_oracle_impl.ts +13 -1
- package/src/pxe_oracle_interface/pxe_oracle_interface.ts +6 -0
- package/src/pxe_service/error_enriching.ts +8 -14
- package/src/pxe_service/pxe_service.ts +10 -4
- package/src/storage/contract_data_provider/contract_data_provider.ts +110 -80
- package/src/storage/contract_data_provider/index.ts +0 -1
- package/src/storage/contract_data_provider/private_functions_tree.ts +11 -75
- package/src/test/pxe_test_suite.ts +3 -1
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { PUBLIC_DISPATCH_SELECTOR } from '@aztec/constants';
|
|
2
|
-
import { Fr } from '@aztec/foundation/fields';
|
|
3
1
|
import type { Logger } from '@aztec/foundation/log';
|
|
4
2
|
import { resolveAssertionMessageFromRevertData, resolveOpcodeLocations } from '@aztec/simulator/client';
|
|
5
3
|
import { FunctionSelector } from '@aztec/stdlib/abi';
|
|
@@ -66,24 +64,20 @@ export async function enrichPublicSimulationError(
|
|
|
66
64
|
) {
|
|
67
65
|
const callStack = err.getCallStack();
|
|
68
66
|
const originalFailingFunction = callStack[callStack.length - 1];
|
|
69
|
-
// TODO(https://github.com/AztecProtocol/aztec-packages/issues/8985): Properly fix this.
|
|
70
|
-
// To be able to resolve the assertion message, we need to use the information from the public dispatch function,
|
|
71
|
-
// no matter what the call stack selector points to (since we've modified it to point to the target function).
|
|
72
|
-
// We should remove this because the AVM (or public protocol) shouldn't be aware of the public dispatch calling convention.
|
|
73
67
|
|
|
74
|
-
const artifact = await contractDataProvider.
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
68
|
+
const artifact = await contractDataProvider.getPublicFunctionArtifact(originalFailingFunction.contractAddress);
|
|
69
|
+
if (!artifact) {
|
|
70
|
+
throw new Error(
|
|
71
|
+
`Artifact not found when enriching public simulation error. Contract address: ${originalFailingFunction.contractAddress}.`,
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
|
|
78
75
|
const assertionMessage = resolveAssertionMessageFromRevertData(err.revertData, artifact);
|
|
79
76
|
if (assertionMessage) {
|
|
80
77
|
err.setOriginalMessage(err.getOriginalMessage() + `${assertionMessage}`);
|
|
81
78
|
}
|
|
82
79
|
|
|
83
|
-
const debugInfo = await contractDataProvider.
|
|
84
|
-
originalFailingFunction.contractAddress,
|
|
85
|
-
FunctionSelector.fromField(new Fr(PUBLIC_DISPATCH_SELECTOR)),
|
|
86
|
-
);
|
|
80
|
+
const debugInfo = await contractDataProvider.getPublicFunctionDebugMetadata(originalFailingFunction.contractAddress);
|
|
87
81
|
|
|
88
82
|
const noirCallStack = err.getNoirCallStack();
|
|
89
83
|
if (debugInfo) {
|
|
@@ -450,10 +450,8 @@ export class PXEService implements PXE {
|
|
|
450
450
|
isContractClassPubliclyRegistered: boolean;
|
|
451
451
|
artifact: ContractArtifact | undefined;
|
|
452
452
|
}> {
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
artifact = await this.contractDataProvider.getContractArtifact(id);
|
|
456
|
-
} catch {
|
|
453
|
+
const artifact = await this.contractDataProvider.getContractArtifact(id);
|
|
454
|
+
if (!artifact) {
|
|
457
455
|
this.log.warn(`No artifact found for contract class ${id.toString()} when looking for its metadata`);
|
|
458
456
|
}
|
|
459
457
|
|
|
@@ -572,6 +570,11 @@ export class PXEService implements PXE {
|
|
|
572
570
|
} else {
|
|
573
571
|
// Otherwise, make sure there is an artifact already registered for that class id
|
|
574
572
|
artifact = await this.contractDataProvider.getContractArtifact(instance.currentContractClassId);
|
|
573
|
+
if (!artifact) {
|
|
574
|
+
throw new Error(
|
|
575
|
+
`Artifact not found when registering an instance. Contract class: ${instance.currentContractClassId}.`,
|
|
576
|
+
);
|
|
577
|
+
}
|
|
575
578
|
}
|
|
576
579
|
|
|
577
580
|
await this.contractDataProvider.addContractInstance(instance);
|
|
@@ -585,6 +588,9 @@ export class PXEService implements PXE {
|
|
|
585
588
|
// class while we're simulating it.
|
|
586
589
|
return this.#putInJobQueue(async () => {
|
|
587
590
|
const currentInstance = await this.contractDataProvider.getContractInstance(contractAddress);
|
|
591
|
+
if (!currentInstance) {
|
|
592
|
+
throw new Error(`Instance not found when updating a contract. Contract address: ${contractAddress}.`);
|
|
593
|
+
}
|
|
588
594
|
const contractClass = await getContractClassFromArtifact(artifact);
|
|
589
595
|
await this.synchronizer.sync();
|
|
590
596
|
|
|
@@ -2,9 +2,9 @@ import type { Fr } from '@aztec/foundation/fields';
|
|
|
2
2
|
import { toArray } from '@aztec/foundation/iterable';
|
|
3
3
|
import type { MembershipWitness } from '@aztec/foundation/trees';
|
|
4
4
|
import type { AztecAsyncKVStore, AztecAsyncMap } from '@aztec/kv-store';
|
|
5
|
-
import { ContractClassNotFoundError, ContractNotFoundError } from '@aztec/simulator/client';
|
|
6
5
|
import {
|
|
7
6
|
type ContractArtifact,
|
|
7
|
+
type FunctionAbi,
|
|
8
8
|
type FunctionArtifact,
|
|
9
9
|
type FunctionArtifactWithContractName,
|
|
10
10
|
type FunctionDebugMetadata,
|
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
type ContractClass,
|
|
20
20
|
type ContractInstanceWithAddress,
|
|
21
21
|
SerializableContractInstance,
|
|
22
|
+
getContractClassFromArtifact,
|
|
22
23
|
} from '@aztec/stdlib/contract';
|
|
23
24
|
|
|
24
25
|
import type { DataProvider } from '../data_provider.js';
|
|
@@ -33,7 +34,11 @@ import { PrivateFunctionsTree } from './private_functions_tree.js';
|
|
|
33
34
|
*/
|
|
34
35
|
export class ContractDataProvider implements DataProvider {
|
|
35
36
|
/** Map from contract class id to private function tree. */
|
|
36
|
-
|
|
37
|
+
// TODO: Update it to be LRU cache so that it doesn't keep all the data all the time.
|
|
38
|
+
#privateFunctionTrees: Map<string, PrivateFunctionsTree> = new Map();
|
|
39
|
+
|
|
40
|
+
/** Map from contract address to contract class id */
|
|
41
|
+
#contractClassIdMap: Map<string, Fr> = new Map();
|
|
37
42
|
|
|
38
43
|
#contractArtifacts: AztecAsyncMap<string, Buffer>;
|
|
39
44
|
#contractInstances: AztecAsyncMap<string, Buffer>;
|
|
@@ -66,6 +71,8 @@ export class ContractDataProvider implements DataProvider {
|
|
|
66
71
|
}
|
|
67
72
|
|
|
68
73
|
async addContractInstance(contract: ContractInstanceWithAddress): Promise<void> {
|
|
74
|
+
this.#contractClassIdMap.set(contract.address.toString(), contract.currentContractClassId);
|
|
75
|
+
|
|
69
76
|
await this.#contractInstances.set(
|
|
70
77
|
contract.address.toString(),
|
|
71
78
|
new SerializableContractInstance(contract).toBuffer(),
|
|
@@ -74,15 +81,15 @@ export class ContractDataProvider implements DataProvider {
|
|
|
74
81
|
|
|
75
82
|
// Private getters
|
|
76
83
|
|
|
77
|
-
async #
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
return
|
|
84
|
+
async #getContractClassId(contractAddress: AztecAddress): Promise<Fr | undefined> {
|
|
85
|
+
if (!this.#contractClassIdMap.has(contractAddress.toString())) {
|
|
86
|
+
const instance = await this.getContractInstance(contractAddress);
|
|
87
|
+
if (!instance) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
this.#contractClassIdMap.set(contractAddress.toString(), instance.currentContractClassId);
|
|
91
|
+
}
|
|
92
|
+
return this.#contractClassIdMap.get(contractAddress.toString());
|
|
86
93
|
}
|
|
87
94
|
|
|
88
95
|
/**
|
|
@@ -95,31 +102,21 @@ export class ContractDataProvider implements DataProvider {
|
|
|
95
102
|
* @returns A ContractTree instance associated with the specified contract address.
|
|
96
103
|
* @throws An Error if the contract is not found in the ContractDatabase.
|
|
97
104
|
*/
|
|
98
|
-
|
|
99
|
-
if (!this.
|
|
100
|
-
const artifact = await this
|
|
105
|
+
async #getPrivateFunctionTreeForClassId(classId: Fr): Promise<PrivateFunctionsTree | undefined> {
|
|
106
|
+
if (!this.#privateFunctionTrees.has(classId.toString())) {
|
|
107
|
+
const artifact = await this.getContractArtifact(classId);
|
|
101
108
|
if (!artifact) {
|
|
102
|
-
|
|
109
|
+
return;
|
|
103
110
|
}
|
|
104
111
|
const tree = await PrivateFunctionsTree.create(artifact);
|
|
105
|
-
this.
|
|
112
|
+
this.#privateFunctionTrees.set(classId.toString(), tree);
|
|
106
113
|
}
|
|
107
|
-
return this.
|
|
114
|
+
return this.#privateFunctionTrees.get(classId.toString())!;
|
|
108
115
|
}
|
|
109
116
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
* Otherwise, a new ContractTree instance will be created using the contract data from the database
|
|
114
|
-
* and added to the cache before returning.
|
|
115
|
-
*
|
|
116
|
-
* @param contractAddress - The AztecAddress of the contract for which the ContractTree is required.
|
|
117
|
-
* @returns A ContractTree instance associated with the specified contract address.
|
|
118
|
-
* @throws An Error if the contract is not found in the ContractDatabase.
|
|
119
|
-
*/
|
|
120
|
-
private async getTreeForAddress(contractAddress: AztecAddress): Promise<PrivateFunctionsTree> {
|
|
121
|
-
const instance = await this.getContractInstance(contractAddress);
|
|
122
|
-
return this.getTreeForClassId(instance.currentContractClassId);
|
|
117
|
+
async #getContractArtifactByAddress(contractAddress: AztecAddress): Promise<ContractArtifact | undefined> {
|
|
118
|
+
const contractClassId = await this.#getContractClassId(contractAddress);
|
|
119
|
+
return contractClassId && this.getContractArtifact(contractClassId);
|
|
123
120
|
}
|
|
124
121
|
|
|
125
122
|
// Public getters
|
|
@@ -130,32 +127,33 @@ export class ContractDataProvider implements DataProvider {
|
|
|
130
127
|
}
|
|
131
128
|
|
|
132
129
|
/** Returns a contract instance for a given address. Throws if not found. */
|
|
133
|
-
public async getContractInstance(contractAddress: AztecAddress): Promise<ContractInstanceWithAddress> {
|
|
134
|
-
const
|
|
135
|
-
|
|
136
|
-
throw new ContractNotFoundError(contractAddress.toString());
|
|
137
|
-
}
|
|
138
|
-
return instance;
|
|
130
|
+
public async getContractInstance(contractAddress: AztecAddress): Promise<ContractInstanceWithAddress | undefined> {
|
|
131
|
+
const contract = await this.#contractInstances.getAsync(contractAddress.toString());
|
|
132
|
+
return contract && SerializableContractInstance.fromBuffer(contract).withAddress(contractAddress);
|
|
139
133
|
}
|
|
140
134
|
|
|
141
|
-
public async getContractArtifact(contractClassId: Fr): Promise<ContractArtifact> {
|
|
142
|
-
const
|
|
143
|
-
|
|
135
|
+
public async getContractArtifact(contractClassId: Fr): Promise<ContractArtifact | undefined> {
|
|
136
|
+
const contract = await this.#contractArtifacts.getAsync(contractClassId.toString());
|
|
137
|
+
// TODO(@spalladino): AztecAsyncMap lies and returns Uint8Arrays instead of Buffers, hence the extra Buffer.from.
|
|
138
|
+
return contract && contractArtifactFromBuffer(Buffer.from(contract));
|
|
144
139
|
}
|
|
145
140
|
|
|
146
141
|
/** Returns a contract class for a given class id. Throws if not found. */
|
|
147
|
-
public async getContractClass(contractClassId: Fr): Promise<ContractClass> {
|
|
148
|
-
const
|
|
149
|
-
return
|
|
142
|
+
public async getContractClass(contractClassId: Fr): Promise<ContractClass | undefined> {
|
|
143
|
+
const artifact = await this.getContractArtifact(contractClassId);
|
|
144
|
+
return artifact && getContractClassFromArtifact(artifact);
|
|
150
145
|
}
|
|
151
146
|
|
|
152
147
|
public async getContract(
|
|
153
148
|
address: AztecAddress,
|
|
154
149
|
): Promise<(ContractInstanceWithAddress & ContractArtifact) | undefined> {
|
|
155
150
|
const instance = await this.getContractInstance(address);
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
151
|
+
if (!instance) {
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
const artifact = await this.getContractArtifact(instance.currentContractClassId);
|
|
155
|
+
if (!artifact) {
|
|
156
|
+
return;
|
|
159
157
|
}
|
|
160
158
|
return { ...instance, ...artifact };
|
|
161
159
|
}
|
|
@@ -172,14 +170,18 @@ export class ContractDataProvider implements DataProvider {
|
|
|
172
170
|
public async getFunctionArtifact(
|
|
173
171
|
contractAddress: AztecAddress,
|
|
174
172
|
selector: FunctionSelector,
|
|
175
|
-
): Promise<FunctionArtifactWithContractName> {
|
|
176
|
-
const
|
|
177
|
-
const
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
173
|
+
): Promise<FunctionArtifactWithContractName | undefined> {
|
|
174
|
+
const artifact = await this.#getContractArtifactByAddress(contractAddress);
|
|
175
|
+
const fnArtifact = artifact && (await this.#findFunctionArtifactBySelector(artifact, selector));
|
|
176
|
+
return fnArtifact && { ...fnArtifact, contractName: artifact.name };
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
public async getPublicFunctionArtifact(
|
|
180
|
+
contractAddress: AztecAddress,
|
|
181
|
+
): Promise<FunctionArtifactWithContractName | undefined> {
|
|
182
|
+
const artifact = await this.#getContractArtifactByAddress(contractAddress);
|
|
183
|
+
const fnArtifact = artifact && artifact.functions.find(fn => fn.functionType === FunctionType.PUBLIC);
|
|
184
|
+
return fnArtifact && { ...fnArtifact, contractName: artifact.name };
|
|
183
185
|
}
|
|
184
186
|
|
|
185
187
|
/**
|
|
@@ -195,8 +197,16 @@ export class ContractDataProvider implements DataProvider {
|
|
|
195
197
|
contractAddress: AztecAddress,
|
|
196
198
|
functionName: string,
|
|
197
199
|
): Promise<FunctionArtifact | undefined> {
|
|
198
|
-
const
|
|
199
|
-
return
|
|
200
|
+
const artifact = await this.#getContractArtifactByAddress(contractAddress);
|
|
201
|
+
return artifact?.functions.find(fn => fn.name === functionName);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
public async getFunctionAbi(
|
|
205
|
+
contractAddress: AztecAddress,
|
|
206
|
+
selector: FunctionSelector,
|
|
207
|
+
): Promise<FunctionAbi | undefined> {
|
|
208
|
+
const artifact = await this.#getContractArtifactByAddress(contractAddress);
|
|
209
|
+
return artifact && (await this.#findFunctionAbiBySelector(artifact, selector));
|
|
200
210
|
}
|
|
201
211
|
|
|
202
212
|
/**
|
|
@@ -213,24 +223,17 @@ export class ContractDataProvider implements DataProvider {
|
|
|
213
223
|
contractAddress: AztecAddress,
|
|
214
224
|
selector: FunctionSelector,
|
|
215
225
|
): Promise<FunctionDebugMetadata | undefined> {
|
|
216
|
-
const
|
|
217
|
-
const
|
|
218
|
-
return getFunctionDebugMetadata(
|
|
226
|
+
const artifact = await this.#getContractArtifactByAddress(contractAddress);
|
|
227
|
+
const fnArtifact = artifact && (await this.#findFunctionArtifactBySelector(artifact, selector));
|
|
228
|
+
return fnArtifact && getFunctionDebugMetadata(artifact, fnArtifact);
|
|
219
229
|
}
|
|
220
230
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
* @param selector - The function selector.
|
|
228
|
-
* @returns A Promise that resolves to a Buffer containing the bytecode of the specified function.
|
|
229
|
-
* @throws Error if the contract address is unknown or not found.
|
|
230
|
-
*/
|
|
231
|
-
public async getBytecode(contractAddress: AztecAddress, selector: FunctionSelector) {
|
|
232
|
-
const tree = await this.getTreeForAddress(contractAddress);
|
|
233
|
-
return tree.getBytecode(selector);
|
|
231
|
+
public async getPublicFunctionDebugMetadata(
|
|
232
|
+
contractAddress: AztecAddress,
|
|
233
|
+
): Promise<FunctionDebugMetadata | undefined> {
|
|
234
|
+
const artifact = await this.#getContractArtifactByAddress(contractAddress);
|
|
235
|
+
const fnArtifact = artifact && artifact.functions.find(fn => fn.functionType === FunctionType.PUBLIC);
|
|
236
|
+
return fnArtifact && getFunctionDebugMetadata(artifact, fnArtifact);
|
|
234
237
|
}
|
|
235
238
|
|
|
236
239
|
/**
|
|
@@ -245,21 +248,20 @@ export class ContractDataProvider implements DataProvider {
|
|
|
245
248
|
public async getFunctionMembershipWitness(
|
|
246
249
|
contractClassId: Fr,
|
|
247
250
|
selector: FunctionSelector,
|
|
248
|
-
): Promise<MembershipWitness<5
|
|
249
|
-
const tree = await this
|
|
250
|
-
return tree
|
|
251
|
+
): Promise<MembershipWitness<5> | undefined> {
|
|
252
|
+
const tree = await this.#getPrivateFunctionTreeForClassId(contractClassId);
|
|
253
|
+
return tree?.getFunctionMembershipWitness(selector);
|
|
251
254
|
}
|
|
252
255
|
|
|
253
256
|
public async getDebugContractName(contractAddress: AztecAddress) {
|
|
254
|
-
const
|
|
255
|
-
return
|
|
257
|
+
const artifact = await this.#getContractArtifactByAddress(contractAddress);
|
|
258
|
+
return artifact?.name;
|
|
256
259
|
}
|
|
257
260
|
|
|
258
261
|
public async getDebugFunctionName(contractAddress: AztecAddress, selector: FunctionSelector) {
|
|
259
|
-
const
|
|
260
|
-
const
|
|
261
|
-
|
|
262
|
-
return `${contractName}:${functionName}`;
|
|
262
|
+
const artifact = await this.#getContractArtifactByAddress(contractAddress);
|
|
263
|
+
const fnArtifact = artifact && (await this.#findFunctionAbiBySelector(artifact, selector));
|
|
264
|
+
return `${artifact?.name ?? contractAddress}:${fnArtifact?.name ?? selector}`;
|
|
263
265
|
}
|
|
264
266
|
|
|
265
267
|
public async getSize() {
|
|
@@ -267,4 +269,32 @@ export class ContractDataProvider implements DataProvider {
|
|
|
267
269
|
.concat(await toArray(this.#contractArtifacts.valuesAsync()))
|
|
268
270
|
.reduce((sum, value) => sum + value.length, 0);
|
|
269
271
|
}
|
|
272
|
+
|
|
273
|
+
async #findFunctionArtifactBySelector(
|
|
274
|
+
artifact: ContractArtifact,
|
|
275
|
+
selector: FunctionSelector,
|
|
276
|
+
): Promise<FunctionArtifact | undefined> {
|
|
277
|
+
const functions = artifact.functions;
|
|
278
|
+
for (let i = 0; i < functions.length; i++) {
|
|
279
|
+
const fn = functions[i];
|
|
280
|
+
const fnSelector = await FunctionSelector.fromNameAndParameters(fn.name, fn.parameters);
|
|
281
|
+
if (fnSelector.equals(selector)) {
|
|
282
|
+
return fn;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
async #findFunctionAbiBySelector(
|
|
288
|
+
artifact: ContractArtifact,
|
|
289
|
+
selector: FunctionSelector,
|
|
290
|
+
): Promise<FunctionAbi | undefined> {
|
|
291
|
+
const functions = [...artifact.functions, ...(artifact.nonDispatchPublicFunctions ?? [])];
|
|
292
|
+
for (let i = 0; i < functions.length; i++) {
|
|
293
|
+
const fn = functions[i];
|
|
294
|
+
const fnSelector = await FunctionSelector.fromNameAndParameters(fn.name, fn.parameters);
|
|
295
|
+
if (fnSelector.equals(selector)) {
|
|
296
|
+
return fn;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
}
|
|
270
300
|
}
|
|
@@ -2,12 +2,12 @@ import { FUNCTION_TREE_HEIGHT } from '@aztec/constants';
|
|
|
2
2
|
import { Fr } from '@aztec/foundation/fields';
|
|
3
3
|
import { assertLength } from '@aztec/foundation/serialize';
|
|
4
4
|
import { MembershipWitness, type MerkleTree } from '@aztec/foundation/trees';
|
|
5
|
-
import { type ContractArtifact,
|
|
5
|
+
import { type ContractArtifact, FunctionSelector, FunctionType } from '@aztec/stdlib/abi';
|
|
6
6
|
import {
|
|
7
|
-
type
|
|
7
|
+
type PrivateFunction,
|
|
8
8
|
computePrivateFunctionLeaf,
|
|
9
9
|
computePrivateFunctionsTree,
|
|
10
|
-
|
|
10
|
+
getContractClassPrivateFunctionFromArtifact,
|
|
11
11
|
} from '@aztec/stdlib/contract';
|
|
12
12
|
|
|
13
13
|
/**
|
|
@@ -19,78 +19,15 @@ import {
|
|
|
19
19
|
export class PrivateFunctionsTree {
|
|
20
20
|
private tree?: MerkleTree;
|
|
21
21
|
|
|
22
|
-
private constructor(private readonly
|
|
22
|
+
private constructor(private readonly privateFunctions: PrivateFunction[]) {}
|
|
23
23
|
|
|
24
24
|
static async create(artifact: ContractArtifact) {
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Retrieve the artifact of a given function.
|
|
31
|
-
* The function is identified by its selector, which represents a unique identifier for the function's signature.
|
|
32
|
-
* Throws an error if the function with the provided selector is not found in the contract.
|
|
33
|
-
*
|
|
34
|
-
* @param selector - The function selector.
|
|
35
|
-
* @returns The artifact object containing relevant information about the targeted function.
|
|
36
|
-
*/
|
|
37
|
-
public async getFunctionArtifact(selector: FunctionSelector): Promise<FunctionArtifact> {
|
|
38
|
-
const functionsAndSelectors = await Promise.all(
|
|
39
|
-
this.artifact.functions.map(async f => ({
|
|
40
|
-
f,
|
|
41
|
-
selector: await FunctionSelector.fromNameAndParameters(f.name, f.parameters),
|
|
42
|
-
})),
|
|
25
|
+
const privateFunctions = await Promise.all(
|
|
26
|
+
artifact.functions
|
|
27
|
+
.filter(fn => fn.functionType === FunctionType.PRIVATE)
|
|
28
|
+
.map(getContractClassPrivateFunctionFromArtifact),
|
|
43
29
|
);
|
|
44
|
-
|
|
45
|
-
if (!artifact) {
|
|
46
|
-
throw new Error(
|
|
47
|
-
`Unknown function. Selector ${selector.toString()} not found in the artifact ${
|
|
48
|
-
this.artifact.name
|
|
49
|
-
} with class ${this.getContractClassId().toString()}.`,
|
|
50
|
-
);
|
|
51
|
-
}
|
|
52
|
-
return artifact;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Retrieve the bytecode of a function in the contract by its function selector.
|
|
57
|
-
* The function selector is a unique identifier for each function in a contract.
|
|
58
|
-
* Throws an error if the function with the given selector is not found in the contract.
|
|
59
|
-
*
|
|
60
|
-
* @param selector - The selector of a function to get bytecode for.
|
|
61
|
-
* @returns The bytecode of the function as a string.
|
|
62
|
-
*/
|
|
63
|
-
public async getBytecode(selector: FunctionSelector) {
|
|
64
|
-
const artifact = await this.getFunctionArtifact(selector);
|
|
65
|
-
return artifact.bytecode;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Calculate and return the root of the function tree for the current contract.
|
|
70
|
-
* This root is a cryptographic commitment to the set of constrained functions within the contract,
|
|
71
|
-
* which is used in the Aztec node's proof system. The root will be cached after the first call.
|
|
72
|
-
*
|
|
73
|
-
* @returns A promise that resolves to the Fr (finite field element) representation of the function tree root.
|
|
74
|
-
*/
|
|
75
|
-
public getFunctionTreeRoot() {
|
|
76
|
-
return this.getTree();
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
/** Returns the contract class object. */
|
|
80
|
-
public getContractClass() {
|
|
81
|
-
return this.contractClass;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/** Returns the contract artifact. */
|
|
85
|
-
public getArtifact() {
|
|
86
|
-
return this.artifact;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* Returns the contract class identifier for the given artifact.
|
|
91
|
-
*/
|
|
92
|
-
public getContractClassId() {
|
|
93
|
-
return this.getContractClass().id;
|
|
30
|
+
return new PrivateFunctionsTree(privateFunctions);
|
|
94
31
|
}
|
|
95
32
|
|
|
96
33
|
/**
|
|
@@ -105,7 +42,7 @@ export class PrivateFunctionsTree {
|
|
|
105
42
|
public async getFunctionMembershipWitness(
|
|
106
43
|
selector: FunctionSelector,
|
|
107
44
|
): Promise<MembershipWitness<typeof FUNCTION_TREE_HEIGHT>> {
|
|
108
|
-
const fn = this.
|
|
45
|
+
const fn = this.privateFunctions.find(f => f.selector.equals(selector));
|
|
109
46
|
if (!fn) {
|
|
110
47
|
throw new Error(`Private function with selector ${selector.toString()} not found in contract class.`);
|
|
111
48
|
}
|
|
@@ -123,8 +60,7 @@ export class PrivateFunctionsTree {
|
|
|
123
60
|
|
|
124
61
|
private async getTree() {
|
|
125
62
|
if (!this.tree) {
|
|
126
|
-
|
|
127
|
-
this.tree = await computePrivateFunctionsTree(fns);
|
|
63
|
+
this.tree = await computePrivateFunctionsTree(this.privateFunctions);
|
|
128
64
|
}
|
|
129
65
|
return this.tree;
|
|
130
66
|
}
|
|
@@ -81,7 +81,9 @@ export const pxeTestSuite = (testName: string, pxeSetup: () => Promise<PXE>) =>
|
|
|
81
81
|
|
|
82
82
|
it('refuses to register a contract with a class that has not been registered', async () => {
|
|
83
83
|
const instance = await randomContractInstanceWithAddress();
|
|
84
|
-
await expect(pxe.registerContract({ instance })).rejects.toThrow(
|
|
84
|
+
await expect(pxe.registerContract({ instance })).rejects.toThrow(
|
|
85
|
+
/Artifact not found when registering an instance/,
|
|
86
|
+
);
|
|
85
87
|
});
|
|
86
88
|
|
|
87
89
|
it('refuses to register a contract with an artifact with mismatching class id', async () => {
|