@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.
@@ -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 trees = this.getTrees();
180
- const stateReference = await trees.getStateReference(false);
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(innerNoteHash: Fr) {
230
+ async avmOpcodeEmitNoteHash(noteHash: Fr) {
219
231
  const db = this.trees.asLatest();
220
- const noteHash = siloNoteHash(this.contractAddress, innerNoteHash);
221
- await db.appendLeaves(MerkleTreeId.NOTE_HASH_TREE, [noteHash]);
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, innerNoteHashes: Fr[]) {
257
+ async addNoteHashes(contractAddress: AztecAddress, noteHashes: Fr[]) {
246
258
  const db = this.trees.asLatest();
247
- const siloedNoteHashes = innerNoteHashes.map(innerNoteHash => siloNoteHash(contractAddress, innerNoteHash));
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(_blockNumber: number, _treeId: MerkleTreeId, _leafValue: Fr): Promise<Fr[] | undefined> {
290
- throw new Error('Method not implemented.');
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 committedDb = new MerkleTreeSnapshotOperationsFacade(this.trees, blockNumber);
304
- const index = await committedDb.findLeafIndex(MerkleTreeId.NULLIFIER_TREE, nullifier.toBuffer());
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 = committedDb.getLeafPreimage(MerkleTreeId.NULLIFIER_TREE, index);
310
- const siblingPathPromise = committedDb.getSiblingPath<typeof NULLIFIER_TREE_HEIGHT>(
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(_blockNumber: number): Promise<Header | undefined> {
350
- throw new Error('Method not implemented.');
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[], innerNoteHash: Fr, counter: number) {
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
- innerNoteHash,
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, innerNoteHash: Fr, _counter: number) {
424
- this.noteCache.nullifyNote(this.contractAddress, innerNullifier, innerNoteHash);
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, _counter: number): void {
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, _counter: number): void {
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, _counter: number): void {
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
- ): Promise<PrivateCallStackItem> {
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
- this.sideEffectsCounter = publicInputs.endSideEffectCounter.toNumber();
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 callStackItem;
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 += executionResult.endSideEffectCounter.toNumber();
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
- ): Promise<PublicCallRequest> {
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 += executionResult.endSideEffectCounter.toNumber();
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
- ): Promise<PublicCallRequest> {
823
+ ) {
873
824
  // Definitely not right, in that the teardown should always be last.
874
825
  // But useful for executing flows.
875
- return this.enqueuePublicFunctionCall(
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
- _counter: number,
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 noteCache = new ExecutionNoteCache();
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
- innerNoteHash: ForeignCallSingle,
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(innerNoteHash),
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
- innerNoteHash: ForeignCallSingle,
461
+ noteHash: ForeignCallSingle,
461
462
  counter: ForeignCallSingle,
462
463
  ) {
463
464
  await this.typedOracle.notifyNullifiedNote(
464
465
  fromSingle(innerNullifier),
465
- fromSingle(innerNoteHash),
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(innerNoteHash: ForeignCallSingle) {
515
- await (this.typedOracle as TXE).avmOpcodeEmitNoteHash(fromSingle(innerNoteHash));
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.toFields())]);
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
- const publicCallRequest = await this.typedOracle.enqueuePublicFunctionCall(
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
- const fields = [
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
- const publicTeardownCallRequest = await this.typedOracle.setPublicTeardownFunctionCall(
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
- const fields = [
720
- publicTeardownCallRequest.contractAddress.toField(),
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
  }