@aztec/txe 0.0.1-commit.04852196a → 0.0.1-commit.04d373f

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 (126) hide show
  1. package/dest/ContractClassRegistry-KKNT527R.js +3 -0
  2. package/dest/ContractClassRegistry-KKNT527R.js.map +7 -0
  3. package/dest/ContractInstanceRegistry-GSKBNL3Q.js +3 -0
  4. package/dest/ContractInstanceRegistry-GSKBNL3Q.js.map +7 -0
  5. package/dest/FeeJuice-GUJ5O6GB.js +3 -0
  6. package/dest/FeeJuice-GUJ5O6GB.js.map +7 -0
  7. package/dest/MultiCallEntrypoint-ZQPCKVKL.js +3 -0
  8. package/dest/MultiCallEntrypoint-ZQPCKVKL.js.map +7 -0
  9. package/dest/SchnorrAccount-QIXE5DXA.js +3 -0
  10. package/dest/SchnorrAccount-QIXE5DXA.js.map +7 -0
  11. package/dest/bin/check_txe_oracle_version.d.ts +2 -0
  12. package/dest/bin/check_txe_oracle_version.d.ts.map +1 -0
  13. package/dest/bin/check_txe_oracle_version.js +32 -0
  14. package/dest/bin/index.js +3 -30
  15. package/dest/bin/index.js.map +7 -0
  16. package/dest/chunk-BJVAAXNA.js +3 -0
  17. package/dest/chunk-BJVAAXNA.js.map +7 -0
  18. package/dest/chunk-DF6RMOC6.js +304 -0
  19. package/dest/chunk-DF6RMOC6.js.map +7 -0
  20. package/dest/chunk-PPJTNNUG.js +265 -0
  21. package/dest/chunk-PPJTNNUG.js.map +7 -0
  22. package/dest/constants.d.ts +3 -1
  23. package/dest/constants.d.ts.map +1 -1
  24. package/dest/constants.js +5 -0
  25. package/dest/dispatcher_pool.d.ts +67 -0
  26. package/dest/dispatcher_pool.d.ts.map +1 -0
  27. package/dest/dispatcher_pool.js +284 -0
  28. package/dest/index.d.ts +188 -7
  29. package/dest/index.d.ts.map +1 -1
  30. package/dest/index.js +155 -116
  31. package/dest/metafile.json +38147 -0
  32. package/dest/msgpackr_fr_extension.d.ts +2 -0
  33. package/dest/msgpackr_fr_extension.d.ts.map +1 -0
  34. package/dest/msgpackr_fr_extension.js +21 -0
  35. package/dest/oracle/interfaces.d.ts +15 -4
  36. package/dest/oracle/interfaces.d.ts.map +1 -1
  37. package/dest/oracle/txe_oracle_public_context.d.ts +6 -1
  38. package/dest/oracle/txe_oracle_public_context.d.ts.map +1 -1
  39. package/dest/oracle/txe_oracle_public_context.js +15 -0
  40. package/dest/oracle/txe_oracle_top_level_context.d.ts +22 -6
  41. package/dest/oracle/txe_oracle_top_level_context.d.ts.map +1 -1
  42. package/dest/oracle/txe_oracle_top_level_context.js +106 -47
  43. package/dest/oracle/txe_private_execution_oracle.d.ts +17 -0
  44. package/dest/oracle/txe_private_execution_oracle.d.ts.map +1 -0
  45. package/dest/oracle/txe_private_execution_oracle.js +15 -0
  46. package/dest/rpc_server.d.ts +14 -0
  47. package/dest/rpc_server.d.ts.map +1 -0
  48. package/dest/rpc_server.js +78 -0
  49. package/dest/rpc_translator.d.ts +90 -34
  50. package/dest/rpc_translator.d.ts.map +1 -1
  51. package/dest/rpc_translator.js +396 -153
  52. package/dest/server.bundle.js +3 -0
  53. package/dest/server.bundle.js.map +7 -0
  54. package/dest/state_machine/archiver.d.ts +4 -4
  55. package/dest/state_machine/archiver.d.ts.map +1 -1
  56. package/dest/state_machine/archiver.js +22 -20
  57. package/dest/state_machine/dummy_p2p_client.d.ts +13 -7
  58. package/dest/state_machine/dummy_p2p_client.d.ts.map +1 -1
  59. package/dest/state_machine/dummy_p2p_client.js +16 -4
  60. package/dest/state_machine/global_variable_builder.d.ts +9 -4
  61. package/dest/state_machine/global_variable_builder.d.ts.map +1 -1
  62. package/dest/state_machine/global_variable_builder.js +9 -3
  63. package/dest/state_machine/index.d.ts +7 -3
  64. package/dest/state_machine/index.d.ts.map +1 -1
  65. package/dest/state_machine/index.js +23 -5
  66. package/dest/state_machine/mock_epoch_cache.d.ts +18 -3
  67. package/dest/state_machine/mock_epoch_cache.d.ts.map +1 -1
  68. package/dest/state_machine/mock_epoch_cache.js +35 -2
  69. package/dest/state_machine/synchronizer.d.ts +5 -5
  70. package/dest/state_machine/synchronizer.d.ts.map +1 -1
  71. package/dest/state_machine/synchronizer.js +4 -4
  72. package/dest/txe_oracle_version.d.ts +17 -0
  73. package/dest/txe_oracle_version.d.ts.map +1 -0
  74. package/dest/txe_oracle_version.js +14 -0
  75. package/dest/txe_session.d.ts +64 -6
  76. package/dest/txe_session.d.ts.map +1 -1
  77. package/dest/txe_session.js +157 -29
  78. package/dest/utils/encoding.d.ts +191 -0
  79. package/dest/utils/encoding.d.ts.map +1 -0
  80. package/dest/{util → utils}/encoding.js +7 -2
  81. package/dest/{util → utils}/expected_failure_error.d.ts +1 -1
  82. package/dest/utils/expected_failure_error.d.ts.map +1 -0
  83. package/dest/{util → utils}/txe_account_store.d.ts +1 -1
  84. package/dest/utils/txe_account_store.d.ts.map +1 -0
  85. package/dest/utils/txe_public_contract_data_source.d.ts +20 -0
  86. package/dest/utils/txe_public_contract_data_source.d.ts.map +1 -0
  87. package/dest/{util → utils}/txe_public_contract_data_source.js +1 -3
  88. package/dest/worker.bundle.js +3 -0
  89. package/dest/worker.bundle.js.map +7 -0
  90. package/dest/worker.d.ts +2 -0
  91. package/dest/worker.d.ts.map +1 -0
  92. package/dest/worker.js +92 -0
  93. package/package.json +37 -21
  94. package/src/bin/check_txe_oracle_version.ts +37 -0
  95. package/src/bin/index.ts +11 -2
  96. package/src/constants.ts +6 -0
  97. package/src/dispatcher_pool.ts +316 -0
  98. package/src/index.ts +172 -123
  99. package/src/msgpackr_fr_extension.ts +23 -0
  100. package/src/oracle/interfaces.ts +16 -3
  101. package/src/oracle/txe_oracle_public_context.ts +30 -0
  102. package/src/oracle/txe_oracle_top_level_context.ts +124 -55
  103. package/src/oracle/txe_private_execution_oracle.ts +30 -0
  104. package/src/rpc_server.ts +87 -0
  105. package/src/rpc_translator.ts +459 -222
  106. package/src/state_machine/archiver.ts +33 -18
  107. package/src/state_machine/dummy_p2p_client.ts +31 -11
  108. package/src/state_machine/global_variable_builder.ts +18 -3
  109. package/src/state_machine/index.ts +25 -6
  110. package/src/state_machine/mock_epoch_cache.ts +46 -3
  111. package/src/state_machine/synchronizer.ts +5 -5
  112. package/src/txe_oracle_version.ts +17 -0
  113. package/src/txe_session.ts +251 -31
  114. package/src/{util → utils}/encoding.ts +8 -2
  115. package/src/{util → utils}/txe_public_contract_data_source.ts +0 -2
  116. package/src/worker.ts +98 -0
  117. package/dest/util/encoding.d.ts +0 -720
  118. package/dest/util/encoding.d.ts.map +0 -1
  119. package/dest/util/expected_failure_error.d.ts.map +0 -1
  120. package/dest/util/txe_account_store.d.ts.map +0 -1
  121. package/dest/util/txe_public_contract_data_source.d.ts +0 -20
  122. package/dest/util/txe_public_contract_data_source.d.ts.map +0 -1
  123. /package/dest/{util → utils}/expected_failure_error.js +0 -0
  124. /package/dest/{util → utils}/txe_account_store.js +0 -0
  125. /package/src/{util → utils}/expected_failure_error.ts +0 -0
  126. /package/src/{util → utils}/txe_account_store.ts +0 -0
