@aztec/txe 5.0.0-rc.1 → 5.0.0-rc.2

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 (107) hide show
  1. package/dest/AuthRegistry-URXCCPYF.js +3 -0
  2. package/dest/AuthRegistry-URXCCPYF.js.map +7 -0
  3. package/dest/{ContractClassRegistry-EHVIHGEK.js → ContractClassRegistry-5RDBM6TC.js} +1 -1
  4. package/dest/{ContractClassRegistry-EHVIHGEK.js.map → ContractClassRegistry-5RDBM6TC.js.map} +2 -2
  5. package/dest/{ContractInstanceRegistry-DWZDXHRG.js → ContractInstanceRegistry-GCR4G4D7.js} +1 -1
  6. package/dest/{ContractInstanceRegistry-DWZDXHRG.js.map → ContractInstanceRegistry-GCR4G4D7.js.map} +1 -1
  7. package/dest/{FeeJuice-MI32ZO7B.js → FeeJuice-O3KOSZO5.js} +1 -1
  8. package/dest/{FeeJuice-MI32ZO7B.js.map → FeeJuice-O3KOSZO5.js.map} +1 -1
  9. package/dest/HandshakeRegistry-TXSMHMNY.js +3 -0
  10. package/dest/HandshakeRegistry-TXSMHMNY.js.map +7 -0
  11. package/dest/MultiCallEntrypoint-P4FSRXAD.js +3 -0
  12. package/dest/MultiCallEntrypoint-P4FSRXAD.js.map +7 -0
  13. package/dest/SchnorrAccount-AQZX7ROU.js +3 -0
  14. package/dest/SchnorrAccount-AQZX7ROU.js.map +7 -0
  15. package/dest/SchnorrInitializerlessAccount-KMX2H3J6.js +3 -0
  16. package/dest/SchnorrInitializerlessAccount-KMX2H3J6.js.map +7 -0
  17. package/dest/bin/index.js +1 -1
  18. package/dest/bin/oracle_test_server.js +2 -2
  19. package/dest/{chunk-UPW55EJX.js → chunk-I6DL4FT2.js} +2 -2
  20. package/dest/chunk-IAO54JS2.js +266 -0
  21. package/dest/{chunk-5U25VAFR.js.map → chunk-IAO54JS2.js.map} +4 -4
  22. package/dest/constants.d.ts +1 -1
  23. package/dest/constants.d.ts.map +1 -1
  24. package/dest/constants.js +1 -1
  25. package/dest/metafile.json +7241 -6706
  26. package/dest/oracle/interfaces.d.ts +10 -5
  27. package/dest/oracle/interfaces.d.ts.map +1 -1
  28. package/dest/oracle/test-resolver/default_fixtures.d.ts +9 -0
  29. package/dest/oracle/test-resolver/default_fixtures.d.ts.map +1 -0
  30. package/dest/oracle/test-resolver/default_fixtures.js +164 -0
  31. package/dest/oracle/test-resolver/index.d.ts +1 -1
  32. package/dest/oracle/test-resolver/index.d.ts.map +1 -1
  33. package/dest/oracle/test-resolver/index.js +1 -2
  34. package/dest/oracle/test-resolver/resolver.d.ts +22 -8
  35. package/dest/oracle/test-resolver/resolver.d.ts.map +1 -1
  36. package/dest/oracle/test-resolver/resolver.js +62 -32
  37. package/dest/oracle/txe_oracle_public_context.d.ts +4 -4
  38. package/dest/oracle/txe_oracle_public_context.d.ts.map +1 -1
  39. package/dest/oracle/txe_oracle_registry.d.ts +156 -3
  40. package/dest/oracle/txe_oracle_registry.d.ts.map +1 -1
  41. package/dest/oracle/txe_oracle_registry.js +179 -26
  42. package/dest/oracle/txe_oracle_top_level_context.d.ts +20 -8
  43. package/dest/oracle/txe_oracle_top_level_context.d.ts.map +1 -1
  44. package/dest/oracle/txe_oracle_top_level_context.js +72 -30
  45. package/dest/oracle/txe_oracle_version.d.ts +2 -2
  46. package/dest/oracle/txe_oracle_version.js +2 -2
  47. package/dest/rpc_translator.d.ts +10 -2
  48. package/dest/rpc_translator.d.ts.map +1 -1
  49. package/dest/rpc_translator.js +69 -5
  50. package/dest/server.bundle.js +1 -1
  51. package/dest/state_machine/archiver.d.ts +1 -1
  52. package/dest/state_machine/archiver.d.ts.map +1 -1
  53. package/dest/state_machine/archiver.js +1 -2
  54. package/dest/state_machine/dummy_p2p_client.d.ts +3 -2
  55. package/dest/state_machine/dummy_p2p_client.d.ts.map +1 -1
  56. package/dest/state_machine/dummy_p2p_client.js +3 -0
  57. package/dest/state_machine/global_variable_builder.d.ts +3 -4
  58. package/dest/state_machine/global_variable_builder.d.ts.map +1 -1
  59. package/dest/state_machine/global_variable_builder.js +0 -3
  60. package/dest/state_machine/index.d.ts +6 -5
  61. package/dest/state_machine/index.d.ts.map +1 -1
  62. package/dest/state_machine/index.js +35 -10
  63. package/dest/state_machine/synchronizer.d.ts +3 -2
  64. package/dest/state_machine/synchronizer.d.ts.map +1 -1
  65. package/dest/state_machine/synchronizer.js +3 -2
  66. package/dest/txe_session.d.ts +8 -6
  67. package/dest/txe_session.d.ts.map +1 -1
  68. package/dest/txe_session.js +53 -27
  69. package/dest/utils/block_creation.d.ts +2 -2
  70. package/dest/utils/block_creation.d.ts.map +1 -1
  71. package/dest/utils/block_creation.js +2 -2
  72. package/dest/worker.bundle.js +1 -1
  73. package/package.json +17 -17
  74. package/src/bin/oracle_test_server.ts +2 -2
  75. package/src/constants.ts +1 -1
  76. package/src/oracle/interfaces.ts +9 -3
  77. package/src/oracle/test-resolver/default_fixtures.ts +226 -0
  78. package/src/oracle/test-resolver/index.ts +1 -2
  79. package/src/oracle/test-resolver/resolver.ts +74 -41
  80. package/src/oracle/txe_oracle_public_context.ts +3 -3
  81. package/src/oracle/txe_oracle_registry.ts +106 -13
  82. package/src/oracle/txe_oracle_top_level_context.ts +76 -30
  83. package/src/oracle/txe_oracle_version.ts +2 -2
  84. package/src/rpc_translator.ts +93 -5
  85. package/src/state_machine/archiver.ts +0 -1
  86. package/src/state_machine/dummy_p2p_client.ts +5 -0
  87. package/src/state_machine/global_variable_builder.ts +2 -16
  88. package/src/state_machine/index.ts +31 -29
  89. package/src/state_machine/synchronizer.ts +3 -2
  90. package/src/txe_session.ts +62 -23
  91. package/src/utils/block_creation.ts +2 -1
  92. package/dest/AuthRegistry-CPGFQR26.js +0 -3
  93. package/dest/AuthRegistry-CPGFQR26.js.map +0 -7
  94. package/dest/HandshakeRegistry-3KSP3ITH.js +0 -3
  95. package/dest/HandshakeRegistry-3KSP3ITH.js.map +0 -7
  96. package/dest/MultiCallEntrypoint-IU7HYFYE.js +0 -3
  97. package/dest/MultiCallEntrypoint-IU7HYFYE.js.map +0 -7
  98. package/dest/SchnorrAccount-6TUE7JX4.js +0 -3
  99. package/dest/SchnorrAccount-6TUE7JX4.js.map +0 -7
  100. package/dest/SchnorrInitializerlessAccount-S3DU2DJK.js +0 -3
  101. package/dest/SchnorrInitializerlessAccount-S3DU2DJK.js.map +0 -7
  102. package/dest/chunk-5U25VAFR.js +0 -265
  103. package/dest/oracle/test-resolver/fixtures.d.ts +0 -43
  104. package/dest/oracle/test-resolver/fixtures.d.ts.map +0 -1
  105. package/dest/oracle/test-resolver/fixtures.js +0 -39
  106. package/src/oracle/test-resolver/fixtures.ts +0 -84
  107. /package/dest/{chunk-UPW55EJX.js.map → chunk-I6DL4FT2.js.map} +0 -0
