@aztec/txe 0.0.1-commit.5de5ca79e → 0.0.1-commit.6201a7b05

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.
Files changed (44) hide show
  1. package/dest/oracle/interfaces.d.ts +5 -2
  2. package/dest/oracle/interfaces.d.ts.map +1 -1
  3. package/dest/oracle/txe_oracle_top_level_context.d.ts +13 -6
  4. package/dest/oracle/txe_oracle_top_level_context.d.ts.map +1 -1
  5. package/dest/oracle/txe_oracle_top_level_context.js +45 -22
  6. package/dest/rpc_translator.d.ts +62 -21
  7. package/dest/rpc_translator.d.ts.map +1 -1
  8. package/dest/rpc_translator.js +238 -60
  9. package/dest/state_machine/archiver.d.ts +1 -1
  10. package/dest/state_machine/archiver.d.ts.map +1 -1
  11. package/dest/state_machine/archiver.js +2 -1
  12. package/dest/state_machine/dummy_p2p_client.d.ts +3 -2
  13. package/dest/state_machine/dummy_p2p_client.d.ts.map +1 -1
  14. package/dest/state_machine/dummy_p2p_client.js +5 -2
  15. package/dest/state_machine/global_variable_builder.d.ts +9 -4
  16. package/dest/state_machine/global_variable_builder.d.ts.map +1 -1
  17. package/dest/state_machine/global_variable_builder.js +9 -3
  18. package/dest/state_machine/index.d.ts +1 -1
  19. package/dest/state_machine/index.d.ts.map +1 -1
  20. package/dest/state_machine/index.js +2 -2
  21. package/dest/state_machine/mock_epoch_cache.d.ts +2 -1
  22. package/dest/state_machine/mock_epoch_cache.d.ts.map +1 -1
  23. package/dest/state_machine/mock_epoch_cache.js +3 -0
  24. package/dest/txe_session.d.ts +48 -4
  25. package/dest/txe_session.d.ts.map +1 -1
  26. package/dest/txe_session.js +76 -20
  27. package/dest/util/encoding.d.ts +3 -1
  28. package/dest/util/encoding.d.ts.map +1 -1
  29. package/dest/util/encoding.js +4 -0
  30. package/dest/util/txe_public_contract_data_source.d.ts +1 -1
  31. package/dest/util/txe_public_contract_data_source.d.ts.map +1 -1
  32. package/dest/util/txe_public_contract_data_source.js +1 -3
  33. package/package.json +15 -15
  34. package/src/oracle/interfaces.ts +1 -1
  35. package/src/oracle/txe_oracle_top_level_context.ts +48 -26
  36. package/src/rpc_translator.ts +279 -68
  37. package/src/state_machine/archiver.ts +1 -0
  38. package/src/state_machine/dummy_p2p_client.ts +6 -2
  39. package/src/state_machine/global_variable_builder.ts +18 -3
  40. package/src/state_machine/index.ts +4 -1
  41. package/src/state_machine/mock_epoch_cache.ts +4 -0
  42. package/src/txe_session.ts +134 -20
  43. package/src/util/encoding.ts +5 -0
  44. package/src/util/txe_public_contract_data_source.ts +0 -2
@@ -1,6 +1,6 @@
1
1
  import type { ContractInstanceWithAddress } from '@aztec/aztec.js/contracts';
2
2
  import { Fr, Point } from '@aztec/aztec.js/fields';
3
- import { MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX } from '@aztec/constants';
3
+ import { MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, PRIVATE_LOG_CIPHERTEXT_LEN } from '@aztec/constants';
4
4
  import { BlockNumber } from '@aztec/foundation/branded-types';