@@ -1,11 +1,13 @@
1
- import { Fr, Point } from '@aztec/aztec.js/fields';
2
- import { MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX } from '@aztec/constants';
1
+ import { Fr } from '@aztec/aztec.js/fields';
2
+ import { ARCHIVE_HEIGHT, MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, MAX_PRIVATE_LOGS_PER_TX, PRIVATE_LOG_SIZE_IN_FIELDS } from '@aztec/constants';
3
3
  import { BlockNumber } from '@aztec/foundation/branded-types';
4
- import { packAsHintedNote } from '@aztec/pxe/simulator';
4
+ import { MembershipWitness } from '@aztec/foundation/trees';
5
+ import { BoundedVec, Option, packAsHintedNote } from '@aztec/pxe/simulator';
5
6
  import { EventSelector, FunctionSelector, NoteSelector } from '@aztec/stdlib/abi';
6
7
  import { AztecAddress } from '@aztec/stdlib/aztec-address';
7
- import { BlockHash } from '@aztec/stdlib/block';
8
- import { addressFromSingle, arrayOfArraysToBoundedVecOfArrays, arrayToBoundedVec, bufferToU8Array, fromArray, fromSingle, fromUintArray, fromUintBoundedVec, toArray, toForeignCallResult, toSingle } from './util/encoding.js';
8
+ import { GasSettings } from '@aztec/stdlib/gas';
9
+ import { MAX_OFFCHAIN_EFFECTS_PER_TXE_QUERY, MAX_OFFCHAIN_EFFECT_LEN } from './constants.js';
10
+ import { addressFromSingle, arrayOfArraysToBoundedVecOfArrays, arrayToBoundedVec, blockHashFromSingle, bufferToU8Array, fromArray, fromSingle, fromUintArray, fromUintBoundedVec, toArray, toForeignCallResult, toSingle } from './utils/encoding.js';
9
11
  const MAX_EVENT_LEN = 10; // This is MAX_MESSAGE_CONTENT_LEN - PRIVATE_EVENT_MSG_PLAINTEXT_RESERVED_FIELDS_LEN
10
12
  const MAX_PRIVATE_EVENTS_PER_TXE_QUERY = 5;
11
13
  export class UnavailableOracleError extends Error {
@@ -60,6 +62,13 @@ export class RPCTranslator {
60
62
  }
61
63
  return this.oracleHandler;
62
64
  }
65
+ // eslint-disable-next-line camelcase
66
+ aztec_txe_assertCompatibleOracleVersion(foreignMajor, foreignMinor) {
67
+ const major = fromSingle(foreignMajor).toNumber();
68
+ const minor = fromSingle(foreignMinor).toNumber();
69
+ this.stateHandler.setTxeOracleVersion(major, minor);
70
+ return toForeignCallResult([]);
71
+ }
63
72
  // TXE session state transition functions - these get handled by the state handler
64
73
  // eslint-disable-next-line camelcase
65
74
  async aztec_txe_setTopLevelTXEContext() {
@@ -67,10 +76,11 @@ export class RPCTranslator {
67
76
  return toForeignCallResult([]);
68
77
  }
69
78
  // eslint-disable-next-line camelcase
70
- async aztec_txe_setPrivateTXEContext(foreignContractAddressIsSome, foreignContractAddressValue, foreignAnchorBlockNumberIsSome, foreignAnchorBlockNumberValue) {
79
+ async aztec_txe_setPrivateTXEContext(foreignContractAddressIsSome, foreignContractAddressValue, foreignAnchorBlockNumberIsSome, foreignAnchorBlockNumberValue, foreignGasSettings) {
71
80
  const contractAddress = fromSingle(foreignContractAddressIsSome).toBool() ? AztecAddress.fromField(fromSingle(foreignContractAddressValue)) : undefined;
72
81
  const anchorBlockNumber = fromSingle(foreignAnchorBlockNumberIsSome).toBool() ? BlockNumber(fromSingle(foreignAnchorBlockNumberValue).toNumber()) : undefined;
73
- const privateContextInputs = await this.stateHandler.enterPrivateState(contractAddress, anchorBlockNumber);
82
+ const gasSettings = GasSettings.fromFields(fromArray(foreignGasSettings));
83
+ const privateContextInputs = await this.stateHandler.enterPrivateState(contractAddress, anchorBlockNumber, gasSettings);
74
84
  return toForeignCallResult(privateContextInputs.toFields().map(toSingle));
75
85
  }
76
86
  // eslint-disable-next-line camelcase
@@ -130,6 +140,7 @@ export class RPCTranslator {
130
140
  instance.deployer.toField(),
131
141
  instance.currentContractClassId,
132
142
  instance.initializationHash,
143
+ instance.immutablesHash,
133
144
  ...instance.publicKeys.toFields()
134
145
  ])
135
146
  ]);
@@ -161,9 +172,10 @@ export class RPCTranslator {
161
172
  }
162
173
  // PXE oracles
163
174
  // eslint-disable-next-line camelcase
164
- aztec_utl_assertCompatibleOracleVersion(foreignVersion) {
165
- const version = fromSingle(foreignVersion).toNumber();
166
- this.handlerAsMisc().assertCompatibleOracleVersion(version);
175
+ aztec_utl_assertCompatibleOracleVersion(foreignMajor, foreignMinor) {
176
+ const major = fromSingle(foreignMajor).toNumber();
177
+ const minor = fromSingle(foreignMinor).toNumber();
178
+ this.handlerAsMisc().assertCompatibleOracleVersion(major, minor);
167
179
  return toForeignCallResult([]);
168
180
  }
169
181
  // eslint-disable-next-line camelcase
@@ -182,11 +194,44 @@ export class RPCTranslator {
182
194
  }
183
195
  // eslint-disable-next-line camelcase
184
196
  async aztec_txe_getLastTxEffects() {
185
- const { txHash, noteHashes, nullifiers } = await this.handlerAsTxe().getLastTxEffects();
197
+ const { txHash, noteHashes, nullifiers, privateLogs } = await this.handlerAsTxe().getLastTxEffects();
198
+ // Same workaround as `aztec_txe_getPrivateEvents`: Noir cannot yet return nested structs with arrays, so we return
199
+ // a flat multidimensional array plus per-log lengths and the total count, and reassemble into a
200
+ // `BoundedVec<BoundedVec<T>>` on the Noir side. Each log contributes only its emitted fields. The rest
201
+ // is zero-padded to `PRIVATE_LOG_SIZE_IN_FIELDS`.
202
+ const emittedLogs = privateLogs.map((log)=>log.getEmittedFields());
203
+ const rawLogStorage = emittedLogs.map((fields)=>fields.concat(Array(PRIVATE_LOG_SIZE_IN_FIELDS - fields.length).fill(new Fr(0)))).concat(Array(MAX_PRIVATE_LOGS_PER_TX - emittedLogs.length).fill(Array(PRIVATE_LOG_SIZE_IN_FIELDS).fill(new Fr(0)))).flat();
204
+ const logLengths = emittedLogs.map((fields)=>new Fr(fields.length)).concat(Array(MAX_PRIVATE_LOGS_PER_TX - emittedLogs.length).fill(new Fr(0)));
205
+ const logCount = new Fr(emittedLogs.length);
186
206
  return toForeignCallResult([
187
207
  toSingle(txHash.hash),
188
208
  ...arrayToBoundedVec(toArray(noteHashes), MAX_NOTE_HASHES_PER_TX),
189
- ...arrayToBoundedVec(toArray(nullifiers), MAX_NULLIFIERS_PER_TX)
209
+ ...arrayToBoundedVec(toArray(nullifiers), MAX_NULLIFIERS_PER_TX),
210
+ toArray(rawLogStorage),
211
+ toArray(logLengths),
212
+ toSingle(logCount)
213
+ ]);
214
+ }
215
+ // eslint-disable-next-line camelcase
216
+ aztec_txe_getLastCallOffchainEffects() {
217
+ const { effects } = this.stateHandler.getLastCallOffchainEffects();
218
+ const rawArrayStorage = effects.map((e)=>e.concat(Array(MAX_OFFCHAIN_EFFECT_LEN - e.length).fill(new Fr(0)))).concat(Array(MAX_OFFCHAIN_EFFECTS_PER_TXE_QUERY - effects.length).fill(Array(MAX_OFFCHAIN_EFFECT_LEN).fill(new Fr(0)))).flat();
219
+ const effectLengths = effects.map((e)=>new Fr(e.length)).concat(Array(MAX_OFFCHAIN_EFFECTS_PER_TXE_QUERY - effects.length).fill(new Fr(0)));
220
+ const count = new Fr(effects.length);
221
+ return toForeignCallResult([
222
+ toArray(rawArrayStorage),
223
+ toArray(effectLengths),
224
+ toSingle(count)
225
+ ]);
226
+ }
227
+ // eslint-disable-next-line camelcase
228
+ aztec_txe_getLastCallContext() {
229
+ const { txHash, anchorBlockTimestamp } = this.stateHandler.getLastCallContext();
230
+ const isSome = txHash.isZero() ? 0 : 1;
231
+ return toForeignCallResult([
232
+ toSingle(isSome),
233
+ toSingle(txHash),
234
+ toSingle(new Fr(anchorBlockTimestamp))
190
235
  ]);
191
236
  }
192
237
  // eslint-disable-next-line camelcase
@@ -219,16 +264,16 @@ export class RPCTranslator {
219
264
  ]);
