@aztec/simulator 0.72.1 → 0.73.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/README.md +1 -1
- package/dest/avm/avm_simulator.d.ts +0 -1
- package/dest/avm/avm_simulator.d.ts.map +1 -1
- package/dest/avm/avm_simulator.js +4 -19
- package/dest/avm/avm_tree.d.ts +9 -8
- package/dest/avm/avm_tree.d.ts.map +1 -1
- package/dest/avm/avm_tree.js +35 -30
- package/dest/avm/fixtures/avm_simulation_tester.d.ts +21 -0
- package/dest/avm/fixtures/avm_simulation_tester.d.ts.map +1 -0
- package/dest/avm/fixtures/avm_simulation_tester.js +74 -0
- package/dest/avm/fixtures/base_avm_simulation_tester.d.ts +35 -0
- package/dest/avm/fixtures/base_avm_simulation_tester.d.ts.map +1 -0
- package/dest/avm/fixtures/base_avm_simulation_tester.js +76 -0
- package/dest/avm/fixtures/index.d.ts +6 -2
- package/dest/avm/fixtures/index.d.ts.map +1 -1
- package/dest/avm/fixtures/index.js +28 -14
- package/dest/avm/fixtures/simple_contract_data_source.d.ts +31 -0
- package/dest/avm/fixtures/simple_contract_data_source.d.ts.map +1 -0
- package/dest/avm/fixtures/simple_contract_data_source.js +75 -0
- package/dest/avm/journal/journal.d.ts +3 -3
- package/dest/avm/journal/journal.d.ts.map +1 -1
- package/dest/avm/journal/journal.js +24 -21
- package/dest/avm/opcodes/accrued_substate.js +2 -2
- package/dest/avm/opcodes/hashing.js +2 -2
- package/dest/avm/test_utils.d.ts +1 -1
- package/dest/avm/test_utils.d.ts.map +1 -1
- package/dest/avm/test_utils.js +4 -3
- package/dest/client/client_execution_context.d.ts +1 -1
- package/dest/client/client_execution_context.d.ts.map +1 -1
- package/dest/client/client_execution_context.js +21 -18
- package/dest/client/execution_note_cache.d.ts +3 -3
- package/dest/client/execution_note_cache.d.ts.map +1 -1
- package/dest/client/execution_note_cache.js +10 -10
- package/dest/client/pick_notes.js +5 -5
- package/dest/client/simulator.js +4 -4
- package/dest/client/view_data_oracle.js +2 -2
- package/dest/common/hashed_values_cache.d.ts +1 -1
- package/dest/common/hashed_values_cache.d.ts.map +1 -1
- package/dest/common/hashed_values_cache.js +5 -5
- package/dest/providers/acvm_wasm.d.ts +2 -0
- package/dest/providers/acvm_wasm.d.ts.map +1 -1
- package/dest/providers/acvm_wasm.js +15 -2
- package/dest/public/execution.d.ts +1 -1
- package/dest/public/execution.d.ts.map +1 -1
- package/dest/public/execution.js +3 -3
- package/dest/public/fee_payment.d.ts +2 -2
- package/dest/public/fee_payment.d.ts.map +1 -1
- package/dest/public/fee_payment.js +3 -3
- package/dest/public/fixtures/index.d.ts +2 -37
- package/dest/public/fixtures/index.d.ts.map +1 -1
- package/dest/public/fixtures/index.js +3 -250
- package/dest/public/fixtures/public_tx_simulation_tester.d.ts +21 -0
- package/dest/public/fixtures/public_tx_simulation_tester.d.ts.map +1 -0
- package/dest/public/fixtures/public_tx_simulation_tester.js +89 -0
- package/dest/public/fixtures/utils.d.ts +17 -0
- package/dest/public/fixtures/utils.d.ts.map +1 -0
- package/dest/public/fixtures/utils.js +66 -0
- package/dest/public/index.d.ts +1 -1
- package/dest/public/index.d.ts.map +1 -1
- package/dest/public/index.js +2 -2
- package/dest/public/public_db_sources.d.ts +2 -1
- package/dest/public/public_db_sources.d.ts.map +1 -1
- package/dest/public/public_db_sources.js +27 -21
- package/dest/public/public_processor.d.ts +1 -1
- package/dest/public/public_processor.d.ts.map +1 -1
- package/dest/public/public_processor.js +19 -18
- package/dest/public/public_tx_context.d.ts +5 -5
- package/dest/public/public_tx_context.d.ts.map +1 -1
- package/dest/public/public_tx_context.js +43 -17
- package/dest/public/public_tx_simulator.js +7 -7
- package/dest/public/{enqueued_call_side_effect_trace.d.ts → side_effect_trace.d.ts} +5 -5
- package/dest/public/side_effect_trace.d.ts.map +1 -0
- package/dest/public/{enqueued_call_side_effect_trace.js → side_effect_trace.js} +7 -7
- package/dest/public/side_effect_trace_interface.d.ts +1 -1
- package/dest/public/side_effect_trace_interface.d.ts.map +1 -1
- package/dest/test/utils.d.ts +1 -1
- package/dest/test/utils.d.ts.map +1 -1
- package/dest/test/utils.js +3 -3
- package/package.json +9 -9
- package/src/avm/avm_simulator.ts +3 -27
- package/src/avm/avm_tree.ts +39 -37
- package/src/avm/fixtures/avm_simulation_tester.ts +105 -0
- package/src/avm/fixtures/base_avm_simulation_tester.ts +104 -0
- package/src/avm/fixtures/index.ts +46 -17
- package/src/avm/fixtures/simple_contract_data_source.ts +98 -0
- package/src/avm/journal/journal.ts +24 -21
- package/src/avm/opcodes/accrued_substate.ts +1 -1
- package/src/avm/opcodes/hashing.ts +1 -1
- package/src/avm/test_utils.ts +3 -4
- package/src/client/client_execution_context.ts +27 -21
- package/src/client/execution_note_cache.ts +19 -14
- package/src/client/pick_notes.ts +4 -4
- package/src/client/simulator.ts +3 -3
- package/src/client/view_data_oracle.ts +1 -1
- package/src/common/hashed_values_cache.ts +4 -4
- package/src/providers/acvm_wasm.ts +13 -2
- package/src/public/execution.ts +3 -3
- package/src/public/fee_payment.ts +2 -2
- package/src/public/fixtures/index.ts +2 -387
- package/src/public/fixtures/public_tx_simulation_tester.ts +174 -0
- package/src/public/fixtures/utils.ts +110 -0
- package/src/public/index.ts +1 -1
- package/src/public/public_db_sources.ts +31 -20
- package/src/public/public_processor.ts +25 -18
- package/src/public/public_tx_context.ts +86 -27
- package/src/public/public_tx_simulator.ts +6 -6
- package/src/public/{enqueued_call_side_effect_trace.ts → side_effect_trace.ts} +7 -7
- package/src/public/side_effect_trace_interface.ts +1 -1
- package/src/test/utils.ts +2 -2
- package/dest/public/enqueued_call_side_effect_trace.d.ts.map +0 -1
- package/dest/public/transitional_adapters.d.ts +0 -4
- package/dest/public/transitional_adapters.d.ts.map +0 -1
- package/dest/public/transitional_adapters.js +0 -29
- package/src/public/transitional_adapters.ts +0 -113
|
@@ -1,387 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
type AvmCircuitInputs,
|
|
4
|
-
BlockHeader,
|
|
5
|
-
CallContext,
|
|
6
|
-
type ContractClassPublic,
|
|
7
|
-
type ContractDataSource,
|
|
8
|
-
type ContractInstanceWithAddress,
|
|
9
|
-
DEFAULT_GAS_LIMIT,
|
|
10
|
-
DEPLOYER_CONTRACT_ADDRESS,
|
|
11
|
-
FunctionSelector,
|
|
12
|
-
Gas,
|
|
13
|
-
GasFees,
|
|
14
|
-
GasSettings,
|
|
15
|
-
GlobalVariables,
|
|
16
|
-
MAX_L2_GAS_PER_TX_PUBLIC_PORTION,
|
|
17
|
-
MAX_PUBLIC_CALLS_TO_UNIQUE_CONTRACT_CLASS_IDS,
|
|
18
|
-
PartialPrivateTailPublicInputsForPublic,
|
|
19
|
-
PrivateKernelTailCircuitPublicInputs,
|
|
20
|
-
type PublicFunction,
|
|
21
|
-
PublicKeys,
|
|
22
|
-
RollupValidationRequests,
|
|
23
|
-
SerializableContractInstance,
|
|
24
|
-
TxConstantData,
|
|
25
|
-
TxContext,
|
|
26
|
-
computePublicBytecodeCommitment,
|
|
27
|
-
} from '@aztec/circuits.js';
|
|
28
|
-
import { siloNullifier } from '@aztec/circuits.js/hash';
|
|
29
|
-
import { makeContractClassPublic, makeContractInstanceFromClassId } from '@aztec/circuits.js/testing';
|
|
30
|
-
import { type ContractArtifact, type FunctionArtifact } from '@aztec/foundation/abi';
|
|
31
|
-
import { AztecAddress } from '@aztec/foundation/aztec-address';
|
|
32
|
-
import { Fr, Point } from '@aztec/foundation/fields';
|
|
33
|
-
import { openTmpStore } from '@aztec/kv-store/lmdb';
|
|
34
|
-
import { AvmTestContractArtifact } from '@aztec/noir-contracts.js/AvmTest';
|
|
35
|
-
import { MerkleTrees } from '@aztec/world-state';
|
|
36
|
-
|
|
37
|
-
import { strict as assert } from 'assert';
|
|
38
|
-
|
|
39
|
-
import { initContext, initExecutionEnvironment, initPersistableStateManager } from '../../avm/fixtures/index.js';
|
|
40
|
-
import { AvmEphemeralForest, AvmSimulator } from '../../server.js';
|
|
41
|
-
import { PublicEnqueuedCallSideEffectTrace } from '../enqueued_call_side_effect_trace.js';
|
|
42
|
-
import { WorldStateDB } from '../public_db_sources.js';
|
|
43
|
-
import { PublicTxSimulator } from '../public_tx_simulator.js';
|
|
44
|
-
|
|
45
|
-
const TIMESTAMP = new Fr(99833);
|
|
46
|
-
|
|
47
|
-
export async function simulateAvmTestContractGenerateCircuitInputs(
|
|
48
|
-
setupFunctionNames: string[],
|
|
49
|
-
setupArgs: Fr[][] = [],
|
|
50
|
-
appFunctionNames: string[],
|
|
51
|
-
appArgs: Fr[][] = [],
|
|
52
|
-
teardownFunctionName?: string,
|
|
53
|
-
teardownArgs: Fr[] = [],
|
|
54
|
-
expectRevert: boolean = false,
|
|
55
|
-
contractDataSource?: MockedAvmTestContractDataSource,
|
|
56
|
-
assertionErrString?: string,
|
|
57
|
-
): Promise<AvmCircuitInputs> {
|
|
58
|
-
const globals = GlobalVariables.empty();
|
|
59
|
-
globals.timestamp = TIMESTAMP;
|
|
60
|
-
|
|
61
|
-
const merkleTrees = await (await MerkleTrees.new(openTmpStore())).fork();
|
|
62
|
-
if (!contractDataSource) {
|
|
63
|
-
contractDataSource = await MockedAvmTestContractDataSource.create();
|
|
64
|
-
}
|
|
65
|
-
await contractDataSource.deployContracts(merkleTrees);
|
|
66
|
-
const worldStateDB = new WorldStateDB(merkleTrees, contractDataSource);
|
|
67
|
-
|
|
68
|
-
const simulator = new PublicTxSimulator(merkleTrees, worldStateDB, globals, /*doMerkleOperations=*/ true);
|
|
69
|
-
|
|
70
|
-
const sender = await AztecAddress.random();
|
|
71
|
-
const callContext = new CallContext(
|
|
72
|
-
sender,
|
|
73
|
-
contractDataSource.firstContractInstance.address,
|
|
74
|
-
contractDataSource.fnSelector,
|
|
75
|
-
/*isStaticCall=*/ false,
|
|
76
|
-
);
|
|
77
|
-
const setupExecutionRequests: PublicExecutionRequest[] = [];
|
|
78
|
-
for (let i = 0; i < setupFunctionNames.length; i++) {
|
|
79
|
-
const functionSelector = getAvmTestContractFunctionSelector(setupFunctionNames[i]);
|
|
80
|
-
const fnArgs = [functionSelector.toField(), ...setupArgs[i]];
|
|
81
|
-
const executionRequest = new PublicExecutionRequest(callContext, fnArgs);
|
|
82
|
-
setupExecutionRequests.push(executionRequest);
|
|
83
|
-
}
|
|
84
|
-
const appExecutionRequests: PublicExecutionRequest[] = [];
|
|
85
|
-
for (let i = 0; i < appFunctionNames.length; i++) {
|
|
86
|
-
const functionSelector = getAvmTestContractFunctionSelector(appFunctionNames[i]);
|
|
87
|
-
const fnArgs = [functionSelector.toField(), ...appArgs[i]];
|
|
88
|
-
const executionRequest = new PublicExecutionRequest(callContext, fnArgs);
|
|
89
|
-
appExecutionRequests.push(executionRequest);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
let teardownExecutionRequest: PublicExecutionRequest | undefined = undefined;
|
|
93
|
-
if (teardownFunctionName) {
|
|
94
|
-
const functionSelector = getAvmTestContractFunctionSelector(teardownFunctionName);
|
|
95
|
-
const fnArgs = [functionSelector.toField(), ...teardownArgs];
|
|
96
|
-
teardownExecutionRequest = new PublicExecutionRequest(callContext, fnArgs);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
const tx: Tx = createTxForPublicCalls(
|
|
100
|
-
setupExecutionRequests,
|
|
101
|
-
appExecutionRequests,
|
|
102
|
-
Fr.random(),
|
|
103
|
-
teardownExecutionRequest,
|
|
104
|
-
);
|
|
105
|
-
|
|
106
|
-
const avmResult = await simulator.simulate(tx);
|
|
107
|
-
|
|
108
|
-
if (!expectRevert) {
|
|
109
|
-
expect(avmResult.revertCode.isOK()).toBe(true);
|
|
110
|
-
} else {
|
|
111
|
-
// Explicit revert when an assertion failed.
|
|
112
|
-
expect(avmResult.revertCode.isOK()).toBe(false);
|
|
113
|
-
expect(avmResult.revertReason).toBeDefined();
|
|
114
|
-
if (assertionErrString !== undefined) {
|
|
115
|
-
expect(avmResult.revertReason?.getMessage()).toContain(assertionErrString);
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
const avmCircuitInputs: AvmCircuitInputs = avmResult.avmProvingRequest.inputs;
|
|
120
|
-
return avmCircuitInputs;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
export async function simulateAvmTestContractCall(
|
|
124
|
-
functionName: string,
|
|
125
|
-
args: Fr[] = [],
|
|
126
|
-
expectRevert: boolean = false,
|
|
127
|
-
contractDataSource?: MockedAvmTestContractDataSource,
|
|
128
|
-
) {
|
|
129
|
-
const globals = GlobalVariables.empty();
|
|
130
|
-
globals.timestamp = TIMESTAMP;
|
|
131
|
-
|
|
132
|
-
if (!contractDataSource) {
|
|
133
|
-
contractDataSource = await MockedAvmTestContractDataSource.create();
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
const merkleTrees = await (await MerkleTrees.new(openTmpStore())).fork();
|
|
137
|
-
await contractDataSource.deployContracts(merkleTrees);
|
|
138
|
-
const worldStateDB = new WorldStateDB(merkleTrees, contractDataSource);
|
|
139
|
-
|
|
140
|
-
const trace = new PublicEnqueuedCallSideEffectTrace();
|
|
141
|
-
const ephemeralTrees = await AvmEphemeralForest.create(worldStateDB.getMerkleInterface());
|
|
142
|
-
const persistableState = initPersistableStateManager({
|
|
143
|
-
worldStateDB,
|
|
144
|
-
trace,
|
|
145
|
-
merkleTrees: ephemeralTrees,
|
|
146
|
-
doMerkleOperations: true,
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
const sender = await AztecAddress.random();
|
|
150
|
-
const functionSelector = getAvmTestContractFunctionSelector(functionName);
|
|
151
|
-
args = [functionSelector.toField(), ...args];
|
|
152
|
-
const environment = initExecutionEnvironment({
|
|
153
|
-
calldata: args,
|
|
154
|
-
globals,
|
|
155
|
-
address: contractDataSource.firstContractInstance.address,
|
|
156
|
-
sender,
|
|
157
|
-
});
|
|
158
|
-
const context = initContext({ env: environment, persistableState });
|
|
159
|
-
|
|
160
|
-
// First we simulate (though it's not needed in this simple case).
|
|
161
|
-
const simulator = new AvmSimulator(context);
|
|
162
|
-
const results = await simulator.execute();
|
|
163
|
-
|
|
164
|
-
expect(results.reverted).toBe(expectRevert);
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
/**
|
|
168
|
-
* Craft a carrier transaction for some public calls for simulation by PublicTxSimulator.
|
|
169
|
-
*/
|
|
170
|
-
export function createTxForPublicCalls(
|
|
171
|
-
setupExecutionRequests: PublicExecutionRequest[],
|
|
172
|
-
appExecutionRequests: PublicExecutionRequest[],
|
|
173
|
-
firstNullifier: Fr,
|
|
174
|
-
teardownExecutionRequest?: PublicExecutionRequest,
|
|
175
|
-
gasUsedByPrivate: Gas = Gas.empty(),
|
|
176
|
-
): Tx {
|
|
177
|
-
assert(
|
|
178
|
-
setupExecutionRequests.length > 0 || appExecutionRequests.length > 0 || teardownExecutionRequest !== undefined,
|
|
179
|
-
"Can't create public tx with no enqueued calls",
|
|
180
|
-
);
|
|
181
|
-
const setupCallRequests = setupExecutionRequests.map(er => er.toCallRequest());
|
|
182
|
-
const appCallRequests = appExecutionRequests.map(er => er.toCallRequest());
|
|
183
|
-
// use max limits
|
|
184
|
-
const gasLimits = new Gas(DEFAULT_GAS_LIMIT, MAX_L2_GAS_PER_TX_PUBLIC_PORTION);
|
|
185
|
-
|
|
186
|
-
const forPublic = PartialPrivateTailPublicInputsForPublic.empty();
|
|
187
|
-
// TODO(#9269): Remove this fake nullifier method as we move away from 1st nullifier as hash.
|
|
188
|
-
forPublic.nonRevertibleAccumulatedData.nullifiers[0] = firstNullifier; // fake tx nullifier
|
|
189
|
-
|
|
190
|
-
// We reverse order because the simulator expects it to be like a "stack" of calls to pop from
|
|
191
|
-
for (let i = setupCallRequests.length - 1; i >= 0; i--) {
|
|
192
|
-
forPublic.nonRevertibleAccumulatedData.publicCallRequests[i] = setupCallRequests[i];
|
|
193
|
-
}
|
|
194
|
-
for (let i = appCallRequests.length - 1; i >= 0; i--) {
|
|
195
|
-
forPublic.revertibleAccumulatedData.publicCallRequests[i] = appCallRequests[i];
|
|
196
|
-
}
|
|
197
|
-
if (teardownExecutionRequest) {
|
|
198
|
-
forPublic.publicTeardownCallRequest = teardownExecutionRequest.toCallRequest();
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
const teardownGasLimits = teardownExecutionRequest ? gasLimits : Gas.empty();
|
|
202
|
-
const gasSettings = new GasSettings(gasLimits, teardownGasLimits, GasFees.empty(), GasFees.empty());
|
|
203
|
-
const txContext = new TxContext(Fr.zero(), Fr.zero(), gasSettings);
|
|
204
|
-
const constantData = new TxConstantData(BlockHeader.empty(), txContext, Fr.zero(), Fr.zero());
|
|
205
|
-
|
|
206
|
-
const txData = new PrivateKernelTailCircuitPublicInputs(
|
|
207
|
-
constantData,
|
|
208
|
-
RollupValidationRequests.empty(),
|
|
209
|
-
/*gasUsed=*/ gasUsedByPrivate,
|
|
210
|
-
AztecAddress.zero(),
|
|
211
|
-
forPublic,
|
|
212
|
-
);
|
|
213
|
-
const tx = Tx.newWithTxData(txData, teardownExecutionRequest);
|
|
214
|
-
|
|
215
|
-
// Reverse order because the simulator expects it to be like a "stack" of calls to pop from.
|
|
216
|
-
// Also push app calls before setup calls for this reason.
|
|
217
|
-
for (let i = appExecutionRequests.length - 1; i >= 0; i--) {
|
|
218
|
-
tx.enqueuedPublicFunctionCalls.push(appExecutionRequests[i]);
|
|
219
|
-
}
|
|
220
|
-
for (let i = setupExecutionRequests.length - 1; i >= 0; i--) {
|
|
221
|
-
tx.enqueuedPublicFunctionCalls.push(setupExecutionRequests[i]);
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
return tx;
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
export class MockedAvmTestContractDataSource implements ContractDataSource {
|
|
228
|
-
private fnName = 'public_dispatch';
|
|
229
|
-
public fnSelector: FunctionSelector = getAvmTestContractFunctionSelector(this.fnName);
|
|
230
|
-
private bytecode: Buffer;
|
|
231
|
-
private publicFn: PublicFunction;
|
|
232
|
-
private bytecodeCommitment: Fr;
|
|
233
|
-
|
|
234
|
-
// maps contract class ID to class
|
|
235
|
-
private contractClasses: Map<string, ContractClassPublic> = new Map();
|
|
236
|
-
// maps contract instance address to instance
|
|
237
|
-
public contractInstances: Map<string, ContractInstanceWithAddress> = new Map();
|
|
238
|
-
|
|
239
|
-
public firstContractInstance: ContractInstanceWithAddress = SerializableContractInstance.default().withAddress(
|
|
240
|
-
AztecAddress.fromNumber(0),
|
|
241
|
-
);
|
|
242
|
-
public instanceSameClassAsFirstContract: ContractInstanceWithAddress =
|
|
243
|
-
SerializableContractInstance.default().withAddress(AztecAddress.fromNumber(0));
|
|
244
|
-
public otherContractInstance!: ContractInstanceWithAddress;
|
|
245
|
-
|
|
246
|
-
private constructor(private skipContractDeployments: boolean) {
|
|
247
|
-
this.bytecode = getAvmTestContractBytecode(this.fnName);
|
|
248
|
-
this.fnSelector = getAvmTestContractFunctionSelector(this.fnName);
|
|
249
|
-
this.publicFn = { bytecode: this.bytecode, selector: this.fnSelector };
|
|
250
|
-
this.bytecodeCommitment = computePublicBytecodeCommitment(this.bytecode);
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
async deployContracts(merkleTrees: MerkleTreeWriteOperations) {
|
|
254
|
-
if (!this.skipContractDeployments) {
|
|
255
|
-
for (const contractInstance of this.contractInstances.values()) {
|
|
256
|
-
const contractAddressNullifier = siloNullifier(
|
|
257
|
-
AztecAddress.fromNumber(DEPLOYER_CONTRACT_ADDRESS),
|
|
258
|
-
contractInstance.address.toField(),
|
|
259
|
-
);
|
|
260
|
-
await merkleTrees.batchInsert(MerkleTreeId.NULLIFIER_TREE, [contractAddressNullifier.toBuffer()], 0);
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
const instanceSameClassAsFirstContractNullifier = siloNullifier(
|
|
264
|
-
AztecAddress.fromNumber(DEPLOYER_CONTRACT_ADDRESS),
|
|
265
|
-
this.instanceSameClassAsFirstContract.address.toField(),
|
|
266
|
-
);
|
|
267
|
-
await merkleTrees.batchInsert(
|
|
268
|
-
MerkleTreeId.NULLIFIER_TREE,
|
|
269
|
-
[instanceSameClassAsFirstContractNullifier.toBuffer()],
|
|
270
|
-
0,
|
|
271
|
-
);
|
|
272
|
-
|
|
273
|
-
// other contract address used by the bulk test's GETCONTRACTINSTANCE test
|
|
274
|
-
const otherContractAddressNullifier = siloNullifier(
|
|
275
|
-
AztecAddress.fromNumber(DEPLOYER_CONTRACT_ADDRESS),
|
|
276
|
-
this.otherContractInstance.address.toField(),
|
|
277
|
-
);
|
|
278
|
-
await merkleTrees.batchInsert(MerkleTreeId.NULLIFIER_TREE, [otherContractAddressNullifier.toBuffer()], 0);
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
public static async create(skipContractDeployments: boolean = false): Promise<MockedAvmTestContractDataSource> {
|
|
283
|
-
const dataSource = new MockedAvmTestContractDataSource(skipContractDeployments);
|
|
284
|
-
// create enough unique classes to hit the limit (plus two extra)
|
|
285
|
-
for (let i = 0; i < MAX_PUBLIC_CALLS_TO_UNIQUE_CONTRACT_CLASS_IDS + 1; i++) {
|
|
286
|
-
const contractClass = makeContractClassPublic(/*seed=*/ i, dataSource.publicFn);
|
|
287
|
-
const contractInstance = await makeContractInstanceFromClassId(contractClass.id, /*seed=*/ i);
|
|
288
|
-
dataSource.contractClasses.set(contractClass.id.toString(), contractClass);
|
|
289
|
-
dataSource.contractInstances.set(contractInstance.address.toString(), contractInstance);
|
|
290
|
-
if (i === 0) {
|
|
291
|
-
dataSource.firstContractInstance = contractInstance;
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
// a contract with the same class but different instance/address as the first contract
|
|
295
|
-
dataSource.instanceSameClassAsFirstContract = await makeContractInstanceFromClassId(
|
|
296
|
-
dataSource.firstContractInstance.contractClassId,
|
|
297
|
-
/*seed=*/ 1000,
|
|
298
|
-
);
|
|
299
|
-
|
|
300
|
-
// The values here should match those in `avm_simulator.test.ts`
|
|
301
|
-
// Used for GETCONTRACTINSTANCE test
|
|
302
|
-
dataSource.otherContractInstance = new SerializableContractInstance({
|
|
303
|
-
version: 1,
|
|
304
|
-
salt: new Fr(0x123),
|
|
305
|
-
deployer: new AztecAddress(new Fr(0x456)),
|
|
306
|
-
contractClassId: new Fr(0x789),
|
|
307
|
-
initializationHash: new Fr(0x101112),
|
|
308
|
-
publicKeys: new PublicKeys(
|
|
309
|
-
new Point(new Fr(0x131415), new Fr(0x161718), false),
|
|
310
|
-
new Point(new Fr(0x192021), new Fr(0x222324), false),
|
|
311
|
-
new Point(new Fr(0x252627), new Fr(0x282930), false),
|
|
312
|
-
new Point(new Fr(0x313233), new Fr(0x343536), false),
|
|
313
|
-
),
|
|
314
|
-
}).withAddress(AztecAddress.fromNumber(0x4444));
|
|
315
|
-
return dataSource;
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
getPublicFunction(_address: AztecAddress, _selector: FunctionSelector): Promise<PublicFunction> {
|
|
319
|
-
return Promise.resolve(this.publicFn);
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
getBlockNumber(): Promise<number> {
|
|
323
|
-
throw new Error('Method not implemented.');
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
getContractClass(id: Fr): Promise<ContractClassPublic | undefined> {
|
|
327
|
-
return Promise.resolve(this.contractClasses.get(id.toString()));
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
getBytecodeCommitment(_id: Fr): Promise<Fr> {
|
|
331
|
-
return Promise.resolve(this.bytecodeCommitment);
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
addContractClass(_contractClass: ContractClassPublic): Promise<void> {
|
|
335
|
-
return Promise.resolve();
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
getContract(address: AztecAddress): Promise<ContractInstanceWithAddress | undefined> {
|
|
339
|
-
if (!this.skipContractDeployments) {
|
|
340
|
-
if (address.equals(this.otherContractInstance.address)) {
|
|
341
|
-
return Promise.resolve(this.otherContractInstance);
|
|
342
|
-
} else if (address.equals(this.instanceSameClassAsFirstContract.address)) {
|
|
343
|
-
return Promise.resolve(this.instanceSameClassAsFirstContract);
|
|
344
|
-
} else {
|
|
345
|
-
return Promise.resolve(this.contractInstances.get(address.toString()));
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
return Promise.resolve(undefined);
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
getContractClassIds(): Promise<Fr[]> {
|
|
352
|
-
throw new Error('Method not implemented.');
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
getContractArtifact(_address: AztecAddress): Promise<ContractArtifact | undefined> {
|
|
356
|
-
throw new Error('Method not implemented.');
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
getContractFunctionName(_address: AztecAddress, _selector: FunctionSelector): Promise<string> {
|
|
360
|
-
return Promise.resolve(this.fnName);
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
registerContractFunctionSignatures(_address: AztecAddress, _signatures: string[]): Promise<void> {
|
|
364
|
-
return Promise.resolve();
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
function getAvmTestContractFunctionSelector(functionName: string): FunctionSelector {
|
|
369
|
-
const artifact = AvmTestContractArtifact.functions.find(f => f.name === functionName)!;
|
|
370
|
-
assert(!!artifact, `Function ${functionName} not found in AvmTestContractArtifact`);
|
|
371
|
-
const params = artifact.parameters;
|
|
372
|
-
return FunctionSelector.fromNameAndParameters(artifact.name, params);
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
function getAvmTestContractArtifact(functionName: string): FunctionArtifact {
|
|
376
|
-
const artifact = AvmTestContractArtifact.functions.find(f => f.name === functionName)!;
|
|
377
|
-
assert(
|
|
378
|
-
!!artifact?.bytecode,
|
|
379
|
-
`No bytecode found for function ${functionName}. Try re-running bootstrap.sh on the repository root.`,
|
|
380
|
-
);
|
|
381
|
-
return artifact;
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
function getAvmTestContractBytecode(functionName: string): Buffer {
|
|
385
|
-
const artifact = getAvmTestContractArtifact(functionName);
|
|
386
|
-
return artifact.bytecode;
|
|
387
|
-
}
|
|
1
|
+
export * from './public_tx_simulation_tester.js';
|
|
2
|
+
export * from './utils.js';
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import { MerkleTreeId, PublicExecutionRequest, type Tx } from '@aztec/circuit-types';
|
|
2
|
+
import {
|
|
3
|
+
type AvmCircuitPublicInputs,
|
|
4
|
+
CallContext,
|
|
5
|
+
FunctionSelector,
|
|
6
|
+
GasFees,
|
|
7
|
+
GlobalVariables,
|
|
8
|
+
MAX_NOTE_HASHES_PER_TX,
|
|
9
|
+
MAX_NULLIFIERS_PER_TX,
|
|
10
|
+
NULLIFIER_SUBTREE_HEIGHT,
|
|
11
|
+
PUBLIC_DATA_TREE_HEIGHT,
|
|
12
|
+
PUBLIC_DISPATCH_SELECTOR,
|
|
13
|
+
} from '@aztec/circuits.js';
|
|
14
|
+
import { type ContractArtifact, encodeArguments } from '@aztec/foundation/abi';
|
|
15
|
+
import { AztecAddress } from '@aztec/foundation/aztec-address';
|
|
16
|
+
import { padArrayEnd } from '@aztec/foundation/collection';
|
|
17
|
+
import { Fr } from '@aztec/foundation/fields';
|
|
18
|
+
import { openTmpStore } from '@aztec/kv-store/lmdb';
|
|
19
|
+
import { AvmTestContractArtifact } from '@aztec/noir-contracts.js/AvmTest';
|
|
20
|
+
import { MerkleTrees } from '@aztec/world-state';
|
|
21
|
+
|
|
22
|
+
import { BaseAvmSimulationTester } from '../../avm/fixtures/base_avm_simulation_tester.js';
|
|
23
|
+
import { getContractFunctionArtifact, getFunctionSelector } from '../../avm/fixtures/index.js';
|
|
24
|
+
import { SimpleContractDataSource } from '../../avm/fixtures/simple_contract_data_source.js';
|
|
25
|
+
import { WorldStateDB } from '../public_db_sources.js';
|
|
26
|
+
import { type PublicTxResult, PublicTxSimulator } from '../public_tx_simulator.js';
|
|
27
|
+
import { createTxForPublicCalls } from './index.js';
|
|
28
|
+
|
|
29
|
+
const TIMESTAMP = new Fr(99833);
|
|
30
|
+
const DEFAULT_GAS_FEES = new GasFees(2, 3);
|
|
31
|
+
|
|
32
|
+
export type TestEnqueuedCall = {
|
|
33
|
+
address: AztecAddress;
|
|
34
|
+
fnName: string;
|
|
35
|
+
args: any[];
|
|
36
|
+
isStaticCall?: boolean;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* A test class that extends the BaseAvmSimulationTester to enable real-app testing of the PublicTxSimulator.
|
|
41
|
+
* It provides an interface for simulating one transaction at a time and maintains state between subsequent
|
|
42
|
+
* transactions.
|
|
43
|
+
*/
|
|
44
|
+
export class PublicTxSimulationTester extends BaseAvmSimulationTester {
|
|
45
|
+
private txCount = 0;
|
|
46
|
+
|
|
47
|
+
public static async create(skipContractDeployments = false): Promise<PublicTxSimulationTester> {
|
|
48
|
+
const contractDataSource = new SimpleContractDataSource();
|
|
49
|
+
const merkleTrees = await (await MerkleTrees.new(openTmpStore())).fork();
|
|
50
|
+
return new PublicTxSimulationTester(contractDataSource, merkleTrees, skipContractDeployments);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
public async simulateTx(
|
|
54
|
+
sender: AztecAddress,
|
|
55
|
+
setupCalls: TestEnqueuedCall[] = [],
|
|
56
|
+
appCalls: TestEnqueuedCall[] = [],
|
|
57
|
+
teardownCall?: TestEnqueuedCall,
|
|
58
|
+
feePayer: AztecAddress = AztecAddress.zero(),
|
|
59
|
+
): Promise<PublicTxResult> {
|
|
60
|
+
const globals = GlobalVariables.empty();
|
|
61
|
+
globals.timestamp = TIMESTAMP;
|
|
62
|
+
globals.gasFees = DEFAULT_GAS_FEES;
|
|
63
|
+
|
|
64
|
+
const worldStateDB = new WorldStateDB(this.merkleTrees, this.contractDataSource);
|
|
65
|
+
const simulator = new PublicTxSimulator(this.merkleTrees, worldStateDB, globals, /*doMerkleOperations=*/ true);
|
|
66
|
+
|
|
67
|
+
const setupExecutionRequests: PublicExecutionRequest[] = [];
|
|
68
|
+
for (let i = 0; i < setupCalls.length; i++) {
|
|
69
|
+
const address = setupCalls[i].address;
|
|
70
|
+
const contractArtifact = await this.contractDataSource.getContractArtifact(address);
|
|
71
|
+
const req = await executionRequestForCall(
|
|
72
|
+
sender,
|
|
73
|
+
address,
|
|
74
|
+
setupCalls[i].fnName,
|
|
75
|
+
setupCalls[i].args,
|
|
76
|
+
setupCalls[i].isStaticCall,
|
|
77
|
+
contractArtifact,
|
|
78
|
+
);
|
|
79
|
+
setupExecutionRequests.push(req);
|
|
80
|
+
}
|
|
81
|
+
const appExecutionRequests: PublicExecutionRequest[] = [];
|
|
82
|
+
for (let i = 0; i < appCalls.length; i++) {
|
|
83
|
+
const address = appCalls[i].address;
|
|
84
|
+
const contractArtifact = await this.contractDataSource.getContractArtifact(address);
|
|
85
|
+
const req = await executionRequestForCall(
|
|
86
|
+
sender,
|
|
87
|
+
address,
|
|
88
|
+
appCalls[i].fnName,
|
|
89
|
+
appCalls[i].args,
|
|
90
|
+
appCalls[i].isStaticCall,
|
|
91
|
+
contractArtifact,
|
|
92
|
+
);
|
|
93
|
+
appExecutionRequests.push(req);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
let teardownExecutionRequest: PublicExecutionRequest | undefined = undefined;
|
|
97
|
+
if (teardownCall) {
|
|
98
|
+
const address = teardownCall.address;
|
|
99
|
+
const contractArtifact = await this.contractDataSource.getContractArtifact(address);
|
|
100
|
+
teardownExecutionRequest = await executionRequestForCall(
|
|
101
|
+
sender,
|
|
102
|
+
address,
|
|
103
|
+
teardownCall.fnName,
|
|
104
|
+
teardownCall.args,
|
|
105
|
+
teardownCall.isStaticCall,
|
|
106
|
+
contractArtifact,
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Use a fake "first nullifier" to make sure note hash nonces are computed properly,
|
|
111
|
+
// but make sure each tx has a unique first nullifier.
|
|
112
|
+
const firstNullifier = new Fr(420000 + this.txCount++);
|
|
113
|
+
|
|
114
|
+
const tx: Tx = await createTxForPublicCalls(
|
|
115
|
+
firstNullifier,
|
|
116
|
+
setupExecutionRequests,
|
|
117
|
+
appExecutionRequests,
|
|
118
|
+
teardownExecutionRequest,
|
|
119
|
+
feePayer,
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
const avmResult = await simulator.simulate(tx);
|
|
123
|
+
|
|
124
|
+
if (avmResult.revertCode.isOK()) {
|
|
125
|
+
await this.commitTxStateUpdates(avmResult.avmProvingRequest.inputs.publicInputs);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return avmResult;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
private async commitTxStateUpdates(avmCircuitInputs: AvmCircuitPublicInputs) {
|
|
132
|
+
await this.merkleTrees.appendLeaves(
|
|
133
|
+
MerkleTreeId.NOTE_HASH_TREE,
|
|
134
|
+
padArrayEnd(avmCircuitInputs.accumulatedData.noteHashes, Fr.ZERO, MAX_NOTE_HASHES_PER_TX),
|
|
135
|
+
);
|
|
136
|
+
try {
|
|
137
|
+
await this.merkleTrees.batchInsert(
|
|
138
|
+
MerkleTreeId.NULLIFIER_TREE,
|
|
139
|
+
padArrayEnd(avmCircuitInputs.accumulatedData.nullifiers, Fr.ZERO, MAX_NULLIFIERS_PER_TX).map(n => n.toBuffer()),
|
|
140
|
+
NULLIFIER_SUBTREE_HEIGHT,
|
|
141
|
+
);
|
|
142
|
+
} catch (error) {
|
|
143
|
+
this.logger.warn(`Detected duplicate nullifier.`);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
await this.merkleTrees.batchInsert(
|
|
147
|
+
MerkleTreeId.PUBLIC_DATA_TREE,
|
|
148
|
+
avmCircuitInputs.accumulatedData.publicDataWrites.map(w => w.toBuffer()),
|
|
149
|
+
PUBLIC_DATA_TREE_HEIGHT,
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
async function executionRequestForCall(
|
|
155
|
+
sender: AztecAddress,
|
|
156
|
+
address: AztecAddress,
|
|
157
|
+
fnName: string,
|
|
158
|
+
args: Fr[] = [],
|
|
159
|
+
isStaticCall: boolean = false,
|
|
160
|
+
contractArtifact: ContractArtifact = AvmTestContractArtifact,
|
|
161
|
+
): Promise<PublicExecutionRequest> {
|
|
162
|
+
const fnSelector = await getFunctionSelector(fnName, contractArtifact);
|
|
163
|
+
const fnAbi = getContractFunctionArtifact(fnName, contractArtifact);
|
|
164
|
+
const encodedArgs = encodeArguments(fnAbi!, args);
|
|
165
|
+
const calldata = [fnSelector.toField(), ...encodedArgs];
|
|
166
|
+
|
|
167
|
+
const callContext = new CallContext(
|
|
168
|
+
sender,
|
|
169
|
+
address,
|
|
170
|
+
/*selector=*/ new FunctionSelector(PUBLIC_DISPATCH_SELECTOR),
|
|
171
|
+
isStaticCall,
|
|
172
|
+
);
|
|
173
|
+
return new PublicExecutionRequest(callContext, calldata);
|
|
174
|
+
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { type PublicExecutionRequest, Tx } from '@aztec/circuit-types';
|
|
2
|
+
import {
|
|
3
|
+
BlockHeader,
|
|
4
|
+
DEFAULT_GAS_LIMIT,
|
|
5
|
+
FunctionSelector,
|
|
6
|
+
Gas,
|
|
7
|
+
GasFees,
|
|
8
|
+
GasSettings,
|
|
9
|
+
MAX_L2_GAS_PER_TX_PUBLIC_PORTION,
|
|
10
|
+
PartialPrivateTailPublicInputsForPublic,
|
|
11
|
+
PrivateKernelTailCircuitPublicInputs,
|
|
12
|
+
RollupValidationRequests,
|
|
13
|
+
TxConstantData,
|
|
14
|
+
TxContext,
|
|
15
|
+
} from '@aztec/circuits.js';
|
|
16
|
+
import { type FunctionArtifact } from '@aztec/foundation/abi';
|
|
17
|
+
import { AztecAddress } from '@aztec/foundation/aztec-address';
|
|
18
|
+
import { Fr } from '@aztec/foundation/fields';
|
|
19
|
+
import { AvmTestContractArtifact } from '@aztec/noir-contracts.js/AvmTest';
|
|
20
|
+
|
|
21
|
+
import { strict as assert } from 'assert';
|
|
22
|
+
|
|
23
|
+
export const PUBLIC_DISPATCH_FN_NAME = 'public_dispatch';
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Craft a carrier transaction for some public calls for simulation by PublicTxSimulator.
|
|
27
|
+
*/
|
|
28
|
+
export async function createTxForPublicCalls(
|
|
29
|
+
firstNullifier: Fr,
|
|
30
|
+
setupExecutionRequests: PublicExecutionRequest[],
|
|
31
|
+
appExecutionRequests: PublicExecutionRequest[],
|
|
32
|
+
teardownExecutionRequest?: PublicExecutionRequest,
|
|
33
|
+
feePayer = AztecAddress.zero(),
|
|
34
|
+
gasUsedByPrivate: Gas = Gas.empty(),
|
|
35
|
+
): Promise<Tx> {
|
|
36
|
+
assert(
|
|
37
|
+
setupExecutionRequests.length > 0 || appExecutionRequests.length > 0 || teardownExecutionRequest !== undefined,
|
|
38
|
+
"Can't create public tx with no enqueued calls",
|
|
39
|
+
);
|
|
40
|
+
const setupCallRequests = await Promise.all(setupExecutionRequests.map(er => er.toCallRequest()));
|
|
41
|
+
const appCallRequests = await Promise.all(appExecutionRequests.map(er => er.toCallRequest()));
|
|
42
|
+
// use max limits
|
|
43
|
+
const gasLimits = new Gas(DEFAULT_GAS_LIMIT, MAX_L2_GAS_PER_TX_PUBLIC_PORTION);
|
|
44
|
+
|
|
45
|
+
const forPublic = PartialPrivateTailPublicInputsForPublic.empty();
|
|
46
|
+
// TODO(#9269): Remove this fake nullifier method as we move away from 1st nullifier as hash.
|
|
47
|
+
forPublic.nonRevertibleAccumulatedData.nullifiers[0] = firstNullifier; // fake tx nullifier
|
|
48
|
+
|
|
49
|
+
// We reverse order because the simulator expects it to be like a "stack" of calls to pop from
|
|
50
|
+
for (let i = setupCallRequests.length - 1; i >= 0; i--) {
|
|
51
|
+
forPublic.nonRevertibleAccumulatedData.publicCallRequests[i] = setupCallRequests[i];
|
|
52
|
+
}
|
|
53
|
+
for (let i = appCallRequests.length - 1; i >= 0; i--) {
|
|
54
|
+
forPublic.revertibleAccumulatedData.publicCallRequests[i] = appCallRequests[i];
|
|
55
|
+
}
|
|
56
|
+
if (teardownExecutionRequest) {
|
|
57
|
+
forPublic.publicTeardownCallRequest = await teardownExecutionRequest.toCallRequest();
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const maxFeesPerGas = feePayer.isZero() ? GasFees.empty() : new GasFees(10, 10);
|
|
61
|
+
const teardownGasLimits = teardownExecutionRequest ? gasLimits : Gas.empty();
|
|
62
|
+
const gasSettings = new GasSettings(gasLimits, teardownGasLimits, maxFeesPerGas, GasFees.empty());
|
|
63
|
+
const txContext = new TxContext(Fr.zero(), Fr.zero(), gasSettings);
|
|
64
|
+
const constantData = new TxConstantData(BlockHeader.empty(), txContext, Fr.zero(), Fr.zero());
|
|
65
|
+
|
|
66
|
+
const txData = new PrivateKernelTailCircuitPublicInputs(
|
|
67
|
+
constantData,
|
|
68
|
+
RollupValidationRequests.empty(),
|
|
69
|
+
/*gasUsed=*/ gasUsedByPrivate,
|
|
70
|
+
feePayer,
|
|
71
|
+
forPublic,
|
|
72
|
+
);
|
|
73
|
+
const tx = Tx.newWithTxData(txData, teardownExecutionRequest);
|
|
74
|
+
|
|
75
|
+
// Reverse order because the simulator expects it to be like a "stack" of calls to pop from.
|
|
76
|
+
// Also push app calls before setup calls for this reason.
|
|
77
|
+
for (let i = appExecutionRequests.length - 1; i >= 0; i--) {
|
|
78
|
+
tx.enqueuedPublicFunctionCalls.push(appExecutionRequests[i]);
|
|
79
|
+
}
|
|
80
|
+
for (let i = setupExecutionRequests.length - 1; i >= 0; i--) {
|
|
81
|
+
tx.enqueuedPublicFunctionCalls.push(setupExecutionRequests[i]);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return tx;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export function getAvmTestContractFunctionSelector(functionName: string): Promise<FunctionSelector> {
|
|
88
|
+
const artifact = AvmTestContractArtifact.functions.find(f => f.name === functionName)!;
|
|
89
|
+
assert(!!artifact, `Function ${functionName} not found in AvmTestContractArtifact`);
|
|
90
|
+
const params = artifact.parameters;
|
|
91
|
+
return FunctionSelector.fromNameAndParameters(artifact.name, params);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export function getAvmTestContractArtifact(functionName: string): FunctionArtifact {
|
|
95
|
+
const artifact = AvmTestContractArtifact.functions.find(f => f.name === functionName)!;
|
|
96
|
+
assert(
|
|
97
|
+
!!artifact?.bytecode,
|
|
98
|
+
`No bytecode found for function ${functionName}. Try re-running bootstrap.sh on the repository root.`,
|
|
99
|
+
);
|
|
100
|
+
return artifact;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export function getAvmTestContractBytecode(functionName: string): Buffer {
|
|
104
|
+
const artifact = getAvmTestContractArtifact(functionName);
|
|
105
|
+
return artifact.bytecode;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export function getAvmTestContractPublicDispatchBytecode(): Buffer {
|
|
109
|
+
return getAvmTestContractBytecode(PUBLIC_DISPATCH_FN_NAME);
|
|
110
|
+
}
|
package/src/public/index.ts
CHANGED
|
@@ -4,5 +4,5 @@ export { type EnqueuedPublicCallExecutionResult, type PublicFunctionCallResult }
|
|
|
4
4
|
export * from './fee_payment.js';
|
|
5
5
|
export * from './public_db_sources.js';
|
|
6
6
|
export { PublicProcessor, PublicProcessorFactory } from './public_processor.js';
|
|
7
|
-
export {
|
|
7
|
+
export { SideEffectTrace } from './side_effect_trace.js';
|
|
8
8
|
export { getExecutionRequestsByPhase } from './utils.js';
|