@@ -3,7 +3,7 @@ import { Fr } from '@aztec/foundation/curves/bn254';
3
3
  import { createLogger } from '@aztec/foundation/log';
4
4
  import { KeyStore } from '@aztec/key-store';
5
5
  import { openEphemeralStore } from '@aztec/kv-store/lmdb-v2';
6
- import { AddressStore, AnchorBlockStore, CapsuleService, CapsuleStore, JobCoordinator, NoteService, NoteStore, PrivateEventStore, RecipientTaggingStore, SenderAddressBookStore, SenderTaggingStore } from '@aztec/pxe/server';
6
+ import { AddressStore, AnchorBlockStore, CapsuleService, CapsuleStore, FactService, FactStore, JobCoordinator, NoteService, NoteStore, PrivateEventStore, RecipientTaggingStore, SenderTaggingStore, TaggingSecretSourcesStore, composeHooks } from '@aztec/pxe/server';
7
7
  import { ExecutionNoteCache, ExecutionTaggingIndexCache, HashedValuesCache, TransientArrayService, UtilityExecutionOracle, buildACIRCallback } from '@aztec/pxe/simulator';
8
8
  import { ExecutionError, WASMSimulator, createSimulationError, extractCallStack, resolveAssertionMessageFromError, toACVMWitness } from '@aztec/simulator/client';
9
9
  import { STANDARD_AUTH_REGISTRY_ADDRESS } from '@aztec/standard-contracts/auth-registry/constants';