220
265
  }
221
266
  // eslint-disable-next-line camelcase
222
- aztec_prv_storeInExecutionCache(foreignValues, foreignHash) {
267
+ aztec_prv_setHashPreimage(foreignValues, foreignHash) {
223
268
  const values = fromArray(foreignValues);
224
269
  const hash = fromSingle(foreignHash);
225
- this.handlerAsPrivate().storeInExecutionCache(values, hash);
270
+ this.handlerAsPrivate().setHashPreimage(values, hash);
226
271
  return toForeignCallResult([]);
227
272
  }
228
273
  // eslint-disable-next-line camelcase
229
- async aztec_prv_loadFromExecutionCache(foreignHash) {
274
+ async aztec_prv_getHashPreimage(foreignHash) {
230
275
  const hash = fromSingle(foreignHash);
231
- const returns = await this.handlerAsPrivate().loadFromExecutionCache(hash);
276
+ const returns = await this.handlerAsPrivate().getHashPreimage(hash);
232
277
  return toForeignCallResult([
233
278
  toArray(returns)
234
279
  ]);
@@ -244,30 +289,27 @@ export class RPCTranslator {
244
289
  return toForeignCallResult([]);
245
290
  }
246
291
  // eslint-disable-next-line camelcase
247
- async aztec_utl_storageRead(foreignBlockHash, foreignContractAddress, foreignStartStorageSlot, foreignNumberOfElements) {
248
- const blockHash = new BlockHash(fromSingle(foreignBlockHash));
292
+ async aztec_utl_getFromPublicStorage(foreignBlockHash, foreignContractAddress, foreignStartStorageSlot, foreignNumberOfElements) {
293
+ const blockHash = blockHashFromSingle(foreignBlockHash);
249
294
  const contractAddress = addressFromSingle(foreignContractAddress);
250
295
  const startStorageSlot = fromSingle(foreignStartStorageSlot);
251
296
  const numberOfElements = fromSingle(foreignNumberOfElements).toNumber();
252
- const values = await this.handlerAsUtility().storageRead(blockHash, contractAddress, startStorageSlot, numberOfElements);
297
+ const values = await this.handlerAsUtility().getFromPublicStorage(blockHash, contractAddress, startStorageSlot, numberOfElements);
253
298
  return toForeignCallResult([
254
299
  toArray(values)
255
300
  ]);
256
301
  }
257
302
  // eslint-disable-next-line camelcase
258
303
  async aztec_utl_getPublicDataWitness(foreignBlockHash, foreignLeafSlot) {
259
- const blockHash = new BlockHash(fromSingle(foreignBlockHash));
304
+ const blockHash = blockHashFromSingle(foreignBlockHash);
260
305
  const leafSlot = fromSingle(foreignLeafSlot);
261
306
  const witness = await this.handlerAsUtility().getPublicDataWitness(blockHash, leafSlot);
262
- if (!witness) {
263
- throw new Error(`Public data witness not found for slot ${leafSlot} at block ${blockHash.toString()}.`);
264
- }
265
307
  return toForeignCallResult(witness.toNoirRepresentation());
266
308
  }
267
309
  // eslint-disable-next-line camelcase
268
310
  async aztec_utl_getNotes(foreignOwnerIsSome, foreignOwnerValue, foreignStorageSlot, foreignNumSelects, foreignSelectByIndexes, foreignSelectByOffsets, foreignSelectByLengths, foreignSelectValues, foreignSelectComparators, foreignSortByIndexes, foreignSortByOffsets, foreignSortByLengths, foreignSortOrder, foreignLimit, foreignOffset, foreignStatus, foreignMaxNotes, foreignPackedHintedNoteLength) {
269
311
  // Parse Option<AztecAddress>: ownerIsSome is 0 for None, 1 for Some
270
- const owner = fromSingle(foreignOwnerIsSome).toBool() ? AztecAddress.fromField(fromSingle(foreignOwnerValue)) : undefined;
312
+ const owner = fromSingle(foreignOwnerIsSome).toBool() ? Option.some(AztecAddress.fromField(fromSingle(foreignOwnerValue))) : Option.none(AztecAddress.ZERO);
271
313
  const storageSlot = fromSingle(foreignStorageSlot);
272
314
  const numSelects = fromSingle(foreignNumSelects).toNumber();
273
315
  const selectByIndexes = fromArray(foreignSelectByIndexes).map((fr)=>fr.toNumber());
@@ -284,8 +326,8 @@ export class RPCTranslator {
284
326
  const status = fromSingle(foreignStatus).toNumber();
285
327
  const maxNotes = fromSingle(foreignMaxNotes).toNumber();
286
328
  const packedHintedNoteLength = fromSingle(foreignPackedHintedNoteLength).toNumber();
287
- const noteDatas = await this.handlerAsUtility().getNotes(owner, storageSlot, numSelects, selectByIndexes, selectByOffsets, selectByLengths, selectValues, selectComparators, sortByIndexes, sortByOffsets, sortByLengths, sortOrder, limit, offset, status);
288
- const returnDataAsArrayOfArrays = noteDatas.map((noteData)=>packAsHintedNote({
329
+ const noteVec = await this.handlerAsUtility().getNotes(owner, storageSlot, numSelects, selectByIndexes, selectByOffsets, selectByLengths, selectValues, selectComparators, sortByIndexes, sortByOffsets, sortByLengths, sortOrder, limit, offset, status, maxNotes, packedHintedNoteLength);
330
+ const returnDataAsArrayOfArrays = Array.from(noteVec.data).map((noteData)=>packAsHintedNote({
289
331
  contractAddress: noteData.contractAddress,
290
332
  owner: noteData.owner,
291
333
  randomness: noteData.randomness,
@@ -294,9 +336,7 @@ export class RPCTranslator {
294
336
  isPending: noteData.isPending,
295
337
  note: noteData.note
296
338
  }));
297
- // Now we convert each sub-array to an array of ForeignCallSingles
298
339
  const returnDataAsArrayOfForeignCallSingleArrays = returnDataAsArrayOfArrays.map((subArray)=>subArray.map(toSingle));
299
- // At last we convert the array of arrays to a bounded vec of arrays
300
340
  return toForeignCallResult(arrayOfArraysToBoundedVecOfArrays(returnDataAsArrayOfForeignCallSingleArrays, maxNotes, packedHintedNoteLength));
301
341
  }
302
342
  // eslint-disable-next-line camelcase
@@ -335,9 +375,9 @@ export class RPCTranslator {
335
375
  ]);
336
376
  }
337
377
  // eslint-disable-next-line camelcase
338
- async aztec_utl_checkNullifierExists(foreignInnerNullifier) {
378
+ async aztec_utl_doesNullifierExist(foreignInnerNullifier) {
339
379
  const innerNullifier = fromSingle(foreignInnerNullifier);
340
- const exists = await this.handlerAsUtility().checkNullifierExists(innerNullifier);
380
+ const exists = await this.handlerAsUtility().doesNullifierExist(innerNullifier);
341
381
  return toForeignCallResult([
342
382
  toSingle(new Fr(exists))
343
383
  ]);
@@ -351,28 +391,40 @@ export class RPCTranslator {
351
391
  instance.deployer.toField(),
352
392
  instance.currentContractClassId,
353
393
  instance.initializationHash,
394
+ instance.immutablesHash,
354
395
  ...instance.publicKeys.toFields()
355
396
  ].map(toSingle));
356
397
  }
357
398
  // eslint-disable-next-line camelcase
358
- async aztec_utl_tryGetPublicKeysAndPartialAddress(foreignAddress) {
399
+ async aztec_utl_getPublicKeysAndPartialAddress(foreignAddress) {
359
400
  const address = addressFromSingle(foreignAddress);
360
- const result = await this.handlerAsUtility().tryGetPublicKeysAndPartialAddress(address);
401
+ const result = await this.handlerAsUtility().getPublicKeysAndPartialAddress(address);
361
402
  // We are going to return a Noir Option struct to represent the possibility of null values. Options are a struct
362
403
  // with two fields: `some` (a boolean) and `value` (a field array in this case).
363
- if (result === undefined) {
404
+ if (!result.isSome()) {
364
405
  // No data was found so we set `some` to 0 and pad `value` with zeros get the correct return size.
406
+ // Wire shape: [npk_m_hash, ivpk_m.x, ivpk_m.y, ovpk_m_hash, tpk_m_hash, mspk_m_hash, fbpk_m_hash, partial_address] = 8 fields.
365
407
  return toForeignCallResult([
366
408
  toSingle(new Fr(0)),
367
- toArray(Array(13).fill(new Fr(0)))
409
+ toArray(Array(8).fill(new Fr(0)))
368
410
  ]);
369
411
  } else {
370
- // Data was found so we set `some` to 1 and return it along with `value`.
412
+ // The Noir side hand-decodes a `[Field; 8]` here (see aztec-nr/aztec/src/oracle/keys.nr), so we
413
+ // emit the 7-field PublicKeys shape + partial_address explicitly
414
+ // rather than going through `publicKeys.toFields()` (which is the struct-flattened 8-field
415
+ // wire for oracle returns that decode via struct shape).
416
+ const { publicKeys, partialAddress } = result.value;
371
417
  return toForeignCallResult([
372
418
  toSingle(new Fr(1)),
373
419
  toArray([
374
- ...result.publicKeys.toFields(),
375
- result.partialAddress
420
+ publicKeys.npkMHash,
421
+ publicKeys.ivpkM.x,
422
+ publicKeys.ivpkM.y,
423
+ publicKeys.ovpkMHash,
424
+ publicKeys.tpkMHash,
425
+ publicKeys.mspkMHash,
426
+ publicKeys.fbpkMHash,
427
+ partialAddress
376
428
  ])
377
429
  ]);
378
430
  }
@@ -384,46 +436,51 @@ export class RPCTranslator {
384
436
  return toForeignCallResult(keyValidationRequest.toFields().map(toSingle));
385
437
  }
386
438
  // eslint-disable-next-line camelcase
387
- aztec_prv_callPrivateFunction(_foreignTargetContractAddress, _foreignFunctionSelector, _foreignArgsHash, _foreignSideEffectCounter, _foreignIsStaticCall) {
388
- throw new Error('Contract calls are forbidden inside a `TestEnvironment::private_context`, use `private_call` instead');
439
+ async aztec_prv_callPrivateFunction(foreignTargetContractAddress, foreignFunctionSelector, foreignArgsHash, foreignSideEffectCounter, foreignIsStaticCall) {
440
+ const targetContractAddress = addressFromSingle(foreignTargetContractAddress);
441
+ const functionSelector = FunctionSelector.fromField(fromSingle(foreignFunctionSelector));
442
+ const argsHash = fromSingle(foreignArgsHash);
443
+ const sideEffectCounter = fromSingle(foreignSideEffectCounter).toNumber();
444
+ const isStaticCall = fromSingle(foreignIsStaticCall).toBool();
445
+ const { endSideEffectCounter, returnsHash } = await this.handlerAsPrivate().callPrivateFunction(targetContractAddress, functionSelector, argsHash, sideEffectCounter, isStaticCall);
446
+ return toForeignCallResult([
447
+ [
448
+ endSideEffectCounter,
449
+ returnsHash
450
+ ].map(toSingle)
451
+ ]);
389
452
  }
390
453
  // eslint-disable-next-line camelcase
391
454
  async aztec_utl_getNullifierMembershipWitness(foreignBlockHash, foreignNullifier) {
392
- const blockHash = new BlockHash(fromSingle(foreignBlockHash));
455
+ const blockHash = blockHashFromSingle(foreignBlockHash);
393
456
  const nullifier = fromSingle(foreignNullifier);
394
457
  const witness = await this.handlerAsUtility().getNullifierMembershipWitness(blockHash, nullifier);
395
- if (!witness) {
396
- throw new Error(`Nullifier membership witness not found at block ${blockHash}.`);
397
- }
398
458
  return toForeignCallResult(witness.toNoirRepresentation());
399
459
  }
400
460
  // eslint-disable-next-line camelcase
401
461
  async aztec_utl_getAuthWitness(foreignMessageHash) {
402
462
  const messageHash = fromSingle(foreignMessageHash);
403
463
  const authWitness = await this.handlerAsUtility().getAuthWitness(messageHash);
404
- if (!authWitness) {
405
- throw new Error(`Auth witness not found for message hash ${messageHash}.`);
406
- }
407
464
  return toForeignCallResult([
408
465
  toArray(authWitness)
409
466
  ]);
410
467
  }
411
468
  // eslint-disable-next-line camelcase
412
- aztec_prv_notifyEnqueuedPublicFunctionCall(_foreignTargetContractAddress, _foreignCalldataHash, _foreignSideEffectCounter, _foreignIsStaticCall) {
413
- throw new Error('Enqueueing public calls is not supported in TestEnvironment::private_context');
414
- }
415
- // eslint-disable-next-line camelcase
416
- aztec_prv_notifySetPublicTeardownFunctionCall(_foreignTargetContractAddress, _foreignCalldataHash, _foreignSideEffectCounter, _foreignIsStaticCall) {
417
- throw new Error('Enqueueing public calls is not supported in TestEnvironment::private_context');
469
+ async aztec_prv_assertValidPublicCalldata(foreignCalldataHash) {
470
+ const calldataHash = fromSingle(foreignCalldataHash);
471
+ await this.handlerAsPrivate().assertValidPublicCalldata(calldataHash);
472
+ return toForeignCallResult([]);
418
473
  }
419
474
  // eslint-disable-next-line camelcase
420
- aztec_prv_notifySetMinRevertibleSideEffectCounter(_foreignMinRevertibleSideEffectCounter) {
421
- throw new Error('Enqueueing public calls is not supported in TestEnvironment::private_context');
475
+ async aztec_prv_notifyRevertiblePhaseStart(foreignMinRevertibleSideEffectCounter) {
476
+ const minRevertibleSideEffectCounter = fromSingle(foreignMinRevertibleSideEffectCounter).toNumber();
477
+ await this.handlerAsPrivate().notifyRevertiblePhaseStart(minRevertibleSideEffectCounter);
478
+ return toForeignCallResult([]);
422
479
  }
423
480
  // eslint-disable-next-line camelcase
424
- async aztec_prv_isSideEffectCounterRevertible(foreignSideEffectCounter) {
481
+ async aztec_prv_isExecutionInRevertiblePhase(foreignSideEffectCounter) {
425
482
  const sideEffectCounter = fromSingle(foreignSideEffectCounter).toNumber();
426
- const isRevertible = await this.handlerAsPrivate().isSideEffectCounterRevertible(sideEffectCounter);
483
+ const isRevertible = await this.handlerAsPrivate().isExecutionInRevertiblePhase(sideEffectCounter);
427
484
  return toForeignCallResult([
428
485
  toSingle(new Fr(isRevertible))
429
486
  ]);
@@ -437,107 +494,168 @@ export class RPCTranslator {
437
494
  async aztec_utl_getBlockHeader(foreignBlockNumber) {
438
495
  const blockNumber = BlockNumber(fromSingle(foreignBlockNumber).toNumber());
439
496
  const header = await this.handlerAsUtility().getBlockHeader(blockNumber);
440
- if (!header) {
441
- throw new Error(`Block header not found for block ${blockNumber}.`);
442
- }
443
497
  return toForeignCallResult(header.toFields().map(toSingle));
444
498
  }
445
499
  // eslint-disable-next-line camelcase
446
500
  async aztec_utl_getNoteHashMembershipWitness(foreignAnchorBlockHash, foreignNoteHash) {
447
- const blockHash = new BlockHash(fromSingle(foreignAnchorBlockHash));
501
+ const blockHash = blockHashFromSingle(foreignAnchorBlockHash);
448
502
  const noteHash = fromSingle(foreignNoteHash);
449
503
  const witness = await this.handlerAsUtility().getNoteHashMembershipWitness(blockHash, noteHash);
450
- if (!witness) {
451
- throw new Error(`Note hash ${noteHash} not found in the note hash tree at block ${blockHash.toString()}.`);
452
- }
453
504
  return toForeignCallResult(witness.toNoirRepresentation());
454
505
  }
455
506
  // eslint-disable-next-line camelcase
456
507
  async aztec_utl_getBlockHashMembershipWitness(foreignAnchorBlockHash, foreignBlockHash) {
457
- const anchorBlockHash = new BlockHash(fromSingle(foreignAnchorBlockHash));
458
- const blockHash = new BlockHash(fromSingle(foreignBlockHash));
459
- const witness = await this.handlerAsUtility().getBlockHashMembershipWitness(anchorBlockHash, blockHash);
460
- if (!witness) {
461
- throw new Error(`Block hash ${blockHash.toString()} not found in the archive tree at anchor block ${anchorBlockHash.toString()}.`);
462
- }
463
- return toForeignCallResult(witness.toNoirRepresentation());
508
+ const anchorBlockHash = blockHashFromSingle(foreignAnchorBlockHash);
509
+ const blockHash = blockHashFromSingle(foreignBlockHash);
510
+ const witnessOpt = await this.handlerAsUtility().getBlockHashMembershipWitness(anchorBlockHash, blockHash);
511
+ const effective = witnessOpt.value ?? MembershipWitness.empty(ARCHIVE_HEIGHT);
512
+ return toForeignCallResult([
513
+ toSingle(new Fr(witnessOpt.isSome() ? 1 : 0)),
514
+ ...effective.toNoirRepresentation()
515
+ ]);
464
516
  }
465
517
  // eslint-disable-next-line camelcase
466
518
  async aztec_utl_getLowNullifierMembershipWitness(foreignBlockHash, foreignNullifier) {
467
- const blockHash = new BlockHash(fromSingle(foreignBlockHash));
519
+ const blockHash = blockHashFromSingle(foreignBlockHash);
468
520
  const nullifier = fromSingle(foreignNullifier);
469
521
  const witness = await this.handlerAsUtility().getLowNullifierMembershipWitness(blockHash, nullifier);
470
- if (!witness) {
471
- throw new Error(`Low nullifier witness not found for nullifier ${nullifier} at block ${blockHash}.`);
472
- }
473
522
  return toForeignCallResult(witness.toNoirRepresentation());
474
523
  }
475
524
  // eslint-disable-next-line camelcase
476
- async aztec_utl_fetchTaggedLogs(foreignPendingTaggedLogArrayBaseSlot) {
477
- const pendingTaggedLogArrayBaseSlot = fromSingle(foreignPendingTaggedLogArrayBaseSlot);
478
- await this.handlerAsUtility().fetchTaggedLogs(pendingTaggedLogArrayBaseSlot);
479
- return toForeignCallResult([]);
525
+ async aztec_utl_getPendingTaggedLogs(foreignScope) {
526
+ const scope = AztecAddress.fromField(fromSingle(foreignScope));
527
+ const slot = await this.handlerAsUtility().getPendingTaggedLogs(scope);
528
+ return toForeignCallResult([
529
+ toSingle(slot)
530
+ ]);
480
531
  }
481
532
  // eslint-disable-next-line camelcase
482
- async aztec_utl_validateAndStoreEnqueuedNotesAndEvents(foreignContractAddress, foreignNoteValidationRequestsArrayBaseSlot, foreignEventValidationRequestsArrayBaseSlot) {
483
- const contractAddress = AztecAddress.fromField(fromSingle(foreignContractAddress));
533
+ async aztec_utl_validateAndStoreEnqueuedNotesAndEvents(foreignNoteValidationRequestsArrayBaseSlot, foreignEventValidationRequestsArrayBaseSlot, foreignScope) {
484
534
  const noteValidationRequestsArrayBaseSlot = fromSingle(foreignNoteValidationRequestsArrayBaseSlot);
485
535
  const eventValidationRequestsArrayBaseSlot = fromSingle(foreignEventValidationRequestsArrayBaseSlot);
486
- await this.handlerAsUtility().validateAndStoreEnqueuedNotesAndEvents(contractAddress, noteValidationRequestsArrayBaseSlot, eventValidationRequestsArrayBaseSlot);
536
+ const scope = AztecAddress.fromField(fromSingle(foreignScope));
537
+ await this.handlerAsUtility().validateAndStoreEnqueuedNotesAndEvents(noteValidationRequestsArrayBaseSlot, eventValidationRequestsArrayBaseSlot, scope);
487
538
  return toForeignCallResult([]);
488
539
  }
489
540
  // eslint-disable-next-line camelcase
490
- async aztec_utl_bulkRetrieveLogs(foreignContractAddress, foreignLogRetrievalRequestsArrayBaseSlot, foreignLogRetrievalResponsesArrayBaseSlot) {
491
- const contractAddress = AztecAddress.fromField(fromSingle(foreignContractAddress));
492
- const logRetrievalRequestsArrayBaseSlot = fromSingle(foreignLogRetrievalRequestsArrayBaseSlot);
493
- const logRetrievalResponsesArrayBaseSlot = fromSingle(foreignLogRetrievalResponsesArrayBaseSlot);
494
- await this.handlerAsUtility().bulkRetrieveLogs(contractAddress, logRetrievalRequestsArrayBaseSlot, logRetrievalResponsesArrayBaseSlot);
495
- return toForeignCallResult([]);
541
+ async aztec_utl_getLogsByTag(foreignRequestArrayBaseSlot) {
542
+ const requestArrayBaseSlot = fromSingle(foreignRequestArrayBaseSlot);
543
+ const responseSlot = await this.handlerAsUtility().getLogsByTag(requestArrayBaseSlot);
544
+ return toForeignCallResult([
545
+ toSingle(responseSlot)
546
+ ]);
547
+ }
548
+ // eslint-disable-next-line camelcase
549
+ async aztec_utl_getMessageContextsByTxHash(foreignRequestArrayBaseSlot) {
550
+ const requestArrayBaseSlot = fromSingle(foreignRequestArrayBaseSlot);
551
+ const responseSlot = await this.handlerAsUtility().getMessageContextsByTxHash(requestArrayBaseSlot);
552
+ return toForeignCallResult([
553
+ toSingle(responseSlot)
554
+ ]);
496
555
  }
497
556
  // eslint-disable-next-line camelcase
498
- async aztec_utl_storeCapsule(foreignContractAddress, foreignSlot, foreignCapsule) {
557
+ aztec_utl_setCapsule(foreignContractAddress, foreignSlot, foreignCapsule, foreignScope) {
499
558
  const contractAddress = AztecAddress.fromField(fromSingle(foreignContractAddress));
500
559
  const slot = fromSingle(foreignSlot);
501
560
  const capsule = fromArray(foreignCapsule);
502
- await this.handlerAsUtility().storeCapsule(contractAddress, slot, capsule);
561
+ const scope = AztecAddress.fromField(fromSingle(foreignScope));
562
+ this.handlerAsUtility().setCapsule(contractAddress, slot, capsule, scope);
503
563
  return toForeignCallResult([]);
504
564
  }
505
565
  // eslint-disable-next-line camelcase
506
- async aztec_utl_loadCapsule(foreignContractAddress, foreignSlot, foreignTSize) {
566
+ async aztec_utl_getCapsule(foreignContractAddress, foreignSlot, foreignTSize, foreignScope) {
507
567
  const contractAddress = AztecAddress.fromField(fromSingle(foreignContractAddress));
508
568
  const slot = fromSingle(foreignSlot);
509
569
  const tSize = fromSingle(foreignTSize).toNumber();
510
- const values = await this.handlerAsUtility().loadCapsule(contractAddress, slot);
570
+ const scope = AztecAddress.fromField(fromSingle(foreignScope));
571
+ const opt = await this.handlerAsUtility().getCapsule(contractAddress, slot, tSize, scope);
511
572
  // We are going to return a Noir Option struct to represent the possibility of null values. Options are a struct
512
573
  // with two fields: `some` (a boolean) and `value` (a field array in this case).
513
- if (values === null) {
514
- // No data was found so we set `some` to 0 and pad `value` with zeros get the correct return size.
574
+ if (opt.isSome()) {
575
+ // Data was found so we set `some` to 1 and return it along with `value`.
515
576
  return toForeignCallResult([
516
- toSingle(new Fr(0)),
517
- toArray(Array(tSize).fill(new Fr(0)))
577
+ toSingle(new Fr(1)),
578
+ toArray(Array.from(opt.value))
518
579
  ]);
519
580
  } else {
520
- // Data was found so we set `some` to 1 and return it along with `value`.
581
+ // No data was found so we set `some` to 0 and pad `value` with zeros get the correct return size.
521
582
  return toForeignCallResult([
522
- toSingle(new Fr(1)),
523
- toArray(values)
583
+ toSingle(new Fr(0)),
584
+ toArray(Array(tSize).fill(new Fr(0)))
524
585
  ]);
525
586
  }
526
587
  }
527
588
  // eslint-disable-next-line camelcase
528
- async aztec_utl_deleteCapsule(foreignContractAddress, foreignSlot) {
589
+ aztec_utl_deleteCapsule(foreignContractAddress, foreignSlot, foreignScope) {
529
590
  const contractAddress = AztecAddress.fromField(fromSingle(foreignContractAddress));
530
591
  const slot = fromSingle(foreignSlot);
531
- await this.handlerAsUtility().deleteCapsule(contractAddress, slot);
592
+ const scope = AztecAddress.fromField(fromSingle(foreignScope));
593
+ this.handlerAsUtility().deleteCapsule(contractAddress, slot, scope);
532
594
  return toForeignCallResult([]);
533
595
  }
534
596
  // eslint-disable-next-line camelcase
535
- async aztec_utl_copyCapsule(foreignContractAddress, foreignSrcSlot, foreignDstSlot, foreignNumEntries) {
597
+ async aztec_utl_copyCapsule(foreignContractAddress, foreignSrcSlot, foreignDstSlot, foreignNumEntries, foreignScope) {
536
598
  const contractAddress = AztecAddress.fromField(fromSingle(foreignContractAddress));
537
599
  const srcSlot = fromSingle(foreignSrcSlot);
538
600
  const dstSlot = fromSingle(foreignDstSlot);
539
601
  const numEntries = fromSingle(foreignNumEntries).toNumber();
540
- await this.handlerAsUtility().copyCapsule(contractAddress, srcSlot, dstSlot, numEntries);
602
+ const scope = AztecAddress.fromField(fromSingle(foreignScope));
603
+ await this.handlerAsUtility().copyCapsule(contractAddress, srcSlot, dstSlot, numEntries, scope);
604
+ return toForeignCallResult([]);
605
+ }
606
+ // eslint-disable-next-line camelcase
607
+ aztec_utl_pushEphemeral(foreignSlot, foreignElements) {
608
+ const slot = fromSingle(foreignSlot);
609
+ const elements = fromArray(foreignElements);
610
+ const newLen = this.handlerAsUtility().pushEphemeral(slot, elements);
611
+ return toForeignCallResult([
612
+ toSingle(new Fr(newLen))
613
+ ]);
614
+ }
615
+ // eslint-disable-next-line camelcase
616
+ aztec_utl_popEphemeral(foreignSlot) {
617
+ const slot = fromSingle(foreignSlot);
618
+ const element = this.handlerAsUtility().popEphemeral(slot);
619
+ return toForeignCallResult([
620
+ toArray(element)
621
+ ]);
622
+ }
623
+ // eslint-disable-next-line camelcase
624
+ aztec_utl_getEphemeral(foreignSlot, foreignIndex) {
625
+ const slot = fromSingle(foreignSlot);
626
+ const index = fromSingle(foreignIndex).toNumber();
627
+ const element = this.handlerAsUtility().getEphemeral(slot, index);
628
+ return toForeignCallResult([
629
+ toArray(element)
630
+ ]);
631
+ }
632
+ // eslint-disable-next-line camelcase
633
+ aztec_utl_setEphemeral(foreignSlot, foreignIndex, foreignElements) {
634
+ const slot = fromSingle(foreignSlot);
635
+ const index = fromSingle(foreignIndex).toNumber();
636
+ const elements = fromArray(foreignElements);
637
+ this.handlerAsUtility().setEphemeral(slot, index, elements);
638
+ return toForeignCallResult([]);
639
+ }
640
+ // eslint-disable-next-line camelcase
641
+ aztec_utl_getEphemeralLen(foreignSlot) {
642
+ const slot = fromSingle(foreignSlot);
643
+ const len = this.handlerAsUtility().getEphemeralLen(slot);
644
+ return toForeignCallResult([
645
+ toSingle(new Fr(len))
646
+ ]);
647
+ }
648
+ // eslint-disable-next-line camelcase
649
+ aztec_utl_removeEphemeral(foreignSlot, foreignIndex) {
650
+ const slot = fromSingle(foreignSlot);
651
+ const index = fromSingle(foreignIndex).toNumber();
652
+ this.handlerAsUtility().removeEphemeral(slot, index);
653
+ return toForeignCallResult([]);
654
+ }
655
+ // eslint-disable-next-line camelcase
656
+ aztec_utl_clearEphemeral(foreignSlot) {
657
+ const slot = fromSingle(foreignSlot);
658
+ this.handlerAsUtility().clearEphemeral(slot);
541
659
  return toForeignCallResult([]);
542
660
  }
543
661
  // TODO: I forgot to add a corresponding function here, when I introduced an oracle method to txe_oracle.ts.
@@ -545,27 +663,65 @@ export class RPCTranslator {
545
663
  // to implement this function here. Isn't there a way to programmatically identify that this is missing, given the
546
664
  // existence of a txe_oracle method?
547
665
  // eslint-disable-next-line camelcase
548
- async aztec_utl_aes128Decrypt(foreignCiphertextBVecStorage, foreignCiphertextLength, foreignIv, foreignSymKey) {
549
- const ciphertext = fromUintBoundedVec(foreignCiphertextBVecStorage, foreignCiphertextLength, 8);
666
+ async aztec_utl_decryptAes128(foreignCiphertextBVecStorage, foreignCiphertextLength, foreignIv, foreignSymKey) {
667
+ const capacity = foreignCiphertextBVecStorage.length;
668
+ const ciphertextBuf = fromUintBoundedVec(foreignCiphertextBVecStorage, foreignCiphertextLength, 8);
669
+ const ciphertext = BoundedVec.from({
670
+ data: [
671
+ ...ciphertextBuf
672
+ ],
673
+ maxLength: capacity
674
+ });
550
675
  const iv = fromUintArray(foreignIv, 8);
551
676
  const symKey = fromUintArray(foreignSymKey, 8);
552
- const plaintextBuffer = await this.handlerAsUtility().aes128Decrypt(ciphertext, iv, symKey);
553
- return toForeignCallResult(arrayToBoundedVec(bufferToU8Array(plaintextBuffer), foreignCiphertextBVecStorage.length));
677
+ // Noir Option<BoundedVec> is encoded as [is_some: Field, storage: Field[], length: Field].
678
+ const plaintextOpt = await this.handlerAsUtility().decryptAes128(ciphertext, iv, symKey);
679
+ if (plaintextOpt.isSome()) {
680
+ const [storage, length] = arrayToBoundedVec(bufferToU8Array(Buffer.from(plaintextOpt.value.data)), capacity);
681
+ return toForeignCallResult([
682
+ toSingle(new Fr(1)),
683
+ storage,
684
+ length
685
+ ]);
686
+ } else {
687
+ const zeroStorage = toArray(Array(capacity).fill(new Fr(0)));
688
+ return toForeignCallResult([
689
+ toSingle(new Fr(0)),
690
+ zeroStorage,
691
+ toSingle(new Fr(0))
692
+ ]);
693
+ }
554
694
  }
555
695
  // eslint-disable-next-line camelcase
556
- async aztec_utl_getSharedSecret(foreignAddress, foreignEphPKField0, foreignEphPKField1, foreignEphPKField2) {
696
+ async aztec_utl_getSharedSecrets(foreignAddress, foreignEphPksSlot, foreignContractAddress) {
557
697
  const address = AztecAddress.fromField(fromSingle(foreignAddress));
558
- const ephPK = Point.fromFields([
559
- fromSingle(foreignEphPKField0),
560
- fromSingle(foreignEphPKField1),
561
- fromSingle(foreignEphPKField2)
698
+ const ephPksSlot = fromSingle(foreignEphPksSlot);
699
+ const contractAddress = AztecAddress.fromField(fromSingle(foreignContractAddress));
700
+ const responseSlot = await this.handlerAsUtility().getSharedSecrets(address, ephPksSlot, contractAddress);
701
+ return toForeignCallResult([
702
+ toSingle(responseSlot)
562
703
  ]);
563
- const secret = await this.handlerAsUtility().getSharedSecret(address, ephPK);
564
- return toForeignCallResult(secret.toFields().map(toSingle));
565
704
  }
566
705
  // eslint-disable-next-line camelcase
567
- aztec_utl_emitOffchainEffect(_foreignData) {
568
- throw new Error('Offchain effects are not yet supported in the TestEnvironment');
706
+ aztec_utl_setContractSyncCacheInvalid(foreignContractAddress, foreignScopes, foreignScopeCount) {
707
+ const contractAddress = addressFromSingle(foreignContractAddress);
708
+ const allFields = fromArray(foreignScopes);
709
+ const count = fromSingle(foreignScopeCount).toNumber();
710
+ const scopes = BoundedVec.from({
711
+ data: allFields.slice(0, count).map((f)=>new AztecAddress(f)),
712
+ maxLength: allFields.length
713
+ });
714
+ this.handlerAsUtility().setContractSyncCacheInvalid(contractAddress, scopes);
715
+ return Promise.resolve(toForeignCallResult([]));
716
+ }
717
+ // eslint-disable-next-line camelcase
718
+ aztec_utl_emitOffchainEffect(foreignData) {
719
+ // Record the raw payload against the currently-executing top-level call. The Noir side
720
+ // (via `env.offchain_messages()`) is responsible for decoding the protocol-reserved prefix
721
+ // (`OFFCHAIN_MESSAGE_IDENTIFIER`, recipient) and turning each payload into an `OffchainMessage` struct suitable
722
+ // for `offchain_receive`.
723
+ this.stateHandler.recordOffchainEffect(fromArray(foreignData));
724
+ return Promise.resolve(toForeignCallResult([]));
569
725
  }
570
726
  // AVM opcodes
571
727
  // eslint-disable-next-line camelcase
@@ -620,6 +776,16 @@ export class RPCTranslator {
620
776
  ]);
621
777
  }
622
778
  // eslint-disable-next-line camelcase
779
+ async aztec_avm_getContractInstanceImmutablesHash(foreignAddress) {
780
+ const address = addressFromSingle(foreignAddress);
781
+ const instance = await this.handlerAsUtility().getContractInstance(address);
782
+ return toForeignCallResult([
783
+ toSingle(instance.immutablesHash),
784
+ // AVM requires an extra boolean indicating the instance was found
785
+ toSingle(new Fr(1))
786
+ ]);
787
+ }
788
+ // eslint-disable-next-line camelcase
623
789
  async aztec_avm_sender() {
624
790
  const sender = await this.handlerAsAvm().sender();
625
791
  return toForeignCallResult([
@@ -689,90 +855,159 @@ export class RPCTranslator {
689
855
  ]);
690
856
  }
691
857
  // eslint-disable-next-line camelcase
692
- aztec_avm_returndataSize() {
693
- throw new Error('Contract calls are forbidden inside a `TestEnvironment::public_context`, use `public_call` instead');
858
+ async aztec_avm_returndataSize() {
859
+ const result = await this.handlerAsAvm().returndataSize();
860
+ return toForeignCallResult([
861
+ toSingle(result)
862
+ ]);
694
863
  }
695
864
  // eslint-disable-next-line camelcase
696
- aztec_avm_returndataCopy(_foreignRdOffset, _foreignCopySize) {
697
- throw new Error('Contract calls are forbidden inside a `TestEnvironment::public_context`, use `public_call` instead');
865
+ async aztec_avm_returndataCopy(foreignRdOffset, foreignCopySize) {
866
+ const rdOffset = fromSingle(foreignRdOffset).toNumber();
867
+ const copySize = fromSingle(foreignCopySize).toNumber();
868
+ const result = await this.handlerAsAvm().returndataCopy(rdOffset, copySize);
869
+ return toForeignCallResult([
870
+ toArray(result)
871
+ ]);
698
872
  }
699
873
  // eslint-disable-next-line camelcase
700
- aztec_avm_call(_foreignL2Gas, _foreignDaGas, _foreignAddress, _foreignLength, _foreignArgs) {
701
- throw new Error('Contract calls are forbidden inside a `TestEnvironment::public_context`, use `public_call` instead');
874
+ async aztec_avm_call(foreignL2Gas, foreignDaGas, foreignAddress, foreignLength, foreignArgs) {
875
+ const l2Gas = fromSingle(foreignL2Gas).toNumber();
876
+ const daGas = fromSingle(foreignDaGas).toNumber();
877
+ const address = addressFromSingle(foreignAddress);
878
+ const argsLength = fromSingle(foreignLength).toNumber();
879
+ const args = fromArray(foreignArgs);
880
+ const result = await this.handlerAsAvm().call(l2Gas, daGas, address, argsLength, args);
881
+ return toForeignCallResult([
882
+ toArray(result)
883
+ ]);
702
884
  }
703
885
  // eslint-disable-next-line camelcase
704
- aztec_avm_staticCall(_foreignL2Gas, _foreignDaGas, _foreignAddress, _foreignLength, _foreignArgs) {
705
- throw new Error('Contract calls are forbidden inside a `TestEnvironment::public_context`, use `public_call` instead');
886
+ async aztec_avm_staticCall(foreignL2Gas, foreignDaGas, foreignAddress, foreignLength, foreignArgs) {
887
+ const l2Gas = fromSingle(foreignL2Gas).toNumber();
888
+ const daGas = fromSingle(foreignDaGas).toNumber();
889
+ const address = addressFromSingle(foreignAddress);
890
+ const argsLength = fromSingle(foreignLength).toNumber();
891
+ const args = fromArray(foreignArgs);
892
+ const result = await this.handlerAsAvm().staticCall(l2Gas, daGas, address, argsLength, args);
893
+ return toForeignCallResult([
894
+ toArray(result)
895
+ ]);
706
896
  }
707
897
  // eslint-disable-next-line camelcase
708
- aztec_avm_successCopy() {
709
- throw new Error('Contract calls are forbidden inside a `TestEnvironment::public_context`, use `public_call` instead');
898
+ async aztec_avm_successCopy() {
899
+ const result = await this.handlerAsAvm().successCopy();
900
+ return toForeignCallResult([
901
+ toSingle(result)
902
+ ]);
710
903
  }
904
+ // TODO(F-674): Move orchestration logic into the handler so the transport layer is pure serialize→delegate→deserialize.
711
905
  // eslint-disable-next-line camelcase
712
- async aztec_txe_privateCallNewFlow(foreignFrom, foreignTargetContractAddress, foreignFunctionSelector, foreignArgs, foreignArgsHash, foreignIsStaticCall) {
713
- const from = addressFromSingle(foreignFrom);
906
+ async aztec_txe_privateCallNewFlow(foreignFromIsSome, foreignFromValue, foreignTargetContractAddress, foreignFunctionSelector, foreignArgs, foreignArgsHash, foreignIsStaticCall, foreignAdditionalScopes, foreignAuthorizedUtilityCallTargets, foreignGasSettings) {
907
+ const from = fromSingle(foreignFromIsSome).toBool() ? addressFromSingle(foreignFromValue) : undefined;
714
908
  const targetContractAddress = addressFromSingle(foreignTargetContractAddress);
715
909
  const functionSelector = FunctionSelector.fromField(fromSingle(foreignFunctionSelector));
716
910
  const args = fromArray(foreignArgs);
717
911
  const argsHash = fromSingle(foreignArgsHash);
718
912
  const isStaticCall = fromSingle(foreignIsStaticCall).toBool();
719
- const returnValues = await this.handlerAsTxe().privateCallNewFlow(from, targetContractAddress, functionSelector, args, argsHash, isStaticCall, this.stateHandler.getCurrentJob());
720
- // TODO(F-335): Avoid doing the following call here.
721
- await this.stateHandler.cycleJob();
913
+ const additionalScopes = fromArray(foreignAdditionalScopes).map((field)=>AztecAddress.fromField(field));
914
+ const authorizedUtilityCallTargets = fromArray(foreignAuthorizedUtilityCallTargets).map((field)=>AztecAddress.fromField(field));
915
+ const gasSettings = GasSettings.fromFields(fromArray(foreignGasSettings));
916
+ const returnValues = await this.stateHandler.withTopLevelCallTracking(async ()=>{
917
+ const { returnValues, offchainEffects } = await this.handlerAsTxe().privateCallNewFlow(from, targetContractAddress, functionSelector, args, argsHash, isStaticCall, additionalScopes, this.stateHandler.getCurrentJob(), authorizedUtilityCallTargets, gasSettings);
918
+ // Private execution collects offchain effects inside PXE's PrivateExecutionOracle rather than
919
+ // round-tripping them through `aztec_utl_emitOffchainEffect`, so the session buffer is empty
920
+ // at this point. Drain the effects from the execution tree into the session buffer so the
921
+ // next `env.offchain_messages()` call in the test sees them.
922
+ for (const data of offchainEffects){
923
+ this.stateHandler.recordOffchainEffect(data);
924
+ }
925
+ // TODO(F-335): Avoid doing the following call here.
926
+ await this.stateHandler.cycleJob();
927
+ if (isStaticCall) {
928
+ // Static calls revert their checkpoint and mine no block, so there is no tx hash to tag
929
+ // offchain effects with. Querying `getLastTxEffects()` here would return an unrelated
930
+ // predecessor tx.
931
+ return {
932
+ result: returnValues
933
+ };
934
+ }
935
+ const { txHash } = await this.handlerAsTxe().getLastTxEffects();
936
+ return {
937
+ result: returnValues,
938
+ txHash: txHash.hash
939
+ };
940
+ });
722
941
  return toForeignCallResult([
723
942
  toArray(returnValues)
724
943
  ]);
725
944
  }
945
+ // TODO(F-674): Move orchestration logic into the handler so the transport layer is pure serialize→delegate→deserialize.
726
946
  // eslint-disable-next-line camelcase
727
- async aztec_txe_executeUtilityFunction(foreignTargetContractAddress, foreignFunctionSelector, foreignArgs) {
947
+ async aztec_txe_executeUtilityFunction(foreignTargetContractAddress, foreignFunctionSelector, foreignArgs, foreignAuthorizedUtilityCallTargets) {
728
948
  const targetContractAddress = addressFromSingle(foreignTargetContractAddress);
729
949
  const functionSelector = FunctionSelector.fromField(fromSingle(foreignFunctionSelector));
730
950
  const args = fromArray(foreignArgs);
731
- const returnValues = await this.handlerAsTxe().executeUtilityFunction(targetContractAddress, functionSelector, args, this.stateHandler.getCurrentJob());
732
- // TODO(F-335): Avoid doing the following call here.
733
- await this.stateHandler.cycleJob();
951
+ const authorizedUtilityCallTargets = fromArray(foreignAuthorizedUtilityCallTargets).map((field)=>AztecAddress.fromField(field));
952
+ const returnValues = await this.stateHandler.withTopLevelCallTracking(async ()=>{
953
+ const returnValues = await this.handlerAsTxe().executeUtilityFunction(targetContractAddress, functionSelector, args, this.stateHandler.getCurrentJob(), authorizedUtilityCallTargets);
954
+ // TODO(F-335): Avoid doing the following call here.
955
+ await this.stateHandler.cycleJob();
956
+ return {
957
+ result: returnValues
958
+ };
959
+ });
734
960
  return toForeignCallResult([
735
961
  toArray(returnValues)
736
962
  ]);
737
963
  }
964
+ // TODO(F-674): Move orchestration logic into the handler so the transport layer is pure serialize→delegate→deserialize.
738
965
  // eslint-disable-next-line camelcase
739
- async aztec_txe_publicCallNewFlow(foreignFrom, foreignAddress, foreignCalldata, foreignIsStaticCall) {
740
- const from = addressFromSingle(foreignFrom);
966
+ async aztec_txe_publicCallNewFlow(foreignFromIsSome, foreignFromValue, foreignAddress, foreignCalldata, foreignIsStaticCall, foreignGasSettings) {
967
+ const from = fromSingle(foreignFromIsSome).toBool() ? addressFromSingle(foreignFromValue) : undefined;
741
968
  const address = addressFromSingle(foreignAddress);
742
969
  const calldata = fromArray(foreignCalldata);
743
970
  const isStaticCall = fromSingle(foreignIsStaticCall).toBool();
744
- const returnValues = await this.handlerAsTxe().publicCallNewFlow(from, address, calldata, isStaticCall);
745
- // TODO(F-335): Avoid doing the following call here.
746
- await this.stateHandler.cycleJob();
971
+ const gasSettings = GasSettings.fromFields(fromArray(foreignGasSettings));
972
+ const returnValues = await this.stateHandler.withTopLevelCallTracking(async ()=>{
973
+ const returnValues = await this.handlerAsTxe().publicCallNewFlow(from, address, calldata, isStaticCall, gasSettings);
974
+ // TODO(F-335): Avoid doing the following call here.
975
+ await this.stateHandler.cycleJob();
976
+ if (isStaticCall) {
977
+ // See equivalent branch in `aztec_txe_privateCallNewFlow`.
978
+ return {
979
+ result: returnValues
980
+ };
981
+ }
982
+ const { txHash } = await this.handlerAsTxe().getLastTxEffects();
983
+ return {
984
+ result: returnValues,
985
+ txHash: txHash.hash
986
+ };
987
+ });
747
988
  return toForeignCallResult([
748
989
  toArray(returnValues)
749
990
  ]);
750
991
  }
751
992
  // eslint-disable-next-line camelcase
752
993
  async aztec_prv_getSenderForTags() {
753
- const sender = await this.handlerAsPrivate().getSenderForTags();
994
+ const senderOpt = await this.handlerAsPrivate().getSenderForTags();
754
995
  // Return a Noir Option struct with `some` and `value` fields
755
- if (sender === undefined) {
756
- // No sender found, return Option with some=0 and value=0
996
+ if (senderOpt.isSome()) {
997
+ // Sender found, return Option with some=1 and value=sender address
757
998
  return toForeignCallResult([
758
- toSingle(0),
759
- toSingle(0)
999
+ toSingle(1),
1000
+ toSingle(senderOpt.value)
760
1001
  ]);
761
1002
  } else {
762
- // Sender found, return Option with some=1 and value=sender address
1003
+ // No sender found, return Option with some=0 and value=0
763
1004
  return toForeignCallResult([
764
- toSingle(1),
765
- toSingle(sender)
1005
+ toSingle(0),
1006
+ toSingle(0)
766
1007
  ]);
767
1008
  }
768
1009
  }
769
1010
  // eslint-disable-next-line camelcase
770
- async aztec_prv_setSenderForTags(foreignSenderForTags) {
771
- const senderForTags = AztecAddress.fromField(fromSingle(foreignSenderForTags));
772
- await this.handlerAsPrivate().setSenderForTags(senderForTags);
773
- return toForeignCallResult([]);
774
- }
775
- // eslint-disable-next-line camelcase
776
1011
  async aztec_prv_getNextAppTagAsSender(foreignSender, foreignRecipient) {
777
1012
  const sender = AztecAddress.fromField(fromSingle(foreignSender));
778
1013
  const recipient = AztecAddress.fromField(fromSingle(foreignRecipient));
@@ -781,4 +1016,12 @@ export class RPCTranslator {
781
1016
  toSingle(nextAppTag.value)
782
1017
  ]);
783
1018
  }
1019
+ // eslint-disable-next-line camelcase
1020
+ async aztec_prv_getNextConstrainedTaggingIndex(foreignAppSiloedSecret) {
1021
+ const appSiloedSecret = fromSingle(foreignAppSiloedSecret);
1022
+ const index = await this.handlerAsPrivate().getNextConstrainedTaggingIndex(appSiloedSecret);
1023
+ return toForeignCallResult([
1024
+ toSingle(new Fr(index))
1025
+ ]);
1026
+ }
784
1027
  }