@aztec/txe 0.0.1-commit.6c91f13 → 0.0.1-commit.6d63667d

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 (52) hide show
  1. package/dest/oracle/interfaces.d.ts +3 -3
  2. package/dest/oracle/interfaces.d.ts.map +1 -1
  3. package/dest/oracle/txe_oracle_public_context.d.ts +3 -3
  4. package/dest/oracle/txe_oracle_public_context.d.ts.map +1 -1
  5. package/dest/oracle/txe_oracle_public_context.js +6 -6
  6. package/dest/oracle/txe_oracle_top_level_context.d.ts +3 -2
  7. package/dest/oracle/txe_oracle_top_level_context.d.ts.map +1 -1
  8. package/dest/oracle/txe_oracle_top_level_context.js +39 -24
  9. package/dest/rpc_translator.d.ts +17 -11
  10. package/dest/rpc_translator.d.ts.map +1 -1
  11. package/dest/rpc_translator.js +73 -48
  12. package/dest/state_machine/archiver.d.ts +20 -67
  13. package/dest/state_machine/archiver.d.ts.map +1 -1
  14. package/dest/state_machine/archiver.js +59 -178
  15. package/dest/state_machine/dummy_p2p_client.d.ts +8 -7
  16. package/dest/state_machine/dummy_p2p_client.d.ts.map +1 -1
  17. package/dest/state_machine/dummy_p2p_client.js +13 -10
  18. package/dest/state_machine/global_variable_builder.d.ts +2 -2
  19. package/dest/state_machine/global_variable_builder.d.ts.map +1 -1
  20. package/dest/state_machine/global_variable_builder.js +1 -1
  21. package/dest/state_machine/index.d.ts +5 -5
  22. package/dest/state_machine/index.d.ts.map +1 -1
  23. package/dest/state_machine/index.js +34 -11
  24. package/dest/state_machine/mock_epoch_cache.d.ts +7 -6
  25. package/dest/state_machine/mock_epoch_cache.d.ts.map +1 -1
  26. package/dest/state_machine/mock_epoch_cache.js +10 -7
  27. package/dest/state_machine/synchronizer.d.ts +3 -3
  28. package/dest/state_machine/synchronizer.d.ts.map +1 -1
  29. package/dest/txe_session.d.ts +5 -3
  30. package/dest/txe_session.d.ts.map +1 -1
  31. package/dest/txe_session.js +34 -15
  32. package/dest/util/encoding.d.ts +17 -17
  33. package/dest/utils/block_creation.d.ts +4 -4
  34. package/dest/utils/block_creation.d.ts.map +1 -1
  35. package/dest/utils/block_creation.js +18 -5
  36. package/dest/utils/tx_effect_creation.d.ts +2 -3
  37. package/dest/utils/tx_effect_creation.d.ts.map +1 -1
  38. package/dest/utils/tx_effect_creation.js +3 -6
  39. package/package.json +16 -16
  40. package/src/oracle/interfaces.ts +2 -2
  41. package/src/oracle/txe_oracle_public_context.ts +6 -8
  42. package/src/oracle/txe_oracle_top_level_context.ts +75 -28
  43. package/src/rpc_translator.ts +76 -50
  44. package/src/state_machine/archiver.ts +54 -220
  45. package/src/state_machine/dummy_p2p_client.ts +18 -13
  46. package/src/state_machine/global_variable_builder.ts +1 -1
  47. package/src/state_machine/index.ts +48 -11
  48. package/src/state_machine/mock_epoch_cache.ts +10 -11
  49. package/src/state_machine/synchronizer.ts +2 -2
  50. package/src/txe_session.ts +43 -21
  51. package/src/utils/block_creation.ts +19 -16
  52. package/src/utils/tx_effect_creation.ts +3 -11
@@ -106,6 +106,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
106
106
  private senderAddressBookStore: SenderAddressBookStore,
107
107
  private capsuleStore: CapsuleStore,
108
108
  private privateEventStore: PrivateEventStore,
109
+ private jobId: string,
109
110
  private nextBlockTimestamp: bigint,
110
111
  private version: Fr,
111
112
  private chainId: Fr,
@@ -156,7 +157,8 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
156
157
  }
157
158
 