@@ -47,8 +47,9 @@ function emptyLastCallState() {
47
47
  accountStore;
48
48
  senderTaggingStore;
49
49
  recipientTaggingStore;
50
- senderAddressBookStore;
50
+ taggingSecretSourcesStore;
51
51
  capsuleStore;
52
+ factStore;
52
53
  privateEventStore;
53
54
  jobCoordinator;
54
55
  currentJobId;
@@ -60,10 +61,11 @@ function emptyLastCallState() {
60
61
  packageName;
61
62
  state;
62
63
  authwits;
64
+ taggingSecretStrategy;
63
65
  lastCallInfo;
64
66
  txeOracleVersion;
65
67
  disposed;
66
- constructor(logger, sessionStore, stateMachine, oracleHandler, contractStore, noteStore, keyStore, addressStore, accountStore, senderTaggingStore, recipientTaggingStore, senderAddressBookStore, capsuleStore, privateEventStore, jobCoordinator, currentJobId, chainId, version, nextBlockTimestamp, artifactResolver, rootPath, packageName){
68
+ constructor(logger, sessionStore, stateMachine, oracleHandler, contractStore, noteStore, keyStore, addressStore, accountStore, senderTaggingStore, recipientTaggingStore, taggingSecretSourcesStore, capsuleStore, factStore, privateEventStore, jobCoordinator, currentJobId, chainId, version, nextBlockTimestamp, artifactResolver, rootPath, packageName){
67
69
  this.logger = logger;
68
70
  this.sessionStore = sessionStore;
69
71
  this.stateMachine = stateMachine;
@@ -75,8 +77,9 @@ function emptyLastCallState() {
75
77
  this.accountStore = accountStore;
76
78
  this.senderTaggingStore = senderTaggingStore;
77
79
  this.recipientTaggingStore = recipientTaggingStore;
78
- this.senderAddressBookStore = senderAddressBookStore;
80
+ this.taggingSecretSourcesStore = taggingSecretSourcesStore;
79
81
  this.capsuleStore = capsuleStore;
82
+ this.factStore = factStore;
80
83
  this.privateEventStore = privateEventStore;
81
84
  this.jobCoordinator = jobCoordinator;
82
85
  this.currentJobId = currentJobId;
@@ -90,6 +93,7 @@ function emptyLastCallState() {
90
93
  name: 'TOP_LEVEL'
91
94
  };
92
95
  this.authwits = new Map();
96
+ this.taggingSecretStrategy = undefined;
93
97
  this.lastCallInfo = emptyLastCallState();
94
98
  this.disposed = false;
95
99
  }
@@ -123,13 +127,15 @@ function emptyLastCallState() {
123
127
  const noteStore = new NoteStore(store);
124
128
  const senderTaggingStore = new SenderTaggingStore(store);
125
129
  const recipientTaggingStore = new RecipientTaggingStore(store);
126
- const senderAddressBookStore = new SenderAddressBookStore(store);
130
+ const taggingSecretSourcesStore = new TaggingSecretSourcesStore(store);
127
131
  const capsuleStore = new CapsuleStore(store);
132
+ const factStore = new FactStore(store);
128
133
  const keyStore = new KeyStore(store);
129
134
  const accountStore = new TXEAccountStore(store);
130
135
  const jobCoordinator = new JobCoordinator(store);
131
136
  jobCoordinator.registerStores([
132
137
  capsuleStore,
138
+ factStore,
133
139
  senderTaggingStore,
134
140
  recipientTaggingStore,
135
141
  privateEventStore,
@@ -143,11 +149,11 @@ function emptyLastCallState() {
143
149
  const chainId = new Fr(await stateMachine.node.getChainId());
144
150
  const initialJobId = jobCoordinator.beginJob();
145
151
  const logger = createLogger('txe:session');
146
- const topLevelOracleHandler = new TXEOracleTopLevelContext(stateMachine, contractStore, noteStore, keyStore, addressStore, accountStore, senderTaggingStore, recipientTaggingStore, senderAddressBookStore, capsuleStore, privateEventStore, nextBlockTimestamp, version, chainId, new Map(), artifactResolver, rootPath, packageName);
152
+ const topLevelOracleHandler = new TXEOracleTopLevelContext(stateMachine, contractStore, noteStore, keyStore, addressStore, accountStore, senderTaggingStore, recipientTaggingStore, taggingSecretSourcesStore, capsuleStore, factStore, privateEventStore, nextBlockTimestamp, version, chainId, new Map(), undefined, artifactResolver, rootPath, packageName);
147
153
  await topLevelOracleHandler.mineDeploymentNullifiers([
148
154
  STANDARD_AUTH_REGISTRY_ADDRESS
149
155
  ]);
150
- return new TXESession(logger, store, stateMachine, topLevelOracleHandler, contractStore, noteStore, keyStore, addressStore, accountStore, senderTaggingStore, recipientTaggingStore, senderAddressBookStore, capsuleStore, privateEventStore, jobCoordinator, initialJobId, version, chainId, nextBlockTimestamp, artifactResolver, rootPath, packageName);
156
+ return new TXESession(logger, store, stateMachine, topLevelOracleHandler, contractStore, noteStore, keyStore, addressStore, accountStore, senderTaggingStore, recipientTaggingStore, taggingSecretSourcesStore, capsuleStore, factStore, privateEventStore, jobCoordinator, initialJobId, version, chainId, nextBlockTimestamp, artifactResolver, rootPath, packageName);
151
157
  }
152
158
  /**
153
159
  * Processes an oracle function invoked by the Noir test associated to this session.
@@ -252,10 +258,10 @@ function emptyLastCallState() {
252
258
  };
253
259
  });
254
260
  }
255
- async executeUtilityFunction(targetContractAddress, functionSelector, args, authorizedUtilityCallTargets) {
261
+ async executeUtilityFunction(from, targetContractAddress, functionSelector, args, authorizedUtilityCallTargets) {
256
262
  const handler = this.handlerAsTxe();
257
263
  return await this.withTopLevelCallTracking(async ()=>{
258
- const returnValues = await handler.executeUtilityFunction(targetContractAddress, functionSelector, args, this.currentJobId, authorizedUtilityCallTargets);
264
+ const returnValues = await handler.executeUtilityFunction(from?.value, targetContractAddress, functionSelector, args, this.currentJobId, authorizedUtilityCallTargets);
259
265
  await this.cycleJob();
260
266
  return {
261
267
  result: returnValues
@@ -332,7 +338,7 @@ function emptyLastCallState() {
332
338
  }
333
339
  // Commit all staged stores from the job that was just completed, then begin a new job
334
340
  await this.cycleJob();
335
- this.oracleHandler = new TXEOracleTopLevelContext(this.stateMachine, this.contractStore, this.noteStore, this.keyStore, this.addressStore, this.accountStore, this.senderTaggingStore, this.recipientTaggingStore, this.senderAddressBookStore, this.capsuleStore, this.privateEventStore, this.nextBlockTimestamp, this.version, this.chainId, this.authwits, this.artifactResolver, this.rootPath, this.packageName);
341
+ this.oracleHandler = new TXEOracleTopLevelContext(this.stateMachine, this.contractStore, this.noteStore, this.keyStore, this.addressStore, this.accountStore, this.senderTaggingStore, this.recipientTaggingStore, this.taggingSecretSourcesStore, this.capsuleStore, this.factStore, this.privateEventStore, this.nextBlockTimestamp, this.version, this.chainId, this.authwits, this.taggingSecretStrategy, this.artifactResolver, this.rootPath, this.packageName);
336
342
  this.state = {
337
343
  name: 'TOP_LEVEL'
338
344
  };
@@ -361,6 +367,7 @@ function emptyLastCallState() {
361
367
  const taggingIndexCache = new ExecutionTaggingIndexCache();
362
368
  const utilityExecutor = this.utilityExecutorForContractSync(anchorBlock);
363
369
  const transientArrayService = new TransientArrayService();
370
+ const taggingSecretStrategy = this.taggingSecretStrategy;
364
371
  this.oracleHandler = new TXEPrivateExecutionOracle({
365
372
  argsHash: Fr.ZERO,
366
373
  txContext: new TxContext(this.chainId, this.version, gasSettings),
@@ -379,15 +386,19 @@ function emptyLastCallState() {
379
386
  aztecNode: this.stateMachine.node,
380
387
  senderTaggingStore: this.senderTaggingStore,
381
388
  recipientTaggingStore: this.recipientTaggingStore,
382
- senderAddressBookStore: this.senderAddressBookStore,
389
+ taggingSecretSourcesStore: this.taggingSecretSourcesStore,
383
390
  capsuleService: new CapsuleService(this.capsuleStore, await this.keyStore.getAccounts()),
391
+ factService: new FactService(this.factStore, await this.keyStore.getAccounts()),
384
392
  privateEventStore: this.privateEventStore,
385
393
  contractSyncService: this.stateMachine.contractSyncService,
386
394
  l2TipsStore: this.stateMachine.l2TipsProvider,
387
395
  jobId: this.currentJobId,
388
396
  scopes: await this.keyStore.getAccounts(),
389
- messageContextService: this.stateMachine.messageContextService,
397
+ txResolver: this.stateMachine.txResolver,
390
398
  simulator: new WASMSimulator(),
399
+ hooks: composeHooks({
400
+ resolveTaggingSecretStrategy: taggingSecretStrategy ? ()=>Promise.resolve(taggingSecretStrategy) : undefined
401
+ }),
391
402
  transientArrayService
392
403
  });
393
404
  // We store the note and tagging index caches fed into the PrivateExecutionOracle (along with some other auxiliary
@@ -440,7 +451,13 @@ function emptyLastCallState() {
440
451
  // TODO(#12553): make the synchronizer sync here instead and remove this
441
452
  await new NoteService(this.noteStore, this.stateMachine.node, anchorBlockHeader, this.currentJobId).syncNoteNullifiers(contractAddress, await this.keyStore.getAccounts());
442
453
  this.oracleHandler = new UtilityExecutionOracle({
443
- contractAddress,
454
+ callContext: CallContext.from({
455
+ msgSender: AztecAddress.NULL_MSG_SENDER,
456
+ contractAddress,
457
+ // No specific function is being executed in this inlined utility context, hence the empty selector.
458
+ functionSelector: FunctionSelector.empty(),
459
+ isStaticCall: true
460
+ }),
444
461
  authWitnesses: [],
445
462
  capsules: [],
446
463
  anchorBlockHeader,
@@ -450,10 +467,11 @@ function emptyLastCallState() {
450
467
  addressStore: this.addressStore,
451
468
  aztecNode: this.stateMachine.node,
452
469
  recipientTaggingStore: this.recipientTaggingStore,
453
- senderAddressBookStore: this.senderAddressBookStore,
470
+ taggingSecretSourcesStore: this.taggingSecretSourcesStore,
454
471
  capsuleService: new CapsuleService(this.capsuleStore, await this.keyStore.getAccounts()),
472
+ factService: new FactService(this.factStore, await this.keyStore.getAccounts()),
455
473
  privateEventStore: this.privateEventStore,
456
- messageContextService: this.stateMachine.messageContextService,
474
+ txResolver: this.stateMachine.txResolver,
457
475
  contractSyncService: this.stateMachine.contractSyncService,
458
476
  l2TipsStore: this.stateMachine.l2TipsProvider,
459
477
  jobId: this.currentJobId,
@@ -475,15 +493,17 @@ function emptyLastCallState() {
475
493
  throw new Error(`Expected to be in state 'TOP_LEVEL', but got '${this.state.name}' instead`);
476
494
  }
477
495
  // Note that while all public and private contexts do is build a single block that we then process when exiting
478
- // those, the top level context performs a large number of actions not captured in the following 'close' call. Among
479
- // others, it will create empty blocks (via `advanceBlocksBy` and `deploy`), create blocks with transactions via
480
- // `privateCallNewFlow` and `publicCallNewFlow`, add accounts to PXE via `addAccount`, etc. This is a
481
- // slight inconsistency in the working model of this class, but is not too bad.
482
- // TODO: it's quite unfortunate that we need to capture the authwits created to later pass them again when the top
483
- // level context is re-created. This is because authwits create a temporary utility context that'd otherwise reset
484
- // the authwits if not persisted, so we'd not be able to pass more than one per execution.
485
- // Ideally authwits would be passed alongside a contract call instead of pre-seeded.
486
- [this.nextBlockTimestamp, this.authwits] = this.oracleHandler.close();
496
+ // them, the top level context does most of its work as it goes: it creates empty blocks (via `advanceBlocksBy`
497
+ // and `deploy`), creates blocks with transactions (via `privateCallNewFlow` and `publicCallNewFlow`), adds
498
+ // accounts to PXE (via `addAccount`), etc. This is a slight inconsistency in the working model of this class, but
499
+ // is not too bad. The `close` call below therefore only hands back the session-scoped values that a test
500
+ // sets directly at the top level, outside any contract execution (e.g. via `advanceTimestampBy`,
501
+ // `addAuthWitness`, `setTaggingSecretStrategy`). The oracle handler is discarded on every state transition,
502
+ // so the session must seed these values into the contexts it creates later.
503
+ // TODO: persisting authwits this way is quite unfortunate: they create a temporary utility context that would
504
+ // otherwise reset them, so we'd not be able to pass more than one per execution. Ideally authwits would be passed
505
+ // alongside a contract call instead of pre-seeded.
506
+ [this.nextBlockTimestamp, this.authwits, this.taggingSecretStrategy] = this.oracleHandler.close();
487
507
  }
488
508
  async exitPrivateState() {
489
509
  if (this.state.name != 'PRIVATE') {
@@ -529,7 +549,12 @@ function emptyLastCallState() {
529
549
  try {
530
550
  const simulator = new WASMSimulator();
531
551
  const oracle = new UtilityExecutionOracle({
532
- contractAddress: call.to,
552
+ callContext: CallContext.from({
553
+ msgSender: AztecAddress.NULL_MSG_SENDER,
554
+ contractAddress: call.to,
555
+ functionSelector: call.selector,
556
+ isStaticCall: true
557
+ }),
533
558
  authWitnesses: [],
534
559
  capsules: [],
535
560
  anchorBlockHeader: anchorBlock,
@@ -539,10 +564,11 @@ function emptyLastCallState() {
539
564
  addressStore: this.addressStore,
540
565
  aztecNode: this.stateMachine.node,
541
566
  recipientTaggingStore: this.recipientTaggingStore,
542
- senderAddressBookStore: this.senderAddressBookStore,
567
+ taggingSecretSourcesStore: this.taggingSecretSourcesStore,
543
568
  capsuleService: new CapsuleService(this.capsuleStore, scopes),
569
+ factService: new FactService(this.factStore, scopes),
544
570
  privateEventStore: this.privateEventStore,
545
- messageContextService: this.stateMachine.messageContextService,
571
+ txResolver: this.stateMachine.txResolver,
546
572
  contractSyncService: this.stateMachine.contractSyncService,
547
573
  l2TipsStore: this.stateMachine.l2TipsProvider,
548
574
  jobId: this.currentJobId,
@@ -9,7 +9,7 @@ import { BlockHeader, GlobalVariables, TxEffect } from '@aztec/stdlib/tx';
9
9
  * @returns The transaction request hash.
10
10
  */
11
11
  export declare function getSingleTxBlockRequestHash(blockNumber: BlockNumber): Fr;
12
- export declare function insertTxEffectIntoWorldTrees(txEffect: TxEffect, worldTrees: MerkleTreeWriteOperations): Promise<void>;
12
+ export declare function insertTxEffectIntoWorldTrees(txEffect: TxEffect, worldTrees: MerkleTreeWriteOperations, l1ToL2Messages?: Fr[]): Promise<void>;
13
13
  export declare function makeTXEBlockHeader(worldTrees: MerkleTreeWriteOperations, globalVariables: GlobalVariables): Promise<BlockHeader>;
14
14
  /**
15
15
  * Creates an L2Block with proper archive chaining.
@@ -25,4 +25,4 @@ export declare function makeTXEBlockHeader(worldTrees: MerkleTreeWriteOperations
25
25
  * @returns The created L2Block with proper archive chaining
26
26
  */
27
27
  export declare function makeTXEBlock(worldTrees: MerkleTreeWriteOperations, globalVariables: GlobalVariables, txEffects: TxEffect[]): Promise<L2Block>;
28
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmxvY2tfY3JlYXRpb24uZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlscy9ibG9ja19jcmVhdGlvbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFNQSxPQUFPLEVBQUUsV0FBVyxFQUEyQyxNQUFNLGlDQUFpQyxDQUFDO0FBRXZHLE9BQU8sRUFBRSxFQUFFLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUNwRCxPQUFPLEVBQVEsT0FBTyxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDcEQsT0FBTyxFQUF3QyxLQUFLLHlCQUF5QixFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDM0csT0FBTyxFQUFFLFdBQVcsRUFBRSxlQUFlLEVBQUUsUUFBUSxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFFMUU7Ozs7R0FJRztBQUNILHdCQUFnQiwyQkFBMkIsQ0FBQyxXQUFXLEVBQUUsV0FBVyxHQUFHLEVBQUUsQ0FFeEU7QUFFRCx3QkFBc0IsNEJBQTRCLENBQ2hELFFBQVEsRUFBRSxRQUFRLEVBQ2xCLFVBQVUsRUFBRSx5QkFBeUIsR0FDcEMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQWtCZjtBQUVELHdCQUFzQixrQkFBa0IsQ0FDdEMsVUFBVSxFQUFFLHlCQUF5QixFQUNyQyxlQUFlLEVBQUUsZUFBZSxHQUMvQixPQUFPLENBQUMsV0FBVyxDQUFDLENBWXRCO0FBRUQ7Ozs7Ozs7Ozs7OztHQVlHO0FBQ0gsd0JBQXNCLFlBQVksQ0FDaEMsVUFBVSxFQUFFLHlCQUF5QixFQUNyQyxlQUFlLEVBQUUsZUFBZSxFQUNoQyxTQUFTLEVBQUUsUUFBUSxFQUFFLEdBQ3BCLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FpQmxCIn0=
28
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmxvY2tfY3JlYXRpb24uZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlscy9ibG9ja19jcmVhdGlvbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFNQSxPQUFPLEVBQUUsV0FBVyxFQUEyQyxNQUFNLGlDQUFpQyxDQUFDO0FBRXZHLE9BQU8sRUFBRSxFQUFFLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUNwRCxPQUFPLEVBQVEsT0FBTyxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDcEQsT0FBTyxFQUF3QyxLQUFLLHlCQUF5QixFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDM0csT0FBTyxFQUFFLFdBQVcsRUFBRSxlQUFlLEVBQUUsUUFBUSxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFFMUU7Ozs7R0FJRztBQUNILHdCQUFnQiwyQkFBMkIsQ0FBQyxXQUFXLEVBQUUsV0FBVyxHQUFHLEVBQUUsQ0FFeEU7QUFFRCx3QkFBc0IsNEJBQTRCLENBQ2hELFFBQVEsRUFBRSxRQUFRLEVBQ2xCLFVBQVUsRUFBRSx5QkFBeUIsRUFDckMsY0FBYyxHQUFFLEVBQUUsRUFBTyxHQUN4QixPQUFPLENBQUMsSUFBSSxDQUFDLENBa0JmO0FBRUQsd0JBQXNCLGtCQUFrQixDQUN0QyxVQUFVLEVBQUUseUJBQXlCLEVBQ3JDLGVBQWUsRUFBRSxlQUFlLEdBQy9CLE9BQU8sQ0FBQyxXQUFXLENBQUMsQ0FZdEI7QUFFRDs7Ozs7Ozs7Ozs7O0dBWUc7QUFDSCx3QkFBc0IsWUFBWSxDQUNoQyxVQUFVLEVBQUUseUJBQXlCLEVBQ3JDLGVBQWUsRUFBRSxlQUFlLEVBQ2hDLFNBQVMsRUFBRSxRQUFRLEVBQUUsR0FDcEIsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQWlCbEIifQ==
@@ -1 +1 @@
1
- {"version":3,"file":"block_creation.d.ts","sourceRoot":"","sources":["../../src/utils/block_creation.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,WAAW,EAA2C,MAAM,iCAAiC,CAAC;AAEvG,OAAO,EAAE,EAAE,EAAE,MAAM,gCAAgC,CAAC;AACpD,OAAO,EAAQ,OAAO,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAwC,KAAK,yBAAyB,EAAE,MAAM,qBAAqB,CAAC;AAC3G,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE1E;;;;GAIG;AACH,wBAAgB,2BAA2B,CAAC,WAAW,EAAE,WAAW,GAAG,EAAE,CAExE;AAED,wBAAsB,4BAA4B,CAChD,QAAQ,EAAE,QAAQ,EAClB,UAAU,EAAE,yBAAyB,GACpC,OAAO,CAAC,IAAI,CAAC,CAkBf;AAED,wBAAsB,kBAAkB,CACtC,UAAU,EAAE,yBAAyB,EACrC,eAAe,EAAE,eAAe,GAC/B,OAAO,CAAC,WAAW,CAAC,CAYtB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,YAAY,CAChC,UAAU,EAAE,yBAAyB,EACrC,eAAe,EAAE,eAAe,EAChC,SAAS,EAAE,QAAQ,EAAE,GACpB,OAAO,CAAC,OAAO,CAAC,CAiBlB"}
1
+ {"version":3,"file":"block_creation.d.ts","sourceRoot":"","sources":["../../src/utils/block_creation.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,WAAW,EAA2C,MAAM,iCAAiC,CAAC;AAEvG,OAAO,EAAE,EAAE,EAAE,MAAM,gCAAgC,CAAC;AACpD,OAAO,EAAQ,OAAO,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAwC,KAAK,yBAAyB,EAAE,MAAM,qBAAqB,CAAC;AAC3G,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE1E;;;;GAIG;AACH,wBAAgB,2BAA2B,CAAC,WAAW,EAAE,WAAW,GAAG,EAAE,CAExE;AAED,wBAAsB,4BAA4B,CAChD,QAAQ,EAAE,QAAQ,EAClB,UAAU,EAAE,yBAAyB,EACrC,cAAc,GAAE,EAAE,EAAO,GACxB,OAAO,CAAC,IAAI,CAAC,CAkBf;AAED,wBAAsB,kBAAkB,CACtC,UAAU,EAAE,yBAAyB,EACrC,eAAe,EAAE,eAAe,GAC/B,OAAO,CAAC,WAAW,CAAC,CAYtB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,YAAY,CAChC,UAAU,EAAE,yBAAyB,EACrC,eAAe,EAAE,eAAe,EAChC,SAAS,EAAE,QAAQ,EAAE,GACpB,OAAO,CAAC,OAAO,CAAC,CAiBlB"}
@@ -12,10 +12,10 @@ import { BlockHeader } from '@aztec/stdlib/tx';
12
12
  */ export function getSingleTxBlockRequestHash(blockNumber) {
13
13
  return new Fr(blockNumber + 9999); // Why does this need to be a high number? Why do small numbered nullifiers already exist?
14
14
  }
15
- export async function insertTxEffectIntoWorldTrees(txEffect, worldTrees) {
15
+ export async function insertTxEffectIntoWorldTrees(txEffect, worldTrees, l1ToL2Messages = []) {
16
16
  await worldTrees.appendLeaves(MerkleTreeId.NOTE_HASH_TREE, padArrayEnd(txEffect.noteHashes, Fr.ZERO, MAX_NOTE_HASHES_PER_TX));
17
17
  await worldTrees.batchInsert(MerkleTreeId.NULLIFIER_TREE, padArrayEnd(txEffect.nullifiers, Fr.ZERO, MAX_NULLIFIERS_PER_TX).map((nullifier)=>nullifier.toBuffer()), NULLIFIER_SUBTREE_HEIGHT);
18
- await worldTrees.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, padArrayEnd(txEffect.l2ToL1Msgs, Fr.ZERO, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP));
18
+ await worldTrees.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, padArrayEnd(l1ToL2Messages, Fr.ZERO, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP));
19
19
  // We do not need to add public data writes because we apply them as we go.
20
20
  }
21
21
  export async function makeTXEBlockHeader(worldTrees, globalVariables) {
@@ -1,3 +1,3 @@
1
1
  import { createRequire as __txeCreateRequire } from 'node:module';
2
2
  const require = __txeCreateRequire(import.meta.url);
3
- import{TXEDispatcher,activeSessionCount,createLogger}from"./chunk-5U25VAFR.js";import{__name}from"./chunk-BJVAAXNA.js";import{BackendType,Barretenberg,BarretenbergSync}from"@aztec/bb.js";import{parentPort,workerData}from"node:worker_threads";Barretenberg.initSingleton({backend:BackendType.Wasm,skipSrsInit:!0,threads:1});BarretenbergSync.initSingleton({backend:BackendType.Wasm});if(!parentPort)throw new Error("worker.ts must be loaded as a worker_thread");var port=parentPort,logger=createLogger("txe:worker"),dispatcherOpts={contractStoreSourceDir:workerData.contractStoreSourceDir,schnorrClassId:workerData.schnorrClassId},dispatcher=new TXEDispatcher(logger,dispatcherOpts);function serializeError(err){return err instanceof Error?{message:err.message,name:err.name,stack:err.stack}:{message:String(err)}}__name(serializeError,"serializeError");process.env.TXE_WORKER_MEMSTAT==="1"&&setInterval(()=>{let m=process.memoryUsage();port.postMessage({type:"memstat",sessions:activeSessionCount(),rss:m.rss,heapTotal:m.heapTotal,heapUsed:m.heapUsed,external:m.external,arrayBuffers:m.arrayBuffers})},2e3).unref();port.on("message",msg=>{switch(msg.type){case"foreign-call":(async()=>{try{let value=await dispatcher.resolve_foreign_call(msg.callData);port.postMessage({type:"result",requestId:msg.requestId,ok:!0,value})}catch(err){port.postMessage({type:"result",requestId:msg.requestId,ok:!1,error:serializeError(err)})}})();return;case"dispose-session":dispatcher.disposeSession(msg.sessionId).catch(err=>logger.warn("disposeSession failed",err));return}});
3
+ import{TXEDispatcher,activeSessionCount,createLogger}from"./chunk-IAO54JS2.js";import{__name}from"./chunk-BJVAAXNA.js";import{BackendType,Barretenberg,BarretenbergSync}from"@aztec/bb.js";import{parentPort,workerData}from"node:worker_threads";Barretenberg.initSingleton({backend:BackendType.Wasm,skipSrsInit:!0,threads:1});BarretenbergSync.initSingleton({backend:BackendType.Wasm});if(!parentPort)throw new Error("worker.ts must be loaded as a worker_thread");var port=parentPort,logger=createLogger("txe:worker"),dispatcherOpts={contractStoreSourceDir:workerData.contractStoreSourceDir,schnorrClassId:workerData.schnorrClassId},dispatcher=new TXEDispatcher(logger,dispatcherOpts);function serializeError(err){return err instanceof Error?{message:err.message,name:err.name,stack:err.stack}:{message:String(err)}}__name(serializeError,"serializeError");process.env.TXE_WORKER_MEMSTAT==="1"&&setInterval(()=>{let m=process.memoryUsage();port.postMessage({type:"memstat",sessions:activeSessionCount(),rss:m.rss,heapTotal:m.heapTotal,heapUsed:m.heapUsed,external:m.external,arrayBuffers:m.arrayBuffers})},2e3).unref();port.on("message",msg=>{switch(msg.type){case"foreign-call":(async()=>{try{let value=await dispatcher.resolve_foreign_call(msg.callData);port.postMessage({type:"result",requestId:msg.requestId,ok:!0,value})}catch(err){port.postMessage({type:"result",requestId:msg.requestId,ok:!1,error:serializeError(err)})}})();return;case"dispose-session":dispatcher.disposeSession(msg.sessionId).catch(err=>logger.warn("disposeSession failed",err));return}});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aztec/txe",
3
- "version": "5.0.0-rc.1",
3
+ "version": "5.0.0-rc.2",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  "./server": {
@@ -69,22 +69,22 @@
69
69
  ]
70
70
  },
71
71
  "dependencies": {
72
- "@aztec/accounts": "5.0.0-rc.1",
73
- "@aztec/archiver": "5.0.0-rc.1",
74
- "@aztec/aztec-node": "5.0.0-rc.1",
75
- "@aztec/aztec.js": "5.0.0-rc.1",
76
- "@aztec/bb-prover": "5.0.0-rc.1",
77
- "@aztec/bb.js": "5.0.0-rc.1",
78
- "@aztec/constants": "5.0.0-rc.1",
79
- "@aztec/foundation": "5.0.0-rc.1",
80
- "@aztec/key-store": "5.0.0-rc.1",
81
- "@aztec/kv-store": "5.0.0-rc.1",
82
- "@aztec/protocol-contracts": "5.0.0-rc.1",
83
- "@aztec/pxe": "5.0.0-rc.1",
84
- "@aztec/simulator": "5.0.0-rc.1",
85
- "@aztec/standard-contracts": "5.0.0-rc.1",
86
- "@aztec/stdlib": "5.0.0-rc.1",
87
- "@aztec/world-state": "5.0.0-rc.1",
72
+ "@aztec/accounts": "5.0.0-rc.2",
73
+ "@aztec/archiver": "5.0.0-rc.2",
74
+ "@aztec/aztec-node": "5.0.0-rc.2",
75
+ "@aztec/aztec.js": "5.0.0-rc.2",
76
+ "@aztec/bb-prover": "5.0.0-rc.2",
77
+ "@aztec/bb.js": "5.0.0-rc.2",
78
+ "@aztec/constants": "5.0.0-rc.2",
79
+ "@aztec/foundation": "5.0.0-rc.2",
80
+ "@aztec/key-store": "5.0.0-rc.2",
81
+ "@aztec/kv-store": "5.0.0-rc.2",
82
+ "@aztec/protocol-contracts": "5.0.0-rc.2",
83
+ "@aztec/pxe": "5.0.0-rc.2",
84
+ "@aztec/simulator": "5.0.0-rc.2",
85
+ "@aztec/standard-contracts": "5.0.0-rc.2",
86
+ "@aztec/stdlib": "5.0.0-rc.2",
87
+ "@aztec/world-state": "5.0.0-rc.2",
88
88
  "msgpackr": "^1.11.2",
89
89
  "zod": "^4"
90
90
  },
@@ -5,8 +5,8 @@ import { startHttpRpcServer } from '@aztec/foundation/json-rpc/server';
5
5
  import { createOracleTestRpcServer } from '../oracle/test-resolver/index.js';
6
6
 
7
7
  /**
8
- * Starts an HTTP RPC server that resolves oracle foreign calls using hardcoded fixture scenarios.
9
- * Used by `nargo test --oracle-resolver` to run `#[oracle_test]` roundtrip tests with a dedicated oracle resolver.
8
+ * Starts an HTTP RPC server that resolves oracle foreign calls using auto-synthesized fixture scenarios. Used by
9
+ * `nargo test --oracle-resolver` to run `#[auto_serialization_test]` serialization tests against a dedicated resolver.
10
10
  * Logs fixture coverage on shutdown.
11
11
  */
12
12
  async function main() {
package/src/constants.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { PRIVATE_LOG_CIPHERTEXT_LEN } from '@aztec/constants';
2
2
  import { AztecAddress } from '@aztec/stdlib/aztec-address';
3
3
 
4
- export const DEFAULT_ADDRESS = AztecAddress.fromNumber(42);
4
+ export const DEFAULT_ADDRESS = AztecAddress.fromNumberUnsafe(42);
5
5
 
6
6
  // This is MAX_MESSAGE_CONTENT_LEN - PRIVATE_EVENT_MSG_PLAINTEXT_RESERVED_FIELDS_LEN
7
7
  export const MAX_PRIVATE_EVENT_LEN = 10;
@@ -2,6 +2,9 @@ import { CompleteAddress } from '@aztec/aztec.js/addresses';
2
2
  import { TxHash } from '@aztec/aztec.js/tx';
3
3
  import { BlockNumber } from '@aztec/foundation/branded-types';
4
4
  import type { Fr } from '@aztec/foundation/curves/bn254';
5
+ import type { EthAddress } from '@aztec/foundation/eth-address';
6
+ import type { TaggingSecretStrategy } from '@aztec/pxe/server';
7
+ import type { Option } from '@aztec/pxe/simulator';
5
8
  import type { EventSelector, FunctionSelector } from '@aztec/stdlib/abi';
6
9
  import type { AztecAddress } from '@aztec/stdlib/aztec-address';
7
10
  import type { GasSettings } from '@aztec/stdlib/gas';
@@ -42,9 +45,9 @@ export interface IAvmExecutionOracle {
42
45
  getContractInstanceImmutablesHash(address: AztecAddress): Promise<{ member: Fr; exists: boolean }>;
43
46
  returndataSize(): Promise<Fr>;
44
47
  returndataCopy(rdOffset: number, copySize: number): Promise<Fr[]>;
45
- call(l2Gas: number, daGas: number, address: AztecAddress, argsLength: number, args: Fr[]): Promise<Fr[]>;
46
- staticCall(l2Gas: number, daGas: number, address: AztecAddress, argsLength: number, args: Fr[]): Promise<Fr[]>;
47
- successCopy(): Promise<Fr>;
48
+ call(l2Gas: number, daGas: number, address: AztecAddress, argsLength: number, args: Fr[]): Promise<void>;
49
+ staticCall(l2Gas: number, daGas: number, address: AztecAddress, argsLength: number, args: Fr[]): Promise<void>;
50
+ successCopy(): Promise<boolean>;
48
51
  }
49
52
 
50
53
  /**
@@ -69,6 +72,8 @@ export interface ITxeExecutionOracle {
69
72
  createAccount(secret: Fr): Promise<CompleteAddress>;
70
73
  addAccount(secret: Fr): Promise<CompleteAddress>;
71
74
  addAuthWitness(address: AztecAddress, messageHash: Fr): Promise<void>;
75
+ sendL1ToL2Message(content: Fr, secretHash: Fr, sender: EthAddress, recipient: AztecAddress): Promise<Fr>;
76
+ setTaggingSecretStrategy(strategy: Option<TaggingSecretStrategy>): void;
72
77
  getLastBlockTimestamp(): Promise<bigint>;
73
78
  getLastTxEffects(): Promise<{
74
79
  txHash: TxHash;
@@ -90,6 +95,7 @@ export interface ITxeExecutionOracle {
90
95
  gasSettings: GasSettings,
91
96
  ): Promise<{ returnValues: Fr[]; offchainEffects: Fr[][] }>;
92
97
  executeUtilityFunction(
98
+ from: AztecAddress | undefined,
93
99
  targetContractAddress: AztecAddress,
94
100
  functionSelector: FunctionSelector,
95
101
  args: Fr[],
@@ -0,0 +1,226 @@
1
+ import { AztecAddress } from '@aztec/aztec.js/addresses';
2
+ import { BlockNumber } from '@aztec/foundation/branded-types';
3
+ import { Fr } from '@aztec/foundation/curves/bn254';
4
+ import { EthAddress } from '@aztec/foundation/eth-address';
5
+ import {
6
+ AZTEC_ADDRESS,
7
+ BIGINT,
8
+ BLOCK_HASH,
9
+ BLOCK_NUMBER,
10
+ BOOL,
11
+ BYTE,
12
+ BoundedVec,
13
+ ETH_ADDRESS,
14
+ FIELD,
15
+ FUNCTION_SELECTOR,
16
+ NOTE_SELECTOR,
17
+ Option,
18
+ type OracleRegistryEntry,
19
+ type TypeMapping,
20
+ U32,
21
+ } from '@aztec/pxe/simulator';
22
+ import { FunctionSelector, NoteSelector } from '@aztec/stdlib/abi';
23
+ import { BlockHash } from '@aztec/stdlib/block';
24
+
25
+ import type { OracleTestScenario } from './resolver.js';
26
+
27
+ /**
28
+ * Synthesizes fixture scenarios for every oracle in the registry whose parameters and return are built from scalars,
29
+ * arrays/bounded vecs of them, or `Option`s of them. The matching Noir serialization tests are auto-generated by
30
+ * `#[auto_serialization_test]` from the same seed/scenario convention.
31
+ */
32
+ export function synthesizeDefaultFixtures(
33
+ registry: Record<string, OracleRegistryEntry>,
34
+ ): Record<string, OracleTestScenario[]> {
35
+ const synthesized: Record<string, OracleTestScenario[]> = {};
36
+
37
+ for (const [name, entry] of Object.entries(registry)) {
38
+ const scenarios = synthesizeScenarios(entry);
39
+ if (scenarios !== undefined) {
40
+ synthesized[name] = scenarios;
41
+ }
42
+ }
43
+
44
+ return synthesized;
45
+ }
46
+
47
+ /**
48
+ * The test-value implementations, one per oracle type, mirroring the Noir `OracleTestValue` trait exactly
49
+ * (`noir-projects/aztec-nr/.../macros/oracle_testing.nr`).
50
+ */
51
+ const TEST_VALUE_IMPLS: TestValueImpl[] = [
52
+ scalar(FIELD, seed => new Fr(seed)),
53
+ scalar(U32, seed => seed),
54
+ scalar(BLOCK_NUMBER, seed => BlockNumber(seed)),
55
+ scalar(BIGINT, seed => BigInt(seed)),
56
+ scalar(BYTE, seed => seed),
57
+ scalar(BOOL, seed => seed % 2 !== 0),
58
+ scalar(AZTEC_ADDRESS, seed => AztecAddress.fromNumberUnsafe(seed)),
59
+ scalar(ETH_ADDRESS, seed => EthAddress.fromField(new Fr(seed))),
60
+ scalar(FUNCTION_SELECTOR, seed => FunctionSelector.fromField(new Fr(seed))),
61
+ scalar(NOTE_SELECTOR, seed => NoteSelector.fromField(new Fr(seed))),
62
+ scalar(BLOCK_HASH, seed => new BlockHash(new Fr(seed))),
63
+ composite(isOption, (type, seed) => [
64
+ named(Option.some(firstValue(type.inner, seed)), 'some'),
65
+ named(Option.none(firstValue(type.inner, seed)), 'none'),
66
+ ]),
67
+ composite(isArray, (type, seed) => [unnamed(collectionData(type.inner, seed, DEFAULT_ARRAY_LENGTH))]),
68
+ composite(isBoundedVec, (type, seed) => [
69
+ unnamed(
70
+ BoundedVec.from({
71
+ data: collectionData(type.inner, seed, DEFAULT_ARRAY_LENGTH),
72
+ maxLength: BOUNDED_VEC_MAX_LENGTH,
73
+ }),
74
+ ),
75
+ ]),
76
+ ];
77
+
78
+ /**
79
+ * The base every seed is offset by, applied once where a parameter's position becomes its seed, so generated values
80
+ * stay clear of 0. Must match `SEED_BASE` in the Noir `oracle_testing.nr`.
81
+ */
82
+ const SEED_BASE = 10;
83
+
84
+ /** Elements per synthesized array and bounded vec. Must match `TEST_COLLECTION_LEN` in the Noir `oracle_testing.nr`. */
85
+ const DEFAULT_ARRAY_LENGTH = 3;
86
+
87
+ /**
88
+ * Capacity of synthesized bounded vecs, deliberately larger than the data length so padding is exercised. Must match
89
+ * `TEST_BOUNDED_VEC_CAP` in the Noir `oracle_testing.nr`.
90
+ */
91
+ const BOUNDED_VEC_MAX_LENGTH = 5;
92
+
93
+ /**
94
+ * One canonical test case for a type: the `value` to put on the wire (or expect back), and the `name` of the
95
+ * serialization shape it exercises (unset for single-scenario types). Mirrors the Noir `Scenario<T>`.
96
+ */
97
+ interface Scenario {
98
+ value: unknown;
99
+ name?: string;
100
+ }
101
+
102
+ function unnamed(value: unknown): Scenario {
103
+ return { value };
104
+ }
105
+ function named(value: unknown, name: string): Scenario {
106
+ return { value, name };
107
+ }
108
+
109
+ /**
110
+ * One type's test-value implementation, mirroring a Noir `impl OracleTestValue<N> for T`: `match` selects the type and
111
+ * `scenarios` yields its [`Scenario`]s for `seed`, one per serialization shape, like Noir's
112
+ * `oracle_test_value(seed) -> [Scenario<Self>; N]`.
113
+ */
114
+ interface TestValueImpl {
115
+ match: (type: TypeMapping<any>) => boolean;
116
+ scenarios: (type: TypeMapping<any>, seed: number) => Scenario[];
117
+ }
118
+
119
+ /** A scalar impl: matches the singleton `type` by identity and yields a single unnamed scenario. */
120
+ function scalar(type: TypeMapping<any>, value: (seed: number) => unknown): TestValueImpl {
121
+ return { match: t => t === type, scenarios: (_type, seed) => [unnamed(value(seed))] };
122
+ }
123
+
124
+ /** A composite impl: selected by the `kind` type guard, recursing through its element/inner mapping. */
125
+ function composite<K extends CompositeMapping>(
126
+ guard: (type: TypeMapping<any>) => type is K,
127
+ scenarios: (type: K, seed: number) => Scenario[],
128
+ ): TestValueImpl {
129
+ return { match: guard, scenarios: (type, seed) => scenarios(type as K, seed) };
130
+ }
131
+
132
+ /** Synthesized element values for a collection. */
133
+ function collectionData(element: TypeMapping<any>, seed: number, length: number): unknown[] {
134
+ return Array.from({ length }, (_, i) => firstValue(element, seed + i));
135
+ }
136
+
137
+ /**
138
+ * The [`Scenario`]s for `type` at `seed`, one per serialization *shape*, mirroring the Noir
139
+ * `OracleTestValue::oracle_test_value(seed) -> [Scenario<Self>; N]`. Throws if the type has no matching impl.
140
+ */
141
+ function scenariosForType(type: TypeMapping<any>, seed: number): Scenario[] {
142
+ const impl = TEST_VALUE_IMPLS.find(i => i.match(type));
143
+ if (!impl) {
144
+ throw new UnsynthesizableTypeError(type);
145
+ }
146
+ return impl.scenarios(type, seed);
147
+ }
148
+
149
+ /** The first (representative) test value of `type`, used for collection elements and `Option` inners. */
150
+ function firstValue(type: TypeMapping<any>, seed: number): unknown {
151
+ return scenariosForType(type, seed)[0].value;
152
+ }
153
+
154
+ class UnsynthesizableTypeError extends Error {
155
+ constructor(type: TypeMapping<any>) {
156
+ super(`No test-value impl for type: ${JSON.stringify(Object.keys(type))}`);
157
+ this.name = 'UnsynthesizableTypeError';
158
+ }
159
+ }
160
+
161
+ /**
162
+ * Synthesizes the scenarios for one oracle by zipping every position's [`Scenario`] list to one case per test (a
163
+ * shorter list wraps around via mod), mirroring the Noir macro. Returns `undefined` if any param or return type is
164
+ * unsynthesizable (structs, ephemeral arrays).
165
+ */
166
+ function synthesizeScenarios(entry: OracleRegistryEntry): OracleTestScenario[] | undefined {
167
+ try {
168
+ return synthesizeScenariosOrThrow(entry);
169
+ } catch (e) {
170
+ if (e instanceof UnsynthesizableTypeError) {
171
+ return undefined;
172
+ }
173
+ throw e;
174
+ }
175
+ }
176
+
177
+ function synthesizeScenariosOrThrow(entry: OracleRegistryEntry): OracleTestScenario[] {
178
+ const params = entry.params.map((param, index) => ({
179
+ name: param.name,
180
+ scenarios: scenariosForType(param.type, SEED_BASE + index),
181
+ }));
182
+ // The return's seed is the slot right after the last parameter, so its value is distinct from every parameter.
183
+ const returnScenarios =
184
+ entry.returnType === undefined ? undefined : scenariosForType(entry.returnType, SEED_BASE + entry.params.length);
185
+
186
+ // Positions with more than one scenario drive the test count; their names are zipped together (joined with `+`) per
187
+ // test, matching the announcements the Noir tests emit and the resolver joins.
188
+ const positions = [...params.map(p => p.scenarios), ...(returnScenarios !== undefined ? [returnScenarios] : [])];
189
+ const namedPositions = positions.filter(s => s.length > 1);
190
+ const testCount = Math.max(1, ...positions.map(s => s.length));
191
+
192
+ const scenarios: OracleTestScenario[] = [];
193
+ for (let index = 0; index < testCount; index++) {
194
+ const inputs: Record<string, unknown> = {};
195
+ for (const { name, scenarios: cases } of params) {
196
+ inputs[name] = cases[index % cases.length].value;
197
+ }
198
+ const output = returnScenarios === undefined ? undefined : returnScenarios[index % returnScenarios.length].value;
199
+ const scenario =
200
+ namedPositions.length === 0
201
+ ? undefined
202
+ : namedPositions.map(cases => cases[index % cases.length].name!).join('+');
203
+ scenarios.push({ scenario, inputs, output });
204
+ }
205
+ return scenarios;
206
+ }
207
+
208
+ /**
209
+ * The composite `TypeMapping`s (`ARRAY`/`BOUNDED_VEC`/`OPTION`), discriminated by `kind`. The combinators attach `kind`
210
+ * plus the inner mapping at construction; the registry erases params to the base `TypeMapping`, so the guards below
211
+ * recover the structure for recursion.
212
+ */
213
+ type ArrayMapping = TypeMapping & { kind: 'array'; inner: TypeMapping };
214
+ type BoundedVecMapping = TypeMapping & { kind: 'bounded-vec'; inner: TypeMapping };
215
+ type OptionMapping = TypeMapping & { kind: 'option'; inner: TypeMapping };
216
+ type CompositeMapping = ArrayMapping | BoundedVecMapping | OptionMapping;
217
+
218
+ function isArray(type: TypeMapping<any>): type is ArrayMapping {
219
+ return 'kind' in type && type.kind === 'array';
220
+ }
221
+ function isBoundedVec(type: TypeMapping<any>): type is BoundedVecMapping {
222
+ return 'kind' in type && type.kind === 'bounded-vec';
223
+ }
224
+ function isOption(type: TypeMapping<any>): type is OptionMapping {
225
+ return 'kind' in type && type.kind === 'option';
226
+ }
@@ -8,7 +8,6 @@ import { z } from 'zod';
8
8
 
9
9
  import { ForeignCallArgsSchema, type ForeignCallResult, ForeignCallResultSchema } from '../../utils/encoding.js';
10
10
  import { TXE_ORACLE_REGISTRY } from '../txe_oracle_registry.js';
11
- import { ORACLE_TEST_FIXTURES } from './fixtures.js';
12
11
  import { type OracleTestCallInput, OracleTestResolver } from './resolver.js';
13
12
 
14
13
  const OracleTestCallInputSchema = zodFor<OracleTestCallInput>()(
@@ -35,7 +34,7 @@ const OracleTestRpcHandlerSchema: ApiSchemaFor<OracleTestRpcHandler> = {
35
34
 
36
35
  /** Creates an RPC server backed by the oracle test resolver. */
37
36
  export function createOracleTestRpcServer(logger: Logger) {
38
- const resolver = new OracleTestResolver(TXE_ORACLE_REGISTRY, ORACLE_TEST_FIXTURES, logger);
37
+ const resolver = OracleTestResolver.fromRegistry(TXE_ORACLE_REGISTRY, logger);
39
38
  const server = createSafeJsonRpcServer<OracleTestRpcHandler>(resolver, OracleTestRpcHandlerSchema, {
40
39
  http200OnError: true,
41
40
  });