@aztec/txe 1.2.1 → 2.0.0-nightly.20250813
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.map +1 -1
- package/dest/index.js +34 -33
- package/dest/oracle/txe_oracle.d.ts +52 -81
- package/dest/oracle/txe_oracle.d.ts.map +1 -1
- package/dest/oracle/txe_oracle.js +167 -408
- package/dest/state_machine/archiver.d.ts +4 -2
- package/dest/state_machine/archiver.d.ts.map +1 -1
- package/dest/state_machine/archiver.js +8 -0
- package/dest/state_machine/dummy_p2p_client.d.ts +6 -3
- package/dest/state_machine/dummy_p2p_client.d.ts.map +1 -1
- package/dest/state_machine/dummy_p2p_client.js +8 -0
- package/dest/state_machine/mock_epoch_cache.d.ts +4 -2
- package/dest/state_machine/mock_epoch_cache.d.ts.map +1 -1
- package/dest/state_machine/mock_epoch_cache.js +7 -1
- package/dest/txe_constants.d.ts +0 -1
- package/dest/txe_constants.d.ts.map +1 -1
- package/dest/txe_constants.js +0 -2
- package/dest/txe_service/txe_service.d.ts +82 -90
- package/dest/txe_service/txe_service.d.ts.map +1 -1
- package/dest/txe_service/txe_service.js +305 -361
- package/dest/util/txe_public_contract_data_source.js +1 -1
- package/package.json +16 -16
- package/src/index.ts +42 -35
- package/src/oracle/txe_oracle.ts +192 -551
- package/src/state_machine/archiver.ts +10 -2
- package/src/state_machine/dummy_p2p_client.ts +29 -3
- package/src/state_machine/mock_epoch_cache.ts +10 -2
- package/src/txe_constants.ts +0 -2
- package/src/txe_service/txe_service.ts +353 -480
- package/src/util/txe_public_contract_data_source.ts +1 -1
package/src/oracle/txe_oracle.ts
CHANGED
|
@@ -3,22 +3,18 @@ import {
|
|
|
3
3
|
DEFAULT_GAS_LIMIT,
|
|
4
4
|
DEFAULT_TEARDOWN_GAS_LIMIT,
|
|
5
5
|
type L1_TO_L2_MSG_TREE_HEIGHT,
|
|
6
|
-
MAX_CONTRACT_CLASS_LOGS_PER_TX,
|
|
7
|
-
MAX_ENQUEUED_CALLS_PER_TX,
|
|
8
6
|
MAX_L2_GAS_PER_TX_PUBLIC_PORTION,
|
|
9
|
-
MAX_L2_TO_L1_MSGS_PER_TX,
|
|
10
7
|
MAX_NOTE_HASHES_PER_TX,
|
|
11
8
|
MAX_NULLIFIERS_PER_TX,
|
|
12
|
-
MAX_PRIVATE_LOGS_PER_TX,
|
|
13
9
|
NULLIFIER_SUBTREE_HEIGHT,
|
|
14
10
|
NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP,
|
|
15
11
|
PRIVATE_CONTEXT_INPUTS_LENGTH,
|
|
16
12
|
} from '@aztec/constants';
|
|
17
13
|
import { padArrayEnd } from '@aztec/foundation/collection';
|
|
18
|
-
import { Aes128, Schnorr
|
|
14
|
+
import { Aes128, Schnorr } from '@aztec/foundation/crypto';
|
|
19
15
|
import { Fr, Point } from '@aztec/foundation/fields';
|
|
20
16
|
import { type Logger, applyStringFormatting } from '@aztec/foundation/log';
|
|
21
|
-
import { TestDateProvider
|
|
17
|
+
import { TestDateProvider } from '@aztec/foundation/timer';
|
|
22
18
|
import { KeyStore } from '@aztec/key-store';
|
|
23
19
|
import type { AztecAsyncKVStore } from '@aztec/kv-store';
|
|
24
20
|
import type { ProtocolContract } from '@aztec/protocol-contracts';
|
|
@@ -39,21 +35,17 @@ import {
|
|
|
39
35
|
type NoteData,
|
|
40
36
|
Oracle,
|
|
41
37
|
PrivateExecutionOracle,
|
|
42
|
-
type TypedOracle,
|
|
43
38
|
UtilityExecutionOracle,
|
|
44
39
|
executePrivateFunction,
|
|
45
|
-
extractPrivateCircuitPublicInputs,
|
|
46
40
|
generateSimulatedProvingResult,
|
|
47
41
|
pickNotes,
|
|
48
42
|
} from '@aztec/pxe/simulator';
|
|
49
43
|
import { WASMSimulator, extractCallStack, toACVMWitness, witnessMapToFields } from '@aztec/simulator/client';
|
|
50
|
-
import { createTxForPublicCalls } from '@aztec/simulator/public/fixtures';
|
|
51
44
|
import {
|
|
52
45
|
ExecutionError,
|
|
53
46
|
GuardedMerkleTreeOperations,
|
|
54
47
|
PublicContractsDB,
|
|
55
48
|
PublicProcessor,
|
|
56
|
-
type PublicTxResult,
|
|
57
49
|
PublicTxSimulator,
|
|
58
50
|
createSimulationError,
|
|
59
51
|
resolveAssertionMessageFromError,
|
|
@@ -70,7 +62,6 @@ import { AuthWitness } from '@aztec/stdlib/auth-witness';
|
|
|
70
62
|
import { PublicDataWrite } from '@aztec/stdlib/avm';
|
|
71
63
|
import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
72
64
|
import type { ContractInstance, ContractInstanceWithAddress } from '@aztec/stdlib/contract';
|
|
73
|
-
import { SimulationError } from '@aztec/stdlib/errors';
|
|
74
65
|
import { Gas, GasFees, GasSettings } from '@aztec/stdlib/gas';
|
|
75
66
|
import {
|
|
76
67
|
computeCalldataHash,
|
|
@@ -89,15 +80,10 @@ import {
|
|
|
89
80
|
PrivateKernelTailCircuitPublicInputs,
|
|
90
81
|
PrivateToPublicAccumulatedData,
|
|
91
82
|
PublicCallRequest,
|
|
92
|
-
RollupValidationRequests,
|
|
93
|
-
ScopedLogHash,
|
|
94
83
|
} from '@aztec/stdlib/kernel';
|
|
95
|
-
import { deriveKeys } from '@aztec/stdlib/keys';
|
|
96
84
|
import { ContractClassLog, IndexedTaggingSecret, PrivateLog, type PublicLog } from '@aztec/stdlib/logs';
|
|
97
|
-
import { ScopedL2ToL1Message } from '@aztec/stdlib/messaging';
|
|
98
85
|
import type { NoteStatus } from '@aztec/stdlib/note';
|
|
99
86
|
import { ClientIvcProof } from '@aztec/stdlib/proofs';
|
|
100
|
-
import type { CircuitWitnessGenerationStats } from '@aztec/stdlib/stats';
|
|
101
87
|
import {
|
|
102
88
|
makeAppendOnlyTreeSnapshot,
|
|
103
89
|
makeContentCommitment,
|
|
@@ -107,7 +93,6 @@ import {
|
|
|
107
93
|
import {
|
|
108
94
|
AppendOnlyTreeSnapshot,
|
|
109
95
|
MerkleTreeId,
|
|
110
|
-
type NullifierLeafPreimage,
|
|
111
96
|
NullifierMembershipWitness,
|
|
112
97
|
PublicDataTreeLeaf,
|
|
113
98
|
type PublicDataTreeLeafPreimage,
|
|
@@ -116,11 +101,9 @@ import {
|
|
|
116
101
|
import {
|
|
117
102
|
BlockHeader,
|
|
118
103
|
CallContext,
|
|
119
|
-
GlobalVariables,
|
|
120
104
|
HashedValues,
|
|
121
105
|
PrivateCallExecutionResult,
|
|
122
106
|
PrivateExecutionResult,
|
|
123
|
-
PublicCallRequestWithCalldata,
|
|
124
107
|
Tx,
|
|
125
108
|
TxConstantData,
|
|
126
109
|
TxContext,
|
|
@@ -132,22 +115,18 @@ import type { UInt64 } from '@aztec/stdlib/types';
|
|
|
132
115
|
import { ForkCheckpoint, NativeWorldStateService } from '@aztec/world-state/native';
|
|
133
116
|
|
|
134
117
|
import { TXEStateMachine } from '../state_machine/index.js';
|
|
135
|
-
import {
|
|
118
|
+
import { GENESIS_TIMESTAMP } from '../txe_constants.js';
|
|
136
119
|
import { TXEAccountDataProvider } from '../util/txe_account_data_provider.js';
|
|
137
120
|
import { TXEContractDataProvider } from '../util/txe_contract_data_provider.js';
|
|
138
121
|
import { TXEPublicContractDataSource } from '../util/txe_public_contract_data_source.js';
|
|
139
122
|
|
|
140
|
-
export class TXE
|
|
123
|
+
export class TXE {
|
|
141
124
|
private blockNumber = 1;
|
|
142
125
|
private timestamp = GENESIS_TIMESTAMP;
|
|
143
126
|
|
|
144
127
|
private sideEffectCounter = 0;
|
|
145
128
|
private msgSender: AztecAddress;
|
|
146
129
|
private functionSelector = FunctionSelector.fromField(new Fr(0));
|
|
147
|
-
private isStaticCall = false;
|
|
148
|
-
// Return/revert data of the latest nested call.
|
|
149
|
-
private nestedCallReturndata: Fr[] = [];
|
|
150
|
-
private nestedCallSuccess: boolean = false;
|
|
151
130
|
|
|
152
131
|
private pxeOracleInterface: PXEOracleInterface;
|
|
153
132
|
|
|
@@ -170,6 +149,9 @@ export class TXE implements TypedOracle {
|
|
|
170
149
|
|
|
171
150
|
private authwits: Map<string, AuthWitness> = new Map();
|
|
172
151
|
|
|
152
|
+
// Used by privateSetSenderForTags and privateGetSenderForTags oracles.
|
|
153
|
+
private senderForTags?: AztecAddress;
|
|
154
|
+
|
|
173
155
|
private constructor(
|
|
174
156
|
private logger: Logger,
|
|
175
157
|
private keyStore: KeyStore,
|
|
@@ -261,11 +243,11 @@ export class TXE implements TypedOracle {
|
|
|
261
243
|
return this.baseFork;
|
|
262
244
|
}
|
|
263
245
|
|
|
264
|
-
|
|
246
|
+
utilityGetChainId(): Promise<Fr> {
|
|
265
247
|
return Promise.resolve(new Fr(this.CHAIN_ID));
|
|
266
248
|
}
|
|
267
249
|
|
|
268
|
-
|
|
250
|
+
utilityGetVersion(): Promise<Fr> {
|
|
269
251
|
return Promise.resolve(new Fr(this.ROLLUP_VERSION));
|
|
270
252
|
}
|
|
271
253
|
|
|
@@ -273,27 +255,7 @@ export class TXE implements TypedOracle {
|
|
|
273
255
|
return this.msgSender;
|
|
274
256
|
}
|
|
275
257
|
|
|
276
|
-
|
|
277
|
-
return this.functionSelector;
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
setMsgSender(msgSender: AztecAddress) {
|
|
281
|
-
this.msgSender = msgSender;
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
setFunctionSelector(functionSelector: FunctionSelector) {
|
|
285
|
-
this.functionSelector = functionSelector;
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
getSideEffectsCounter() {
|
|
289
|
-
return this.sideEffectCounter;
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
setSideEffectsCounter(sideEffectsCounter: number) {
|
|
293
|
-
this.sideEffectCounter = sideEffectsCounter;
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
setContractAddress(contractAddress: AztecAddress) {
|
|
258
|
+
txeSetContractAddress(contractAddress: AztecAddress) {
|
|
297
259
|
this.contractAddress = contractAddress;
|
|
298
260
|
}
|
|
299
261
|
|
|
@@ -302,7 +264,7 @@ export class TXE implements TypedOracle {
|
|
|
302
264
|
this.blockNumber = blockNumber;
|
|
303
265
|
}
|
|
304
266
|
|
|
305
|
-
|
|
267
|
+
txeAdvanceTimestampBy(duration: UInt64) {
|
|
306
268
|
this.timestamp = this.timestamp + duration;
|
|
307
269
|
}
|
|
308
270
|
|
|
@@ -330,16 +292,14 @@ export class TXE implements TypedOracle {
|
|
|
330
292
|
await this.contractDataProvider.addContractArtifact(contractClassId, artifact);
|
|
331
293
|
}
|
|
332
294
|
|
|
333
|
-
async
|
|
295
|
+
async txeGetPrivateContextInputs(
|
|
334
296
|
blockNumber: number | null,
|
|
335
|
-
timestamp: UInt64 | null,
|
|
336
297
|
sideEffectsCounter = this.sideEffectCounter,
|
|
337
298
|
isStaticCall = false,
|
|
338
299
|
) {
|
|
339
300
|
// If blockNumber or timestamp is null, use the values corresponding to the latest historical block (number of
|
|
340
301
|
// the block being built - 1)
|
|
341
302
|
blockNumber = blockNumber ?? this.blockNumber - 1;
|
|
342
|
-
timestamp = timestamp ?? this.timestamp - AZTEC_SLOT_DURATION;
|
|
343
303
|
|
|
344
304
|
const snap = this.nativeWorldStateService.getSnapshot(blockNumber);
|
|
345
305
|
const previousBlockState = this.nativeWorldStateService.getSnapshot(blockNumber - 1);
|
|
@@ -349,7 +309,7 @@ export class TXE implements TypedOracle {
|
|
|
349
309
|
inputs.txContext.chainId = new Fr(this.CHAIN_ID);
|
|
350
310
|
inputs.txContext.version = new Fr(this.ROLLUP_VERSION);
|
|
351
311
|
inputs.historicalHeader.globalVariables.blockNumber = blockNumber;
|
|
352
|
-
inputs.historicalHeader.globalVariables.timestamp =
|
|
312
|
+
inputs.historicalHeader.globalVariables.timestamp = await this.getBlockTimestamp(blockNumber);
|
|
353
313
|
inputs.historicalHeader.state = stateReference;
|
|
354
314
|
inputs.historicalHeader.lastArchive.root = Fr.fromBuffer(
|
|
355
315
|
(await previousBlockState.getTreeInfo(MerkleTreeId.ARCHIVE)).root,
|
|
@@ -359,11 +319,7 @@ export class TXE implements TypedOracle {
|
|
|
359
319
|
return inputs;
|
|
360
320
|
}
|
|
361
321
|
|
|
362
|
-
|
|
363
|
-
return deriveKeys(secret);
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
async addAuthWitness(address: AztecAddress, messageHash: Fr) {
|
|
322
|
+
async txeAddAuthWitness(address: AztecAddress, messageHash: Fr) {
|
|
367
323
|
const account = await this.accountDataProvider.getAccount(address);
|
|
368
324
|
const privateKey = await this.keyStore.getMasterSecretKey(account.publicKeys.masterIncomingViewingPublicKey);
|
|
369
325
|
const schnorr = new Schnorr();
|
|
@@ -401,57 +357,33 @@ export class TXE implements TypedOracle {
|
|
|
401
357
|
this.uniqueNoteHashesFromPublic.push(...siloedNoteHashes);
|
|
402
358
|
}
|
|
403
359
|
|
|
404
|
-
async addPrivateLogs(contractAddress: AztecAddress, privateLogs: PrivateLog[]) {
|
|
405
|
-
for (const privateLog of privateLogs) {
|
|
406
|
-
privateLog.fields[0] = await poseidon2Hash([contractAddress, privateLog.fields[0]]);
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
this.privateLogs.push(...privateLogs);
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
addPublicLogs(logs: PublicLog[]) {
|
|
413
|
-
logs.forEach(log => {
|
|
414
|
-
try {
|
|
415
|
-
const tag = log.fields[0];
|
|
416
|
-
this.logger.verbose(`Found tagged public log with tag ${tag.toString()} in block ${this.blockNumber}`);
|
|
417
|
-
this.publicLogs.push(log);
|
|
418
|
-
} catch (err) {
|
|
419
|
-
this.logger.warn(`Failed to add tagged log to store: ${err}`);
|
|
420
|
-
}
|
|
421
|
-
});
|
|
422
|
-
}
|
|
423
|
-
|
|
424
360
|
// TypedOracle
|
|
425
361
|
|
|
426
|
-
|
|
362
|
+
utilityGetBlockNumber() {
|
|
427
363
|
return Promise.resolve(this.blockNumber);
|
|
428
364
|
}
|
|
429
365
|
|
|
430
|
-
|
|
366
|
+
utilityGetTimestamp() {
|
|
431
367
|
return Promise.resolve(this.timestamp);
|
|
432
368
|
}
|
|
433
369
|
|
|
434
|
-
|
|
435
|
-
return
|
|
436
|
-
}
|
|
437
|
-
|
|
438
|
-
setIsStaticCall(isStatic: boolean) {
|
|
439
|
-
this.isStaticCall = isStatic;
|
|
370
|
+
txeGetLastBlockTimestamp() {
|
|
371
|
+
return this.getBlockTimestamp(this.blockNumber - 1);
|
|
440
372
|
}
|
|
441
373
|
|
|
442
|
-
|
|
443
|
-
return this.
|
|
374
|
+
utilityGetContractAddress() {
|
|
375
|
+
return Promise.resolve(this.contractAddress);
|
|
444
376
|
}
|
|
445
377
|
|
|
446
|
-
|
|
378
|
+
utilityGetRandomField() {
|
|
447
379
|
return Fr.random();
|
|
448
380
|
}
|
|
449
381
|
|
|
450
|
-
|
|
382
|
+
privateStoreInExecutionCache(values: Fr[], hash: Fr) {
|
|
451
383
|
return this.executionCache.store(values, hash);
|
|
452
384
|
}
|
|
453
385
|
|
|
454
|
-
|
|
386
|
+
privateLoadFromExecutionCache(hash: Fr) {
|
|
455
387
|
const preimage = this.executionCache.getPreimage(hash);
|
|
456
388
|
if (!preimage) {
|
|
457
389
|
throw new Error(`Preimage for hash ${hash.toString()} not found in cache`);
|
|
@@ -459,109 +391,50 @@ export class TXE implements TypedOracle {
|
|
|
459
391
|
return Promise.resolve(preimage);
|
|
460
392
|
}
|
|
461
393
|
|
|
462
|
-
|
|
394
|
+
utilityGetKeyValidationRequest(pkMHash: Fr): Promise<KeyValidationRequest> {
|
|
463
395
|
return this.keyStore.getKeyValidationRequest(pkMHash, this.contractAddress);
|
|
464
396
|
}
|
|
465
397
|
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
if (!contractInstance) {
|
|
469
|
-
throw new Error(`Contract instance not found for address ${address}`);
|
|
470
|
-
}
|
|
471
|
-
return contractInstance;
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
async getMembershipWitness(blockNumber: number, treeId: MerkleTreeId, leafValue: Fr): Promise<Fr[] | undefined> {
|
|
475
|
-
const snap = this.nativeWorldStateService.getSnapshot(blockNumber);
|
|
476
|
-
const index = (await snap.findLeafIndices(treeId, [leafValue.toBuffer()]))[0];
|
|
477
|
-
if (index === undefined) {
|
|
478
|
-
throw new Error(`Leaf value: ${leafValue} not found in ${MerkleTreeId[treeId]} at block ${blockNumber}`);
|
|
479
|
-
}
|
|
480
|
-
const siblingPath = await snap.getSiblingPath(treeId, index);
|
|
481
|
-
|
|
482
|
-
return [new Fr(index), ...siblingPath.toFields()];
|
|
398
|
+
utilityGetContractInstance(address: AztecAddress): Promise<ContractInstance> {
|
|
399
|
+
return this.pxeOracleInterface.getContractInstance(address);
|
|
483
400
|
}
|
|
484
401
|
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
const result = await snap.getSiblingPath(treeId, leafIndex.toBigInt());
|
|
489
|
-
return result.toFields();
|
|
402
|
+
utilityGetMembershipWitness(blockNumber: number, treeId: MerkleTreeId, leafValue: Fr): Promise<Fr[] | undefined> {
|
|
403
|
+
return this.pxeOracleInterface.getMembershipWitness(blockNumber, treeId, leafValue);
|
|
490
404
|
}
|
|
491
405
|
|
|
492
|
-
|
|
406
|
+
utilityGetNullifierMembershipWitness(
|
|
493
407
|
blockNumber: number,
|
|
494
408
|
nullifier: Fr,
|
|
495
409
|
): Promise<NullifierMembershipWitness | undefined> {
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
const [index] = await snap.findLeafIndices(MerkleTreeId.NULLIFIER_TREE, [nullifier.toBuffer()]);
|
|
499
|
-
if (!index) {
|
|
500
|
-
return undefined;
|
|
501
|
-
}
|
|
502
|
-
|
|
503
|
-
const leafPreimagePromise = snap.getLeafPreimage(MerkleTreeId.NULLIFIER_TREE, index);
|
|
504
|
-
const siblingPathPromise = snap.getSiblingPath(MerkleTreeId.NULLIFIER_TREE, BigInt(index));
|
|
505
|
-
|
|
506
|
-
const [leafPreimage, siblingPath] = await Promise.all([leafPreimagePromise, siblingPathPromise]);
|
|
507
|
-
|
|
508
|
-
if (!leafPreimage) {
|
|
509
|
-
return undefined;
|
|
510
|
-
}
|
|
511
|
-
|
|
512
|
-
return new NullifierMembershipWitness(BigInt(index), leafPreimage as NullifierLeafPreimage, siblingPath);
|
|
410
|
+
return this.pxeOracleInterface.getNullifierMembershipWitness(blockNumber, nullifier);
|
|
513
411
|
}
|
|
514
412
|
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
const lowLeafResult = await snap.getPreviousValueIndex(MerkleTreeId.PUBLIC_DATA_TREE, leafSlot.toBigInt());
|
|
519
|
-
if (!lowLeafResult) {
|
|
520
|
-
return undefined;
|
|
521
|
-
} else {
|
|
522
|
-
const preimage = (await snap.getLeafPreimage(
|
|
523
|
-
MerkleTreeId.PUBLIC_DATA_TREE,
|
|
524
|
-
lowLeafResult.index,
|
|
525
|
-
)) as PublicDataTreeLeafPreimage;
|
|
526
|
-
const path = await snap.getSiblingPath(MerkleTreeId.PUBLIC_DATA_TREE, lowLeafResult.index);
|
|
527
|
-
return new PublicDataWitness(lowLeafResult.index, preimage, path);
|
|
528
|
-
}
|
|
413
|
+
utilityGetPublicDataWitness(blockNumber: number, leafSlot: Fr): Promise<PublicDataWitness | undefined> {
|
|
414
|
+
return this.pxeOracleInterface.getPublicDataWitness(blockNumber, leafSlot);
|
|
529
415
|
}
|
|
530
416
|
|
|
531
|
-
|
|
417
|
+
utilityGetLowNullifierMembershipWitness(
|
|
532
418
|
blockNumber: number,
|
|
533
419
|
nullifier: Fr,
|
|
534
420
|
): Promise<NullifierMembershipWitness | undefined> {
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
const findResult = await snap.getPreviousValueIndex(MerkleTreeId.NULLIFIER_TREE, nullifier.toBigInt());
|
|
538
|
-
if (!findResult) {
|
|
539
|
-
return undefined;
|
|
540
|
-
}
|
|
541
|
-
const { index, alreadyPresent } = findResult;
|
|
542
|
-
if (alreadyPresent) {
|
|
543
|
-
this.logger.warn(`Nullifier ${nullifier.toBigInt()} already exists in the tree`);
|
|
544
|
-
}
|
|
545
|
-
const preimageData = (await snap.getLeafPreimage(MerkleTreeId.NULLIFIER_TREE, index))!;
|
|
546
|
-
|
|
547
|
-
const siblingPath = await snap.getSiblingPath(MerkleTreeId.NULLIFIER_TREE, BigInt(index));
|
|
548
|
-
return new NullifierMembershipWitness(BigInt(index), preimageData as NullifierLeafPreimage, siblingPath);
|
|
421
|
+
return this.pxeOracleInterface.getLowNullifierMembershipWitness(blockNumber, nullifier);
|
|
549
422
|
}
|
|
550
423
|
|
|
551
|
-
|
|
424
|
+
utilityGetBlockHeader(blockNumber: number): Promise<BlockHeader | undefined> {
|
|
552
425
|
return this.stateMachine.archiver.getBlockHeader(blockNumber);
|
|
553
426
|
}
|
|
554
427
|
|
|
555
|
-
|
|
428
|
+
utilityGetCompleteAddress(account: AztecAddress) {
|
|
556
429
|
return Promise.resolve(this.accountDataProvider.getAccount(account));
|
|
557
430
|
}
|
|
558
431
|
|
|
559
|
-
|
|
432
|
+
utilityGetAuthWitness(messageHash: Fr) {
|
|
560
433
|
const authwit = this.authwits.get(messageHash.toString());
|
|
561
434
|
return Promise.resolve(authwit?.witness);
|
|
562
435
|
}
|
|
563
436
|
|
|
564
|
-
async
|
|
437
|
+
async utilityGetNotes(
|
|
565
438
|
storageSlot: Fr,
|
|
566
439
|
numSelects: number,
|
|
567
440
|
selectByIndexes: number[],
|
|
@@ -607,7 +480,7 @@ export class TXE implements TypedOracle {
|
|
|
607
480
|
return notes;
|
|
608
481
|
}
|
|
609
482
|
|
|
610
|
-
|
|
483
|
+
privateNotifyCreatedNote(storageSlot: Fr, _noteTypeId: NoteSelector, noteItems: Fr[], noteHash: Fr, counter: number) {
|
|
611
484
|
const note = new Note(noteItems);
|
|
612
485
|
this.noteCache.addNewNote(
|
|
613
486
|
{
|
|
@@ -623,23 +496,26 @@ export class TXE implements TypedOracle {
|
|
|
623
496
|
this.sideEffectCounter = counter + 1;
|
|
624
497
|
}
|
|
625
498
|
|
|
626
|
-
async
|
|
499
|
+
async privateNotifyNullifiedNote(innerNullifier: Fr, noteHash: Fr, counter: number) {
|
|
627
500
|
await this.checkNullifiersNotInTree(this.contractAddress, [innerNullifier]);
|
|
628
501
|
await this.noteCache.nullifyNote(this.contractAddress, innerNullifier, noteHash);
|
|
629
502
|
this.sideEffectCounter = counter + 1;
|
|
630
503
|
}
|
|
631
504
|
|
|
632
|
-
async
|
|
505
|
+
async privateNotifyCreatedNullifier(innerNullifier: Fr): Promise<void> {
|
|
633
506
|
await this.checkNullifiersNotInTree(this.contractAddress, [innerNullifier]);
|
|
634
507
|
await this.noteCache.nullifierCreated(this.contractAddress, innerNullifier);
|
|
635
508
|
}
|
|
636
509
|
|
|
637
|
-
async
|
|
510
|
+
async utilityCheckNullifierExists(innerNullifier: Fr): Promise<boolean> {
|
|
638
511
|
const snap = this.nativeWorldStateService.getSnapshot(this.blockNumber - 1);
|
|
639
512
|
|
|
640
513
|
const nullifier = await siloNullifier(this.contractAddress, innerNullifier!);
|
|
641
514
|
const [index] = await snap.findLeafIndices(MerkleTreeId.NULLIFIER_TREE, [nullifier.toBuffer()]);
|
|
642
|
-
|
|
515
|
+
|
|
516
|
+
const inPendingCache = this.noteCache.getNullifiers(this.contractAddress).has(nullifier.toBigInt());
|
|
517
|
+
|
|
518
|
+
return index !== undefined || inPendingCache;
|
|
643
519
|
}
|
|
644
520
|
|
|
645
521
|
getL1ToL2MembershipWitness(
|
|
@@ -650,7 +526,7 @@ export class TXE implements TypedOracle {
|
|
|
650
526
|
throw new Error('Method not implemented.');
|
|
651
527
|
}
|
|
652
528
|
|
|
653
|
-
async
|
|
529
|
+
async utilityStorageRead(
|
|
654
530
|
contractAddress: AztecAddress,
|
|
655
531
|
startStorageSlot: Fr,
|
|
656
532
|
blockNumber: number,
|
|
@@ -698,7 +574,7 @@ export class TXE implements TypedOracle {
|
|
|
698
574
|
}
|
|
699
575
|
|
|
700
576
|
async commitState() {
|
|
701
|
-
const blockNumber = await this.
|
|
577
|
+
const blockNumber = await this.utilityGetBlockNumber();
|
|
702
578
|
const { usedTxRequestHashForNonces } = this.noteCache.finish();
|
|
703
579
|
if (this.committedBlocks.has(blockNumber)) {
|
|
704
580
|
throw new Error('Already committed state');
|
|
@@ -786,7 +662,11 @@ export class TXE implements TypedOracle {
|
|
|
786
662
|
);
|
|
787
663
|
|
|
788
664
|
header.globalVariables.blockNumber = blockNumber;
|
|
789
|
-
header.globalVariables.timestamp = await this.
|
|
665
|
+
header.globalVariables.timestamp = await this.utilityGetTimestamp();
|
|
666
|
+
header.globalVariables.version = new Fr(this.ROLLUP_VERSION);
|
|
667
|
+
header.globalVariables.chainId = new Fr(this.CHAIN_ID);
|
|
668
|
+
|
|
669
|
+
this.logger.info(`Created block ${blockNumber} with timestamp ${header.globalVariables.timestamp}`);
|
|
790
670
|
|
|
791
671
|
l2Block.header = header;
|
|
792
672
|
|
|
@@ -837,7 +717,7 @@ export class TXE implements TypedOracle {
|
|
|
837
717
|
selector: call.selector,
|
|
838
718
|
});
|
|
839
719
|
|
|
840
|
-
const args = await this.
|
|
720
|
+
const args = await this.privateLoadFromExecutionCache(argsHash);
|
|
841
721
|
const initialWitness = toACVMWitness(0, args);
|
|
842
722
|
const acirExecutionResult = await this.simulator
|
|
843
723
|
.executeUserCircuit(initialWitness, entryPointArtifact, new Oracle(oracle).toACIRCallback())
|
|
@@ -859,89 +739,13 @@ export class TXE implements TypedOracle {
|
|
|
859
739
|
|
|
860
740
|
const returnHash = await computeVarArgsHash(returnWitness);
|
|
861
741
|
|
|
862
|
-
this.
|
|
742
|
+
this.privateStoreInExecutionCache(returnWitness, returnHash);
|
|
863
743
|
return returnHash;
|
|
864
744
|
} catch (err) {
|
|
865
745
|
throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during private execution'));
|
|
866
746
|
}
|
|
867
747
|
}
|
|
868
748
|
|
|
869
|
-
async callPrivateFunction(
|
|
870
|
-
targetContractAddress: AztecAddress,
|
|
871
|
-
functionSelector: FunctionSelector,
|
|
872
|
-
argsHash: Fr,
|
|
873
|
-
sideEffectCounter: number,
|
|
874
|
-
isStaticCall: boolean,
|
|
875
|
-
) {
|
|
876
|
-
this.logger.verbose(
|
|
877
|
-
`Executing external function ${await this.getDebugFunctionName(
|
|
878
|
-
targetContractAddress,
|
|
879
|
-
functionSelector,
|
|
880
|
-
)}@${targetContractAddress} isStaticCall=${isStaticCall}`,
|
|
881
|
-
);
|
|
882
|
-
|
|
883
|
-
// Store and modify env
|
|
884
|
-
const currentContractAddress = this.contractAddress;
|
|
885
|
-
const currentMessageSender = this.msgSender;
|
|
886
|
-
const currentFunctionSelector = FunctionSelector.fromField(this.functionSelector.toField());
|
|
887
|
-
this.setMsgSender(this.contractAddress);
|
|
888
|
-
this.setContractAddress(targetContractAddress);
|
|
889
|
-
this.setFunctionSelector(functionSelector);
|
|
890
|
-
|
|
891
|
-
const artifact = await this.contractDataProvider.getFunctionArtifact(targetContractAddress, functionSelector);
|
|
892
|
-
if (!artifact) {
|
|
893
|
-
throw new Error(`Artifact not found when calling private function. Contract address: ${targetContractAddress}.`);
|
|
894
|
-
}
|
|
895
|
-
|
|
896
|
-
const initialWitness = await this.getInitialWitness(artifact, argsHash, sideEffectCounter, isStaticCall);
|
|
897
|
-
const acvmCallback = new Oracle(this);
|
|
898
|
-
const timer = new Timer();
|
|
899
|
-
const acirExecutionResult = await this.simulator
|
|
900
|
-
.executeUserCircuit(initialWitness, artifact, acvmCallback.toACIRCallback())
|
|
901
|
-
.catch((err: Error) => {
|
|
902
|
-
err.message = resolveAssertionMessageFromError(err, artifact);
|
|
903
|
-
|
|
904
|
-
const execError = new ExecutionError(
|
|
905
|
-
err.message,
|
|
906
|
-
{
|
|
907
|
-
contractAddress: targetContractAddress,
|
|
908
|
-
functionSelector,
|
|
909
|
-
},
|
|
910
|
-
extractCallStack(err, artifact.debug),
|
|
911
|
-
{ cause: err },
|
|
912
|
-
);
|
|
913
|
-
this.logger.debug(`Error executing private function ${targetContractAddress}:${functionSelector}`);
|
|
914
|
-
throw createSimulationError(execError);
|
|
915
|
-
});
|
|
916
|
-
const duration = timer.ms();
|
|
917
|
-
const publicInputs = extractPrivateCircuitPublicInputs(artifact, acirExecutionResult.partialWitness);
|
|
918
|
-
|
|
919
|
-
const initialWitnessSize = witnessMapToFields(initialWitness).length * Fr.SIZE_IN_BYTES;
|
|
920
|
-
this.logger.debug(`Ran external function ${targetContractAddress.toString()}:${functionSelector}`, {
|
|
921
|
-
circuitName: 'app-circuit',
|
|
922
|
-
duration,
|
|
923
|
-
eventName: 'circuit-witness-generation',
|
|
924
|
-
inputSize: initialWitnessSize,
|
|
925
|
-
outputSize: publicInputs.toBuffer().length,
|
|
926
|
-
appCircuitName: 'noname',
|
|
927
|
-
} satisfies CircuitWitnessGenerationStats);
|
|
928
|
-
|
|
929
|
-
// Apply side effects
|
|
930
|
-
const endSideEffectCounter = publicInputs.endSideEffectCounter;
|
|
931
|
-
this.sideEffectCounter = endSideEffectCounter.toNumber() + 1;
|
|
932
|
-
|
|
933
|
-
await this.addPrivateLogs(
|
|
934
|
-
targetContractAddress,
|
|
935
|
-
publicInputs.privateLogs.filter(privateLog => !privateLog.isEmpty()).map(privateLog => privateLog.log),
|
|
936
|
-
);
|
|
937
|
-
|
|
938
|
-
this.setContractAddress(currentContractAddress);
|
|
939
|
-
this.setMsgSender(currentMessageSender);
|
|
940
|
-
this.setFunctionSelector(currentFunctionSelector);
|
|
941
|
-
|
|
942
|
-
return { endSideEffectCounter, returnsHash: publicInputs.returnsHash };
|
|
943
|
-
}
|
|
944
|
-
|
|
945
749
|
async getInitialWitness(abi: FunctionAbi, argsHash: Fr, sideEffectCounter: number, isStaticCall: boolean) {
|
|
946
750
|
const argumentsSize = countArgumentsSize(abi);
|
|
947
751
|
|
|
@@ -951,9 +755,10 @@ export class TXE implements TypedOracle {
|
|
|
951
755
|
throw new Error('Invalid arguments size');
|
|
952
756
|
}
|
|
953
757
|
|
|
954
|
-
const
|
|
955
|
-
|
|
956
|
-
|
|
758
|
+
const historicalBlockNumber = this.blockNumber - 1; // i.e. last
|
|
759
|
+
|
|
760
|
+
const privateContextInputs = await this.txeGetPrivateContextInputs(
|
|
761
|
+
historicalBlockNumber,
|
|
957
762
|
sideEffectCounter,
|
|
958
763
|
isStaticCall,
|
|
959
764
|
);
|
|
@@ -970,179 +775,22 @@ export class TXE implements TypedOracle {
|
|
|
970
775
|
return await this.contractDataProvider.getDebugFunctionName(address, selector);
|
|
971
776
|
}
|
|
972
777
|
|
|
973
|
-
|
|
974
|
-
calldata: Fr[],
|
|
975
|
-
msgSender: AztecAddress,
|
|
976
|
-
contractAddress: AztecAddress,
|
|
977
|
-
isStaticCall: boolean,
|
|
978
|
-
isTeardown: boolean = false,
|
|
979
|
-
) {
|
|
980
|
-
const callRequest = await PublicCallRequest.fromCalldata(msgSender, contractAddress, isStaticCall, calldata);
|
|
981
|
-
const executionRequest = new PublicCallRequestWithCalldata(callRequest, calldata);
|
|
982
|
-
|
|
983
|
-
const db = this.baseFork;
|
|
984
|
-
|
|
985
|
-
const globalVariables = GlobalVariables.empty();
|
|
986
|
-
globalVariables.chainId = new Fr(this.CHAIN_ID);
|
|
987
|
-
globalVariables.version = new Fr(this.ROLLUP_VERSION);
|
|
988
|
-
globalVariables.blockNumber = this.blockNumber;
|
|
989
|
-
globalVariables.timestamp = this.timestamp;
|
|
990
|
-
globalVariables.gasFees = new GasFees(1, 1);
|
|
991
|
-
|
|
992
|
-
let result: PublicTxResult;
|
|
993
|
-
// Checkpoint here so that we can revert merkle ops after simulation.
|
|
994
|
-
// See note at revert below.
|
|
995
|
-
const checkpoint = await ForkCheckpoint.new(db);
|
|
996
|
-
try {
|
|
997
|
-
const contractsDB = new PublicContractsDB(new TXEPublicContractDataSource(this));
|
|
998
|
-
const simulator = new PublicTxSimulator(
|
|
999
|
-
this.baseFork,
|
|
1000
|
-
contractsDB,
|
|
1001
|
-
globalVariables,
|
|
1002
|
-
/*doMerkleOperations=*/ false,
|
|
1003
|
-
/*skipFeeEnforcement=*/ false,
|
|
1004
|
-
/*clientInitiatedSimulation=*/ true,
|
|
1005
|
-
);
|
|
1006
|
-
|
|
1007
|
-
const { usedTxRequestHashForNonces } = this.noteCache.finish();
|
|
1008
|
-
const firstNullifier = usedTxRequestHashForNonces
|
|
1009
|
-
? this.getTxRequestHash()
|
|
1010
|
-
: this.noteCache.getAllNullifiers()[0];
|
|
1011
|
-
|
|
1012
|
-
// When setting up a teardown call, we tell it that
|
|
1013
|
-
// private execution used Gas(1, 1) so it can compute a tx fee.
|
|
1014
|
-
const gasUsedByPrivate = isTeardown ? new Gas(1, 1) : Gas.empty();
|
|
1015
|
-
const tx = createTxForPublicCalls(
|
|
1016
|
-
{
|
|
1017
|
-
nonRevertible: {
|
|
1018
|
-
nullifiers: [firstNullifier],
|
|
1019
|
-
},
|
|
1020
|
-
},
|
|
1021
|
-
/*setupExecutionRequests=*/ [],
|
|
1022
|
-
/*appExecutionRequests=*/ isTeardown ? [] : [executionRequest],
|
|
1023
|
-
/*teardownExecutionRequests=*/ isTeardown ? executionRequest : undefined,
|
|
1024
|
-
/*feePayer=*/ AztecAddress.zero(),
|
|
1025
|
-
gasUsedByPrivate,
|
|
1026
|
-
);
|
|
1027
|
-
|
|
1028
|
-
result = await simulator.simulate(tx);
|
|
1029
|
-
} finally {
|
|
1030
|
-
// NOTE: Don't accept any merkle updates from the AVM since this was just 1 enqueued call
|
|
1031
|
-
// and the TXE will re-apply all txEffects after entire execution (all enqueued calls)
|
|
1032
|
-
// complete.
|
|
1033
|
-
await checkpoint.revert();
|
|
1034
|
-
// If an error is thrown during the above simulation, this revert is the last
|
|
1035
|
-
// thing executed and we skip the postprocessing below.
|
|
1036
|
-
}
|
|
1037
|
-
|
|
1038
|
-
const noteHashes = result.avmProvingRequest.inputs.publicInputs.accumulatedData.noteHashes.filter(
|
|
1039
|
-
s => !s.isEmpty(),
|
|
1040
|
-
);
|
|
1041
|
-
|
|
1042
|
-
const publicDataWrites = result.avmProvingRequest.inputs.publicInputs.accumulatedData.publicDataWrites.filter(
|
|
1043
|
-
s => !s.isEmpty(),
|
|
1044
|
-
);
|
|
1045
|
-
// For now, public data writes are the only merkle operations that are readable by later enqueued calls in the TXE.
|
|
1046
|
-
await this.addPublicDataWrites(publicDataWrites);
|
|
1047
|
-
|
|
1048
|
-
this.addUniqueNoteHashesFromPublic(noteHashes);
|
|
1049
|
-
|
|
1050
|
-
this.addPublicLogs(
|
|
1051
|
-
result.avmProvingRequest.inputs.publicInputs.accumulatedData.publicLogs.filter(
|
|
1052
|
-
log => !log.contractAddress.equals(AztecAddress.ZERO),
|
|
1053
|
-
),
|
|
1054
|
-
);
|
|
1055
|
-
|
|
1056
|
-
return Promise.resolve(result);
|
|
1057
|
-
}
|
|
1058
|
-
|
|
1059
|
-
async notifyEnqueuedPublicFunctionCall(
|
|
1060
|
-
targetContractAddress: AztecAddress,
|
|
1061
|
-
calldataHash: Fr,
|
|
1062
|
-
_sideEffectCounter: number,
|
|
1063
|
-
isStaticCall: boolean,
|
|
1064
|
-
isTeardown = false,
|
|
1065
|
-
): Promise<void> {
|
|
1066
|
-
// Store and modify env
|
|
1067
|
-
const currentContractAddress = this.contractAddress;
|
|
1068
|
-
const currentMessageSender = this.msgSender;
|
|
1069
|
-
const currentFunctionSelector = FunctionSelector.fromField(this.functionSelector.toField());
|
|
1070
|
-
const calldata = this.executionCache.getPreimage(calldataHash);
|
|
1071
|
-
if (!calldata) {
|
|
1072
|
-
throw new Error('Calldata for enqueued call not found in cache');
|
|
1073
|
-
}
|
|
1074
|
-
const functionSelector = FunctionSelector.fromField(calldata[0]);
|
|
1075
|
-
this.setMsgSender(this.contractAddress);
|
|
1076
|
-
this.setContractAddress(targetContractAddress);
|
|
1077
|
-
this.setFunctionSelector(functionSelector);
|
|
1078
|
-
|
|
1079
|
-
const executionResult = await this.executePublicFunction(
|
|
1080
|
-
calldata,
|
|
1081
|
-
/* msgSender */ currentContractAddress,
|
|
1082
|
-
targetContractAddress,
|
|
1083
|
-
isStaticCall,
|
|
1084
|
-
isTeardown,
|
|
1085
|
-
);
|
|
1086
|
-
|
|
1087
|
-
// Poor man's revert handling
|
|
1088
|
-
if (!executionResult.revertCode.isOK()) {
|
|
1089
|
-
if (executionResult.revertReason && executionResult.revertReason instanceof SimulationError) {
|
|
1090
|
-
await enrichPublicSimulationError(executionResult.revertReason, this.contractDataProvider, this.logger);
|
|
1091
|
-
throw new Error(executionResult.revertReason.message);
|
|
1092
|
-
} else {
|
|
1093
|
-
throw new Error(`Enqueued public function call reverted: ${executionResult.revertReason}`);
|
|
1094
|
-
}
|
|
1095
|
-
}
|
|
1096
|
-
|
|
1097
|
-
// Apply side effects
|
|
1098
|
-
const sideEffects = executionResult.avmProvingRequest.inputs.publicInputs.accumulatedData;
|
|
1099
|
-
|
|
1100
|
-
const { usedTxRequestHashForNonces } = this.noteCache.finish();
|
|
1101
|
-
const firstNullifier = usedTxRequestHashForNonces ? this.getTxRequestHash() : this.noteCache.getAllNullifiers()[0];
|
|
1102
|
-
const nullifiers = sideEffects.nullifiers.filter(s => !s.isEmpty()).filter(s => !s.equals(firstNullifier));
|
|
1103
|
-
|
|
1104
|
-
// For some reason we cannot move this up to 'executePublicFunction'. It gives us an error of trying to modify the same nullifier twice.
|
|
1105
|
-
this.addSiloedNullifiersFromPublic(nullifiers);
|
|
1106
|
-
|
|
1107
|
-
this.setContractAddress(currentContractAddress);
|
|
1108
|
-
this.setMsgSender(currentMessageSender);
|
|
1109
|
-
this.setFunctionSelector(currentFunctionSelector);
|
|
1110
|
-
}
|
|
1111
|
-
|
|
1112
|
-
async notifySetPublicTeardownFunctionCall(
|
|
1113
|
-
targetContractAddress: AztecAddress,
|
|
1114
|
-
calldataHash: Fr,
|
|
1115
|
-
sideEffectCounter: number,
|
|
1116
|
-
isStaticCall: boolean,
|
|
1117
|
-
): Promise<void> {
|
|
1118
|
-
// Definitely not right, in that the teardown should always be last.
|
|
1119
|
-
// But useful for executing flows.
|
|
1120
|
-
await this.notifyEnqueuedPublicFunctionCall(
|
|
1121
|
-
targetContractAddress,
|
|
1122
|
-
calldataHash,
|
|
1123
|
-
sideEffectCounter,
|
|
1124
|
-
isStaticCall,
|
|
1125
|
-
/*isTeardown=*/ true,
|
|
1126
|
-
);
|
|
1127
|
-
}
|
|
1128
|
-
|
|
1129
|
-
async notifySetMinRevertibleSideEffectCounter(minRevertibleSideEffectCounter: number) {
|
|
1130
|
-
await this.noteCache.setMinRevertibleSideEffectCounter(minRevertibleSideEffectCounter);
|
|
1131
|
-
}
|
|
1132
|
-
|
|
1133
|
-
debugLog(message: string, fields: Fr[]): void {
|
|
778
|
+
utilityDebugLog(message: string, fields: Fr[]): void {
|
|
1134
779
|
this.logger.verbose(`${applyStringFormatting(message, fields)}`, { module: `${this.logger.module}:debug_log` });
|
|
1135
780
|
}
|
|
1136
781
|
|
|
1137
|
-
async
|
|
782
|
+
async privateIncrementAppTaggingSecretIndexAsSender(sender: AztecAddress, recipient: AztecAddress): Promise<void> {
|
|
1138
783
|
await this.pxeOracleInterface.incrementAppTaggingSecretIndexAsSender(this.contractAddress, sender, recipient);
|
|
1139
784
|
}
|
|
1140
785
|
|
|
1141
|
-
async
|
|
786
|
+
async utilityGetIndexedTaggingSecretAsSender(
|
|
787
|
+
sender: AztecAddress,
|
|
788
|
+
recipient: AztecAddress,
|
|
789
|
+
): Promise<IndexedTaggingSecret> {
|
|
1142
790
|
return await this.pxeOracleInterface.getIndexedTaggingSecretAsSender(this.contractAddress, sender, recipient);
|
|
1143
791
|
}
|
|
1144
792
|
|
|
1145
|
-
async
|
|
793
|
+
async utilityFetchTaggedLogs(pendingTaggedLogArrayBaseSlot: Fr) {
|
|
1146
794
|
await this.pxeOracleInterface.syncTaggedLogs(this.contractAddress, pendingTaggedLogArrayBaseSlot);
|
|
1147
795
|
|
|
1148
796
|
await this.pxeOracleInterface.removeNullifiedNotes(this.contractAddress);
|
|
@@ -1150,7 +798,7 @@ export class TXE implements TypedOracle {
|
|
|
1150
798
|
return Promise.resolve();
|
|
1151
799
|
}
|
|
1152
800
|
|
|
1153
|
-
public async
|
|
801
|
+
public async utilityValidateEnqueuedNotesAndEvents(
|
|
1154
802
|
contractAddress: AztecAddress,
|
|
1155
803
|
noteValidationRequestsArrayBaseSlot: Fr,
|
|
1156
804
|
eventValidationRequestsArrayBaseSlot: Fr,
|
|
@@ -1162,7 +810,7 @@ export class TXE implements TypedOracle {
|
|
|
1162
810
|
);
|
|
1163
811
|
}
|
|
1164
812
|
|
|
1165
|
-
async
|
|
813
|
+
async utilityBulkRetrieveLogs(
|
|
1166
814
|
contractAddress: AztecAddress,
|
|
1167
815
|
logRetrievalRequestsArrayBaseSlot: Fr,
|
|
1168
816
|
logRetrievalResponsesArrayBaseSlot: Fr,
|
|
@@ -1174,67 +822,14 @@ export class TXE implements TypedOracle {
|
|
|
1174
822
|
);
|
|
1175
823
|
}
|
|
1176
824
|
|
|
1177
|
-
// AVM oracles
|
|
1178
|
-
|
|
1179
|
-
async avmOpcodeCall(
|
|
1180
|
-
targetContractAddress: AztecAddress,
|
|
1181
|
-
calldata: Fr[],
|
|
1182
|
-
isStaticCall: boolean,
|
|
1183
|
-
): Promise<PublicTxResult> {
|
|
1184
|
-
// Store and modify env
|
|
1185
|
-
const currentContractAddress = this.contractAddress;
|
|
1186
|
-
const currentMessageSender = this.msgSender;
|
|
1187
|
-
this.setMsgSender(this.contractAddress);
|
|
1188
|
-
this.setContractAddress(targetContractAddress);
|
|
1189
|
-
|
|
1190
|
-
const executionResult = await this.executePublicFunction(
|
|
1191
|
-
calldata,
|
|
1192
|
-
/* msgSender */ currentContractAddress,
|
|
1193
|
-
targetContractAddress,
|
|
1194
|
-
isStaticCall,
|
|
1195
|
-
);
|
|
1196
|
-
// Save return/revert data for later.
|
|
1197
|
-
this.nestedCallReturndata = executionResult.processedPhases[0]!.returnValues[0].values!;
|
|
1198
|
-
this.nestedCallSuccess = executionResult.revertCode.isOK();
|
|
1199
|
-
|
|
1200
|
-
// Apply side effects
|
|
1201
|
-
if (executionResult.revertCode.isOK()) {
|
|
1202
|
-
const sideEffects = executionResult.avmProvingRequest.inputs.publicInputs.accumulatedData;
|
|
1203
|
-
const publicDataWrites = sideEffects.publicDataWrites.filter(s => !s.isEmpty());
|
|
1204
|
-
const noteHashes = sideEffects.noteHashes.filter(s => !s.isEmpty());
|
|
1205
|
-
const { usedTxRequestHashForNonces } = this.noteCache.finish();
|
|
1206
|
-
const firstNullifier = usedTxRequestHashForNonces
|
|
1207
|
-
? this.getTxRequestHash()
|
|
1208
|
-
: this.noteCache.getAllNullifiers()[0];
|
|
1209
|
-
const nullifiers = sideEffects.nullifiers.filter(s => !s.isEmpty()).filter(s => !s.equals(firstNullifier));
|
|
1210
|
-
await this.addPublicDataWrites(publicDataWrites);
|
|
1211
|
-
this.addUniqueNoteHashesFromPublic(noteHashes);
|
|
1212
|
-
this.addSiloedNullifiersFromPublic(nullifiers);
|
|
1213
|
-
}
|
|
1214
|
-
|
|
1215
|
-
this.setContractAddress(currentContractAddress);
|
|
1216
|
-
this.setMsgSender(currentMessageSender);
|
|
1217
|
-
|
|
1218
|
-
return executionResult;
|
|
1219
|
-
}
|
|
1220
|
-
|
|
1221
|
-
avmOpcodeSuccessCopy(): boolean {
|
|
1222
|
-
return this.nestedCallSuccess;
|
|
1223
|
-
}
|
|
1224
|
-
|
|
1225
|
-
avmOpcodeReturndataSize(): number {
|
|
1226
|
-
return this.nestedCallReturndata.length;
|
|
1227
|
-
}
|
|
1228
|
-
|
|
1229
|
-
avmOpcodeReturndataCopy(rdOffset: number, copySize: number): Fr[] {
|
|
1230
|
-
return this.nestedCallReturndata.slice(rdOffset, rdOffset + copySize);
|
|
1231
|
-
}
|
|
1232
|
-
|
|
1233
825
|
async avmOpcodeNullifierExists(innerNullifier: Fr, targetAddress: AztecAddress): Promise<boolean> {
|
|
1234
826
|
const nullifier = await siloNullifier(targetAddress, innerNullifier!);
|
|
1235
827
|
const db = this.baseFork;
|
|
1236
|
-
|
|
1237
|
-
|
|
828
|
+
|
|
829
|
+
const treeIndex = (await db.findLeafIndices(MerkleTreeId.NULLIFIER_TREE, [nullifier.toBuffer()]))[0];
|
|
830
|
+
const transientIndex = this.siloedNullifiersFromPublic.find(n => n.equals(nullifier));
|
|
831
|
+
|
|
832
|
+
return treeIndex !== undefined || transientIndex !== undefined;
|
|
1238
833
|
}
|
|
1239
834
|
|
|
1240
835
|
async avmOpcodeEmitNullifier(nullifier: Fr) {
|
|
@@ -1267,7 +862,7 @@ export class TXE implements TypedOracle {
|
|
|
1267
862
|
return preimage.leaf.value;
|
|
1268
863
|
}
|
|
1269
864
|
|
|
1270
|
-
|
|
865
|
+
utilityStoreCapsule(contractAddress: AztecAddress, slot: Fr, capsule: Fr[]): Promise<void> {
|
|
1271
866
|
if (!contractAddress.equals(this.contractAddress)) {
|
|
1272
867
|
// TODO(#10727): instead of this check that this.contractAddress is allowed to access the external DB
|
|
1273
868
|
throw new Error(`Contract ${contractAddress} is not allowed to access ${this.contractAddress}'s PXE DB`);
|
|
@@ -1275,7 +870,7 @@ export class TXE implements TypedOracle {
|
|
|
1275
870
|
return this.pxeOracleInterface.storeCapsule(this.contractAddress, slot, capsule);
|
|
1276
871
|
}
|
|
1277
872
|
|
|
1278
|
-
|
|
873
|
+
utilityLoadCapsule(contractAddress: AztecAddress, slot: Fr): Promise<Fr[] | null> {
|
|
1279
874
|
if (!contractAddress.equals(this.contractAddress)) {
|
|
1280
875
|
// TODO(#10727): instead of this check that this.contractAddress is allowed to access the external DB
|
|
1281
876
|
throw new Error(`Contract ${contractAddress} is not allowed to access ${this.contractAddress}'s PXE DB`);
|
|
@@ -1283,7 +878,7 @@ export class TXE implements TypedOracle {
|
|
|
1283
878
|
return this.pxeOracleInterface.loadCapsule(this.contractAddress, slot);
|
|
1284
879
|
}
|
|
1285
880
|
|
|
1286
|
-
|
|
881
|
+
utilityDeleteCapsule(contractAddress: AztecAddress, slot: Fr): Promise<void> {
|
|
1287
882
|
if (!contractAddress.equals(this.contractAddress)) {
|
|
1288
883
|
// TODO(#10727): instead of this check that this.contractAddress is allowed to access the external DB
|
|
1289
884
|
throw new Error(`Contract ${contractAddress} is not allowed to access ${this.contractAddress}'s PXE DB`);
|
|
@@ -1291,7 +886,7 @@ export class TXE implements TypedOracle {
|
|
|
1291
886
|
return this.pxeOracleInterface.deleteCapsule(this.contractAddress, slot);
|
|
1292
887
|
}
|
|
1293
888
|
|
|
1294
|
-
|
|
889
|
+
utilityCopyCapsule(contractAddress: AztecAddress, srcSlot: Fr, dstSlot: Fr, numEntries: number): Promise<void> {
|
|
1295
890
|
if (!contractAddress.equals(this.contractAddress)) {
|
|
1296
891
|
// TODO(#10727): instead of this check that this.contractAddress is allowed to access the external DB
|
|
1297
892
|
throw new Error(`Contract ${contractAddress} is not allowed to access ${this.contractAddress}'s PXE DB`);
|
|
@@ -1299,21 +894,25 @@ export class TXE implements TypedOracle {
|
|
|
1299
894
|
return this.pxeOracleInterface.copyCapsule(this.contractAddress, srcSlot, dstSlot, numEntries);
|
|
1300
895
|
}
|
|
1301
896
|
|
|
1302
|
-
|
|
897
|
+
utilityAes128Decrypt(ciphertext: Buffer, iv: Buffer, symKey: Buffer): Promise<Buffer> {
|
|
1303
898
|
const aes128 = new Aes128();
|
|
1304
899
|
return aes128.decryptBufferCBC(ciphertext, iv, symKey);
|
|
1305
900
|
}
|
|
1306
901
|
|
|
1307
|
-
|
|
902
|
+
utilityGetSharedSecret(address: AztecAddress, ephPk: Point): Promise<Point> {
|
|
1308
903
|
return this.pxeOracleInterface.getSharedSecret(address, ephPk);
|
|
1309
904
|
}
|
|
1310
905
|
|
|
1311
|
-
|
|
1312
|
-
|
|
906
|
+
privateGetSenderForTags(): Promise<AztecAddress | undefined> {
|
|
907
|
+
return Promise.resolve(this.senderForTags);
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
privateSetSenderForTags(senderForTags: AztecAddress): Promise<void> {
|
|
911
|
+
this.senderForTags = senderForTags;
|
|
1313
912
|
return Promise.resolve();
|
|
1314
913
|
}
|
|
1315
914
|
|
|
1316
|
-
async
|
|
915
|
+
async txePrivateCallNewFlow(
|
|
1317
916
|
from: AztecAddress,
|
|
1318
917
|
targetContractAddress: AztecAddress = AztecAddress.zero(),
|
|
1319
918
|
functionSelector: FunctionSelector = FunctionSelector.empty(),
|
|
@@ -1331,7 +930,13 @@ export class TXE implements TypedOracle {
|
|
|
1331
930
|
const artifact = await this.contractDataProvider.getFunctionArtifact(targetContractAddress, functionSelector);
|
|
1332
931
|
|
|
1333
932
|
if (artifact === undefined) {
|
|
1334
|
-
|
|
933
|
+
if (functionSelector.equals(await FunctionSelector.fromSignature('verify_private_authwit(Field)'))) {
|
|
934
|
+
throw new Error(
|
|
935
|
+
'Found no account contract artifact for a private authwit check - use `create_contract_account` instead of `create_light_account` for authwit support.',
|
|
936
|
+
);
|
|
937
|
+
} else {
|
|
938
|
+
throw new Error('Function Artifact does not exist');
|
|
939
|
+
}
|
|
1335
940
|
}
|
|
1336
941
|
|
|
1337
942
|
const callContext = new CallContext(from, targetContractAddress, functionSelector, isStaticCall);
|
|
@@ -1348,6 +953,7 @@ export class TXE implements TypedOracle {
|
|
|
1348
953
|
|
|
1349
954
|
const noteCache = new ExecutionNoteCache(this.getTxRequestHash());
|
|
1350
955
|
|
|
956
|
+
// TODO(benesjan): Fix stale 'context' name.
|
|
1351
957
|
const context = new PrivateExecutionOracle(
|
|
1352
958
|
argsHash,
|
|
1353
959
|
txContext,
|
|
@@ -1355,7 +961,7 @@ export class TXE implements TypedOracle {
|
|
|
1355
961
|
/** Header of a block whose state is used during private execution (not the block the transaction is included in). */
|
|
1356
962
|
blockHeader,
|
|
1357
963
|
/** List of transient auth witnesses to be used during this simulation */
|
|
1358
|
-
|
|
964
|
+
Array.from(this.authwits.values()),
|
|
1359
965
|
/** List of transient auth witnesses to be used during this simulation */
|
|
1360
966
|
[],
|
|
1361
967
|
HashedValuesCache.create(),
|
|
@@ -1364,9 +970,16 @@ export class TXE implements TypedOracle {
|
|
|
1364
970
|
this.simulator,
|
|
1365
971
|
0,
|
|
1366
972
|
1,
|
|
973
|
+
undefined, // log
|
|
974
|
+
undefined, // scopes
|
|
975
|
+
/**
|
|
976
|
+
* In TXE, the typical transaction entrypoint is skipped, so we need to simulate the actions that such a
|
|
977
|
+
* contract would perform, including setting senderForTags.
|
|
978
|
+
*/
|
|
979
|
+
from,
|
|
1367
980
|
);
|
|
1368
981
|
|
|
1369
|
-
context.
|
|
982
|
+
context.privateStoreInExecutionCache(args, argsHash);
|
|
1370
983
|
|
|
1371
984
|
// 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.
|
|
1372
985
|
let result: PrivateExecutionResult;
|
|
@@ -1382,13 +995,15 @@ export class TXE implements TypedOracle {
|
|
|
1382
995
|
const { usedTxRequestHashForNonces } = noteCache.finish();
|
|
1383
996
|
const firstNullifierHint = usedTxRequestHashForNonces ? Fr.ZERO : noteCache.getAllNullifiers()[0];
|
|
1384
997
|
|
|
1385
|
-
const publicCallRequests = collectNested([executionResult], r =>
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
998
|
+
const publicCallRequests = collectNested([executionResult], r =>
|
|
999
|
+
r.publicInputs.publicCallRequests
|
|
1000
|
+
.getActiveItems()
|
|
1001
|
+
.map(r => r.inner)
|
|
1002
|
+
.concat(r.publicInputs.publicTeardownCallRequest.isEmpty() ? [] : [r.publicInputs.publicTeardownCallRequest]),
|
|
1003
|
+
);
|
|
1389
1004
|
const publicFunctionsCalldata = await Promise.all(
|
|
1390
1005
|
publicCallRequests.map(async r => {
|
|
1391
|
-
const calldata = await context.
|
|
1006
|
+
const calldata = await context.privateLoadFromExecutionCache(r.calldataHash);
|
|
1392
1007
|
return new HashedValues(calldata, r.calldataHash);
|
|
1393
1008
|
}),
|
|
1394
1009
|
);
|
|
@@ -1403,7 +1018,7 @@ export class TXE implements TypedOracle {
|
|
|
1403
1018
|
// This is a bit of a hack to not deal with returning a slice in nr which is what normally happens.
|
|
1404
1019
|
// Investigate whether it is faster to do this or return from the oracle directly.
|
|
1405
1020
|
const returnValuesHash = await computeVarArgsHash(returnValues);
|
|
1406
|
-
this.
|
|
1021
|
+
this.privateStoreInExecutionCache(returnValues, returnValuesHash);
|
|
1407
1022
|
}
|
|
1408
1023
|
|
|
1409
1024
|
// According to the protocol rules, the nonce generator for the note hashes
|
|
@@ -1415,6 +1030,8 @@ export class TXE implements TypedOracle {
|
|
|
1415
1030
|
const globals = makeGlobalVariables();
|
|
1416
1031
|
globals.blockNumber = this.blockNumber;
|
|
1417
1032
|
globals.timestamp = this.timestamp;
|
|
1033
|
+
globals.chainId = new Fr(this.CHAIN_ID);
|
|
1034
|
+
globals.version = new Fr(this.ROLLUP_VERSION);
|
|
1418
1035
|
globals.gasFees = GasFees.empty();
|
|
1419
1036
|
|
|
1420
1037
|
const contractsDB = new PublicContractsDB(new TXEPublicContractDataSource(this));
|
|
@@ -1422,7 +1039,12 @@ export class TXE implements TypedOracle {
|
|
|
1422
1039
|
const simulator = new PublicTxSimulator(guardedMerkleTrees, contractsDB, globals, true, true);
|
|
1423
1040
|
const processor = new PublicProcessor(globals, guardedMerkleTrees, contractsDB, simulator, new TestDateProvider());
|
|
1424
1041
|
|
|
1425
|
-
const tx =
|
|
1042
|
+
const tx = await Tx.create({
|
|
1043
|
+
data: publicInputs,
|
|
1044
|
+
clientIvcProof: ClientIvcProof.empty(),
|
|
1045
|
+
contractClassLogFields: [],
|
|
1046
|
+
publicFunctionCalldata: result.publicFunctionCalldata,
|
|
1047
|
+
});
|
|
1426
1048
|
|
|
1427
1049
|
let checkpoint;
|
|
1428
1050
|
if (isStaticCall) {
|
|
@@ -1431,21 +1053,27 @@ export class TXE implements TypedOracle {
|
|
|
1431
1053
|
|
|
1432
1054
|
const results = await processor.process([tx]);
|
|
1433
1055
|
|
|
1434
|
-
const
|
|
1056
|
+
const [processedTx] = results[0];
|
|
1435
1057
|
const failedTxs = results[1];
|
|
1436
1058
|
|
|
1437
1059
|
if (failedTxs.length !== 0) {
|
|
1438
|
-
throw new Error(
|
|
1060
|
+
throw new Error(`Public execution has failed: ${failedTxs[0].error}`);
|
|
1061
|
+
} else if (!processedTx.revertCode.isOK()) {
|
|
1062
|
+
if (processedTx.revertReason) {
|
|
1063
|
+
await enrichPublicSimulationError(processedTx.revertReason, this.contractDataProvider, this.logger);
|
|
1064
|
+
throw new Error(`Contract execution has reverted: ${processedTx.revertReason.getMessage()}`);
|
|
1065
|
+
} else {
|
|
1066
|
+
throw new Error('Contract execution has reverted');
|
|
1067
|
+
}
|
|
1439
1068
|
}
|
|
1440
1069
|
|
|
1441
1070
|
if (isStaticCall) {
|
|
1442
1071
|
await checkpoint!.revert();
|
|
1443
|
-
const txRequestHash = this.getTxRequestHash();
|
|
1444
1072
|
|
|
1445
1073
|
return {
|
|
1446
1074
|
endSideEffectCounter: result.entrypoint.publicInputs.endSideEffectCounter,
|
|
1447
1075
|
returnsHash: result.entrypoint.publicInputs.returnsHash,
|
|
1448
|
-
txHash:
|
|
1076
|
+
txHash: tx.getTxHash(),
|
|
1449
1077
|
};
|
|
1450
1078
|
}
|
|
1451
1079
|
|
|
@@ -1453,11 +1081,11 @@ export class TXE implements TypedOracle {
|
|
|
1453
1081
|
|
|
1454
1082
|
const txEffect = TxEffect.empty();
|
|
1455
1083
|
|
|
1456
|
-
txEffect.noteHashes =
|
|
1457
|
-
txEffect.nullifiers =
|
|
1458
|
-
txEffect.privateLogs =
|
|
1459
|
-
txEffect.publicLogs =
|
|
1460
|
-
txEffect.publicDataWrites =
|
|
1084
|
+
txEffect.noteHashes = processedTx!.txEffect.noteHashes;
|
|
1085
|
+
txEffect.nullifiers = processedTx!.txEffect.nullifiers;
|
|
1086
|
+
txEffect.privateLogs = processedTx!.txEffect.privateLogs;
|
|
1087
|
+
txEffect.publicLogs = processedTx!.txEffect.publicLogs;
|
|
1088
|
+
txEffect.publicDataWrites = processedTx!.txEffect.publicDataWrites;
|
|
1461
1089
|
|
|
1462
1090
|
txEffect.txHash = new TxHash(new Fr(this.blockNumber));
|
|
1463
1091
|
|
|
@@ -1492,18 +1120,15 @@ export class TXE implements TypedOracle {
|
|
|
1492
1120
|
|
|
1493
1121
|
await this.stateMachine.handleL2Block(l2Block);
|
|
1494
1122
|
|
|
1495
|
-
const txRequestHash = this.getTxRequestHash();
|
|
1496
|
-
|
|
1497
1123
|
this.setBlockNumber(this.blockNumber + 1);
|
|
1498
|
-
this.advanceTimestampBy(AZTEC_SLOT_DURATION);
|
|
1499
1124
|
return {
|
|
1500
1125
|
endSideEffectCounter: result.entrypoint.publicInputs.endSideEffectCounter,
|
|
1501
1126
|
returnsHash: result.entrypoint.publicInputs.returnsHash,
|
|
1502
|
-
txHash:
|
|
1127
|
+
txHash: tx.getTxHash(),
|
|
1503
1128
|
};
|
|
1504
1129
|
}
|
|
1505
1130
|
|
|
1506
|
-
async
|
|
1131
|
+
async txePublicCallNewFlow(
|
|
1507
1132
|
from: AztecAddress,
|
|
1508
1133
|
targetContractAddress: AztecAddress,
|
|
1509
1134
|
calldata: Fr[],
|
|
@@ -1526,22 +1151,14 @@ export class TXE implements TypedOracle {
|
|
|
1526
1151
|
|
|
1527
1152
|
const blockHeader = await this.pxeOracleInterface.getBlockHeader();
|
|
1528
1153
|
|
|
1529
|
-
const uniqueNoteHashes: Fr[] = [];
|
|
1530
|
-
const taggedPrivateLogs: PrivateLog[] = [];
|
|
1531
|
-
const nullifiers: Fr[] = !isStaticCall ? [this.getTxRequestHash()] : [];
|
|
1532
|
-
const l2ToL1Messages: ScopedL2ToL1Message[] = [];
|
|
1533
|
-
const contractClassLogsHashes: ScopedLogHash[] = [];
|
|
1534
|
-
|
|
1535
1154
|
const calldataHash = await computeCalldataHash(calldata);
|
|
1536
|
-
|
|
1537
1155
|
const calldataHashedValues = new HashedValues(calldata, calldataHash);
|
|
1538
1156
|
|
|
1539
|
-
const publicCallRequest = new PublicCallRequest(from, targetContractAddress, isStaticCall, calldataHash);
|
|
1540
|
-
const publicCallRequests: PublicCallRequest[] = [publicCallRequest];
|
|
1541
|
-
|
|
1542
1157
|
const globals = makeGlobalVariables();
|
|
1543
1158
|
globals.blockNumber = this.blockNumber;
|
|
1544
1159
|
globals.timestamp = this.timestamp;
|
|
1160
|
+
globals.chainId = new Fr(this.CHAIN_ID);
|
|
1161
|
+
globals.version = new Fr(this.ROLLUP_VERSION);
|
|
1545
1162
|
globals.gasFees = GasFees.empty();
|
|
1546
1163
|
|
|
1547
1164
|
const contractsDB = new PublicContractsDB(new TXEPublicContractDataSource(this));
|
|
@@ -1549,36 +1166,48 @@ export class TXE implements TypedOracle {
|
|
|
1549
1166
|
const simulator = new PublicTxSimulator(guardedMerkleTrees, contractsDB, globals, true, true);
|
|
1550
1167
|
const processor = new PublicProcessor(globals, guardedMerkleTrees, contractsDB, simulator, new TestDateProvider());
|
|
1551
1168
|
|
|
1552
|
-
|
|
1169
|
+
// We're simulating a scenario in which private execution immediately enqueues a public call and halts. The private
|
|
1170
|
+
// kernel init would in this case inject a nullifier with the transaction request hash as a non-revertible
|
|
1171
|
+
// side-effect, which the AVM then expects to exist in order to use it as the nonce generator when siloing notes as
|
|
1172
|
+
// unique.
|
|
1173
|
+
const nonRevertibleAccumulatedData = PrivateToPublicAccumulatedData.empty();
|
|
1174
|
+
if (!isStaticCall) {
|
|
1175
|
+
nonRevertibleAccumulatedData.nullifiers[0] = this.getTxRequestHash();
|
|
1176
|
+
}
|
|
1553
1177
|
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1178
|
+
// The enqueued public call itself we make be revertible so that the public execution is itself revertible, as tests
|
|
1179
|
+
// may require producing reverts.
|
|
1180
|
+
const revertibleAccumulatedData = PrivateToPublicAccumulatedData.empty();
|
|
1181
|
+
revertibleAccumulatedData.publicCallRequests[0] = new PublicCallRequest(
|
|
1182
|
+
from,
|
|
1183
|
+
targetContractAddress,
|
|
1184
|
+
isStaticCall,
|
|
1185
|
+
calldataHash,
|
|
1561
1186
|
);
|
|
1562
1187
|
|
|
1563
1188
|
const inputsForPublic = new PartialPrivateTailPublicInputsForPublic(
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
// revertible
|
|
1567
|
-
// We are using revertible (app phase) because only the app-phase returns are exposed.
|
|
1568
|
-
accumulatedDataForPublic,
|
|
1189
|
+
nonRevertibleAccumulatedData,
|
|
1190
|
+
revertibleAccumulatedData,
|
|
1569
1191
|
PublicCallRequest.empty(),
|
|
1570
1192
|
);
|
|
1571
1193
|
|
|
1194
|
+
const constantData = new TxConstantData(blockHeader, txContext, Fr.zero(), Fr.zero());
|
|
1195
|
+
|
|
1572
1196
|
const txData = new PrivateKernelTailCircuitPublicInputs(
|
|
1573
1197
|
constantData,
|
|
1574
|
-
RollupValidationRequests.empty(),
|
|
1575
1198
|
/*gasUsed=*/ new Gas(0, 0),
|
|
1576
1199
|
/*feePayer=*/ AztecAddress.zero(),
|
|
1200
|
+
/*includeByTimestamp=*/ 0n,
|
|
1577
1201
|
inputsForPublic,
|
|
1578
1202
|
undefined,
|
|
1579
1203
|
);
|
|
1580
1204
|
|
|
1581
|
-
const tx =
|
|
1205
|
+
const tx = await Tx.create({
|
|
1206
|
+
data: txData,
|
|
1207
|
+
clientIvcProof: ClientIvcProof.empty(),
|
|
1208
|
+
contractClassLogFields: [],
|
|
1209
|
+
publicFunctionCalldata: [calldataHashedValues],
|
|
1210
|
+
});
|
|
1582
1211
|
|
|
1583
1212
|
let checkpoint;
|
|
1584
1213
|
if (isStaticCall) {
|
|
@@ -1587,11 +1216,18 @@ export class TXE implements TypedOracle {
|
|
|
1587
1216
|
|
|
1588
1217
|
const results = await processor.process([tx]);
|
|
1589
1218
|
|
|
1590
|
-
const
|
|
1219
|
+
const [processedTx] = results[0];
|
|
1591
1220
|
const failedTxs = results[1];
|
|
1592
1221
|
|
|
1593
|
-
if (failedTxs.length !== 0
|
|
1594
|
-
throw new Error(
|
|
1222
|
+
if (failedTxs.length !== 0) {
|
|
1223
|
+
throw new Error(`Public execution has failed: ${failedTxs[0].error}`);
|
|
1224
|
+
} else if (!processedTx.revertCode.isOK()) {
|
|
1225
|
+
if (processedTx.revertReason) {
|
|
1226
|
+
await enrichPublicSimulationError(processedTx.revertReason, this.contractDataProvider, this.logger);
|
|
1227
|
+
throw new Error(`Contract execution has reverted: ${processedTx.revertReason.getMessage()}`);
|
|
1228
|
+
} else {
|
|
1229
|
+
throw new Error('Contract execution has reverted');
|
|
1230
|
+
}
|
|
1595
1231
|
}
|
|
1596
1232
|
|
|
1597
1233
|
const returnValues = results[3][0].values;
|
|
@@ -1601,16 +1237,15 @@ export class TXE implements TypedOracle {
|
|
|
1601
1237
|
// This is a bit of a hack to not deal with returning a slice in nr which is what normally happens.
|
|
1602
1238
|
// Investigate whether it is faster to do this or return from the oracle directly.
|
|
1603
1239
|
returnValuesHash = await computeVarArgsHash(returnValues);
|
|
1604
|
-
this.
|
|
1240
|
+
this.privateStoreInExecutionCache(returnValues, returnValuesHash);
|
|
1605
1241
|
}
|
|
1606
1242
|
|
|
1607
1243
|
if (isStaticCall) {
|
|
1608
1244
|
await checkpoint!.revert();
|
|
1609
|
-
const txRequestHash = this.getTxRequestHash();
|
|
1610
1245
|
|
|
1611
1246
|
return {
|
|
1612
1247
|
returnsHash: returnValuesHash ?? Fr.ZERO,
|
|
1613
|
-
txHash:
|
|
1248
|
+
txHash: tx.getTxHash(),
|
|
1614
1249
|
};
|
|
1615
1250
|
}
|
|
1616
1251
|
|
|
@@ -1618,11 +1253,11 @@ export class TXE implements TypedOracle {
|
|
|
1618
1253
|
|
|
1619
1254
|
const txEffect = TxEffect.empty();
|
|
1620
1255
|
|
|
1621
|
-
txEffect.noteHashes =
|
|
1622
|
-
txEffect.nullifiers =
|
|
1623
|
-
txEffect.privateLogs =
|
|
1624
|
-
txEffect.publicLogs =
|
|
1625
|
-
txEffect.publicDataWrites =
|
|
1256
|
+
txEffect.noteHashes = processedTx!.txEffect.noteHashes;
|
|
1257
|
+
txEffect.nullifiers = processedTx!.txEffect.nullifiers;
|
|
1258
|
+
txEffect.privateLogs = processedTx!.txEffect.privateLogs;
|
|
1259
|
+
txEffect.publicLogs = processedTx!.txEffect.publicLogs;
|
|
1260
|
+
txEffect.publicDataWrites = processedTx!.txEffect.publicDataWrites;
|
|
1626
1261
|
|
|
1627
1262
|
txEffect.txHash = new TxHash(new Fr(this.blockNumber));
|
|
1628
1263
|
|
|
@@ -1657,14 +1292,20 @@ export class TXE implements TypedOracle {
|
|
|
1657
1292
|
|
|
1658
1293
|
await this.stateMachine.handleL2Block(l2Block);
|
|
1659
1294
|
|
|
1660
|
-
const txRequestHash = this.getTxRequestHash();
|
|
1661
|
-
|
|
1662
1295
|
this.setBlockNumber(this.blockNumber + 1);
|
|
1663
|
-
this.advanceTimestampBy(AZTEC_SLOT_DURATION);
|
|
1664
1296
|
|
|
1665
1297
|
return {
|
|
1666
1298
|
returnsHash: returnValuesHash ?? Fr.ZERO,
|
|
1667
|
-
txHash:
|
|
1299
|
+
txHash: tx.getTxHash(),
|
|
1668
1300
|
};
|
|
1669
1301
|
}
|
|
1302
|
+
|
|
1303
|
+
private async getBlockTimestamp(blockNumber: number) {
|
|
1304
|
+
const blockHeader = await this.stateMachine.archiver.getBlockHeader(blockNumber);
|
|
1305
|
+
if (!blockHeader) {
|
|
1306
|
+
throw new Error(`Requested timestamp for block ${blockNumber}, which does not exist`);
|
|
1307
|
+
}
|
|
1308
|
+
|
|
1309
|
+
return blockHeader.globalVariables.timestamp;
|
|
1310
|
+
}
|
|
1670
1311
|
}
|