@aztec/txe 0.0.1-commit.3469e52 → 0.0.1-commit.381b1a9
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/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 +5 -5
- 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 +7 -8
- package/dest/oracle/txe_oracle_top_level_context.d.ts.map +1 -1
- package/dest/oracle/txe_oracle_top_level_context.js +105 -34
- package/dest/rpc_translator.d.ts +16 -10
- package/dest/rpc_translator.d.ts.map +1 -1
- package/dest/rpc_translator.js +75 -39
- package/dest/state_machine/archiver.d.ts +4 -4
- package/dest/state_machine/archiver.d.ts.map +1 -1
- package/dest/state_machine/archiver.js +8 -9
- package/dest/state_machine/dummy_p2p_client.d.ts +16 -12
- package/dest/state_machine/dummy_p2p_client.d.ts.map +1 -1
- package/dest/state_machine/dummy_p2p_client.js +28 -16
- package/dest/state_machine/index.d.ts +7 -7
- package/dest/state_machine/index.d.ts.map +1 -1
- package/dest/state_machine/index.js +31 -17
- package/dest/state_machine/mock_epoch_cache.d.ts +6 -2
- package/dest/state_machine/mock_epoch_cache.d.ts.map +1 -1
- package/dest/state_machine/mock_epoch_cache.js +6 -1
- 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 +9 -6
- package/dest/txe_session.d.ts.map +1 -1
- package/dest/txe_session.js +83 -23
- package/dest/util/txe_public_contract_data_source.d.ts +2 -3
- package/dest/util/txe_public_contract_data_source.d.ts.map +1 -1
- package/dest/util/txe_public_contract_data_source.js +5 -22
- package/dest/utils/block_creation.d.ts +5 -5
- package/dest/utils/block_creation.d.ts.map +1 -1
- package/dest/utils/block_creation.js +7 -5
- package/package.json +15 -15
- package/src/index.ts +83 -49
- package/src/oracle/interfaces.ts +8 -3
- package/src/oracle/txe_oracle_public_context.ts +8 -10
- package/src/oracle/txe_oracle_top_level_context.ts +134 -81
- package/src/rpc_translator.ts +79 -32
- package/src/state_machine/archiver.ts +9 -11
- package/src/state_machine/dummy_p2p_client.ts +40 -22
- package/src/state_machine/index.ts +49 -19
- package/src/state_machine/mock_epoch_cache.ts +7 -1
- package/src/state_machine/synchronizer.ts +2 -2
- package/src/txe_session.ts +98 -82
- package/src/util/txe_public_contract_data_source.ts +10 -36
- package/src/utils/block_creation.ts +8 -6
- package/dest/util/txe_contract_store.d.ts +0 -12
- package/dest/util/txe_contract_store.d.ts.map +0 -1
- package/dest/util/txe_contract_store.js +0 -22
- package/src/util/txe_contract_store.ts +0 -36
|
@@ -12,9 +12,11 @@ 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
|
AddressStore,
|
|
17
18
|
CapsuleStore,
|
|
19
|
+
type ContractStore,
|
|
18
20
|
NoteStore,
|
|
19
21
|
ORACLE_VERSION,
|
|
20
22
|
PrivateEventStore,
|
|
@@ -83,7 +85,6 @@ import { ForkCheckpoint } from '@aztec/world-state';
|
|
|
83
85
|
import { DEFAULT_ADDRESS } from '../constants.js';
|
|
84
86
|
import type { TXEStateMachine } from '../state_machine/index.js';
|
|
85
87
|
import type { TXEAccountStore } from '../util/txe_account_store.js';
|
|
86
|
-
import type { TXEContractStore } from '../util/txe_contract_store.js';
|
|
87
88
|
import { TXEPublicContractDataSource } from '../util/txe_public_contract_data_source.js';
|
|
88
89
|
import { getSingleTxBlockRequestHash, insertTxEffectIntoWorldTrees, makeTXEBlock } from '../utils/block_creation.js';
|
|
89
90
|
import type { ITxeExecutionOracle } from './interfaces.js';
|
|
@@ -96,7 +97,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
96
97
|
|
|
97
98
|
constructor(
|
|
98
99
|
private stateMachine: TXEStateMachine,
|
|
99
|
-
private contractStore:
|
|
100
|
+
private contractStore: ContractStore,
|
|
100
101
|
private noteStore: NoteStore,
|
|
101
102
|
private keyStore: KeyStore,
|
|
102
103
|
private addressStore: AddressStore,
|
|
@@ -106,7 +107,6 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
106
107
|
private senderAddressBookStore: SenderAddressBookStore,
|
|
107
108
|
private capsuleStore: CapsuleStore,
|
|
108
109
|
private privateEventStore: PrivateEventStore,
|
|
109
|
-
private jobId: string,
|
|
110
110
|
private nextBlockTimestamp: bigint,
|
|
111
111
|
private version: Fr,
|
|
112
112
|
private chainId: Fr,
|
|
@@ -131,13 +131,14 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
131
131
|
}
|
|
132
132
|
|
|
133
133
|
// We instruct users to debug contracts via this oracle, so it makes sense that they'd expect it to also work in tests
|
|
134
|
-
|
|
134
|
+
utilityLog(level: number, message: string, fields: Fr[]): Promise<void> {
|
|
135
135
|
if (!LogLevels[level]) {
|
|
136
|
-
throw new Error(`Invalid
|
|
136
|
+
throw new Error(`Invalid log level: ${level}`);
|
|
137
137
|
}
|
|
138
138
|
const levelName = LogLevels[level];
|
|
139
139
|
|
|
140
140
|
this.logger[levelName](`${applyStringFormatting(message, fields)}`, { module: `${this.logger.module}:debug_log` });
|
|
141
|
+
return Promise.resolve();
|
|
141
142
|
}
|
|
142
143
|
|
|
143
144
|
txeGetDefaultAddress(): AztecAddress {
|
|
@@ -170,6 +171,25 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
170
171
|
return { txHash: txEffects.txHash, noteHashes: txEffects.noteHashes, nullifiers: txEffects.nullifiers };
|
|
171
172
|
}
|
|
172
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
|
+
|
|
173
193
|
async txeGetPrivateEvents(selector: EventSelector, contractAddress: AztecAddress, scope: AztecAddress) {
|
|
174
194
|
return (
|
|
175
195
|
await this.privateEventStore.getPrivateEvents(selector, {
|
|
@@ -209,7 +229,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
209
229
|
await this.txeAddAccount(artifact, instance, secret);
|
|
210
230
|
} else {
|
|
211
231
|
await this.contractStore.addContractInstance(instance);
|
|
212
|
-
await this.contractStore.addContractArtifact(
|
|
232
|
+
await this.contractStore.addContractArtifact(artifact);
|
|
213
233
|
this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
|
|
214
234
|
}
|
|
215
235
|
}
|
|
@@ -219,7 +239,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
219
239
|
|
|
220
240
|
this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
|
|
221
241
|
await this.contractStore.addContractInstance(instance);
|
|
222
|
-
await this.contractStore.addContractArtifact(
|
|
242
|
+
await this.contractStore.addContractArtifact(artifact);
|
|
223
243
|
|
|
224
244
|
const completeAddress = await this.keyStore.addAccount(secret, partialAddress);
|
|
225
245
|
await this.accountStore.setAccount(completeAddress.address, completeAddress);
|
|
@@ -283,6 +303,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
283
303
|
args: Fr[],
|
|
284
304
|
argsHash: Fr = Fr.zero(),
|
|
285
305
|
isStaticCall: boolean = false,
|
|
306
|
+
jobId: string,
|
|
286
307
|
) {
|
|
287
308
|
this.logger.verbose(
|
|
288
309
|
`Executing external function ${await this.contractStore.getDebugFunctionName(targetContractAddress, functionSelector)}@${targetContractAddress} isStaticCall=${isStaticCall}`,
|
|
@@ -296,12 +317,24 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
296
317
|
throw new Error(message);
|
|
297
318
|
}
|
|
298
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
|
+
|
|
299
324
|
// Sync notes before executing private function to discover notes from previous transactions
|
|
300
|
-
const utilityExecutor = async (call: FunctionCall) => {
|
|
301
|
-
await this.executeUtilityCall(call);
|
|
325
|
+
const utilityExecutor = async (call: FunctionCall, execScopes: AccessScopes) => {
|
|
326
|
+
await this.executeUtilityCall(call, execScopes, jobId);
|
|
302
327
|
};
|
|
303
328
|
|
|
304
|
-
await this.
|
|
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
|
+
);
|
|
305
338
|
|
|
306
339
|
const blockNumber = await this.txeGetNextBlockNumber();
|
|
307
340
|
|
|
@@ -313,8 +346,6 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
313
346
|
|
|
314
347
|
const txContext = new TxContext(this.chainId, this.version, gasSettings);
|
|
315
348
|
|
|
316
|
-
const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
317
|
-
|
|
318
349
|
const protocolNullifier = await computeProtocolNullifier(getSingleTxBlockRequestHash(blockNumber));
|
|
319
350
|
const noteCache = new ExecutionNoteCache(protocolNullifier);
|
|
320
351
|
// In production, the account contract sets the min revertible counter before calling the app function.
|
|
@@ -326,43 +357,37 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
326
357
|
|
|
327
358
|
const simulator = new WASMSimulator();
|
|
328
359
|
|
|
329
|
-
const privateExecutionOracle = new PrivateExecutionOracle(
|
|
360
|
+
const privateExecutionOracle = new PrivateExecutionOracle({
|
|
330
361
|
argsHash,
|
|
331
362
|
txContext,
|
|
332
363
|
callContext,
|
|
333
|
-
|
|
334
|
-
blockHeader,
|
|
364
|
+
anchorBlockHeader: blockHeader,
|
|
335
365
|
utilityExecutor,
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
[],
|
|
340
|
-
HashedValuesCache.create([new HashedValues(args, argsHash)]),
|
|
366
|
+
authWitnesses: Array.from(this.authwits.values()),
|
|
367
|
+
capsules: [],
|
|
368
|
+
executionCache: HashedValuesCache.create([new HashedValues(args, argsHash)]),
|
|
341
369
|
noteCache,
|
|
342
370
|
taggingIndexCache,
|
|
343
|
-
this.contractStore,
|
|
344
|
-
this.noteStore,
|
|
345
|
-
this.keyStore,
|
|
346
|
-
this.addressStore,
|
|
347
|
-
this.stateMachine.node,
|
|
348
|
-
this.
|
|
349
|
-
this.
|
|
350
|
-
this.
|
|
351
|
-
this.
|
|
352
|
-
this.
|
|
353
|
-
this.
|
|
354
|
-
|
|
355
|
-
0,
|
|
356
|
-
minRevertibleSideEffectCounter,
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
* contract would perform, including setting senderForTags.
|
|
362
|
-
*/
|
|
363
|
-
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,
|
|
364
389
|
simulator,
|
|
365
|
-
);
|
|
390
|
+
});
|
|
366
391
|
|
|
367
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.
|
|
368
393
|
let result: PrivateExecutionResult;
|
|
@@ -401,7 +426,8 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
401
426
|
// We pass the non-zero minRevertibleSideEffectCounter to make sure the side effects are split correctly.
|
|
402
427
|
const { publicInputs } = await generateSimulatedProvingResult(
|
|
403
428
|
result,
|
|
404
|
-
this.contractStore,
|
|
429
|
+
(addr, sel) => this.contractStore.getDebugFunctionName(addr, sel),
|
|
430
|
+
this.stateMachine.node,
|
|
405
431
|
minRevertibleSideEffectCounter,
|
|
406
432
|
);
|
|
407
433
|
|
|
@@ -414,7 +440,11 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
414
440
|
|
|
415
441
|
const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
|
|
416
442
|
|
|
417
|
-
const
|
|
443
|
+
const bindings = this.logger.getBindings();
|
|
444
|
+
const contractsDB = new PublicContractsDB(
|
|
445
|
+
new TXEPublicContractDataSource(blockNumber, this.contractStore),
|
|
446
|
+
bindings,
|
|
447
|
+
);
|
|
418
448
|
const guardedMerkleTrees = new GuardedMerkleTreeOperations(forkedWorldTrees);
|
|
419
449
|
const config = PublicSimulatorConfig.from({
|
|
420
450
|
skipFeeEnforcement: true,
|
|
@@ -427,8 +457,10 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
427
457
|
globals,
|
|
428
458
|
guardedMerkleTrees,
|
|
429
459
|
contractsDB,
|
|
430
|
-
new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config),
|
|
460
|
+
new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config, bindings),
|
|
431
461
|
new TestDateProvider(),
|
|
462
|
+
undefined,
|
|
463
|
+
createLogger('simulator:public-processor', bindings),
|
|
432
464
|
);
|
|
433
465
|
|
|
434
466
|
const tx = await Tx.create({
|
|
@@ -525,7 +557,11 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
525
557
|
|
|
526
558
|
const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
|
|
527
559
|
|
|
528
|
-
const
|
|
560
|
+
const bindings2 = this.logger.getBindings();
|
|
561
|
+
const contractsDB = new PublicContractsDB(
|
|
562
|
+
new TXEPublicContractDataSource(blockNumber, this.contractStore),
|
|
563
|
+
bindings2,
|
|
564
|
+
);
|
|
529
565
|
const guardedMerkleTrees = new GuardedMerkleTreeOperations(forkedWorldTrees);
|
|
530
566
|
const config = PublicSimulatorConfig.from({
|
|
531
567
|
skipFeeEnforcement: true,
|
|
@@ -534,8 +570,16 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
534
570
|
collectStatistics: false,
|
|
535
571
|
collectCallMetadata: true,
|
|
536
572
|
});
|
|
537
|
-
const simulator = new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config);
|
|
538
|
-
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
|
+
);
|
|
539
583
|
|
|
540
584
|
// We're simulating a scenario in which private execution immediately enqueues a public call and halts. The private
|
|
541
585
|
// kernel init would in this case inject a nullifier with the transaction request hash as a non-revertible
|
|
@@ -566,7 +610,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
566
610
|
constantData,
|
|
567
611
|
/*gasUsed=*/ new Gas(0, 0),
|
|
568
612
|
/*feePayer=*/ AztecAddress.zero(),
|
|
569
|
-
/*
|
|
613
|
+
/*expirationTimestamp=*/ 0n,
|
|
570
614
|
inputsForPublic,
|
|
571
615
|
undefined,
|
|
572
616
|
);
|
|
@@ -634,10 +678,11 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
634
678
|
return returnValues ?? [];
|
|
635
679
|
}
|
|
636
680
|
|
|
637
|
-
async
|
|
681
|
+
async txeExecuteUtilityFunction(
|
|
638
682
|
targetContractAddress: AztecAddress,
|
|
639
683
|
functionSelector: FunctionSelector,
|
|
640
684
|
args: Fr[],
|
|
685
|
+
jobId: string,
|
|
641
686
|
) {
|
|
642
687
|
const artifact = await this.contractStore.getFunctionArtifact(targetContractAddress, functionSelector);
|
|
643
688
|
if (!artifact) {
|
|
@@ -645,25 +690,33 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
645
690
|
}
|
|
646
691
|
|
|
647
692
|
// Sync notes before executing utility function to discover notes from previous transactions
|
|
648
|
-
await this.
|
|
649
|
-
|
|
650
|
-
});
|
|
651
|
-
|
|
652
|
-
const call = new FunctionCall(
|
|
653
|
-
artifact.name,
|
|
693
|
+
const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
694
|
+
await this.stateMachine.contractSyncService.ensureContractSynced(
|
|
654
695
|
targetContractAddress,
|
|
655
696
|
functionSelector,
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
697
|
+
async (call, execScopes) => {
|
|
698
|
+
await this.executeUtilityCall(call, execScopes, jobId);
|
|
699
|
+
},
|
|
700
|
+
blockHeader,
|
|
701
|
+
jobId,
|
|
702
|
+
'ALL_SCOPES',
|
|
661
703
|
);
|
|
662
704
|
|
|
663
|
-
|
|
705
|
+
const call = FunctionCall.from({
|
|
706
|
+
name: artifact.name,
|
|
707
|
+
to: targetContractAddress,
|
|
708
|
+
selector: functionSelector,
|
|
709
|
+
type: FunctionType.UTILITY,
|
|
710
|
+
hideMsgSender: false,
|
|
711
|
+
isStatic: false,
|
|
712
|
+
args,
|
|
713
|
+
returnTypes: [],
|
|
714
|
+
});
|
|
715
|
+
|
|
716
|
+
return this.executeUtilityCall(call, 'ALL_SCOPES', jobId);
|
|
664
717
|
}
|
|
665
718
|
|
|
666
|
-
private async executeUtilityCall(call: FunctionCall): Promise<Fr[]> {
|
|
719
|
+
private async executeUtilityCall(call: FunctionCall, scopes: AccessScopes, jobId: string): Promise<Fr[]> {
|
|
667
720
|
const entryPointArtifact = await this.contractStore.getFunctionArtifactWithDebugMetadata(call.to, call.selector);
|
|
668
721
|
if (entryPointArtifact.functionType !== FunctionType.UTILITY) {
|
|
669
722
|
throw new Error(`Cannot run ${entryPointArtifact.functionType} function as utility`);
|
|
@@ -676,23 +729,23 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
676
729
|
|
|
677
730
|
try {
|
|
678
731
|
const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
679
|
-
const oracle = new UtilityExecutionOracle(
|
|
680
|
-
call.to,
|
|
681
|
-
[],
|
|
682
|
-
[],
|
|
732
|
+
const oracle = new UtilityExecutionOracle({
|
|
733
|
+
contractAddress: call.to,
|
|
734
|
+
authWitnesses: [],
|
|
735
|
+
capsules: [],
|
|
683
736
|
anchorBlockHeader,
|
|
684
|
-
this.contractStore,
|
|
685
|
-
this.noteStore,
|
|
686
|
-
this.keyStore,
|
|
687
|
-
this.addressStore,
|
|
688
|
-
this.stateMachine.node,
|
|
689
|
-
this.
|
|
690
|
-
this.
|
|
691
|
-
this.
|
|
692
|
-
this.
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
);
|
|
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
|
+
});
|
|
696
749
|
const acirExecutionResult = await new WASMSimulator()
|
|
697
750
|
.executeUserCircuit(toACVMWitness(0, call.args), entryPointArtifact, new Oracle(oracle).toACIRCallback())
|
|
698
751
|
.catch((err: Error) => {
|
|
@@ -708,10 +761,10 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
708
761
|
);
|
|
709
762
|
});
|
|
710
763
|
|
|
711
|
-
this.logger.verbose(`Utility
|
|
764
|
+
this.logger.verbose(`Utility execution for ${call.to}.${call.selector} completed`);
|
|
712
765
|
return witnessMapToFields(acirExecutionResult.returnWitness);
|
|
713
766
|
} catch (err) {
|
|
714
|
-
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'));
|
|
715
768
|
}
|
|
716
769
|
}
|
|
717
770
|
|
package/src/rpc_translator.ts
CHANGED
|
@@ -10,8 +10,7 @@ import {
|
|
|
10
10
|
} from '@aztec/pxe/simulator';
|
|
11
11
|
import { type ContractArtifact, EventSelector, FunctionSelector, NoteSelector } from '@aztec/stdlib/abi';
|
|
12
12
|
import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
13
|
-
import {
|
|
14
|
-
import { MerkleTreeId } from '@aztec/stdlib/trees';
|
|
13
|
+
import { BlockHash } from '@aztec/stdlib/block';
|
|
15
14
|
|
|
16
15
|
import type { IAvmExecutionOracle, ITxeExecutionOracle } from './oracle/interfaces.js';
|
|
17
16
|
import type { TXESessionStateHandler } from './txe_session.js';
|
|
@@ -31,7 +30,7 @@ import {
|
|
|
31
30
|
toSingle,
|
|
32
31
|
} from './util/encoding.js';
|
|
33
32
|
|
|
34
|
-
const MAX_EVENT_LEN =
|
|
33
|
+
const MAX_EVENT_LEN = 10; // This is MAX_MESSAGE_CONTENT_LEN - PRIVATE_EVENT_MSG_PLAINTEXT_RESERVED_FIELDS_LEN
|
|
35
34
|
const MAX_PRIVATE_EVENTS_PER_TXE_QUERY = 5;
|
|
36
35
|
|
|
37
36
|
export class UnavailableOracleError extends Error {
|
|
@@ -286,6 +285,13 @@ export class RPCTranslator {
|
|
|
286
285
|
const contractAddress = addressFromSingle(foreignContractAddress);
|
|
287
286
|
const scope = addressFromSingle(foreignScope);
|
|
288
287
|
|
|
288
|
+
// TODO(F-335): Avoid doing the following 2 calls here.
|
|
289
|
+
{
|
|
290
|
+
await this.handlerAsTxe().syncContractNonOracleMethod(contractAddress, scope, this.stateHandler.getCurrentJob());
|
|
291
|
+
// We cycle job to commit the stores after the contract sync.
|
|
292
|
+
await this.stateHandler.cycleJob();
|
|
293
|
+
}
|
|
294
|
+
|
|
289
295
|
const events = await this.handlerAsTxe().txeGetPrivateEvents(selector, contractAddress, scope);
|
|
290
296
|
|
|
291
297
|
if (events.length > MAX_PRIVATE_EVENTS_PER_TXE_QUERY) {
|
|
@@ -329,7 +335,7 @@ export class RPCTranslator {
|
|
|
329
335
|
|
|
330
336
|
// When the argument is a slice, noir automatically adds a length field to oracle call.
|
|
331
337
|
// When the argument is an array, we add the field length manually to the signature.
|
|
332
|
-
|
|
338
|
+
async utilityLog(
|
|
333
339
|
foreignLevel: ForeignCallSingle,
|
|
334
340
|
foreignMessage: ForeignCallArray,
|
|
335
341
|
_foreignLength: ForeignCallSingle,
|
|
@@ -341,7 +347,7 @@ export class RPCTranslator {
|
|
|
341
347
|
.join('');
|
|
342
348
|
const fields = fromArray(foreignFields);
|
|
343
349
|
|
|
344
|
-
this.handlerAsMisc().
|
|
350
|
+
await this.handlerAsMisc().utilityLog(level, message, fields);
|
|
345
351
|
|
|
346
352
|
return toForeignCallResult([]);
|
|
347
353
|
}
|
|
@@ -352,7 +358,7 @@ export class RPCTranslator {
|
|
|
352
358
|
foreignStartStorageSlot: ForeignCallSingle,
|
|
353
359
|
foreignNumberOfElements: ForeignCallSingle,
|
|
354
360
|
) {
|
|
355
|
-
const blockHash =
|
|
361
|
+
const blockHash = new BlockHash(fromSingle(foreignBlockHash));
|
|
356
362
|
const contractAddress = addressFromSingle(foreignContractAddress);
|
|
357
363
|
const startStorageSlot = fromSingle(foreignStartStorageSlot);
|
|
358
364
|
const numberOfElements = fromSingle(foreignNumberOfElements).toNumber();
|
|
@@ -368,7 +374,7 @@ export class RPCTranslator {
|
|
|
368
374
|
}
|
|
369
375
|
|
|
370
376
|
async utilityGetPublicDataWitness(foreignBlockHash: ForeignCallSingle, foreignLeafSlot: ForeignCallSingle) {
|
|
371
|
-
const blockHash =
|
|
377
|
+
const blockHash = new BlockHash(fromSingle(foreignBlockHash));
|
|
372
378
|
const leafSlot = fromSingle(foreignLeafSlot);
|
|
373
379
|
|
|
374
380
|
const witness = await this.handlerAsUtility().utilityGetPublicDataWitness(blockHash, leafSlot);
|
|
@@ -513,6 +519,15 @@ export class RPCTranslator {
|
|
|
513
519
|
return toForeignCallResult([]);
|
|
514
520
|
}
|
|
515
521
|
|
|
522
|
+
async privateIsNullifierPending(foreignInnerNullifier: ForeignCallSingle, foreignContractAddress: ForeignCallSingle) {
|
|
523
|
+
const innerNullifier = fromSingle(foreignInnerNullifier);
|
|
524
|
+
const contractAddress = addressFromSingle(foreignContractAddress);
|
|
525
|
+
|
|
526
|
+
const isPending = await this.handlerAsPrivate().privateIsNullifierPending(innerNullifier, contractAddress);
|
|
527
|
+
|
|
528
|
+
return toForeignCallResult([toSingle(new Fr(isPending))]);
|
|
529
|
+
}
|
|
530
|
+
|
|
516
531
|
async utilityCheckNullifierExists(foreignInnerNullifier: ForeignCallSingle) {
|
|
517
532
|
const innerNullifier = fromSingle(foreignInnerNullifier);
|
|
518
533
|
|
|
@@ -537,12 +552,23 @@ export class RPCTranslator {
|
|
|
537
552
|
);
|
|
538
553
|
}
|
|
539
554
|
|
|
540
|
-
async
|
|
555
|
+
async utilityTryGetPublicKeysAndPartialAddress(foreignAddress: ForeignCallSingle) {
|
|
541
556
|
const address = addressFromSingle(foreignAddress);
|
|
542
557
|
|
|
543
|
-
const
|
|
558
|
+
const result = await this.handlerAsUtility().utilityTryGetPublicKeysAndPartialAddress(address);
|
|
544
559
|
|
|
545
|
-
return
|
|
560
|
+
// We are going to return a Noir Option struct to represent the possibility of null values. Options are a struct
|
|
561
|
+
// with two fields: `some` (a boolean) and `value` (a field array in this case).
|
|
562
|
+
if (result === undefined) {
|
|
563
|
+
// No data was found so we set `some` to 0 and pad `value` with zeros get the correct return size.
|
|
564
|
+
return toForeignCallResult([toSingle(new Fr(0)), toArray(Array(13).fill(new Fr(0)))]);
|
|
565
|
+
} else {
|
|
566
|
+
// Data was found so we set `some` to 1 and return it along with `value`.
|
|
567
|
+
return toForeignCallResult([
|
|
568
|
+
toSingle(new Fr(1)),
|
|
569
|
+
toArray([...result.publicKeys.toFields(), result.partialAddress]),
|
|
570
|
+
]);
|
|
571
|
+
}
|
|
546
572
|
}
|
|
547
573
|
|
|
548
574
|
async utilityGetKeyValidationRequest(foreignPkMHash: ForeignCallSingle) {
|
|
@@ -566,7 +592,7 @@ export class RPCTranslator {
|
|
|
566
592
|
}
|
|
567
593
|
|
|
568
594
|
async utilityGetNullifierMembershipWitness(foreignBlockHash: ForeignCallSingle, foreignNullifier: ForeignCallSingle) {
|
|
569
|
-
const blockHash =
|
|
595
|
+
const blockHash = new BlockHash(fromSingle(foreignBlockHash));
|
|
570
596
|
const nullifier = fromSingle(foreignNullifier);
|
|
571
597
|
|
|
572
598
|
const witness = await this.handlerAsUtility().utilityGetNullifierMembershipWitness(blockHash, nullifier);
|
|
@@ -633,30 +659,43 @@ export class RPCTranslator {
|
|
|
633
659
|
return toForeignCallResult(header.toFields().map(toSingle));
|
|
634
660
|
}
|
|
635
661
|
|
|
636
|
-
async
|
|
662
|
+
async utilityGetNoteHashMembershipWitness(
|
|
663
|
+
foreignAnchorBlockHash: ForeignCallSingle,
|
|
664
|
+
foreignNoteHash: ForeignCallSingle,
|
|
665
|
+
) {
|
|
666
|
+
const blockHash = new BlockHash(fromSingle(foreignAnchorBlockHash));
|
|
667
|
+
const noteHash = fromSingle(foreignNoteHash);
|
|
668
|
+
|
|
669
|
+
const witness = await this.handlerAsUtility().utilityGetNoteHashMembershipWitness(blockHash, noteHash);
|
|
670
|
+
|
|
671
|
+
if (!witness) {
|
|
672
|
+
throw new Error(`Note hash ${noteHash} not found in the note hash tree at block ${blockHash.toString()}.`);
|
|
673
|
+
}
|
|
674
|
+
return toForeignCallResult(witness.toNoirRepresentation());
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
async utilityGetBlockHashMembershipWitness(
|
|
678
|
+
foreignAnchorBlockHash: ForeignCallSingle,
|
|
637
679
|
foreignBlockHash: ForeignCallSingle,
|
|
638
|
-
foreignTreeId: ForeignCallSingle,
|
|
639
|
-
foreignLeafValue: ForeignCallSingle,
|
|
640
680
|
) {
|
|
641
|
-
const
|
|
642
|
-
const
|
|
643
|
-
const leafValue = fromSingle(foreignLeafValue);
|
|
681
|
+
const anchorBlockHash = new BlockHash(fromSingle(foreignAnchorBlockHash));
|
|
682
|
+
const blockHash = new BlockHash(fromSingle(foreignBlockHash));
|
|
644
683
|
|
|
645
|
-
const witness = await this.handlerAsUtility().
|
|
684
|
+
const witness = await this.handlerAsUtility().utilityGetBlockHashMembershipWitness(anchorBlockHash, blockHash);
|
|
646
685
|
|
|
647
686
|
if (!witness) {
|
|
648
687
|
throw new Error(
|
|
649
|
-
`
|
|
688
|
+
`Block hash ${blockHash.toString()} not found in the archive tree at anchor block ${anchorBlockHash.toString()}.`,
|
|
650
689
|
);
|
|
651
690
|
}
|
|
652
|
-
return toForeignCallResult(
|
|
691
|
+
return toForeignCallResult(witness.toNoirRepresentation());
|
|
653
692
|
}
|
|
654
693
|
|
|
655
694
|
async utilityGetLowNullifierMembershipWitness(
|
|
656
695
|
foreignBlockHash: ForeignCallSingle,
|
|
657
696
|
foreignNullifier: ForeignCallSingle,
|
|
658
697
|
) {
|
|
659
|
-
const blockHash =
|
|
698
|
+
const blockHash = new BlockHash(fromSingle(foreignBlockHash));
|
|
660
699
|
const nullifier = fromSingle(foreignNullifier);
|
|
661
700
|
|
|
662
701
|
const witness = await this.handlerAsUtility().utilityGetLowNullifierMembershipWitness(blockHash, nullifier);
|
|
@@ -675,7 +714,7 @@ export class RPCTranslator {
|
|
|
675
714
|
return toForeignCallResult([]);
|
|
676
715
|
}
|
|
677
716
|
|
|
678
|
-
public async
|
|
717
|
+
public async utilityValidateAndStoreEnqueuedNotesAndEvents(
|
|
679
718
|
foreignContractAddress: ForeignCallSingle,
|
|
680
719
|
foreignNoteValidationRequestsArrayBaseSlot: ForeignCallSingle,
|
|
681
720
|
foreignEventValidationRequestsArrayBaseSlot: ForeignCallSingle,
|
|
@@ -684,7 +723,7 @@ export class RPCTranslator {
|
|
|
684
723
|
const noteValidationRequestsArrayBaseSlot = fromSingle(foreignNoteValidationRequestsArrayBaseSlot);
|
|
685
724
|
const eventValidationRequestsArrayBaseSlot = fromSingle(foreignEventValidationRequestsArrayBaseSlot);
|
|
686
725
|
|
|
687
|
-
await this.handlerAsUtility().
|
|
726
|
+
await this.handlerAsUtility().utilityValidateAndStoreEnqueuedNotesAndEvents(
|
|
688
727
|
contractAddress,
|
|
689
728
|
noteValidationRequestsArrayBaseSlot,
|
|
690
729
|
eventValidationRequestsArrayBaseSlot,
|
|
@@ -817,15 +856,16 @@ export class RPCTranslator {
|
|
|
817
856
|
|
|
818
857
|
// AVM opcodes
|
|
819
858
|
|
|
820
|
-
|
|
859
|
+
avmOpcodeEmitPublicLog(_foreignMessage: ForeignCallArray) {
|
|
821
860
|
// TODO(#8811): Implement
|
|
822
861
|
return toForeignCallResult([]);
|
|
823
862
|
}
|
|
824
863
|
|
|
825
|
-
async avmOpcodeStorageRead(foreignSlot: ForeignCallSingle) {
|
|
864
|
+
async avmOpcodeStorageRead(foreignSlot: ForeignCallSingle, foreignContractAddress: ForeignCallSingle) {
|
|
826
865
|
const slot = fromSingle(foreignSlot);
|
|
866
|
+
const contractAddress = AztecAddress.fromField(fromSingle(foreignContractAddress));
|
|
827
867
|
|
|
828
|
-
const value = (await this.handlerAsAvm().avmOpcodeStorageRead(slot)).value;
|
|
868
|
+
const value = (await this.handlerAsAvm().avmOpcodeStorageRead(slot, contractAddress)).value;
|
|
829
869
|
|
|
830
870
|
return toForeignCallResult([toSingle(new Fr(value))]);
|
|
831
871
|
}
|
|
@@ -897,11 +937,10 @@ export class RPCTranslator {
|
|
|
897
937
|
return toForeignCallResult([]);
|
|
898
938
|
}
|
|
899
939
|
|
|
900
|
-
async avmOpcodeNullifierExists(
|
|
901
|
-
const
|
|
902
|
-
const targetAddress = AztecAddress.fromField(fromSingle(foreignTargetAddress));
|
|
940
|
+
async avmOpcodeNullifierExists(foreignSiloedNullifier: ForeignCallSingle) {
|
|
941
|
+
const siloedNullifier = fromSingle(foreignSiloedNullifier);
|
|
903
942
|
|
|
904
|
-
const exists = await this.handlerAsAvm().avmOpcodeNullifierExists(
|
|
943
|
+
const exists = await this.handlerAsAvm().avmOpcodeNullifierExists(siloedNullifier);
|
|
905
944
|
|
|
906
945
|
return toForeignCallResult([toSingle(new Fr(exists))]);
|
|
907
946
|
}
|
|
@@ -1006,12 +1045,15 @@ export class RPCTranslator {
|
|
|
1006
1045
|
args,
|
|
1007
1046
|
argsHash,
|
|
1008
1047
|
isStaticCall,
|
|
1048
|
+
this.stateHandler.getCurrentJob(),
|
|
1009
1049
|
);
|
|
1010
1050
|
|
|
1051
|
+
// TODO(F-335): Avoid doing the following call here.
|
|
1052
|
+
await this.stateHandler.cycleJob();
|
|
1011
1053
|
return toForeignCallResult([toArray(returnValues)]);
|
|
1012
1054
|
}
|
|
1013
1055
|
|
|
1014
|
-
async
|
|
1056
|
+
async txeExecuteUtilityFunction(
|
|
1015
1057
|
foreignTargetContractAddress: ForeignCallSingle,
|
|
1016
1058
|
foreignFunctionSelector: ForeignCallSingle,
|
|
1017
1059
|
foreignArgs: ForeignCallArray,
|
|
@@ -1020,12 +1062,15 @@ export class RPCTranslator {
|
|
|
1020
1062
|
const functionSelector = FunctionSelector.fromField(fromSingle(foreignFunctionSelector));
|
|
1021
1063
|
const args = fromArray(foreignArgs);
|
|
1022
1064
|
|
|
1023
|
-
const returnValues = await this.handlerAsTxe().
|
|
1065
|
+
const returnValues = await this.handlerAsTxe().txeExecuteUtilityFunction(
|
|
1024
1066
|
targetContractAddress,
|
|
1025
1067
|
functionSelector,
|
|
1026
1068
|
args,
|
|
1069
|
+
this.stateHandler.getCurrentJob(),
|
|
1027
1070
|
);
|
|
1028
1071
|
|
|
1072
|
+
// TODO(F-335): Avoid doing the following call here.
|
|
1073
|
+
await this.stateHandler.cycleJob();
|
|
1029
1074
|
return toForeignCallResult([toArray(returnValues)]);
|
|
1030
1075
|
}
|
|
1031
1076
|
|
|
@@ -1042,6 +1087,8 @@ export class RPCTranslator {
|
|
|
1042
1087
|
|
|
1043
1088
|
const returnValues = await this.handlerAsTxe().txePublicCallNewFlow(from, address, calldata, isStaticCall);
|
|
1044
1089
|
|
|
1090
|
+
// TODO(F-335): Avoid doing the following call here.
|
|
1091
|
+
await this.stateHandler.cycleJob();
|
|
1045
1092
|
return toForeignCallResult([toArray(returnValues)]);
|
|
1046
1093
|
}
|
|
1047
1094
|
|