5
5
  import {
6
6
  type IMiscOracle,
@@ -10,7 +10,6 @@ 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 { BlockHash } from '@aztec/stdlib/block';
14
13
 
15
14
  import type { IAvmExecutionOracle, ITxeExecutionOracle } from './oracle/interfaces.js';
16
15
  import type { TXESessionStateHandler } from './txe_session.js';
@@ -20,6 +19,7 @@ import {
20
19
  addressFromSingle,
21
20
  arrayOfArraysToBoundedVecOfArrays,
22
21
  arrayToBoundedVec,
22
+ blockHashFromSingle,
23
23
  bufferToU8Array,
24
24
  fromArray,
25
25
  fromSingle,
@@ -264,10 +264,11 @@ export class RPCTranslator {
264
264
  // PXE oracles
265
265
 
266
266
  // eslint-disable-next-line camelcase
267
- aztec_utl_assertCompatibleOracleVersion(foreignVersion: ForeignCallSingle) {
268
- const version = fromSingle(foreignVersion).toNumber();
267
+ aztec_utl_assertCompatibleOracleVersionV2(foreignMajor: ForeignCallSingle, foreignMinor: ForeignCallSingle) {
268
+ const major = fromSingle(foreignMajor).toNumber();
269
+ const minor = fromSingle(foreignMinor).toNumber();
269
270
 
270
- this.handlerAsMisc().assertCompatibleOracleVersion(version);
271
+ this.handlerAsMisc().assertCompatibleOracleVersion(major, minor);
271
272
 
272
273
  return toForeignCallResult([]);
273
274
  }
@@ -297,6 +298,46 @@ export class RPCTranslator {
297
298
  ]);
298
299
  }
299
300
 
301
+ // eslint-disable-next-line camelcase
302
+ aztec_txe_getLastCallOffchainEffects() {
303
+ // This oracle returns all offchain effect payloads (messages, authwit requests, etc.) emitted by the last top-level call,
304
+ // MAX_OFFCHAIN_EFFECTS_PER_TXE_QUERY is arbitrarily set at 64 because we need a bound. Nothing inherent about it.
305
+ const MAX_OFFCHAIN_EFFECTS_PER_TXE_QUERY = 64;
306
+ // Must match MAX_OFFCHAIN_EFFECT_LEN in txe_oracles.nr.
307
+ const MAX_OFFCHAIN_EFFECT_LEN = 2 + PRIVATE_LOG_CIPHERTEXT_LEN;
308
+
309
+ const { effects } = this.stateHandler.getLastCallOffchainEffects();
310
+
311
+ if (effects.length > MAX_OFFCHAIN_EFFECTS_PER_TXE_QUERY) {
312
+ throw new Error(`${effects.length} offchain effects exceed max ${MAX_OFFCHAIN_EFFECTS_PER_TXE_QUERY}`);
313
+ }
314
+ if (effects.some(e => e.length > MAX_OFFCHAIN_EFFECT_LEN)) {
315
+ throw new Error(`Some offchain effect has length larger than max ${MAX_OFFCHAIN_EFFECT_LEN}`);
316
+ }
317
+
318
+ const rawArrayStorage = effects
319
+ .map(e => e.concat(Array(MAX_OFFCHAIN_EFFECT_LEN - e.length).fill(new Fr(0))))
320
+ .concat(
321
+ Array(MAX_OFFCHAIN_EFFECTS_PER_TXE_QUERY - effects.length).fill(Array(MAX_OFFCHAIN_EFFECT_LEN).fill(new Fr(0))),
322
+ )
323
+ .flat();
324
+
325
+ const effectLengths = effects
326
+ .map(e => new Fr(e.length))
327
+ .concat(Array(MAX_OFFCHAIN_EFFECTS_PER_TXE_QUERY - effects.length).fill(new Fr(0)));
328
+
329
+ const count = new Fr(effects.length);
330
+
331
+ return toForeignCallResult([toArray(rawArrayStorage), toArray(effectLengths), toSingle(count)]);
332
+ }
333
+
334
+ // eslint-disable-next-line camelcase
335
+ aztec_txe_getLastCallContext() {
336
+ const { txHash, anchorBlockTimestamp } = this.stateHandler.getLastCallContext();
337
+ const isSome = txHash.isZero() ? 0 : 1;
338
+ return toForeignCallResult([toSingle(isSome), toSingle(txHash), toSingle(new Fr(anchorBlockTimestamp))]);
339
+ }
340
+
300
341
  // eslint-disable-next-line camelcase
301
342
  async aztec_txe_getPrivateEvents(
302
343
  foreignSelector: ForeignCallSingle,
@@ -339,20 +380,20 @@ export class RPCTranslator {
339
380
  }
340
381
 
341
382
  // eslint-disable-next-line camelcase
342
- aztec_prv_storeInExecutionCache(foreignValues: ForeignCallArray, foreignHash: ForeignCallSingle) {
383
+ aztec_prv_setHashPreimage(foreignValues: ForeignCallArray, foreignHash: ForeignCallSingle) {
343
384
  const values = fromArray(foreignValues);
344
385
  const hash = fromSingle(foreignHash);
345
386
 
346
- this.handlerAsPrivate().storeInExecutionCache(values, hash);
387
+ this.handlerAsPrivate().setHashPreimage(values, hash);
347
388
 
348
389
  return toForeignCallResult([]);
349
390
  }
350
391
 
351
392
  // eslint-disable-next-line camelcase
352
- async aztec_prv_loadFromExecutionCache(foreignHash: ForeignCallSingle) {
393
+ async aztec_prv_getHashPreimage(foreignHash: ForeignCallSingle) {
353
394
  const hash = fromSingle(foreignHash);
354
395
 
355
- const returns = await this.handlerAsPrivate().loadFromExecutionCache(hash);
396
+ const returns = await this.handlerAsPrivate().getHashPreimage(hash);
356
397
 
357
398
  return toForeignCallResult([toArray(returns)]);
358
399
  }
@@ -378,18 +419,18 @@ export class RPCTranslator {
378
419
  }
379
420
 
380
421
  // eslint-disable-next-line camelcase
381
- async aztec_utl_storageRead(
422
+ async aztec_utl_getFromPublicStorage(
382
423
  foreignBlockHash: ForeignCallSingle,
383
424
  foreignContractAddress: ForeignCallSingle,
384
425
  foreignStartStorageSlot: ForeignCallSingle,
385
426
  foreignNumberOfElements: ForeignCallSingle,
386
427
  ) {
387
- const blockHash = new BlockHash(fromSingle(foreignBlockHash));
428
+ const blockHash = blockHashFromSingle(foreignBlockHash);
388
429
  const contractAddress = addressFromSingle(foreignContractAddress);
389
430
  const startStorageSlot = fromSingle(foreignStartStorageSlot);
390
431
  const numberOfElements = fromSingle(foreignNumberOfElements).toNumber();
391
432
 
392
- const values = await this.handlerAsUtility().storageRead(
433
+ const values = await this.handlerAsUtility().getFromPublicStorage(
393
434
  blockHash,
394
435
  contractAddress,
395
436
  startStorageSlot,
@@ -401,7 +442,7 @@ export class RPCTranslator {
401
442
 
402
443
  // eslint-disable-next-line camelcase
403
444
  async aztec_utl_getPublicDataWitness(foreignBlockHash: ForeignCallSingle, foreignLeafSlot: ForeignCallSingle) {
404
- const blockHash = new BlockHash(fromSingle(foreignBlockHash));
445
+ const blockHash = blockHashFromSingle(foreignBlockHash);
405
446
  const leafSlot = fromSingle(foreignLeafSlot);
406
447
 
407
448
  const witness = await this.handlerAsUtility().getPublicDataWitness(blockHash, leafSlot);
@@ -556,10 +597,10 @@ export class RPCTranslator {
556
597
  }
557
598
 
558
599
  // eslint-disable-next-line camelcase
559
- async aztec_utl_checkNullifierExists(foreignInnerNullifier: ForeignCallSingle) {
600
+ async aztec_utl_doesNullifierExist(foreignInnerNullifier: ForeignCallSingle) {
560
601
  const innerNullifier = fromSingle(foreignInnerNullifier);
561
602
 
562
- const exists = await this.handlerAsUtility().checkNullifierExists(innerNullifier);
603
+ const exists = await this.handlerAsUtility().doesNullifierExist(innerNullifier);
563
604
 
564
605
  return toForeignCallResult([toSingle(new Fr(exists))]);
565
606
  }
@@ -582,10 +623,10 @@ export class RPCTranslator {
582
623
  }
583
624
 
584
625
  // eslint-disable-next-line camelcase
585
- async aztec_utl_tryGetPublicKeysAndPartialAddress(foreignAddress: ForeignCallSingle) {
626
+ async aztec_utl_getPublicKeysAndPartialAddress(foreignAddress: ForeignCallSingle) {
586
627
  const address = addressFromSingle(foreignAddress);
587
628
 
588
- const result = await this.handlerAsUtility().tryGetPublicKeysAndPartialAddress(address);
629
+ const result = await this.handlerAsUtility().getPublicKeysAndPartialAddress(address);
589
630
 
590
631
  // We are going to return a Noir Option struct to represent the possibility of null values. Options are a struct
591
632
  // with two fields: `some` (a boolean) and `value` (a field array in this case).
@@ -628,7 +669,7 @@ export class RPCTranslator {
628
669
  foreignBlockHash: ForeignCallSingle,
629
670
  foreignNullifier: ForeignCallSingle,
630
671
  ) {
631
- const blockHash = new BlockHash(fromSingle(foreignBlockHash));
672
+ const blockHash = blockHashFromSingle(foreignBlockHash);
632
673
  const nullifier = fromSingle(foreignNullifier);
633
674
 
634
675
  const witness = await this.handlerAsUtility().getNullifierMembershipWitness(blockHash, nullifier);
@@ -652,7 +693,7 @@ export class RPCTranslator {
652
693
  }
653
694
 
654
695
  // eslint-disable-next-line camelcase
655
- public aztec_prv_validatePublicCalldata(_foreignCalldataHash: ForeignCallSingle) {
696
+ public aztec_prv_assertValidPublicCalldata(_foreignCalldataHash: ForeignCallSingle) {
656
697
  throw new Error('Enqueueing public calls is not supported in TestEnvironment::private_context');
657
698
  }
658
699
 
@@ -662,9 +703,9 @@ export class RPCTranslator {
662
703
  }
663
704
 
664
705
  // eslint-disable-next-line camelcase
665
- public async aztec_prv_inRevertiblePhase(foreignSideEffectCounter: ForeignCallSingle) {
706
+ public async aztec_prv_isExecutionInRevertiblePhase(foreignSideEffectCounter: ForeignCallSingle) {
666
707
  const sideEffectCounter = fromSingle(foreignSideEffectCounter).toNumber();
667
- const isRevertible = await this.handlerAsPrivate().inRevertiblePhase(sideEffectCounter);
708
+ const isRevertible = await this.handlerAsPrivate().isExecutionInRevertiblePhase(sideEffectCounter);
668
709
  return toForeignCallResult([toSingle(new Fr(isRevertible))]);
669
710
  }
670
711
 
@@ -692,7 +733,7 @@ export class RPCTranslator {
692
733
  foreignAnchorBlockHash: ForeignCallSingle,
693
734
  foreignNoteHash: ForeignCallSingle,
694
735
  ) {
695
- const blockHash = new BlockHash(fromSingle(foreignAnchorBlockHash));
736
+ const blockHash = blockHashFromSingle(foreignAnchorBlockHash);
696
737
  const noteHash = fromSingle(foreignNoteHash);
697
738
 
698
739
  const witness = await this.handlerAsUtility().getNoteHashMembershipWitness(blockHash, noteHash);
@@ -708,8 +749,8 @@ export class RPCTranslator {
708
749
  foreignAnchorBlockHash: ForeignCallSingle,
709
750
  foreignBlockHash: ForeignCallSingle,
710
751
  ) {
711
- const anchorBlockHash = new BlockHash(fromSingle(foreignAnchorBlockHash));
712
- const blockHash = new BlockHash(fromSingle(foreignBlockHash));
752
+ const anchorBlockHash = blockHashFromSingle(foreignAnchorBlockHash);
753
+ const blockHash = blockHashFromSingle(foreignBlockHash);
713
754
 
714
755
  const witness = await this.handlerAsUtility().getBlockHashMembershipWitness(anchorBlockHash, blockHash);
715
756
 
@@ -726,7 +767,7 @@ export class RPCTranslator {
726
767
  foreignBlockHash: ForeignCallSingle,
727
768
  foreignNullifier: ForeignCallSingle,
728
769
  ) {
729
- const blockHash = new BlockHash(fromSingle(foreignBlockHash));
770
+ const blockHash = blockHashFromSingle(foreignBlockHash);
730
771
  const nullifier = fromSingle(foreignNullifier);
731
772
 
732
773
  const witness = await this.handlerAsUtility().getLowNullifierMembershipWitness(blockHash, nullifier);
@@ -738,14 +779,25 @@ export class RPCTranslator {
738
779
  }
739
780
 
740
781
  // eslint-disable-next-line camelcase
741
- async aztec_utl_fetchTaggedLogs(foreignPendingTaggedLogArrayBaseSlot: ForeignCallSingle) {
782
+ async aztec_utl_getPendingTaggedLogs(
783
+ foreignPendingTaggedLogArrayBaseSlot: ForeignCallSingle,
784
+ foreignScope: ForeignCallSingle,
785
+ ) {
742
786
  const pendingTaggedLogArrayBaseSlot = fromSingle(foreignPendingTaggedLogArrayBaseSlot);
787
+ const scope = AztecAddress.fromField(fromSingle(foreignScope));
743
788
 
744
- await this.handlerAsUtility().fetchTaggedLogs(pendingTaggedLogArrayBaseSlot);
789
+ await this.handlerAsUtility().getPendingTaggedLogs(pendingTaggedLogArrayBaseSlot, scope);
745
790
 
746
791
  return toForeignCallResult([]);
747
792
  }
748
793
 
794
+ // eslint-disable-next-line camelcase
795
+ async aztec_utl_getPendingTaggedLogs_v2(foreignScope: ForeignCallSingle) {
796
+ const scope = AztecAddress.fromField(fromSingle(foreignScope));
797
+ const slot = await this.handlerAsUtility().getPendingTaggedLogsV2(scope);
798
+ return toForeignCallResult([toSingle(slot)]);
799
+ }
800
+
749
801
  // eslint-disable-next-line camelcase
750
802
  public async aztec_utl_validateAndStoreEnqueuedNotesAndEvents(
751
803
  foreignContractAddress: ForeignCallSingle,
@@ -753,12 +805,14 @@ export class RPCTranslator {
753
805
  foreignEventValidationRequestsArrayBaseSlot: ForeignCallSingle,
754
806
  foreignMaxNotePackedLen: ForeignCallSingle,
755
807
  foreignMaxEventSerializedLen: ForeignCallSingle,
808
+ foreignScope: ForeignCallSingle,
756
809
  ) {
757
810
  const contractAddress = AztecAddress.fromField(fromSingle(foreignContractAddress));
758
811
  const noteValidationRequestsArrayBaseSlot = fromSingle(foreignNoteValidationRequestsArrayBaseSlot);
759
812
  const eventValidationRequestsArrayBaseSlot = fromSingle(foreignEventValidationRequestsArrayBaseSlot);
760
813
  const maxNotePackedLen = fromSingle(foreignMaxNotePackedLen).toNumber();
761
814
  const maxEventSerializedLen = fromSingle(foreignMaxEventSerializedLen).toNumber();
815
+ const scope = AztecAddress.fromField(fromSingle(foreignScope));
762
816
 
763
817
  await this.handlerAsUtility().validateAndStoreEnqueuedNotesAndEvents(
764
818
  contractAddress,
@@ -766,75 +820,125 @@ export class RPCTranslator {
766
820
  eventValidationRequestsArrayBaseSlot,
767
821
  maxNotePackedLen,
768
822
  maxEventSerializedLen,
823
+ scope,
824
+ );
825
+
826
+ return toForeignCallResult([]);
827
+ }
828
+
829
+ // eslint-disable-next-line camelcase
830
+ public async aztec_utl_validateAndStoreEnqueuedNotesAndEvents_v2(
831
+ foreignNoteValidationRequestsArrayBaseSlot: ForeignCallSingle,
832
+ foreignEventValidationRequestsArrayBaseSlot: ForeignCallSingle,
833
+ foreignMaxNotePackedLen: ForeignCallSingle,
834
+ foreignMaxEventSerializedLen: ForeignCallSingle,
835
+ foreignScope: ForeignCallSingle,
836
+ ) {
837
+ const noteValidationRequestsArrayBaseSlot = fromSingle(foreignNoteValidationRequestsArrayBaseSlot);
838
+ const eventValidationRequestsArrayBaseSlot = fromSingle(foreignEventValidationRequestsArrayBaseSlot);
839
+ const maxNotePackedLen = fromSingle(foreignMaxNotePackedLen).toNumber();
840
+ const maxEventSerializedLen = fromSingle(foreignMaxEventSerializedLen).toNumber();
841
+ const scope = AztecAddress.fromField(fromSingle(foreignScope));
842
+
843
+ await this.handlerAsUtility().validateAndStoreEnqueuedNotesAndEventsV2(
844
+ noteValidationRequestsArrayBaseSlot,
845
+ eventValidationRequestsArrayBaseSlot,
846
+ maxNotePackedLen,
847
+ maxEventSerializedLen,
848
+ scope,
769
849
  );
770
850
 
771
851
  return toForeignCallResult([]);
772
852
  }
773
853
 
774
854
  // eslint-disable-next-line camelcase
775
- public async aztec_utl_bulkRetrieveLogs(
855
+ public async aztec_utl_getLogsByTag(
776
856
  foreignContractAddress: ForeignCallSingle,
777
857
  foreignLogRetrievalRequestsArrayBaseSlot: ForeignCallSingle,
778
858
  foreignLogRetrievalResponsesArrayBaseSlot: ForeignCallSingle,
859
+ foreignScope: ForeignCallSingle,
779
860
  ) {
780
861
  const contractAddress = AztecAddress.fromField(fromSingle(foreignContractAddress));
781
862
  const logRetrievalRequestsArrayBaseSlot = fromSingle(foreignLogRetrievalRequestsArrayBaseSlot);
782
863
  const logRetrievalResponsesArrayBaseSlot = fromSingle(foreignLogRetrievalResponsesArrayBaseSlot);
864
+ const scope = AztecAddress.fromField(fromSingle(foreignScope));
783
865
 
784
- await this.handlerAsUtility().bulkRetrieveLogs(
866
+ await this.handlerAsUtility().getLogsByTag(
785
867
  contractAddress,
786
868
  logRetrievalRequestsArrayBaseSlot,
787
869
  logRetrievalResponsesArrayBaseSlot,
870
+ scope,
788
871
  );
789
872
 
790
873
  return toForeignCallResult([]);
791
874
  }
792
875
 
793
876
  // eslint-disable-next-line camelcase
794
- public async aztec_utl_utilityResolveMessageContexts(
877
+ public async aztec_utl_getMessageContextsByTxHash(
795
878
  foreignContractAddress: ForeignCallSingle,
796
879
  foreignMessageContextRequestsArrayBaseSlot: ForeignCallSingle,
797
880
  foreignMessageContextResponsesArrayBaseSlot: ForeignCallSingle,
881
+ foreignScope: ForeignCallSingle,
798
882
  ) {
799
883
  const contractAddress = AztecAddress.fromField(fromSingle(foreignContractAddress));
800
884
  const messageContextRequestsArrayBaseSlot = fromSingle(foreignMessageContextRequestsArrayBaseSlot);
801
885
  const messageContextResponsesArrayBaseSlot = fromSingle(foreignMessageContextResponsesArrayBaseSlot);
886
+ const scope = AztecAddress.fromField(fromSingle(foreignScope));
802
887
 
803
- await this.handlerAsUtility().utilityResolveMessageContexts(
888
+ await this.handlerAsUtility().getMessageContextsByTxHash(
804
889
  contractAddress,
805
890
  messageContextRequestsArrayBaseSlot,
806
891
  messageContextResponsesArrayBaseSlot,
892
+ scope,
807
893
  );
808
894
 
809
895
  return toForeignCallResult([]);
810
896
  }
811
897
 
812
898
  // eslint-disable-next-line camelcase
813
- async aztec_utl_storeCapsule(
899
+ async aztec_utl_getLogsByTag_v2(foreignRequestArrayBaseSlot: ForeignCallSingle) {
900
+ const requestArrayBaseSlot = fromSingle(foreignRequestArrayBaseSlot);
901
+ const responseSlot = await this.handlerAsUtility().getLogsByTagV2(requestArrayBaseSlot);
902
+ return toForeignCallResult([toSingle(responseSlot)]);
903
+ }
904
+
905
+ // eslint-disable-next-line camelcase
906
+ async aztec_utl_getMessageContextsByTxHash_v2(foreignRequestArrayBaseSlot: ForeignCallSingle) {
907
+ const requestArrayBaseSlot = fromSingle(foreignRequestArrayBaseSlot);
908
+ const responseSlot = await this.handlerAsUtility().getMessageContextsByTxHashV2(requestArrayBaseSlot);
909
+ return toForeignCallResult([toSingle(responseSlot)]);
910
+ }
911
+
912
+ // eslint-disable-next-line camelcase
913
+ aztec_utl_setCapsule(
814
914
  foreignContractAddress: ForeignCallSingle,
815
915
  foreignSlot: ForeignCallSingle,
816
916
  foreignCapsule: ForeignCallArray,
917
+ foreignScope: ForeignCallSingle,
817
918
  ) {
818
919
  const contractAddress = AztecAddress.fromField(fromSingle(foreignContractAddress));
819
920
  const slot = fromSingle(foreignSlot);
820
921
  const capsule = fromArray(foreignCapsule);
922
+ const scope = AztecAddress.fromField(fromSingle(foreignScope));
821
923
 
822
- await this.handlerAsUtility().storeCapsule(contractAddress, slot, capsule);
924
+ this.handlerAsUtility().setCapsule(contractAddress, slot, capsule, scope);
823
925
 
824
926
  return toForeignCallResult([]);
825
927
  }
826
928
 
827
929
  // eslint-disable-next-line camelcase
828
- async aztec_utl_loadCapsule(
930
+ async aztec_utl_getCapsule(
829
931
  foreignContractAddress: ForeignCallSingle,
830
932
  foreignSlot: ForeignCallSingle,
831
933
  foreignTSize: ForeignCallSingle,
934
+ foreignScope: ForeignCallSingle,
832
935
  ) {
833
936
  const contractAddress = AztecAddress.fromField(fromSingle(foreignContractAddress));
834
937
  const slot = fromSingle(foreignSlot);
835
938
  const tSize = fromSingle(foreignTSize).toNumber();
939
+ const scope = AztecAddress.fromField(fromSingle(foreignScope));
836
940
 
837
- const values = await this.handlerAsUtility().loadCapsule(contractAddress, slot);
941
+ const values = await this.handlerAsUtility().getCapsule(contractAddress, slot, scope);
838
942
 
839
943
  // We are going to return a Noir Option struct to represent the possibility of null values. Options are a struct
840
944
  // with two fields: `some` (a boolean) and `value` (a field array in this case).
@@ -848,11 +952,16 @@ export class RPCTranslator {
848
952
  }
849
953
 
850
954
  // eslint-disable-next-line camelcase
851
- async aztec_utl_deleteCapsule(foreignContractAddress: ForeignCallSingle, foreignSlot: ForeignCallSingle) {
955
+ aztec_utl_deleteCapsule(
956
+ foreignContractAddress: ForeignCallSingle,
957
+ foreignSlot: ForeignCallSingle,
958
+ foreignScope: ForeignCallSingle,
959
+ ) {
852
960
  const contractAddress = AztecAddress.fromField(fromSingle(foreignContractAddress));
853
961
  const slot = fromSingle(foreignSlot);
962
+ const scope = AztecAddress.fromField(fromSingle(foreignScope));
854
963
 
855
- await this.handlerAsUtility().deleteCapsule(contractAddress, slot);
964
+ this.handlerAsUtility().deleteCapsule(contractAddress, slot, scope);
856
965
 
857
966
  return toForeignCallResult([]);
858
967
  }
@@ -863,14 +972,74 @@ export class RPCTranslator {
863
972
  foreignSrcSlot: ForeignCallSingle,
864
973
  foreignDstSlot: ForeignCallSingle,
865
974
  foreignNumEntries: ForeignCallSingle,
975
+ foreignScope: ForeignCallSingle,
866
976
  ) {
867
977
  const contractAddress = AztecAddress.fromField(fromSingle(foreignContractAddress));
868
978
  const srcSlot = fromSingle(foreignSrcSlot);
869
979
  const dstSlot = fromSingle(foreignDstSlot);
870
980
  const numEntries = fromSingle(foreignNumEntries).toNumber();
981
+ const scope = AztecAddress.fromField(fromSingle(foreignScope));
982
+
983
+ await this.handlerAsUtility().copyCapsule(contractAddress, srcSlot, dstSlot, numEntries, scope);
984
+
985
+ return toForeignCallResult([]);
986
+ }
987
+
988
+ // eslint-disable-next-line camelcase
989
+ aztec_utl_pushEphemeral(foreignSlot: ForeignCallSingle, foreignElements: ForeignCallArray) {
990
+ const slot = fromSingle(foreignSlot);
991
+ const elements = fromArray(foreignElements);
992
+ const newLen = this.handlerAsUtility().pushEphemeral(slot, elements);
993
+ return toForeignCallResult([toSingle(new Fr(newLen))]);
994
+ }
995
+
996
+ // eslint-disable-next-line camelcase
997
+ aztec_utl_popEphemeral(foreignSlot: ForeignCallSingle) {
998
+ const slot = fromSingle(foreignSlot);
999
+ const element = this.handlerAsUtility().popEphemeral(slot);
1000
+ return toForeignCallResult([toArray(element)]);
1001
+ }
1002
+
1003
+ // eslint-disable-next-line camelcase
1004
+ aztec_utl_getEphemeral(foreignSlot: ForeignCallSingle, foreignIndex: ForeignCallSingle) {
1005
+ const slot = fromSingle(foreignSlot);
1006
+ const index = fromSingle(foreignIndex).toNumber();
1007
+ const element = this.handlerAsUtility().getEphemeral(slot, index);
1008
+ return toForeignCallResult([toArray(element)]);
1009
+ }
1010
+
1011
+ // eslint-disable-next-line camelcase
1012
+ aztec_utl_setEphemeral(
1013
+ foreignSlot: ForeignCallSingle,
1014
+ foreignIndex: ForeignCallSingle,
1015
+ foreignElements: ForeignCallArray,
1016
+ ) {
1017
+ const slot = fromSingle(foreignSlot);
1018
+ const index = fromSingle(foreignIndex).toNumber();
1019
+ const elements = fromArray(foreignElements);
1020
+ this.handlerAsUtility().setEphemeral(slot, index, elements);
1021
+ return toForeignCallResult([]);
1022
+ }
871
1023
 
872
- await this.handlerAsUtility().copyCapsule(contractAddress, srcSlot, dstSlot, numEntries);
1024
+ // eslint-disable-next-line camelcase
1025
+ aztec_utl_getEphemeralLen(foreignSlot: ForeignCallSingle) {
1026
+ const slot = fromSingle(foreignSlot);
1027
+ const len = this.handlerAsUtility().getEphemeralLen(slot);
1028
+ return toForeignCallResult([toSingle(new Fr(len))]);
1029
+ }
1030
+
1031
+ // eslint-disable-next-line camelcase
1032
+ aztec_utl_removeEphemeral(foreignSlot: ForeignCallSingle, foreignIndex: ForeignCallSingle) {
1033
+ const slot = fromSingle(foreignSlot);
1034
+ const index = fromSingle(foreignIndex).toNumber();
1035
+ this.handlerAsUtility().removeEphemeral(slot, index);
1036
+ return toForeignCallResult([]);
1037
+ }
873
1038
 
1039
+ // eslint-disable-next-line camelcase
1040
+ aztec_utl_clearEphemeral(foreignSlot: ForeignCallSingle) {
1041
+ const slot = fromSingle(foreignSlot);
1042
+ this.handlerAsUtility().clearEphemeral(slot);
874
1043
  return toForeignCallResult([]);
875
1044
  }
876
1045
 
@@ -879,7 +1048,7 @@ export class RPCTranslator {
879
1048
  // to implement this function here. Isn't there a way to programmatically identify that this is missing, given the
880
1049
  // existence of a txe_oracle method?
881
1050
  // eslint-disable-next-line camelcase
882
- async aztec_utl_tryAes128Decrypt(
1051
+ async aztec_utl_decryptAes128(
883
1052
  foreignCiphertextBVecStorage: ForeignCallArray,
884
1053
  foreignCiphertextLength: ForeignCallSingle,
885
1054
  foreignIv: ForeignCallArray,
@@ -891,7 +1060,7 @@ export class RPCTranslator {
891
1060
 
892
1061
  // Noir Option<BoundedVec> is encoded as [is_some: Field, storage: Field[], length: Field].
893
1062
  try {
894
- const plaintextBuffer = await this.handlerAsUtility().aes128Decrypt(ciphertext, iv, symKey);
1063
+ const plaintextBuffer = await this.handlerAsUtility().decryptAes128(ciphertext, iv, symKey);
895
1064
  const [storage, length] = arrayToBoundedVec(
896
1065
  bufferToU8Array(plaintextBuffer),
897
1066
  foreignCiphertextBVecStorage.length,
@@ -909,6 +1078,7 @@ export class RPCTranslator {
909
1078
  foreignEphPKField0: ForeignCallSingle,
910
1079
  foreignEphPKField1: ForeignCallSingle,
911
1080
  foreignEphPKField2: ForeignCallSingle,
1081
+ foreignContractAddress: ForeignCallSingle,
912
1082
  ) {
913
1083
  const address = AztecAddress.fromField(fromSingle(foreignAddress));
914
1084
  const ephPK = Point.fromFields([
@@ -916,14 +1086,15 @@ export class RPCTranslator {
916
1086
  fromSingle(foreignEphPKField1),
917
1087
  fromSingle(foreignEphPKField2),
918
1088
  ]);
1089
+ const contractAddress = AztecAddress.fromField(fromSingle(foreignContractAddress));
919
1090
 
920
- const secret = await this.handlerAsUtility().getSharedSecret(address, ephPK);
1091
+ const secret = await this.handlerAsUtility().getSharedSecret(address, ephPK, contractAddress);
921
1092
 
922
- return toForeignCallResult(secret.toFields().map(toSingle));
1093
+ return toForeignCallResult([toSingle(secret)]);
923
1094
  }
924
1095
 
925
1096
  // eslint-disable-next-line camelcase
926
- aztec_utl_invalidateContractSyncCache(
1097
+ aztec_utl_setContractSyncCacheInvalid(
927
1098
  foreignContractAddress: ForeignCallSingle,
928
1099
  foreignScopes: ForeignCallArray,
929
1100
  foreignScopeCount: ForeignCallSingle,
@@ -934,14 +1105,19 @@ export class RPCTranslator {
934
1105
  .slice(0, count)
935
1106
  .map(f => new AztecAddress(f));
936
1107
 
937
- this.handlerAsUtility().invalidateContractSyncCache(contractAddress, scopes);
1108
+ this.handlerAsUtility().setContractSyncCacheInvalid(contractAddress, scopes);
938
1109
 
939
1110
  return Promise.resolve(toForeignCallResult([]));
940
1111
  }
941
1112
 
942
1113
  // eslint-disable-next-line camelcase
943
- aztec_utl_emitOffchainEffect(_foreignData: ForeignCallArray) {
944
- throw new Error('Offchain effects are not yet supported in the TestEnvironment');
1114
+ aztec_utl_emitOffchainEffect(foreignData: ForeignCallArray) {
1115
+ // Record the raw payload against the currently-executing top-level call. The Noir side
1116
+ // (via `env.offchain_messages()`) is responsible for decoding the protocol-reserved prefix
1117
+ // (`OFFCHAIN_MESSAGE_IDENTIFIER`, recipient) and turning each payload into an `OffchainMessage` struct suitable
1118
+ // for `offchain_receive`.
1119
+ this.stateHandler.recordOffchainEffect(fromArray(foreignData));
1120
+ return Promise.resolve(toForeignCallResult([]));
945
1121
  }
946
1122
 
947
1123
  // AVM opcodes
@@ -1150,18 +1326,38 @@ export class RPCTranslator {
1150
1326
  const argsHash = fromSingle(foreignArgsHash);
1151
1327
  const isStaticCall = fromSingle(foreignIsStaticCall).toBool();
1152
1328
 
1153
- const returnValues = await this.handlerAsTxe().privateCallNewFlow(
1154
- from,
1155
- targetContractAddress,
1156
- functionSelector,
1157
- args,
1158
- argsHash,
1159
- isStaticCall,
1160
- this.stateHandler.getCurrentJob(),
1161
- );
1329
+ const returnValues = await this.stateHandler.withTopLevelCallTracking(async () => {
1330
+ const { returnValues, offchainEffects } = await this.handlerAsTxe().privateCallNewFlow(
1331
+ from,
1332
+ targetContractAddress,
1333
+ functionSelector,
1334
+ args,
1335
+ argsHash,
1336
+ isStaticCall,
1337
+ this.stateHandler.getCurrentJob(),
1338
+ );
1339
+
1340
+ // Private execution collects offchain effects inside PXE's PrivateExecutionOracle rather than
1341
+ // round-tripping them through `aztec_utl_emitOffchainEffect`, so the session buffer is empty
1342
+ // at this point. Drain the effects from the execution tree into the session buffer so the
1343
+ // next `env.offchain_messages()` call in the test sees them.
1344
+ for (const data of offchainEffects) {
1345
+ this.stateHandler.recordOffchainEffect(data);
1346
+ }
1347
+
1348
+ // TODO(F-335): Avoid doing the following call here.
1349
+ await this.stateHandler.cycleJob();
1350
+
1351
+ if (isStaticCall) {
1352
+ // Static calls revert their checkpoint and mine no block, so there is no tx hash to tag
1353
+ // offchain effects with. Querying `getLastTxEffects()` here would return an unrelated
1354
+ // predecessor tx.
1355
+ return { result: returnValues };
1356
+ }
1357
+ const { txHash } = await this.handlerAsTxe().getLastTxEffects();
1358
+ return { result: returnValues, txHash: txHash.hash };
1359
+ });
1162
1360
 
1163
- // TODO(F-335): Avoid doing the following call here.
1164
- await this.stateHandler.cycleJob();
1165
1361
  return toForeignCallResult([toArray(returnValues)]);
1166
1362
  }
1167
1363
 
@@ -1175,15 +1371,20 @@ export class RPCTranslator {
1175
1371
  const functionSelector = FunctionSelector.fromField(fromSingle(foreignFunctionSelector));
1176
1372
  const args = fromArray(foreignArgs);
1177
1373
 
1178
- const returnValues = await this.handlerAsTxe().executeUtilityFunction(
1179
- targetContractAddress,
1180
- functionSelector,
1181
- args,
1182
- this.stateHandler.getCurrentJob(),
1183
- );
1374
+ const returnValues = await this.stateHandler.withTopLevelCallTracking(async () => {
1375
+ const returnValues = await this.handlerAsTxe().executeUtilityFunction(
1376
+ targetContractAddress,
1377
+ functionSelector,
1378
+ args,
1379
+ this.stateHandler.getCurrentJob(),
1380
+ );
1381
+
1382
+ // TODO(F-335): Avoid doing the following call here.
1383
+ await this.stateHandler.cycleJob();
1384
+
1385
+ return { result: returnValues };
1386
+ });
1184
1387
 
1185
- // TODO(F-335): Avoid doing the following call here.
1186
- await this.stateHandler.cycleJob();
1187
1388
  return toForeignCallResult([toArray(returnValues)]);
1188
1389
  }
1189
1390
 
@@ -1199,10 +1400,20 @@ export class RPCTranslator {
1199
1400
  const calldata = fromArray(foreignCalldata);
1200
1401
  const isStaticCall = fromSingle(foreignIsStaticCall).toBool();
1201
1402
 
1202
- const returnValues = await this.handlerAsTxe().publicCallNewFlow(from, address, calldata, isStaticCall);
1403
+ const returnValues = await this.stateHandler.withTopLevelCallTracking(async () => {
1404
+ const returnValues = await this.handlerAsTxe().publicCallNewFlow(from, address, calldata, isStaticCall);
1405
+
1406
+ // TODO(F-335): Avoid doing the following call here.
1407
+ await this.stateHandler.cycleJob();
1408
+
1409
+ if (isStaticCall) {
1410
+ // See equivalent branch in `aztec_txe_privateCallNewFlow`.
1411
+ return { result: returnValues };
1412
+ }
1413
+ const { txHash } = await this.handlerAsTxe().getLastTxEffects();
1414
+ return { result: returnValues, txHash: txHash.hash };
1415
+ });
1203
1416
 
1204
- // TODO(F-335): Avoid doing the following call here.
1205
- await this.stateHandler.cycleJob();
1206
1417
  return toForeignCallResult([toArray(returnValues)]);
1207
1418
  }
1208
1419
 
@@ -76,6 +76,7 @@ export class TXEArchiver extends ArchiverDataSourceBase {
76
76
  proven: tipId,
77
77
  finalized: tipId,
78
78
  checkpointed: tipId,
79
+ proposedCheckpoint: tipId,
79
80
  };
80
81
  }
81
82