158
159
  async txeGetLastTxEffects() {
159
- const block = await this.stateMachine.archiver.getL2Block('latest');
160
+ const latestBlockNumber = await this.stateMachine.archiver.getBlockNumber();
161
+ const block = await this.stateMachine.archiver.getBlock(latestBlockNumber);
160
162
 
161
163
  if (block!.body.txEffects.length != 1) {
162
164
  // Note that calls like env.mine() will result in blocks with no transactions, hitting this
@@ -294,12 +296,24 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
294
296
  throw new Error(message);
295
297
  }
296
298
 
299
+ // When `from` is the zero address (used when creating a new contract account for example),
300
+ // we disable scope filtering by setting effectiveScopes to undefined. This allows these operations
301
+ // to proceed without requiring keys registered for the zero address.
302
+ const effectiveScopes = from.isZero() ? undefined : [from];
303
+
297
304
  // Sync notes before executing private function to discover notes from previous transactions
298
305
  const utilityExecutor = async (call: FunctionCall) => {
299
- await this.executeUtilityCall(call);
306
+ await this.executeUtilityCall(call, effectiveScopes);
300
307
  };
301
308
 
302
- await this.contractStore.syncPrivateState(targetContractAddress, functionSelector, utilityExecutor);
309
+ const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
310
+ await this.stateMachine.contractSyncService.ensureContractSynced(
311
+ targetContractAddress,
312
+ functionSelector,
313
+ utilityExecutor,
314
+ blockHeader,
315
+ this.jobId,
316
+ );
303
317
 
304
318
  const blockNumber = await this.txeGetNextBlockNumber();
305
319
 
@@ -311,10 +325,13 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
311
325
 
312
326
  const txContext = new TxContext(this.chainId, this.version, gasSettings);
313
327
 
314
- const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
315
-
316
328
  const protocolNullifier = await computeProtocolNullifier(getSingleTxBlockRequestHash(blockNumber));
317
329
  const noteCache = new ExecutionNoteCache(protocolNullifier);
330
+ // In production, the account contract sets the min revertible counter before calling the app function.
331
+ // Since TXE bypasses the account contract, we simulate this by setting minRevertibleSideEffectCounter to 1,
332
+ // marking all side effects as revertible.
333
+ const minRevertibleSideEffectCounter = 1;
334
+ await noteCache.setMinRevertibleSideEffectCounter(minRevertibleSideEffectCounter);
318
335
  const taggingIndexCache = new ExecutionTaggingIndexCache();
319
336
 
320
337
  const simulator = new WASMSimulator();
@@ -338,16 +355,17 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
338
355
  this.keyStore,
339
356
  this.addressStore,
340
357
  this.stateMachine.node,
341
- this.stateMachine.anchorBlockStore,
342
358
  this.senderTaggingStore,
343
359
  this.recipientTaggingStore,
344
360
  this.senderAddressBookStore,
345
361
  this.capsuleStore,
346
362
  this.privateEventStore,
347
- 0,
348
- 1,
363
+ this.stateMachine.contractSyncService,
364
+ this.jobId,
365
+ 0, // totalPublicArgsCount
366
+ minRevertibleSideEffectCounter, // (start) sideEffectCounter
349
367
  undefined, // log
350
- undefined, // scopes
368
+ effectiveScopes, // scopes
351
369
  /**
352
370
  * In TXE, the typical transaction entrypoint is skipped, so we need to simulate the actions that such a
353
371
  * contract would perform, including setting senderForTags.
@@ -381,19 +399,21 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
381
399
  }),
382
400
  );
383
401
 
384
- // TXE's top level context does not track side effect counters, and as such, minRevertibleSideEffectCounter is always 0.
385
- // This has the unfortunate consequence of always producing revertible nullifiers, which means we
386
- // must set the firstNullifierHint to Fr.ZERO so the txRequestHash is always used as nonce generator
387
- result = new PrivateExecutionResult(executionResult, Fr.ZERO, publicFunctionsCalldata);
402
+ noteCache.finish();
403
+ const nonceGenerator = noteCache.getNonceGenerator();
404
+ result = new PrivateExecutionResult(executionResult, nonceGenerator, publicFunctionsCalldata);
388
405
  } catch (err) {
389
406
  throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during private execution'));
390
407
  }
391
408
 
392
- // According to the protocol rules, the nonce generator for the note hashes
393
- // can either be the first nullifier in the tx or the hash of the initial tx request
394
- // if there are none.
395
- const nonceGenerator = result.firstNullifier.equals(Fr.ZERO) ? protocolNullifier : result.firstNullifier;
396
- const { publicInputs } = await generateSimulatedProvingResult(result, nonceGenerator, this.contractStore);
409
+ // According to the protocol rules, there must be at least one nullifier in the tx. The first nullifier is used as
410
+ // the nonce generator for the note hashes.
411
+ // We pass the non-zero minRevertibleSideEffectCounter to make sure the side effects are split correctly.
412
+ const { publicInputs } = await generateSimulatedProvingResult(
413
+ result,
414
+ this.contractStore,
415
+ minRevertibleSideEffectCounter,
416
+ );
397
417
 
398
418
  const globals = makeGlobalVariables();
399
419
  globals.blockNumber = blockNumber;
@@ -404,7 +424,11 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
404
424
 
405
425
  const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
406
426
 
407
- const contractsDB = new PublicContractsDB(new TXEPublicContractDataSource(blockNumber, this.contractStore));
427
+ const bindings = this.logger.getBindings();
428
+ const contractsDB = new PublicContractsDB(
429
+ new TXEPublicContractDataSource(blockNumber, this.contractStore),
430
+ bindings,
431
+ );
408
432
  const guardedMerkleTrees = new GuardedMerkleTreeOperations(forkedWorldTrees);
409
433
  const config = PublicSimulatorConfig.from({
410
434
  skipFeeEnforcement: true,
@@ -417,8 +441,10 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
417
441
  globals,
418
442
  guardedMerkleTrees,
419
443
  contractsDB,
420
- new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config),
444
+ new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config, bindings),
421
445
  new TestDateProvider(),
446
+ undefined,
447
+ createLogger('simulator:public-processor', bindings),
422
448
  );
423
449
 
424
450
  const tx = await Tx.create({
@@ -515,7 +541,11 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
515
541
 
516
542
  const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
517
543
 
518
- const contractsDB = new PublicContractsDB(new TXEPublicContractDataSource(blockNumber, this.contractStore));
544
+ const bindings2 = this.logger.getBindings();
545
+ const contractsDB = new PublicContractsDB(
546
+ new TXEPublicContractDataSource(blockNumber, this.contractStore),
547
+ bindings2,
548
+ );
519
549
  const guardedMerkleTrees = new GuardedMerkleTreeOperations(forkedWorldTrees);
520
550
  const config = PublicSimulatorConfig.from({
521
551
  skipFeeEnforcement: true,
@@ -524,8 +554,16 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
524
554
  collectStatistics: false,
525
555
  collectCallMetadata: true,
526
556
  });
527
- const simulator = new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config);
528
- const processor = new PublicProcessor(globals, guardedMerkleTrees, contractsDB, simulator, new TestDateProvider());
557
+ const simulator = new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config, bindings2);
558
+ const processor = new PublicProcessor(
559
+ globals,
560
+ guardedMerkleTrees,
561
+ contractsDB,
562
+ simulator,
563
+ new TestDateProvider(),
564
+ undefined,
565
+ createLogger('simulator:public-processor', bindings2),
566
+ );
529
567
 
530
568
  // We're simulating a scenario in which private execution immediately enqueues a public call and halts. The private
531
569
  // kernel init would in this case inject a nullifier with the transaction request hash as a non-revertible
@@ -635,9 +673,16 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
635
673
  }
636
674
 
637
675
  // Sync notes before executing utility function to discover notes from previous transactions
638
- await this.contractStore.syncPrivateState(targetContractAddress, functionSelector, async call => {
639
- await this.executeUtilityCall(call);
640
- });
676
+ const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
677
+ await this.stateMachine.contractSyncService.ensureContractSynced(
678
+ targetContractAddress,
679
+ functionSelector,
680
+ async call => {
681
+ await this.executeUtilityCall(call);
682
+ },
683
+ blockHeader,
684
+ this.jobId,
685
+ );
641
686
 
642
687
  const call = new FunctionCall(
643
688
  artifact.name,
@@ -653,7 +698,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
653
698
  return this.executeUtilityCall(call);
654
699
  }
655
700
 
656
- private async executeUtilityCall(call: FunctionCall): Promise<Fr[]> {
701
+ private async executeUtilityCall(call: FunctionCall, scopes?: AztecAddress[]): Promise<Fr[]> {
657
702
  const entryPointArtifact = await this.contractStore.getFunctionArtifactWithDebugMetadata(call.to, call.selector);
658
703
  if (entryPointArtifact.functionType !== FunctionType.UTILITY) {
659
704
  throw new Error(`Cannot run ${entryPointArtifact.functionType} function as utility`);
@@ -676,11 +721,13 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
676
721
  this.keyStore,
677
722
  this.addressStore,
678
723
  this.stateMachine.node,
679
- this.stateMachine.anchorBlockStore,
680
724
  this.recipientTaggingStore,
681
725
  this.senderAddressBookStore,
682
726
  this.capsuleStore,
683
727
  this.privateEventStore,
728
+ this.jobId,
729
+ undefined, // log
730
+ scopes, // scopes - used to filter notes by account
684
731
  );
685
732
  const acirExecutionResult = await new WASMSimulator()
686
733
  .executeUserCircuit(toACVMWitness(0, call.args), entryPointArtifact, new Oracle(oracle).toACIRCallback())
@@ -6,11 +6,11 @@ import {
6
6
  type IMiscOracle,
7
7
  type IPrivateExecutionOracle,
8
8
  type IUtilityExecutionOracle,
9
- packAsRetrievedNote,
9
+ packAsHintedNote,
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 { MerkleTreeId } from '@aztec/stdlib/trees';
13
+ import { BlockHash } from '@aztec/stdlib/block';
14
14
 
15
15
  import type { IAvmExecutionOracle, ITxeExecutionOracle } from './oracle/interfaces.js';
16
16
  import type { TXESessionStateHandler } from './txe_session.js';
@@ -346,34 +346,34 @@ export class RPCTranslator {
346
346
  }
347
347
 
348
348
  async utilityStorageRead(
349
+ foreignBlockHash: ForeignCallSingle,
349
350
  foreignContractAddress: ForeignCallSingle,
350
351
  foreignStartStorageSlot: ForeignCallSingle,
351
- foreignBlockNumber: ForeignCallSingle,
352
352
  foreignNumberOfElements: ForeignCallSingle,
353
353
  ) {
354
+ const blockHash = new BlockHash(fromSingle(foreignBlockHash));
354
355
  const contractAddress = addressFromSingle(foreignContractAddress);
355
356
  const startStorageSlot = fromSingle(foreignStartStorageSlot);
356
- const blockNumber = BlockNumber(fromSingle(foreignBlockNumber).toNumber());
357
357
  const numberOfElements = fromSingle(foreignNumberOfElements).toNumber();
358
358
 
359
359
  const values = await this.handlerAsUtility().utilityStorageRead(
360
+ blockHash,
360
361
  contractAddress,
361
362
  startStorageSlot,
362
- blockNumber,
363
363
  numberOfElements,
364
364
  );
365
365
 
366
366
  return toForeignCallResult([toArray(values)]);
367
367
  }
368
368
 
369
- async utilityGetPublicDataWitness(foreignBlockNumber: ForeignCallSingle, foreignLeafSlot: ForeignCallSingle) {
370
- const blockNumber = BlockNumber(fromSingle(foreignBlockNumber).toNumber());
369
+ async utilityGetPublicDataWitness(foreignBlockHash: ForeignCallSingle, foreignLeafSlot: ForeignCallSingle) {
370
+ const blockHash = new BlockHash(fromSingle(foreignBlockHash));
371
371
  const leafSlot = fromSingle(foreignLeafSlot);
372
372
 
373
- const witness = await this.handlerAsUtility().utilityGetPublicDataWitness(blockNumber, leafSlot);
373
+ const witness = await this.handlerAsUtility().utilityGetPublicDataWitness(blockHash, leafSlot);
374
374
 
375
375
  if (!witness) {
376
- throw new Error(`Public data witness not found for slot ${leafSlot} at block ${blockNumber}.`);
376
+ throw new Error(`Public data witness not found for slot ${leafSlot} at block ${blockHash.toString()}.`);
377
377
  }
378
378
  return toForeignCallResult(witness.toNoirRepresentation());
379
379
  }
@@ -396,7 +396,7 @@ export class RPCTranslator {
396
396
  foreignOffset: ForeignCallSingle,
397
397
  foreignStatus: ForeignCallSingle,
398
398
  foreignMaxNotes: ForeignCallSingle,
399
- foreignPackedRetrievedNoteLength: ForeignCallSingle,
399
+ foreignPackedHintedNoteLength: ForeignCallSingle,
400
400
  ) {
401
401
  // Parse Option<AztecAddress>: ownerIsSome is 0 for None, 1 for Some
402
402
  const owner = fromSingle(foreignOwnerIsSome).toBool()
@@ -417,7 +417,7 @@ export class RPCTranslator {
417
417
  const offset = fromSingle(foreignOffset).toNumber();
418
418
  const status = fromSingle(foreignStatus).toNumber();
419
419
  const maxNotes = fromSingle(foreignMaxNotes).toNumber();
420
- const packedRetrievedNoteLength = fromSingle(foreignPackedRetrievedNoteLength).toNumber();
420
+ const packedHintedNoteLength = fromSingle(foreignPackedHintedNoteLength).toNumber();
421
421
 
422
422
  const noteDatas = await this.handlerAsUtility().utilityGetNotes(
423
423
  owner,
@@ -438,13 +438,13 @@ export class RPCTranslator {
438
438
  );
439
439
 
440
440
  const returnDataAsArrayOfArrays = noteDatas.map(noteData =>
441
- packAsRetrievedNote({
441
+ packAsHintedNote({
442
442
  contractAddress: noteData.contractAddress,
443
443
  owner: noteData.owner,
444
444
  randomness: noteData.randomness,
445
445
  storageSlot: noteData.storageSlot,
446
446
  noteNonce: noteData.noteNonce,
447
- index: noteData.index,
447
+ isPending: noteData.isPending,
448
448
  note: noteData.note,
449
449
  }),
450
450
  );
@@ -456,11 +456,7 @@ export class RPCTranslator {
456
456
 
457
457
  // At last we convert the array of arrays to a bounded vec of arrays
458
458
  return toForeignCallResult(
459
- arrayOfArraysToBoundedVecOfArrays(
460
- returnDataAsArrayOfForeignCallSingleArrays,
461
- maxNotes,
462
- packedRetrievedNoteLength,
463
- ),
459
+ arrayOfArraysToBoundedVecOfArrays(returnDataAsArrayOfForeignCallSingleArrays, maxNotes, packedHintedNoteLength),
464
460
  );
465
461
  }
466
462
 
@@ -516,6 +512,15 @@ export class RPCTranslator {
516
512
  return toForeignCallResult([]);
517
513
  }
518
514
 
515
+ async privateIsNullifierPending(foreignInnerNullifier: ForeignCallSingle, foreignContractAddress: ForeignCallSingle) {
516
+ const innerNullifier = fromSingle(foreignInnerNullifier);
517
+ const contractAddress = addressFromSingle(foreignContractAddress);
518
+
519
+ const isPending = await this.handlerAsPrivate().privateIsNullifierPending(innerNullifier, contractAddress);
520
+
521
+ return toForeignCallResult([toSingle(new Fr(isPending))]);
522
+ }
523
+
519
524
  async utilityCheckNullifierExists(foreignInnerNullifier: ForeignCallSingle) {
520
525
  const innerNullifier = fromSingle(foreignInnerNullifier);
521
526
 
@@ -540,12 +545,23 @@ export class RPCTranslator {
540
545
  );
541
546
  }
542
547
 
543
- async utilityGetPublicKeysAndPartialAddress(foreignAddress: ForeignCallSingle) {
548
+ async utilityTryGetPublicKeysAndPartialAddress(foreignAddress: ForeignCallSingle) {
544
549
  const address = addressFromSingle(foreignAddress);
545
550
 
546
- const { publicKeys, partialAddress } = await this.handlerAsUtility().utilityGetPublicKeysAndPartialAddress(address);
551
+ const result = await this.handlerAsUtility().utilityTryGetPublicKeysAndPartialAddress(address);
547
552
 
548
- return toForeignCallResult([toArray([...publicKeys.toFields(), partialAddress])]);
553
+ // We are going to return a Noir Option struct to represent the possibility of null values. Options are a struct
554
+ // with two fields: `some` (a boolean) and `value` (a field array in this case).
555
+ if (result === undefined) {
556
+ // No data was found so we set `some` to 0 and pad `value` with zeros get the correct return size.
557
+ return toForeignCallResult([toSingle(new Fr(0)), toArray(Array(13).fill(new Fr(0)))]);
558
+ } else {
559
+ // Data was found so we set `some` to 1 and return it along with `value`.
560
+ return toForeignCallResult([
561
+ toSingle(new Fr(1)),
562
+ toArray([...result.publicKeys.toFields(), result.partialAddress]),
563
+ ]);
564
+ }
549
565
  }
550
566
 
551
567
  async utilityGetKeyValidationRequest(foreignPkMHash: ForeignCallSingle) {
@@ -568,17 +584,14 @@ export class RPCTranslator {
568
584
  );
569
585
  }
570
586
 
571
- async utilityGetNullifierMembershipWitness(
572
- foreignBlockNumber: ForeignCallSingle,
573
- foreignNullifier: ForeignCallSingle,
574
- ) {
575
- const blockNumber = BlockNumber(fromSingle(foreignBlockNumber).toNumber());
587
+ async utilityGetNullifierMembershipWitness(foreignBlockHash: ForeignCallSingle, foreignNullifier: ForeignCallSingle) {
588
+ const blockHash = new BlockHash(fromSingle(foreignBlockHash));
576
589
  const nullifier = fromSingle(foreignNullifier);
577
590
 
578
- const witness = await this.handlerAsUtility().utilityGetNullifierMembershipWitness(blockNumber, nullifier);
591
+ const witness = await this.handlerAsUtility().utilityGetNullifierMembershipWitness(blockHash, nullifier);
579
592
 
580
593
  if (!witness) {
581
- throw new Error(`Nullifier membership witness not found at block ${blockNumber}.`);
594
+ throw new Error(`Nullifier membership witness not found at block ${blockHash}.`);
582
595
  }
583
596
  return toForeignCallResult(witness.toNoirRepresentation());
584
597
  }
@@ -639,36 +652,49 @@ export class RPCTranslator {
639
652
  return toForeignCallResult(header.toFields().map(toSingle));
640
653
  }
641
654
 
642
- async utilityGetMembershipWitness(
643
- foreignBlockNumber: ForeignCallSingle,
644
- foreignTreeId: ForeignCallSingle,
645
- foreignLeafValue: ForeignCallSingle,
655
+ async utilityGetNoteHashMembershipWitness(
656
+ foreignAnchorBlockHash: ForeignCallSingle,
657
+ foreignNoteHash: ForeignCallSingle,
646
658
  ) {
647
- const blockNumber = BlockNumber(fromSingle(foreignBlockNumber).toNumber());
648
- const treeId = fromSingle(foreignTreeId).toNumber();
649
- const leafValue = fromSingle(foreignLeafValue);
659
+ const blockHash = new BlockHash(fromSingle(foreignAnchorBlockHash));
660
+ const noteHash = fromSingle(foreignNoteHash);
661
+
662
+ const witness = await this.handlerAsUtility().utilityGetNoteHashMembershipWitness(blockHash, noteHash);
663
+
664
+ if (!witness) {
665
+ throw new Error(`Note hash ${noteHash} not found in the note hash tree at block ${blockHash.toString()}.`);
666
+ }
667
+ return toForeignCallResult(witness.toNoirRepresentation());
668
+ }
669
+
670
+ async utilityGetBlockHashMembershipWitness(
671
+ foreignAnchorBlockHash: ForeignCallSingle,
672
+ foreignBlockHash: ForeignCallSingle,
673
+ ) {
674
+ const anchorBlockHash = new BlockHash(fromSingle(foreignAnchorBlockHash));
675
+ const blockHash = new BlockHash(fromSingle(foreignBlockHash));
650
676
 
651
- const witness = await this.handlerAsUtility().utilityGetMembershipWitness(blockNumber, treeId, leafValue);
677
+ const witness = await this.handlerAsUtility().utilityGetBlockHashMembershipWitness(anchorBlockHash, blockHash);
652
678
 
653
679
  if (!witness) {
654
680
  throw new Error(
655
- `Membership witness in tree ${MerkleTreeId[treeId]} not found for value ${leafValue} at block ${blockNumber}.`,
681
+ `Block hash ${blockHash.toString()} not found in the archive tree at anchor block ${anchorBlockHash.toString()}.`,
656
682
  );
657
683
  }
658
- return toForeignCallResult([toSingle(witness[0]), toArray(witness.slice(1))]);
684
+ return toForeignCallResult(witness.toNoirRepresentation());
659
685
  }
660
686
 
661
687
  async utilityGetLowNullifierMembershipWitness(
662
- foreignBlockNumber: ForeignCallSingle,
688
+ foreignBlockHash: ForeignCallSingle,
663
689
  foreignNullifier: ForeignCallSingle,
664
690
  ) {
665
- const blockNumber = BlockNumber(fromSingle(foreignBlockNumber).toNumber());
691
+ const blockHash = new BlockHash(fromSingle(foreignBlockHash));
666
692
  const nullifier = fromSingle(foreignNullifier);
667
693
 
668
- const witness = await this.handlerAsUtility().utilityGetLowNullifierMembershipWitness(blockNumber, nullifier);
694
+ const witness = await this.handlerAsUtility().utilityGetLowNullifierMembershipWitness(blockHash, nullifier);
669
695
 
670
696
  if (!witness) {
671
- throw new Error(`Low nullifier witness not found for nullifier ${nullifier} at block ${blockNumber}.`);
697
+ throw new Error(`Low nullifier witness not found for nullifier ${nullifier} at block ${blockHash}.`);
672
698
  }
673
699
  return toForeignCallResult(witness.toNoirRepresentation());
674
700
  }
@@ -681,7 +707,7 @@ export class RPCTranslator {
681
707
  return toForeignCallResult([]);
682
708
  }
683
709
 
684
- public async utilityValidateEnqueuedNotesAndEvents(
710
+ public async utilityValidateAndStoreEnqueuedNotesAndEvents(
685
711
  foreignContractAddress: ForeignCallSingle,
686
712
  foreignNoteValidationRequestsArrayBaseSlot: ForeignCallSingle,
687
713
  foreignEventValidationRequestsArrayBaseSlot: ForeignCallSingle,
@@ -690,7 +716,7 @@ export class RPCTranslator {
690
716
  const noteValidationRequestsArrayBaseSlot = fromSingle(foreignNoteValidationRequestsArrayBaseSlot);
691
717
  const eventValidationRequestsArrayBaseSlot = fromSingle(foreignEventValidationRequestsArrayBaseSlot);
692
718
 
693
- await this.handlerAsUtility().utilityValidateEnqueuedNotesAndEvents(
719
+ await this.handlerAsUtility().utilityValidateAndStoreEnqueuedNotesAndEvents(
694
720
  contractAddress,
695
721
  noteValidationRequestsArrayBaseSlot,
696
722
  eventValidationRequestsArrayBaseSlot,
@@ -828,10 +854,11 @@ export class RPCTranslator {
828
854
  return toForeignCallResult([]);
829
855
  }
830
856
 
831
- async avmOpcodeStorageRead(foreignSlot: ForeignCallSingle) {
857
+ async avmOpcodeStorageRead(foreignSlot: ForeignCallSingle, foreignContractAddress: ForeignCallSingle) {
832
858
  const slot = fromSingle(foreignSlot);
859
+ const contractAddress = AztecAddress.fromField(fromSingle(foreignContractAddress));
833
860
 
834
- const value = (await this.handlerAsAvm().avmOpcodeStorageRead(slot)).value;
861
+ const value = (await this.handlerAsAvm().avmOpcodeStorageRead(slot, contractAddress)).value;
835
862
 
836
863
  return toForeignCallResult([toSingle(new Fr(value))]);
837
864
  }
@@ -903,11 +930,10 @@ export class RPCTranslator {
903
930
  return toForeignCallResult([]);
904
931
  }
905
932
 
906
- async avmOpcodeNullifierExists(foreignInnerNullifier: ForeignCallSingle, foreignTargetAddress: ForeignCallSingle) {
907
- const innerNullifier = fromSingle(foreignInnerNullifier);
908
- const targetAddress = AztecAddress.fromField(fromSingle(foreignTargetAddress));
933
+ async avmOpcodeNullifierExists(foreignSiloedNullifier: ForeignCallSingle) {
934
+ const siloedNullifier = fromSingle(foreignSiloedNullifier);
909
935
 
910
- const exists = await this.handlerAsAvm().avmOpcodeNullifierExists(innerNullifier, targetAddress);
936
+ const exists = await this.handlerAsAvm().avmOpcodeNullifierExists(siloedNullifier);
911
937
 
912
938
  return toForeignCallResult([toSingle(new Fr(exists))]);
913
939
  }