@aztec/txe 0.0.1-commit.03f7ef2 → 0.0.1-commit.0658669b3
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/constants.d.ts +3 -0
- package/dest/constants.d.ts.map +1 -0
- package/dest/constants.js +2 -0
- package/dest/index.d.ts +1 -1
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +82 -50
- package/dest/oracle/interfaces.d.ts +6 -5
- package/dest/oracle/interfaces.d.ts.map +1 -1
- package/dest/oracle/txe_oracle_public_context.d.ts +3 -3
- package/dest/oracle/txe_oracle_public_context.d.ts.map +1 -1
- package/dest/oracle/txe_oracle_public_context.js +6 -6
- package/dest/oracle/txe_oracle_top_level_context.d.ts +18 -16
- package/dest/oracle/txe_oracle_top_level_context.d.ts.map +1 -1
- package/dest/oracle/txe_oracle_top_level_context.js +159 -72
- package/dest/rpc_translator.d.ts +21 -15
- package/dest/rpc_translator.d.ts.map +1 -1
- package/dest/rpc_translator.js +91 -54
- package/dest/state_machine/archiver.d.ts +20 -67
- package/dest/state_machine/archiver.d.ts.map +1 -1
- package/dest/state_machine/archiver.js +59 -178
- package/dest/state_machine/dummy_p2p_client.d.ts +20 -15
- package/dest/state_machine/dummy_p2p_client.d.ts.map +1 -1
- package/dest/state_machine/dummy_p2p_client.js +39 -24
- package/dest/state_machine/global_variable_builder.d.ts +2 -2
- package/dest/state_machine/global_variable_builder.d.ts.map +1 -1
- package/dest/state_machine/global_variable_builder.js +1 -1
- package/dest/state_machine/index.d.ts +6 -6
- package/dest/state_machine/index.d.ts.map +1 -1
- package/dest/state_machine/index.js +37 -14
- package/dest/state_machine/mock_epoch_cache.d.ts +9 -6
- package/dest/state_machine/mock_epoch_cache.d.ts.map +1 -1
- package/dest/state_machine/mock_epoch_cache.js +14 -7
- package/dest/state_machine/synchronizer.d.ts +3 -3
- package/dest/state_machine/synchronizer.d.ts.map +1 -1
- package/dest/txe_session.d.ts +22 -16
- package/dest/txe_session.d.ts.map +1 -1
- package/dest/txe_session.js +150 -53
- package/dest/util/encoding.d.ts +17 -17
- package/dest/util/txe_account_store.d.ts +10 -0
- package/dest/util/txe_account_store.d.ts.map +1 -0
- package/dest/util/{txe_account_data_provider.js → txe_account_store.js} +1 -1
- package/dest/util/txe_public_contract_data_source.d.ts +5 -6
- package/dest/util/txe_public_contract_data_source.d.ts.map +1 -1
- package/dest/util/txe_public_contract_data_source.js +12 -29
- package/dest/utils/block_creation.d.ts +4 -4
- package/dest/utils/block_creation.d.ts.map +1 -1
- package/dest/utils/block_creation.js +18 -5
- package/dest/utils/tx_effect_creation.d.ts +2 -3
- package/dest/utils/tx_effect_creation.d.ts.map +1 -1
- package/dest/utils/tx_effect_creation.js +3 -6
- package/package.json +16 -16
- package/src/constants.ts +3 -0
- package/src/index.ts +83 -49
- package/src/oracle/interfaces.ts +8 -3
- package/src/oracle/txe_oracle_public_context.ts +6 -8
- package/src/oracle/txe_oracle_top_level_context.ts +196 -112
- package/src/rpc_translator.ts +96 -55
- package/src/state_machine/archiver.ts +54 -220
- package/src/state_machine/dummy_p2p_client.ts +55 -32
- package/src/state_machine/global_variable_builder.ts +1 -1
- package/src/state_machine/index.ts +50 -12
- package/src/state_machine/mock_epoch_cache.ts +15 -11
- package/src/state_machine/synchronizer.ts +2 -2
- package/src/txe_session.ts +204 -117
- package/src/util/{txe_account_data_provider.ts → txe_account_store.ts} +1 -1
- package/src/util/txe_public_contract_data_source.ts +16 -42
- package/src/utils/block_creation.ts +19 -16
- package/src/utils/tx_effect_creation.ts +3 -11
- package/dest/util/txe_account_data_provider.d.ts +0 -10
- package/dest/util/txe_account_data_provider.d.ts.map +0 -1
- package/dest/util/txe_contract_data_provider.d.ts +0 -12
- package/dest/util/txe_contract_data_provider.d.ts.map +0 -1
- package/dest/util/txe_contract_data_provider.js +0 -22
- package/src/util/txe_contract_data_provider.ts +0 -36
|
@@ -12,14 +12,17 @@ import { Fr } from '@aztec/foundation/curves/bn254';
|
|
|
12
12
|
import { LogLevels, type Logger, applyStringFormatting, createLogger } from '@aztec/foundation/log';
|
|
13
13
|
import { TestDateProvider } from '@aztec/foundation/timer';
|
|
14
14
|
import type { KeyStore } from '@aztec/key-store';
|
|
15
|
+
import type { AccessScopes } from '@aztec/pxe/client/lazy';
|
|
15
16
|
import {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
AddressStore,
|
|
18
|
+
CapsuleStore,
|
|
19
|
+
type ContractStore,
|
|
20
|
+
NoteStore,
|
|
19
21
|
ORACLE_VERSION,
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
22
|
+
PrivateEventStore,
|
|
23
|
+
RecipientTaggingStore,
|
|
24
|
+
SenderAddressBookStore,
|
|
25
|
+
SenderTaggingStore,
|
|
23
26
|
enrichPublicSimulationError,
|
|
24
27
|
} from '@aztec/pxe/server';
|
|
25
28
|
import {
|
|
@@ -48,7 +51,7 @@ import {
|
|
|
48
51
|
PublicContractsDB,
|
|
49
52
|
PublicProcessor,
|
|
50
53
|
} from '@aztec/simulator/server';
|
|
51
|
-
import { type ContractArtifact, EventSelector, FunctionSelector, FunctionType } from '@aztec/stdlib/abi';
|
|
54
|
+
import { type ContractArtifact, EventSelector, FunctionCall, FunctionSelector, FunctionType } from '@aztec/stdlib/abi';
|
|
52
55
|
import { AuthWitness } from '@aztec/stdlib/auth-witness';
|
|
53
56
|
import { PublicSimulatorConfig } from '@aztec/stdlib/avm';
|
|
54
57
|
import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
@@ -79,10 +82,9 @@ import {
|
|
|
79
82
|
import type { UInt64 } from '@aztec/stdlib/types';
|
|
80
83
|
import { ForkCheckpoint } from '@aztec/world-state';
|
|
81
84
|
|
|
85
|
+
import { DEFAULT_ADDRESS } from '../constants.js';
|
|
82
86
|
import type { TXEStateMachine } from '../state_machine/index.js';
|
|
83
|
-
import {
|
|
84
|
-
import type { TXEAccountDataProvider } from '../util/txe_account_data_provider.js';
|
|
85
|
-
import type { TXEContractDataProvider } from '../util/txe_contract_data_provider.js';
|
|
87
|
+
import type { TXEAccountStore } from '../util/txe_account_store.js';
|
|
86
88
|
import { TXEPublicContractDataSource } from '../util/txe_public_contract_data_source.js';
|
|
87
89
|
import { getSingleTxBlockRequestHash, insertTxEffectIntoWorldTrees, makeTXEBlock } from '../utils/block_creation.js';
|
|
88
90
|
import type { ITxeExecutionOracle } from './interfaces.js';
|
|
@@ -95,15 +97,16 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
95
97
|
|
|
96
98
|
constructor(
|
|
97
99
|
private stateMachine: TXEStateMachine,
|
|
98
|
-
private
|
|
99
|
-
private
|
|
100
|
+
private contractStore: ContractStore,
|
|
101
|
+
private noteStore: NoteStore,
|
|
100
102
|
private keyStore: KeyStore,
|
|
101
|
-
private
|
|
102
|
-
private
|
|
103
|
-
private
|
|
104
|
-
private
|
|
105
|
-
private
|
|
106
|
-
private
|
|
103
|
+
private addressStore: AddressStore,
|
|
104
|
+
private accountStore: TXEAccountStore,
|
|
105
|
+
private senderTaggingStore: SenderTaggingStore,
|
|
106
|
+
private recipientTaggingStore: RecipientTaggingStore,
|
|
107
|
+
private senderAddressBookStore: SenderAddressBookStore,
|
|
108
|
+
private capsuleStore: CapsuleStore,
|
|
109
|
+
private privateEventStore: PrivateEventStore,
|
|
107
110
|
private nextBlockTimestamp: bigint,
|
|
108
111
|
private version: Fr,
|
|
109
112
|
private chainId: Fr,
|
|
@@ -128,13 +131,14 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
128
131
|
}
|
|
129
132
|
|
|
130
133
|
// We instruct users to debug contracts via this oracle, so it makes sense that they'd expect it to also work in tests
|
|
131
|
-
|
|
134
|
+
utilityLog(level: number, message: string, fields: Fr[]): Promise<void> {
|
|
132
135
|
if (!LogLevels[level]) {
|
|
133
|
-
throw new Error(`Invalid
|
|
136
|
+
throw new Error(`Invalid log level: ${level}`);
|
|
134
137
|
}
|
|
135
138
|
const levelName = LogLevels[level];
|
|
136
139
|
|
|
137
140
|
this.logger[levelName](`${applyStringFormatting(message, fields)}`, { module: `${this.logger.module}:debug_log` });
|
|
141
|
+
return Promise.resolve();
|
|
138
142
|
}
|
|
139
143
|
|
|
140
144
|
txeGetDefaultAddress(): AztecAddress {
|
|
@@ -154,7 +158,8 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
154
158
|
}
|
|
155
159
|
|
|
156
160
|
async txeGetLastTxEffects() {
|
|
157
|
-
const
|
|
161
|
+
const latestBlockNumber = await this.stateMachine.archiver.getBlockNumber();
|
|
162
|
+
const block = await this.stateMachine.archiver.getBlock(latestBlockNumber);
|
|
158
163
|
|
|
159
164
|
if (block!.body.txEffects.length != 1) {
|
|
160
165
|
// Note that calls like env.mine() will result in blocks with no transactions, hitting this
|
|
@@ -166,9 +171,28 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
166
171
|
return { txHash: txEffects.txHash, noteHashes: txEffects.noteHashes, nullifiers: txEffects.nullifiers };
|
|
167
172
|
}
|
|
168
173
|
|
|
174
|
+
async syncContractNonOracleMethod(contractAddress: AztecAddress, scope: AztecAddress, jobId: string) {
|
|
175
|
+
if (contractAddress.equals(DEFAULT_ADDRESS)) {
|
|
176
|
+
this.logger.debug(`Skipping sync in txeGetPrivateEvents because the events correspond to the default address.`);
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
181
|
+
await this.stateMachine.contractSyncService.ensureContractSynced(
|
|
182
|
+
contractAddress,
|
|
183
|
+
null,
|
|
184
|
+
async (call, execScopes) => {
|
|
185
|
+
await this.executeUtilityCall(call, execScopes, jobId);
|
|
186
|
+
},
|
|
187
|
+
blockHeader,
|
|
188
|
+
jobId,
|
|
189
|
+
[scope],
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
|
|
169
193
|
async txeGetPrivateEvents(selector: EventSelector, contractAddress: AztecAddress, scope: AztecAddress) {
|
|
170
194
|
return (
|
|
171
|
-
await this.
|
|
195
|
+
await this.privateEventStore.getPrivateEvents(selector, {
|
|
172
196
|
contractAddress,
|
|
173
197
|
scopes: [scope],
|
|
174
198
|
fromBlock: 0,
|
|
@@ -204,8 +228,8 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
204
228
|
if (!secret.equals(Fr.ZERO)) {
|
|
205
229
|
await this.txeAddAccount(artifact, instance, secret);
|
|
206
230
|
} else {
|
|
207
|
-
await this.
|
|
208
|
-
await this.
|
|
231
|
+
await this.contractStore.addContractInstance(instance);
|
|
232
|
+
await this.contractStore.addContractArtifact(artifact);
|
|
209
233
|
this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
|
|
210
234
|
}
|
|
211
235
|
}
|
|
@@ -214,12 +238,12 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
214
238
|
const partialAddress = await computePartialAddress(instance);
|
|
215
239
|
|
|
216
240
|
this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
|
|
217
|
-
await this.
|
|
218
|
-
await this.
|
|
241
|
+
await this.contractStore.addContractInstance(instance);
|
|
242
|
+
await this.contractStore.addContractArtifact(artifact);
|
|
219
243
|
|
|
220
244
|
const completeAddress = await this.keyStore.addAccount(secret, partialAddress);
|
|
221
|
-
await this.
|
|
222
|
-
await this.
|
|
245
|
+
await this.accountStore.setAccount(completeAddress.address, completeAddress);
|
|
246
|
+
await this.addressStore.addCompleteAddress(completeAddress);
|
|
223
247
|
this.logger.debug(`Created account ${completeAddress.address}`);
|
|
224
248
|
|
|
225
249
|
return completeAddress;
|
|
@@ -228,15 +252,15 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
228
252
|
async txeCreateAccount(secret: Fr) {
|
|
229
253
|
// This is a foot gun !
|
|
230
254
|
const completeAddress = await this.keyStore.addAccount(secret, secret);
|
|
231
|
-
await this.
|
|
232
|
-
await this.
|
|
255
|
+
await this.accountStore.setAccount(completeAddress.address, completeAddress);
|
|
256
|
+
await this.addressStore.addCompleteAddress(completeAddress);
|
|
233
257
|
this.logger.debug(`Created account ${completeAddress.address}`);
|
|
234
258
|
|
|
235
259
|
return completeAddress;
|
|
236
260
|
}
|
|
237
261
|
|
|
238
262
|
async txeAddAuthWitness(address: AztecAddress, messageHash: Fr) {
|
|
239
|
-
const account = await this.
|
|
263
|
+
const account = await this.accountStore.getAccount(address);
|
|
240
264
|
const privateKey = await this.keyStore.getMasterSecretKey(account.publicKeys.masterIncomingViewingPublicKey);
|
|
241
265
|
|
|
242
266
|
const schnorr = new Schnorr();
|
|
@@ -279,12 +303,13 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
279
303
|
args: Fr[],
|
|
280
304
|
argsHash: Fr = Fr.zero(),
|
|
281
305
|
isStaticCall: boolean = false,
|
|
306
|
+
jobId: string,
|
|
282
307
|
) {
|
|
283
308
|
this.logger.verbose(
|
|
284
|
-
`Executing external function ${await this.
|
|
309
|
+
`Executing external function ${await this.contractStore.getDebugFunctionName(targetContractAddress, functionSelector)}@${targetContractAddress} isStaticCall=${isStaticCall}`,
|
|
285
310
|
);
|
|
286
311
|
|
|
287
|
-
const artifact = await this.
|
|
312
|
+
const artifact = await this.contractStore.getFunctionArtifact(targetContractAddress, functionSelector);
|
|
288
313
|
if (!artifact) {
|
|
289
314
|
const message = functionSelector.equals(await FunctionSelector.fromSignature('verify_private_authwit(Field)'))
|
|
290
315
|
? 'Found no account contract artifact for a private authwit check - use `create_contract_account` instead of `create_light_account` for authwit support.'
|
|
@@ -292,60 +317,77 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
292
317
|
throw new Error(message);
|
|
293
318
|
}
|
|
294
319
|
|
|
320
|
+
// When `from` is the zero address (e.g. when deploying a new account contract), we return an
|
|
321
|
+
// empty scope list which acts as deny-all: no notes are visible and no keys are accessible.
|
|
322
|
+
const effectiveScopes = from.isZero() ? [] : [from];
|
|
323
|
+
|
|
324
|
+
// Sync notes before executing private function to discover notes from previous transactions
|
|
325
|
+
const utilityExecutor = async (call: FunctionCall, execScopes: AccessScopes) => {
|
|
326
|
+
await this.executeUtilityCall(call, execScopes, jobId);
|
|
327
|
+
};
|
|
328
|
+
|
|
329
|
+
const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
330
|
+
await this.stateMachine.contractSyncService.ensureContractSynced(
|
|
331
|
+
targetContractAddress,
|
|
332
|
+
functionSelector,
|
|
333
|
+
utilityExecutor,
|
|
334
|
+
blockHeader,
|
|
335
|
+
jobId,
|
|
336
|
+
effectiveScopes,
|
|
337
|
+
);
|
|
338
|
+
|
|
295
339
|
const blockNumber = await this.txeGetNextBlockNumber();
|
|
296
340
|
|
|
297
341
|
const callContext = new CallContext(from, targetContractAddress, functionSelector, isStaticCall);
|
|
298
342
|
|
|
299
343
|
const gasLimits = new Gas(DEFAULT_DA_GAS_LIMIT, DEFAULT_L2_GAS_LIMIT);
|
|
300
|
-
|
|
301
344
|
const teardownGasLimits = new Gas(DEFAULT_TEARDOWN_DA_GAS_LIMIT, DEFAULT_TEARDOWN_L2_GAS_LIMIT);
|
|
302
|
-
|
|
303
345
|
const gasSettings = new GasSettings(gasLimits, teardownGasLimits, GasFees.empty(), GasFees.empty());
|
|
304
346
|
|
|
305
347
|
const txContext = new TxContext(this.chainId, this.version, gasSettings);
|
|
306
348
|
|
|
307
|
-
const blockHeader = await this.stateMachine.anchorBlockDataProvider.getBlockHeader();
|
|
308
|
-
|
|
309
349
|
const protocolNullifier = await computeProtocolNullifier(getSingleTxBlockRequestHash(blockNumber));
|
|
310
350
|
const noteCache = new ExecutionNoteCache(protocolNullifier);
|
|
351
|
+
// In production, the account contract sets the min revertible counter before calling the app function.
|
|
352
|
+
// Since TXE bypasses the account contract, we simulate this by setting minRevertibleSideEffectCounter to 1,
|
|
353
|
+
// marking all side effects as revertible.
|
|
354
|
+
const minRevertibleSideEffectCounter = 1;
|
|
355
|
+
await noteCache.setMinRevertibleSideEffectCounter(minRevertibleSideEffectCounter);
|
|
311
356
|
const taggingIndexCache = new ExecutionTaggingIndexCache();
|
|
312
357
|
|
|
313
358
|
const simulator = new WASMSimulator();
|
|
314
359
|
|
|
315
|
-
const privateExecutionOracle = new PrivateExecutionOracle(
|
|
360
|
+
const privateExecutionOracle = new PrivateExecutionOracle({
|
|
316
361
|
argsHash,
|
|
317
362
|
txContext,
|
|
318
363
|
callContext,
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
[],
|
|
325
|
-
HashedValuesCache.create([new HashedValues(args, argsHash)]),
|
|
364
|
+
anchorBlockHeader: blockHeader,
|
|
365
|
+
utilityExecutor,
|
|
366
|
+
authWitnesses: Array.from(this.authwits.values()),
|
|
367
|
+
capsules: [],
|
|
368
|
+
executionCache: HashedValuesCache.create([new HashedValues(args, argsHash)]),
|
|
326
369
|
noteCache,
|
|
327
370
|
taggingIndexCache,
|
|
328
|
-
this.
|
|
329
|
-
this.
|
|
330
|
-
this.keyStore,
|
|
331
|
-
this.
|
|
332
|
-
this.stateMachine.node,
|
|
333
|
-
this.
|
|
334
|
-
this.
|
|
335
|
-
this.
|
|
336
|
-
this.
|
|
337
|
-
this.
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
from,
|
|
371
|
+
contractStore: this.contractStore,
|
|
372
|
+
noteStore: this.noteStore,
|
|
373
|
+
keyStore: this.keyStore,
|
|
374
|
+
addressStore: this.addressStore,
|
|
375
|
+
aztecNode: this.stateMachine.node,
|
|
376
|
+
senderTaggingStore: this.senderTaggingStore,
|
|
377
|
+
recipientTaggingStore: this.recipientTaggingStore,
|
|
378
|
+
senderAddressBookStore: this.senderAddressBookStore,
|
|
379
|
+
capsuleStore: this.capsuleStore,
|
|
380
|
+
privateEventStore: this.privateEventStore,
|
|
381
|
+
contractSyncService: this.stateMachine.contractSyncService,
|
|
382
|
+
jobId,
|
|
383
|
+
totalPublicCalldataCount: 0,
|
|
384
|
+
sideEffectCounter: minRevertibleSideEffectCounter,
|
|
385
|
+
scopes: effectiveScopes,
|
|
386
|
+
// In TXE, the typical transaction entrypoint is skipped, so we need to simulate the actions that such a
|
|
387
|
+
// contract would perform, including setting senderForTags.
|
|
388
|
+
senderForTags: from,
|
|
347
389
|
simulator,
|
|
348
|
-
);
|
|
390
|
+
});
|
|
349
391
|
|
|
350
392
|
// Note: This is a slight modification of simulator.run without any of the checks. Maybe we should modify simulator.run with a boolean value to skip checks.
|
|
351
393
|
let result: PrivateExecutionResult;
|
|
@@ -372,19 +414,22 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
372
414
|
}),
|
|
373
415
|
);
|
|
374
416
|
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
result = new PrivateExecutionResult(executionResult, Fr.ZERO, publicFunctionsCalldata);
|
|
417
|
+
noteCache.finish();
|
|
418
|
+
const nonceGenerator = noteCache.getNonceGenerator();
|
|
419
|
+
result = new PrivateExecutionResult(executionResult, nonceGenerator, publicFunctionsCalldata);
|
|
379
420
|
} catch (err) {
|
|
380
421
|
throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during private execution'));
|
|
381
422
|
}
|
|
382
423
|
|
|
383
|
-
// According to the protocol rules,
|
|
384
|
-
//
|
|
385
|
-
//
|
|
386
|
-
const
|
|
387
|
-
|
|
424
|
+
// According to the protocol rules, there must be at least one nullifier in the tx. The first nullifier is used as
|
|
425
|
+
// the nonce generator for the note hashes.
|
|
426
|
+
// We pass the non-zero minRevertibleSideEffectCounter to make sure the side effects are split correctly.
|
|
427
|
+
const { publicInputs } = await generateSimulatedProvingResult(
|
|
428
|
+
result,
|
|
429
|
+
(addr, sel) => this.contractStore.getDebugFunctionName(addr, sel),
|
|
430
|
+
this.stateMachine.node,
|
|
431
|
+
minRevertibleSideEffectCounter,
|
|
432
|
+
);
|
|
388
433
|
|
|
389
434
|
const globals = makeGlobalVariables();
|
|
390
435
|
globals.blockNumber = blockNumber;
|
|
@@ -395,7 +440,11 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
395
440
|
|
|
396
441
|
const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
|
|
397
442
|
|
|
398
|
-
const
|
|
443
|
+
const bindings = this.logger.getBindings();
|
|
444
|
+
const contractsDB = new PublicContractsDB(
|
|
445
|
+
new TXEPublicContractDataSource(blockNumber, this.contractStore),
|
|
446
|
+
bindings,
|
|
447
|
+
);
|
|
399
448
|
const guardedMerkleTrees = new GuardedMerkleTreeOperations(forkedWorldTrees);
|
|
400
449
|
const config = PublicSimulatorConfig.from({
|
|
401
450
|
skipFeeEnforcement: true,
|
|
@@ -408,8 +457,10 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
408
457
|
globals,
|
|
409
458
|
guardedMerkleTrees,
|
|
410
459
|
contractsDB,
|
|
411
|
-
new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config),
|
|
460
|
+
new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config, bindings),
|
|
412
461
|
new TestDateProvider(),
|
|
462
|
+
undefined,
|
|
463
|
+
createLogger('simulator:public-processor', bindings),
|
|
413
464
|
);
|
|
414
465
|
|
|
415
466
|
const tx = await Tx.create({
|
|
@@ -434,7 +485,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
434
485
|
} else if (!processedTx.revertCode.isOK()) {
|
|
435
486
|
if (processedTx.revertReason) {
|
|
436
487
|
try {
|
|
437
|
-
await enrichPublicSimulationError(processedTx.revertReason, this.
|
|
488
|
+
await enrichPublicSimulationError(processedTx.revertReason, this.contractStore, this.logger);
|
|
438
489
|
// eslint-disable-next-line no-empty
|
|
439
490
|
} catch {}
|
|
440
491
|
throw new Error(`Contract execution has reverted: ${processedTx.revertReason.getMessage()}`);
|
|
@@ -479,7 +530,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
479
530
|
isStaticCall: boolean,
|
|
480
531
|
) {
|
|
481
532
|
this.logger.verbose(
|
|
482
|
-
`Executing public function ${await this.
|
|
533
|
+
`Executing public function ${await this.contractStore.getDebugFunctionName(targetContractAddress, FunctionSelector.fromField(calldata[0]))}@${targetContractAddress} isStaticCall=${isStaticCall}`,
|
|
483
534
|
);
|
|
484
535
|
|
|
485
536
|
const blockNumber = await this.txeGetNextBlockNumber();
|
|
@@ -492,7 +543,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
492
543
|
|
|
493
544
|
const txContext = new TxContext(this.chainId, this.version, gasSettings);
|
|
494
545
|
|
|
495
|
-
const anchorBlockHeader = await this.stateMachine.
|
|
546
|
+
const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
496
547
|
|
|
497
548
|
const calldataHash = await computeCalldataHash(calldata);
|
|
498
549
|
const calldataHashedValues = new HashedValues(calldata, calldataHash);
|
|
@@ -506,7 +557,11 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
506
557
|
|
|
507
558
|
const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
|
|
508
559
|
|
|
509
|
-
const
|
|
560
|
+
const bindings2 = this.logger.getBindings();
|
|
561
|
+
const contractsDB = new PublicContractsDB(
|
|
562
|
+
new TXEPublicContractDataSource(blockNumber, this.contractStore),
|
|
563
|
+
bindings2,
|
|
564
|
+
);
|
|
510
565
|
const guardedMerkleTrees = new GuardedMerkleTreeOperations(forkedWorldTrees);
|
|
511
566
|
const config = PublicSimulatorConfig.from({
|
|
512
567
|
skipFeeEnforcement: true,
|
|
@@ -515,8 +570,16 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
515
570
|
collectStatistics: false,
|
|
516
571
|
collectCallMetadata: true,
|
|
517
572
|
});
|
|
518
|
-
const simulator = new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config);
|
|
519
|
-
const processor = new PublicProcessor(
|
|
573
|
+
const simulator = new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config, bindings2);
|
|
574
|
+
const processor = new PublicProcessor(
|
|
575
|
+
globals,
|
|
576
|
+
guardedMerkleTrees,
|
|
577
|
+
contractsDB,
|
|
578
|
+
simulator,
|
|
579
|
+
new TestDateProvider(),
|
|
580
|
+
undefined,
|
|
581
|
+
createLogger('simulator:public-processor', bindings2),
|
|
582
|
+
);
|
|
520
583
|
|
|
521
584
|
// We're simulating a scenario in which private execution immediately enqueues a public call and halts. The private
|
|
522
585
|
// kernel init would in this case inject a nullifier with the transaction request hash as a non-revertible
|
|
@@ -547,7 +610,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
547
610
|
constantData,
|
|
548
611
|
/*gasUsed=*/ new Gas(0, 0),
|
|
549
612
|
/*feePayer=*/ AztecAddress.zero(),
|
|
550
|
-
/*
|
|
613
|
+
/*expirationTimestamp=*/ 0n,
|
|
551
614
|
inputsForPublic,
|
|
552
615
|
undefined,
|
|
553
616
|
);
|
|
@@ -574,7 +637,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
574
637
|
} else if (!processedTx.revertCode.isOK()) {
|
|
575
638
|
if (processedTx.revertReason) {
|
|
576
639
|
try {
|
|
577
|
-
await enrichPublicSimulationError(processedTx.revertReason, this.
|
|
640
|
+
await enrichPublicSimulationError(processedTx.revertReason, this.contractStore, this.logger);
|
|
578
641
|
// eslint-disable-next-line no-empty
|
|
579
642
|
} catch {}
|
|
580
643
|
throw new Error(`Contract execution has reverted: ${processedTx.revertReason.getMessage()}`);
|
|
@@ -615,26 +678,46 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
615
678
|
return returnValues ?? [];
|
|
616
679
|
}
|
|
617
680
|
|
|
618
|
-
async
|
|
681
|
+
async txeExecuteUtilityFunction(
|
|
619
682
|
targetContractAddress: AztecAddress,
|
|
620
683
|
functionSelector: FunctionSelector,
|
|
621
684
|
args: Fr[],
|
|
685
|
+
jobId: string,
|
|
622
686
|
) {
|
|
623
|
-
const artifact = await this.
|
|
687
|
+
const artifact = await this.contractStore.getFunctionArtifact(targetContractAddress, functionSelector);
|
|
624
688
|
if (!artifact) {
|
|
625
689
|
throw new Error(`Cannot call ${functionSelector} as there is no artifact found at ${targetContractAddress}.`);
|
|
626
690
|
}
|
|
627
691
|
|
|
628
|
-
|
|
692
|
+
// Sync notes before executing utility function to discover notes from previous transactions
|
|
693
|
+
const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
694
|
+
await this.stateMachine.contractSyncService.ensureContractSynced(
|
|
695
|
+
targetContractAddress,
|
|
696
|
+
functionSelector,
|
|
697
|
+
async (call, execScopes) => {
|
|
698
|
+
await this.executeUtilityCall(call, execScopes, jobId);
|
|
699
|
+
},
|
|
700
|
+
blockHeader,
|
|
701
|
+
jobId,
|
|
702
|
+
'ALL_SCOPES',
|
|
703
|
+
);
|
|
704
|
+
|
|
705
|
+
const call = FunctionCall.from({
|
|
629
706
|
name: artifact.name,
|
|
630
|
-
selector: functionSelector,
|
|
631
707
|
to: targetContractAddress,
|
|
632
|
-
|
|
708
|
+
selector: functionSelector,
|
|
709
|
+
type: FunctionType.UTILITY,
|
|
710
|
+
hideMsgSender: false,
|
|
711
|
+
isStatic: false,
|
|
712
|
+
args,
|
|
713
|
+
returnTypes: [],
|
|
714
|
+
});
|
|
633
715
|
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
716
|
+
return this.executeUtilityCall(call, 'ALL_SCOPES', jobId);
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
private async executeUtilityCall(call: FunctionCall, scopes: AccessScopes, jobId: string): Promise<Fr[]> {
|
|
720
|
+
const entryPointArtifact = await this.contractStore.getFunctionArtifactWithDebugMetadata(call.to, call.selector);
|
|
638
721
|
if (entryPointArtifact.functionType !== FunctionType.UTILITY) {
|
|
639
722
|
throw new Error(`Cannot run ${entryPointArtifact.functionType} function as utility`);
|
|
640
723
|
}
|
|
@@ -645,25 +728,26 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
645
728
|
});
|
|
646
729
|
|
|
647
730
|
try {
|
|
648
|
-
const anchorBlockHeader = await this.stateMachine.
|
|
649
|
-
const oracle = new UtilityExecutionOracle(
|
|
650
|
-
call.to,
|
|
651
|
-
[],
|
|
652
|
-
[],
|
|
731
|
+
const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
732
|
+
const oracle = new UtilityExecutionOracle({
|
|
733
|
+
contractAddress: call.to,
|
|
734
|
+
authWitnesses: [],
|
|
735
|
+
capsules: [],
|
|
653
736
|
anchorBlockHeader,
|
|
654
|
-
this.
|
|
655
|
-
this.
|
|
656
|
-
this.keyStore,
|
|
657
|
-
this.
|
|
658
|
-
this.stateMachine.node,
|
|
659
|
-
this.
|
|
660
|
-
this.
|
|
661
|
-
this.
|
|
662
|
-
this.
|
|
663
|
-
|
|
664
|
-
|
|
737
|
+
contractStore: this.contractStore,
|
|
738
|
+
noteStore: this.noteStore,
|
|
739
|
+
keyStore: this.keyStore,
|
|
740
|
+
addressStore: this.addressStore,
|
|
741
|
+
aztecNode: this.stateMachine.node,
|
|
742
|
+
recipientTaggingStore: this.recipientTaggingStore,
|
|
743
|
+
senderAddressBookStore: this.senderAddressBookStore,
|
|
744
|
+
capsuleStore: this.capsuleStore,
|
|
745
|
+
privateEventStore: this.privateEventStore,
|
|
746
|
+
jobId,
|
|
747
|
+
scopes,
|
|
748
|
+
});
|
|
665
749
|
const acirExecutionResult = await new WASMSimulator()
|
|
666
|
-
.executeUserCircuit(toACVMWitness(0, args), entryPointArtifact, new Oracle(oracle).toACIRCallback())
|
|
750
|
+
.executeUserCircuit(toACVMWitness(0, call.args), entryPointArtifact, new Oracle(oracle).toACIRCallback())
|
|
667
751
|
.catch((err: Error) => {
|
|
668
752
|
err.message = resolveAssertionMessageFromError(err, entryPointArtifact);
|
|
669
753
|
throw new ExecutionError(
|
|
@@ -677,10 +761,10 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
677
761
|
);
|
|
678
762
|
});
|
|
679
763
|
|
|
680
|
-
this.logger.verbose(`Utility
|
|
764
|
+
this.logger.verbose(`Utility execution for ${call.to}.${call.selector} completed`);
|
|
681
765
|
return witnessMapToFields(acirExecutionResult.returnWitness);
|
|
682
766
|
} catch (err) {
|
|
683
|
-
throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during utility
|
|
767
|
+
throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during utility execution'));
|
|
684
768
|
}
|
|
685
769
|
}
|
|
686
770
|
|