@aztec/txe 0.47.0 → 0.48.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dest/oracle/txe_oracle.d.ts +20 -16
- package/dest/oracle/txe_oracle.d.ts.map +1 -1
- package/dest/oracle/txe_oracle.js +76 -89
- package/dest/txe_service/txe_service.d.ts +10 -3
- package/dest/txe_service/txe_service.d.ts.map +1 -1
- package/dest/txe_service/txe_service.js +41 -34
- package/package.json +15 -14
- package/src/oracle/txe_oracle.ts +79 -123
- package/src/txe_service/txe_service.ts +44 -34
package/src/oracle/txe_oracle.ts
CHANGED
|
@@ -9,13 +9,13 @@ import {
|
|
|
9
9
|
NullifierMembershipWitness,
|
|
10
10
|
PublicDataWitness,
|
|
11
11
|
PublicDataWrite,
|
|
12
|
+
PublicExecutionRequest,
|
|
12
13
|
TaggedLog,
|
|
13
14
|
type UnencryptedL2Log,
|
|
14
15
|
} from '@aztec/circuit-types';
|
|
15
16
|
import { type CircuitWitnessGenerationStats } from '@aztec/circuit-types/stats';
|
|
16
17
|
import {
|
|
17
18
|
CallContext,
|
|
18
|
-
FunctionData,
|
|
19
19
|
Gas,
|
|
20
20
|
GlobalVariables,
|
|
21
21
|
Header,
|
|
@@ -25,10 +25,8 @@ import {
|
|
|
25
25
|
type NullifierLeafPreimage,
|
|
26
26
|
PUBLIC_DATA_SUBTREE_HEIGHT,
|
|
27
27
|
type PUBLIC_DATA_TREE_HEIGHT,
|
|
28
|
-
PrivateCallStackItem,
|
|
29
28
|
PrivateCircuitPublicInputs,
|
|
30
29
|
PrivateContextInputs,
|
|
31
|
-
PublicCallRequest,
|
|
32
30
|
PublicDataTreeLeaf,
|
|
33
31
|
type PublicDataTreeLeafPreimage,
|
|
34
32
|
TxContext,
|
|
@@ -70,6 +68,7 @@ import {
|
|
|
70
68
|
toACVMWitness,
|
|
71
69
|
witnessMapToFields,
|
|
72
70
|
} from '@aztec/simulator';
|
|
71
|
+
import { NoopTelemetryClient } from '@aztec/telemetry-client/noop';
|
|
73
72
|
import { type ContractInstance, type ContractInstanceWithAddress } from '@aztec/types/contracts';
|
|
74
73
|
import { MerkleTreeSnapshotOperationsFacade, type MerkleTrees } from '@aztec/world-state';
|
|
75
74
|
|
|
@@ -105,6 +104,14 @@ export class TXE implements TypedOracle {
|
|
|
105
104
|
|
|
106
105
|
// Utils
|
|
107
106
|
|
|
107
|
+
async #getTreesAt(blockNumber: number) {
|
|
108
|
+
const db =
|
|
109
|
+
blockNumber === (await this.getBlockNumber())
|
|
110
|
+
? this.trees.asLatest()
|
|
111
|
+
: new MerkleTreeSnapshotOperationsFacade(this.trees, blockNumber);
|
|
112
|
+
return db;
|
|
113
|
+
}
|
|
114
|
+
|
|
108
115
|
getChainId() {
|
|
109
116
|
return Promise.resolve(this.chainId);
|
|
110
117
|
}
|
|
@@ -176,11 +183,16 @@ export class TXE implements TypedOracle {
|
|
|
176
183
|
isStaticCall = false,
|
|
177
184
|
isDelegateCall = false,
|
|
178
185
|
) {
|
|
179
|
-
const
|
|
180
|
-
const
|
|
186
|
+
const db = await this.#getTreesAt(blockNumber);
|
|
187
|
+
const previousBlockState = await this.#getTreesAt(blockNumber - 1);
|
|
188
|
+
|
|
189
|
+
const stateReference = await db.getStateReference();
|
|
181
190
|
const inputs = PrivateContextInputs.empty();
|
|
182
191
|
inputs.historicalHeader.globalVariables.blockNumber = new Fr(blockNumber);
|
|
183
192
|
inputs.historicalHeader.state = stateReference;
|
|
193
|
+
inputs.historicalHeader.lastArchive.root = Fr.fromBuffer(
|
|
194
|
+
(await previousBlockState.getTreeInfo(MerkleTreeId.ARCHIVE)).root,
|
|
195
|
+
);
|
|
184
196
|
inputs.callContext.msgSender = this.msgSender;
|
|
185
197
|
inputs.callContext.storageContractAddress = this.contractAddress;
|
|
186
198
|
inputs.callContext.isStaticCall = isStaticCall;
|
|
@@ -215,10 +227,10 @@ export class TXE implements TypedOracle {
|
|
|
215
227
|
return Promise.resolve();
|
|
216
228
|
}
|
|
217
229
|
|
|
218
|
-
async avmOpcodeEmitNoteHash(
|
|
230
|
+
async avmOpcodeEmitNoteHash(noteHash: Fr) {
|
|
219
231
|
const db = this.trees.asLatest();
|
|
220
|
-
const
|
|
221
|
-
await db.appendLeaves(MerkleTreeId.NOTE_HASH_TREE, [
|
|
232
|
+
const siloedNoteHash = siloNoteHash(this.contractAddress, noteHash);
|
|
233
|
+
await db.appendLeaves(MerkleTreeId.NOTE_HASH_TREE, [siloedNoteHash]);
|
|
222
234
|
return Promise.resolve();
|
|
223
235
|
}
|
|
224
236
|
|
|
@@ -242,9 +254,9 @@ export class TXE implements TypedOracle {
|
|
|
242
254
|
await db.batchInsert(MerkleTreeId.NULLIFIER_TREE, siloedNullifiers, NULLIFIER_SUBTREE_HEIGHT);
|
|
243
255
|
}
|
|
244
256
|
|
|
245
|
-
async addNoteHashes(contractAddress: AztecAddress,
|
|
257
|
+
async addNoteHashes(contractAddress: AztecAddress, noteHashes: Fr[]) {
|
|
246
258
|
const db = this.trees.asLatest();
|
|
247
|
-
const siloedNoteHashes =
|
|
259
|
+
const siloedNoteHashes = noteHashes.map(noteHash => siloNoteHash(contractAddress, noteHash));
|
|
248
260
|
await db.appendLeaves(MerkleTreeId.NOTE_HASH_TREE, siloedNoteHashes);
|
|
249
261
|
}
|
|
250
262
|
|
|
@@ -286,8 +298,14 @@ export class TXE implements TypedOracle {
|
|
|
286
298
|
return contractInstance;
|
|
287
299
|
}
|
|
288
300
|
|
|
289
|
-
getMembershipWitness(
|
|
290
|
-
|
|
301
|
+
async getMembershipWitness(blockNumber: number, treeId: MerkleTreeId, leafValue: Fr): Promise<Fr[] | undefined> {
|
|
302
|
+
const db = await this.#getTreesAt(blockNumber);
|
|
303
|
+
const index = await db.findLeafIndex(treeId, leafValue.toBuffer());
|
|
304
|
+
if (!index) {
|
|
305
|
+
throw new Error(`Leaf value: ${leafValue} not found in ${MerkleTreeId[treeId]} at block ${blockNumber}`);
|
|
306
|
+
}
|
|
307
|
+
const siblingPath = await db.getSiblingPath(treeId, index);
|
|
308
|
+
return [new Fr(index), ...siblingPath.toFields()];
|
|
291
309
|
}
|
|
292
310
|
|
|
293
311
|
async getSiblingPath(blockNumber: number, treeId: MerkleTreeId, leafIndex: Fr) {
|
|
@@ -300,14 +318,14 @@ export class TXE implements TypedOracle {
|
|
|
300
318
|
blockNumber: number,
|
|
301
319
|
nullifier: Fr,
|
|
302
320
|
): Promise<NullifierMembershipWitness | undefined> {
|
|
303
|
-
const
|
|
304
|
-
const index = await
|
|
321
|
+
const db = await this.#getTreesAt(blockNumber);
|
|
322
|
+
const index = await db.findLeafIndex(MerkleTreeId.NULLIFIER_TREE, nullifier.toBuffer());
|
|
305
323
|
if (!index) {
|
|
306
324
|
return undefined;
|
|
307
325
|
}
|
|
308
326
|
|
|
309
|
-
const leafPreimagePromise =
|
|
310
|
-
const siblingPathPromise =
|
|
327
|
+
const leafPreimagePromise = db.getLeafPreimage(MerkleTreeId.NULLIFIER_TREE, index);
|
|
328
|
+
const siblingPathPromise = db.getSiblingPath<typeof NULLIFIER_TREE_HEIGHT>(
|
|
311
329
|
MerkleTreeId.NULLIFIER_TREE,
|
|
312
330
|
BigInt(index),
|
|
313
331
|
);
|
|
@@ -346,8 +364,12 @@ export class TXE implements TypedOracle {
|
|
|
346
364
|
throw new Error('Method not implemented.');
|
|
347
365
|
}
|
|
348
366
|
|
|
349
|
-
getHeader(
|
|
350
|
-
|
|
367
|
+
async getHeader(blockNumber: number): Promise<Header | undefined> {
|
|
368
|
+
const header = Header.empty();
|
|
369
|
+
const db = await this.#getTreesAt(blockNumber);
|
|
370
|
+
header.state = await db.getStateReference();
|
|
371
|
+
header.globalVariables.blockNumber = new Fr(blockNumber);
|
|
372
|
+
return header;
|
|
351
373
|
}
|
|
352
374
|
|
|
353
375
|
getCompleteAddress(account: AztecAddress) {
|
|
@@ -404,7 +426,7 @@ export class TXE implements TypedOracle {
|
|
|
404
426
|
return Promise.resolve(notes);
|
|
405
427
|
}
|
|
406
428
|
|
|
407
|
-
notifyCreatedNote(storageSlot: Fr, noteTypeId: NoteSelector, noteItems: Fr[],
|
|
429
|
+
notifyCreatedNote(storageSlot: Fr, noteTypeId: NoteSelector, noteItems: Fr[], noteHash: Fr, counter: number) {
|
|
408
430
|
const note = new Note(noteItems);
|
|
409
431
|
this.noteCache.addNewNote(
|
|
410
432
|
{
|
|
@@ -413,15 +435,17 @@ export class TXE implements TypedOracle {
|
|
|
413
435
|
nonce: Fr.ZERO, // Nonce cannot be known during private execution.
|
|
414
436
|
note,
|
|
415
437
|
siloedNullifier: undefined, // Siloed nullifier cannot be known for newly created note.
|
|
416
|
-
|
|
438
|
+
noteHash,
|
|
417
439
|
},
|
|
418
440
|
counter,
|
|
419
441
|
);
|
|
442
|
+
this.sideEffectsCounter = counter + 1;
|
|
420
443
|
return Promise.resolve();
|
|
421
444
|
}
|
|
422
445
|
|
|
423
|
-
notifyNullifiedNote(innerNullifier: Fr,
|
|
424
|
-
this.noteCache.nullifyNote(this.contractAddress, innerNullifier,
|
|
446
|
+
notifyNullifiedNote(innerNullifier: Fr, noteHash: Fr, counter: number) {
|
|
447
|
+
this.noteCache.nullifyNote(this.contractAddress, innerNullifier, noteHash);
|
|
448
|
+
this.sideEffectsCounter = counter + 1;
|
|
425
449
|
return Promise.resolve();
|
|
426
450
|
}
|
|
427
451
|
|
|
@@ -470,11 +494,7 @@ export class TXE implements TypedOracle {
|
|
|
470
494
|
blockNumber: number,
|
|
471
495
|
numberOfElements: number,
|
|
472
496
|
): Promise<Fr[]> {
|
|
473
|
-
const db =
|
|
474
|
-
blockNumber === (await this.getBlockNumber())
|
|
475
|
-
? this.trees.asLatest()
|
|
476
|
-
: new MerkleTreeSnapshotOperationsFacade(this.trees, blockNumber);
|
|
477
|
-
|
|
497
|
+
const db = await this.#getTreesAt(blockNumber);
|
|
478
498
|
const values = [];
|
|
479
499
|
for (let i = 0n; i < numberOfElements; i++) {
|
|
480
500
|
const storageSlot = startStorageSlot.add(new Fr(i));
|
|
@@ -512,11 +532,13 @@ export class TXE implements TypedOracle {
|
|
|
512
532
|
return publicDataWrites.map(write => write.newValue);
|
|
513
533
|
}
|
|
514
534
|
|
|
515
|
-
emitEncryptedLog(_contractAddress: AztecAddress, _randomness: Fr, _encryptedNote: Buffer,
|
|
535
|
+
emitEncryptedLog(_contractAddress: AztecAddress, _randomness: Fr, _encryptedNote: Buffer, counter: number): void {
|
|
536
|
+
this.sideEffectsCounter = counter + 1;
|
|
516
537
|
return;
|
|
517
538
|
}
|
|
518
539
|
|
|
519
|
-
emitEncryptedNoteLog(_noteHashCounter: number, _encryptedNote: Buffer,
|
|
540
|
+
emitEncryptedNoteLog(_noteHashCounter: number, _encryptedNote: Buffer, counter: number): void {
|
|
541
|
+
this.sideEffectsCounter = counter + 1;
|
|
520
542
|
return;
|
|
521
543
|
}
|
|
522
544
|
|
|
@@ -538,7 +560,8 @@ export class TXE implements TypedOracle {
|
|
|
538
560
|
return taggedNote.encrypt(ephSk, recipient, ivpkM, ovKeys);
|
|
539
561
|
}
|
|
540
562
|
|
|
541
|
-
emitUnencryptedLog(_log: UnencryptedL2Log,
|
|
563
|
+
emitUnencryptedLog(_log: UnencryptedL2Log, counter: number): void {
|
|
564
|
+
this.sideEffectsCounter = counter + 1;
|
|
542
565
|
return;
|
|
543
566
|
}
|
|
544
567
|
|
|
@@ -553,7 +576,7 @@ export class TXE implements TypedOracle {
|
|
|
553
576
|
sideEffectCounter: number,
|
|
554
577
|
isStaticCall: boolean,
|
|
555
578
|
isDelegateCall: boolean,
|
|
556
|
-
)
|
|
579
|
+
) {
|
|
557
580
|
this.logger.verbose(
|
|
558
581
|
`Executing external function ${targetContractAddress}:${functionSelector}(${await this.getDebugFunctionName(
|
|
559
582
|
targetContractAddress,
|
|
@@ -609,13 +632,9 @@ export class TXE implements TypedOracle {
|
|
|
609
632
|
appCircuitName: 'noname',
|
|
610
633
|
} satisfies CircuitWitnessGenerationStats);
|
|
611
634
|
|
|
612
|
-
const callStackItem = new PrivateCallStackItem(
|
|
613
|
-
targetContractAddress,
|
|
614
|
-
new FunctionData(functionSelector, true),
|
|
615
|
-
publicInputs,
|
|
616
|
-
);
|
|
617
635
|
// Apply side effects
|
|
618
|
-
|
|
636
|
+
const endSideEffectCounter = publicInputs.endSideEffectCounter;
|
|
637
|
+
this.sideEffectsCounter = endSideEffectCounter.toNumber() + 1;
|
|
619
638
|
|
|
620
639
|
await this.addNullifiers(
|
|
621
640
|
targetContractAddress,
|
|
@@ -627,7 +646,7 @@ export class TXE implements TypedOracle {
|
|
|
627
646
|
publicInputs.noteHashes.filter(noteHash => !noteHash.isEmpty()).map(noteHash => noteHash.value),
|
|
628
647
|
);
|
|
629
648
|
|
|
630
|
-
return
|
|
649
|
+
return { endSideEffectCounter, returnsHash: publicInputs.returnsHash };
|
|
631
650
|
} finally {
|
|
632
651
|
this.setContractAddress(currentContractAddress);
|
|
633
652
|
this.setMsgSender(currentMessageSender);
|
|
@@ -684,37 +703,21 @@ export class TXE implements TypedOracle {
|
|
|
684
703
|
|
|
685
704
|
async executePublicFunction(
|
|
686
705
|
targetContractAddress: AztecAddress,
|
|
687
|
-
functionSelector: FunctionSelector,
|
|
688
706
|
args: Fr[],
|
|
689
707
|
callContext: CallContext,
|
|
708
|
+
counter: number,
|
|
690
709
|
) {
|
|
691
710
|
const header = Header.empty();
|
|
692
711
|
header.state = await this.trees.getStateReference(true);
|
|
693
712
|
header.globalVariables.blockNumber = new Fr(await this.getBlockNumber());
|
|
694
|
-
header.state.partial.nullifierTree.root = Fr.fromBuffer(
|
|
695
|
-
(await this.trees.getTreeInfo(MerkleTreeId.NULLIFIER_TREE, true)).root,
|
|
696
|
-
);
|
|
697
|
-
header.state.partial.noteHashTree.root = Fr.fromBuffer(
|
|
698
|
-
(await this.trees.getTreeInfo(MerkleTreeId.NOTE_HASH_TREE, true)).root,
|
|
699
|
-
);
|
|
700
|
-
header.state.partial.publicDataTree.root = Fr.fromBuffer(
|
|
701
|
-
(await this.trees.getTreeInfo(MerkleTreeId.PUBLIC_DATA_TREE, true)).root,
|
|
702
|
-
);
|
|
703
|
-
header.state.l1ToL2MessageTree.root = Fr.fromBuffer(
|
|
704
|
-
(await this.trees.getTreeInfo(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, true)).root,
|
|
705
|
-
);
|
|
706
713
|
const executor = new PublicExecutor(
|
|
707
714
|
new TXEPublicStateDB(this),
|
|
708
715
|
new ContractsDataSourcePublicDB(new TXEPublicContractDataSource(this)),
|
|
709
716
|
new WorldStateDB(this.trees.asLatest()),
|
|
710
717
|
header,
|
|
718
|
+
new NoopTelemetryClient(),
|
|
711
719
|
);
|
|
712
|
-
const execution =
|
|
713
|
-
contractAddress: targetContractAddress,
|
|
714
|
-
functionSelector,
|
|
715
|
-
args,
|
|
716
|
-
callContext,
|
|
717
|
-
};
|
|
720
|
+
const execution = new PublicExecutionRequest(targetContractAddress, callContext, args);
|
|
718
721
|
|
|
719
722
|
return executor.simulate(
|
|
720
723
|
execution,
|
|
@@ -723,6 +726,7 @@ export class TXE implements TypedOracle {
|
|
|
723
726
|
TxContext.empty(),
|
|
724
727
|
/* pendingNullifiers */ [],
|
|
725
728
|
/* transactionFee */ Fr.ONE,
|
|
729
|
+
counter,
|
|
726
730
|
);
|
|
727
731
|
}
|
|
728
732
|
|
|
@@ -750,14 +754,14 @@ export class TXE implements TypedOracle {
|
|
|
750
754
|
|
|
751
755
|
const executionResult = await this.executePublicFunction(
|
|
752
756
|
targetContractAddress,
|
|
753
|
-
functionSelector,
|
|
754
757
|
args,
|
|
755
758
|
callContext,
|
|
759
|
+
this.sideEffectsCounter,
|
|
756
760
|
);
|
|
757
761
|
|
|
758
762
|
// Apply side effects
|
|
759
763
|
if (!executionResult.reverted) {
|
|
760
|
-
this.sideEffectsCounter
|
|
764
|
+
this.sideEffectsCounter = executionResult.endSideEffectCounter.toNumber() + 1;
|
|
761
765
|
}
|
|
762
766
|
this.setContractAddress(currentContractAddress);
|
|
763
767
|
this.setMsgSender(currentMessageSender);
|
|
@@ -766,47 +770,6 @@ export class TXE implements TypedOracle {
|
|
|
766
770
|
return executionResult;
|
|
767
771
|
}
|
|
768
772
|
|
|
769
|
-
async callPublicFunction(
|
|
770
|
-
targetContractAddress: AztecAddress,
|
|
771
|
-
functionSelector: FunctionSelector,
|
|
772
|
-
argsHash: Fr,
|
|
773
|
-
sideEffectCounter: number,
|
|
774
|
-
isStaticCall: boolean,
|
|
775
|
-
isDelegateCall: boolean,
|
|
776
|
-
): Promise<Fr[]> {
|
|
777
|
-
// Store and modify env
|
|
778
|
-
const currentContractAddress = AztecAddress.fromField(this.contractAddress);
|
|
779
|
-
const currentMessageSender = AztecAddress.fromField(this.msgSender);
|
|
780
|
-
const currentFunctionSelector = FunctionSelector.fromField(this.functionSelector.toField());
|
|
781
|
-
this.setMsgSender(this.contractAddress);
|
|
782
|
-
this.setContractAddress(targetContractAddress);
|
|
783
|
-
this.setFunctionSelector(functionSelector);
|
|
784
|
-
|
|
785
|
-
const callContext = CallContext.empty();
|
|
786
|
-
callContext.msgSender = this.msgSender;
|
|
787
|
-
callContext.functionSelector = this.functionSelector;
|
|
788
|
-
callContext.storageContractAddress = targetContractAddress;
|
|
789
|
-
callContext.isStaticCall = isStaticCall;
|
|
790
|
-
callContext.isDelegateCall = isDelegateCall;
|
|
791
|
-
|
|
792
|
-
const args = this.packedValuesCache.unpack(argsHash);
|
|
793
|
-
|
|
794
|
-
const executionResult = await this.executePublicFunction(
|
|
795
|
-
targetContractAddress,
|
|
796
|
-
functionSelector,
|
|
797
|
-
args,
|
|
798
|
-
callContext,
|
|
799
|
-
);
|
|
800
|
-
|
|
801
|
-
// Apply side effects
|
|
802
|
-
this.sideEffectsCounter = executionResult.endSideEffectCounter.toNumber();
|
|
803
|
-
this.setContractAddress(currentContractAddress);
|
|
804
|
-
this.setMsgSender(currentMessageSender);
|
|
805
|
-
this.setFunctionSelector(currentFunctionSelector);
|
|
806
|
-
|
|
807
|
-
return executionResult.returnValues;
|
|
808
|
-
}
|
|
809
|
-
|
|
810
773
|
async enqueuePublicFunctionCall(
|
|
811
774
|
targetContractAddress: AztecAddress,
|
|
812
775
|
functionSelector: FunctionSelector,
|
|
@@ -814,7 +777,7 @@ export class TXE implements TypedOracle {
|
|
|
814
777
|
sideEffectCounter: number,
|
|
815
778
|
isStaticCall: boolean,
|
|
816
779
|
isDelegateCall: boolean,
|
|
817
|
-
)
|
|
780
|
+
) {
|
|
818
781
|
// Store and modify env
|
|
819
782
|
const currentContractAddress = AztecAddress.fromField(this.contractAddress);
|
|
820
783
|
const currentMessageSender = AztecAddress.fromField(this.msgSender);
|
|
@@ -834,45 +797,33 @@ export class TXE implements TypedOracle {
|
|
|
834
797
|
|
|
835
798
|
const executionResult = await this.executePublicFunction(
|
|
836
799
|
targetContractAddress,
|
|
837
|
-
functionSelector,
|
|
838
800
|
args,
|
|
839
801
|
callContext,
|
|
802
|
+
sideEffectCounter,
|
|
840
803
|
);
|
|
841
804
|
|
|
805
|
+
if (executionResult.reverted) {
|
|
806
|
+
throw new Error(`Execution reverted with reason: ${executionResult.revertReason}`);
|
|
807
|
+
}
|
|
808
|
+
|
|
842
809
|
// Apply side effects
|
|
843
|
-
this.sideEffectsCounter
|
|
810
|
+
this.sideEffectsCounter = executionResult.endSideEffectCounter.toNumber() + 1;
|
|
844
811
|
this.setContractAddress(currentContractAddress);
|
|
845
812
|
this.setMsgSender(currentMessageSender);
|
|
846
813
|
this.setFunctionSelector(currentFunctionSelector);
|
|
847
|
-
|
|
848
|
-
const parentCallContext = CallContext.empty();
|
|
849
|
-
parentCallContext.msgSender = currentMessageSender;
|
|
850
|
-
parentCallContext.functionSelector = currentFunctionSelector;
|
|
851
|
-
parentCallContext.storageContractAddress = currentContractAddress;
|
|
852
|
-
parentCallContext.isStaticCall = isStaticCall;
|
|
853
|
-
parentCallContext.isDelegateCall = isDelegateCall;
|
|
854
|
-
|
|
855
|
-
return PublicCallRequest.from({
|
|
856
|
-
parentCallContext,
|
|
857
|
-
contractAddress: targetContractAddress,
|
|
858
|
-
functionSelector,
|
|
859
|
-
callContext,
|
|
860
|
-
sideEffectCounter,
|
|
861
|
-
args,
|
|
862
|
-
});
|
|
863
814
|
}
|
|
864
815
|
|
|
865
|
-
setPublicTeardownFunctionCall(
|
|
816
|
+
async setPublicTeardownFunctionCall(
|
|
866
817
|
targetContractAddress: AztecAddress,
|
|
867
818
|
functionSelector: FunctionSelector,
|
|
868
819
|
argsHash: Fr,
|
|
869
820
|
sideEffectCounter: number,
|
|
870
821
|
isStaticCall: boolean,
|
|
871
822
|
isDelegateCall: boolean,
|
|
872
|
-
)
|
|
823
|
+
) {
|
|
873
824
|
// Definitely not right, in that the teardown should always be last.
|
|
874
825
|
// But useful for executing flows.
|
|
875
|
-
|
|
826
|
+
await this.enqueuePublicFunctionCall(
|
|
876
827
|
targetContractAddress,
|
|
877
828
|
functionSelector,
|
|
878
829
|
argsHash,
|
|
@@ -882,6 +833,10 @@ export class TXE implements TypedOracle {
|
|
|
882
833
|
);
|
|
883
834
|
}
|
|
884
835
|
|
|
836
|
+
notifySetMinRevertibleSideEffectCounter(minRevertibleSideEffectCounter: number) {
|
|
837
|
+
this.noteCache.setMinRevertibleSideEffectCounter(minRevertibleSideEffectCounter);
|
|
838
|
+
}
|
|
839
|
+
|
|
885
840
|
aes128Encrypt(input: Buffer, initializationVector: Buffer, key: Buffer): Buffer {
|
|
886
841
|
const aes128 = new Aes128();
|
|
887
842
|
return aes128.encryptBufferCBC(input, initializationVector, key);
|
|
@@ -895,8 +850,9 @@ export class TXE implements TypedOracle {
|
|
|
895
850
|
_contractAddress: AztecAddress,
|
|
896
851
|
_randomness: Fr,
|
|
897
852
|
_encryptedEvent: Buffer,
|
|
898
|
-
|
|
853
|
+
counter: number,
|
|
899
854
|
): void {
|
|
855
|
+
this.sideEffectsCounter = counter + 1;
|
|
900
856
|
return;
|
|
901
857
|
}
|
|
902
858
|
|
|
@@ -40,7 +40,8 @@ export class TXEService {
|
|
|
40
40
|
const store = openTmpStore(true);
|
|
41
41
|
const trees = await MerkleTrees.new(store, logger);
|
|
42
42
|
const packedValuesCache = new PackedValuesCache();
|
|
43
|
-
const
|
|
43
|
+
const txHash = new Fr(1); // The txHash is used for computing the revertible nullifiers for non-revertible note hashes. It can be any value for testing.
|
|
44
|
+
const noteCache = new ExecutionNoteCache(txHash);
|
|
44
45
|
const keyStore = new KeyStore(store);
|
|
45
46
|
const txeDatabase = new TXEDatabase(store);
|
|
46
47
|
logger.info(`TXE service initialized`);
|
|
@@ -66,16 +67,16 @@ export class TXEService {
|
|
|
66
67
|
const nBlocks = fromSingle(blocks).toNumber();
|
|
67
68
|
this.logger.debug(`time traveling ${nBlocks} blocks`);
|
|
68
69
|
const trees = (this.typedOracle as TXE).getTrees();
|
|
69
|
-
const header = Header.empty();
|
|
70
|
-
const l2Block = L2Block.empty();
|
|
71
|
-
header.state = await trees.getStateReference(true);
|
|
72
|
-
const blockNumber = await this.typedOracle.getBlockNumber();
|
|
73
|
-
header.globalVariables.blockNumber = new Fr(blockNumber);
|
|
74
|
-
l2Block.archive.root = Fr.fromBuffer((await trees.getTreeInfo(MerkleTreeId.ARCHIVE, true)).root);
|
|
75
|
-
l2Block.header = header;
|
|
76
70
|
for (let i = 0; i < nBlocks; i++) {
|
|
77
71
|
const blockNumber = await this.typedOracle.getBlockNumber();
|
|
72
|
+
const header = Header.empty();
|
|
73
|
+
const l2Block = L2Block.empty();
|
|
74
|
+
header.state = await trees.getStateReference(true);
|
|
78
75
|
header.globalVariables.blockNumber = new Fr(blockNumber);
|
|
76
|
+
await trees.appendLeaves(MerkleTreeId.ARCHIVE, [header.hash()]);
|
|
77
|
+
l2Block.archive.root = Fr.fromBuffer((await trees.getTreeInfo(MerkleTreeId.ARCHIVE, true)).root);
|
|
78
|
+
l2Block.header = header;
|
|
79
|
+
this.logger.debug(`Block ${blockNumber} created, header hash ${header.hash().toString()}`);
|
|
79
80
|
await trees.handleL2BlockAndMessages(l2Block, []);
|
|
80
81
|
(this.typedOracle as TXE).setBlockNumber(blockNumber + 1);
|
|
81
82
|
}
|
|
@@ -442,14 +443,14 @@ export class TXEService {
|
|
|
442
443
|
storageSlot: ForeignCallSingle,
|
|
443
444
|
noteTypeId: ForeignCallSingle,
|
|
444
445
|
note: ForeignCallArray,
|
|
445
|
-
|
|
446
|
+
noteHash: ForeignCallSingle,
|
|
446
447
|
counter: ForeignCallSingle,
|
|
447
448
|
) {
|
|
448
449
|
this.typedOracle.notifyCreatedNote(
|
|
449
450
|
fromSingle(storageSlot),
|
|
450
451
|
NoteSelector.fromField(fromSingle(noteTypeId)),
|
|
451
452
|
fromArray(note),
|
|
452
|
-
fromSingle(
|
|
453
|
+
fromSingle(noteHash),
|
|
453
454
|
fromSingle(counter).toNumber(),
|
|
454
455
|
);
|
|
455
456
|
return toForeignCallResult([toSingle(new Fr(0))]);
|
|
@@ -457,12 +458,12 @@ export class TXEService {
|
|
|
457
458
|
|
|
458
459
|
async notifyNullifiedNote(
|
|
459
460
|
innerNullifier: ForeignCallSingle,
|
|
460
|
-
|
|
461
|
+
noteHash: ForeignCallSingle,
|
|
461
462
|
counter: ForeignCallSingle,
|
|
462
463
|
) {
|
|
463
464
|
await this.typedOracle.notifyNullifiedNote(
|
|
464
465
|
fromSingle(innerNullifier),
|
|
465
|
-
fromSingle(
|
|
466
|
+
fromSingle(noteHash),
|
|
466
467
|
fromSingle(counter).toNumber(),
|
|
467
468
|
);
|
|
468
469
|
return toForeignCallResult([toSingle(new Fr(0))]);
|
|
@@ -511,8 +512,8 @@ export class TXEService {
|
|
|
511
512
|
return toForeignCallResult([]);
|
|
512
513
|
}
|
|
513
514
|
|
|
514
|
-
async avmOpcodeEmitNoteHash(
|
|
515
|
-
await (this.typedOracle as TXE).avmOpcodeEmitNoteHash(fromSingle(
|
|
515
|
+
async avmOpcodeEmitNoteHash(noteHash: ForeignCallSingle) {
|
|
516
|
+
await (this.typedOracle as TXE).avmOpcodeEmitNoteHash(fromSingle(noteHash));
|
|
516
517
|
return toForeignCallResult([]);
|
|
517
518
|
}
|
|
518
519
|
|
|
@@ -652,7 +653,7 @@ export class TXEService {
|
|
|
652
653
|
fromSingle(isStaticCall).toBool(),
|
|
653
654
|
fromSingle(isDelegateCall).toBool(),
|
|
654
655
|
);
|
|
655
|
-
return toForeignCallResult([toArray(result.
|
|
656
|
+
return toForeignCallResult([toArray([result.endSideEffectCounter, result.returnsHash])]);
|
|
656
657
|
}
|
|
657
658
|
|
|
658
659
|
async getNullifierMembershipWitness(blockNumber: ForeignCallSingle, nullifier: ForeignCallSingle) {
|
|
@@ -681,7 +682,7 @@ export class TXEService {
|
|
|
681
682
|
isStaticCall: ForeignCallSingle,
|
|
682
683
|
isDelegateCall: ForeignCallSingle,
|
|
683
684
|
) {
|
|
684
|
-
|
|
685
|
+
await this.typedOracle.enqueuePublicFunctionCall(
|
|
685
686
|
fromSingle(targetContractAddress),
|
|
686
687
|
FunctionSelector.fromField(fromSingle(functionSelector)),
|
|
687
688
|
fromSingle(argsHash),
|
|
@@ -689,14 +690,7 @@ export class TXEService {
|
|
|
689
690
|
fromSingle(isStaticCall).toBool(),
|
|
690
691
|
fromSingle(isDelegateCall).toBool(),
|
|
691
692
|
);
|
|
692
|
-
|
|
693
|
-
publicCallRequest.contractAddress.toField(),
|
|
694
|
-
publicCallRequest.functionSelector.toField(),
|
|
695
|
-
...publicCallRequest.callContext.toFields(),
|
|
696
|
-
fromSingle(sideEffectCounter),
|
|
697
|
-
publicCallRequest.getArgsHash(),
|
|
698
|
-
];
|
|
699
|
-
return toForeignCallResult([toArray(fields)]);
|
|
693
|
+
return toForeignCallResult([]);
|
|
700
694
|
}
|
|
701
695
|
|
|
702
696
|
public async setPublicTeardownFunctionCall(
|
|
@@ -707,7 +701,7 @@ export class TXEService {
|
|
|
707
701
|
isStaticCall: ForeignCallSingle,
|
|
708
702
|
isDelegateCall: ForeignCallSingle,
|
|
709
703
|
) {
|
|
710
|
-
|
|
704
|
+
await this.typedOracle.setPublicTeardownFunctionCall(
|
|
711
705
|
fromSingle(targetContractAddress),
|
|
712
706
|
FunctionSelector.fromField(fromSingle(functionSelector)),
|
|
713
707
|
fromSingle(argsHash),
|
|
@@ -715,16 +709,11 @@ export class TXEService {
|
|
|
715
709
|
fromSingle(isStaticCall).toBool(),
|
|
716
710
|
fromSingle(isDelegateCall).toBool(),
|
|
717
711
|
);
|
|
712
|
+
return toForeignCallResult([]);
|
|
713
|
+
}
|
|
718
714
|
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
publicTeardownCallRequest.functionSelector.toField(),
|
|
722
|
-
...publicTeardownCallRequest.callContext.toFields(),
|
|
723
|
-
fromSingle(sideEffectCounter),
|
|
724
|
-
publicTeardownCallRequest.getArgsHash(),
|
|
725
|
-
];
|
|
726
|
-
|
|
727
|
-
return toForeignCallResult([toArray(fields)]);
|
|
715
|
+
public notifySetMinRevertibleSideEffectCounter(minRevertibleSideEffectCounter: ForeignCallSingle) {
|
|
716
|
+
this.typedOracle.notifySetMinRevertibleSideEffectCounter(fromSingle(minRevertibleSideEffectCounter).toNumber());
|
|
728
717
|
}
|
|
729
718
|
|
|
730
719
|
async getChainId() {
|
|
@@ -744,4 +733,25 @@ export class TXEService {
|
|
|
744
733
|
await (this.typedOracle as TXE).addNoteHashes(fromSingle(contractAddress), fromArray(noteHashes));
|
|
745
734
|
return toForeignCallResult([]);
|
|
746
735
|
}
|
|
736
|
+
|
|
737
|
+
async getHeader(blockNumber: ForeignCallSingle) {
|
|
738
|
+
const header = await this.typedOracle.getHeader(fromSingle(blockNumber).toNumber());
|
|
739
|
+
if (!header) {
|
|
740
|
+
throw new Error(`Block header not found for block ${blockNumber}.`);
|
|
741
|
+
}
|
|
742
|
+
return toForeignCallResult([toArray(header.toFields())]);
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
async getMembershipWitness(blockNumber: ForeignCallSingle, treeId: ForeignCallSingle, leafValue: ForeignCallSingle) {
|
|
746
|
+
const parsedBlockNumber = fromSingle(blockNumber).toNumber();
|
|
747
|
+
const parsedTreeId = fromSingle(treeId).toNumber();
|
|
748
|
+
const parsedLeafValue = fromSingle(leafValue);
|
|
749
|
+
const witness = await this.typedOracle.getMembershipWitness(parsedBlockNumber, parsedTreeId, parsedLeafValue);
|
|
750
|
+
if (!witness) {
|
|
751
|
+
throw new Error(
|
|
752
|
+
`Membership witness in tree ${MerkleTreeId[parsedTreeId]} not found for value ${parsedLeafValue} at block ${parsedBlockNumber}.`,
|
|
753
|
+
);
|
|
754
|
+
}
|
|
755
|
+
return toForeignCallResult([toArray(witness)]);
|
|
756
|
+
}
|
|
747
757
|
}
|