@aztec/txe 0.0.1-commit.86469d5 → 0.0.1-commit.8655d4a

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 (134) 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 +148 -75
  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 +40 -28
  36. package/dest/oracle/interfaces.d.ts.map +1 -1
  37. package/dest/oracle/txe_oracle_public_context.d.ts +18 -13
  38. package/dest/oracle/txe_oracle_public_context.d.ts.map +1 -1
  39. package/dest/oracle/txe_oracle_public_context.js +27 -12
  40. package/dest/oracle/txe_oracle_top_level_context.d.ts +39 -24
  41. package/dest/oracle/txe_oracle_top_level_context.d.ts.map +1 -1
  42. package/dest/oracle/txe_oracle_top_level_context.js +205 -78
  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 +140 -84
  50. package/dest/rpc_translator.d.ts.map +1 -1
  51. package/dest/rpc_translator.js +587 -239
  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 +24 -20
  57. package/dest/state_machine/dummy_p2p_client.d.ts +26 -16
  58. package/dest/state_machine/dummy_p2p_client.d.ts.map +1 -1
  59. package/dest/state_machine/dummy_p2p_client.js +44 -20
  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 +10 -6
  64. package/dest/state_machine/index.d.ts.map +1 -1
  65. package/dest/state_machine/index.js +35 -12
  66. package/dest/state_machine/mock_epoch_cache.d.ts +20 -3
  67. package/dest/state_machine/mock_epoch_cache.d.ts.map +1 -1
  68. package/dest/state_machine/mock_epoch_cache.js +39 -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 +71 -10
  76. package/dest/txe_session.d.ts.map +1 -1
  77. package/dest/txe_session.js +227 -40
  78. package/dest/utils/block_creation.d.ts +1 -1
  79. package/dest/utils/block_creation.d.ts.map +1 -1
  80. package/dest/utils/block_creation.js +3 -1
  81. package/dest/utils/encoding.d.ts +191 -0
  82. package/dest/utils/encoding.d.ts.map +1 -0
  83. package/dest/{util → utils}/encoding.js +7 -2
  84. package/dest/{util → utils}/expected_failure_error.d.ts +1 -1
  85. package/dest/utils/expected_failure_error.d.ts.map +1 -0
  86. package/dest/{util → utils}/txe_account_store.d.ts +1 -1
  87. package/dest/utils/txe_account_store.d.ts.map +1 -0
  88. package/dest/utils/txe_public_contract_data_source.d.ts +20 -0
  89. package/dest/utils/txe_public_contract_data_source.d.ts.map +1 -0
  90. package/dest/{util → utils}/txe_public_contract_data_source.js +6 -25
  91. package/dest/worker.bundle.js +3 -0
  92. package/dest/worker.bundle.js.map +7 -0
  93. package/dest/worker.d.ts +2 -0
  94. package/dest/worker.d.ts.map +1 -0
  95. package/dest/worker.js +92 -0
  96. package/package.json +37 -21
  97. package/src/bin/check_txe_oracle_version.ts +37 -0
  98. package/src/bin/index.ts +11 -2
  99. package/src/constants.ts +6 -0
  100. package/src/dispatcher_pool.ts +316 -0
  101. package/src/index.ts +166 -80
  102. package/src/msgpackr_fr_extension.ts +23 -0
  103. package/src/oracle/interfaces.ts +48 -34
  104. package/src/oracle/txe_oracle_public_context.ts +42 -12
  105. package/src/oracle/txe_oracle_top_level_context.ts +231 -144
  106. package/src/oracle/txe_private_execution_oracle.ts +30 -0
  107. package/src/rpc_server.ts +87 -0
  108. package/src/rpc_translator.ts +662 -316
  109. package/src/state_machine/archiver.ts +35 -18
  110. package/src/state_machine/dummy_p2p_client.ts +70 -32
  111. package/src/state_machine/global_variable_builder.ts +18 -3
  112. package/src/state_machine/index.ts +48 -13
  113. package/src/state_machine/mock_epoch_cache.ts +51 -3
  114. package/src/state_machine/synchronizer.ts +5 -5
  115. package/src/txe_oracle_version.ts +17 -0
  116. package/src/txe_session.ts +324 -90
  117. package/src/utils/block_creation.ts +3 -1
  118. package/src/{util → utils}/encoding.ts +8 -2
  119. package/src/{util → utils}/txe_public_contract_data_source.ts +10 -38
  120. package/src/worker.ts +98 -0
  121. package/dest/util/encoding.d.ts +0 -720
  122. package/dest/util/encoding.d.ts.map +0 -1
  123. package/dest/util/expected_failure_error.d.ts.map +0 -1
  124. package/dest/util/txe_account_store.d.ts.map +0 -1
  125. package/dest/util/txe_contract_store.d.ts +0 -12
  126. package/dest/util/txe_contract_store.d.ts.map +0 -1
  127. package/dest/util/txe_contract_store.js +0 -22
  128. package/dest/util/txe_public_contract_data_source.d.ts +0 -21
  129. package/dest/util/txe_public_contract_data_source.d.ts.map +0 -1
  130. package/src/util/txe_contract_store.ts +0 -36
  131. /package/dest/{util → utils}/expected_failure_error.js +0 -0
  132. /package/dest/{util → utils}/txe_account_store.js +0 -0
  133. /package/src/{util → utils}/expected_failure_error.ts +0 -0
  134. /package/src/{util → utils}/txe_account_store.ts +0 -0
@@ -1,9 +1,6 @@
1
1
  import {
2
2
  CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS,
3
- DEFAULT_DA_GAS_LIMIT,
4
- DEFAULT_L2_GAS_LIMIT,
5
- DEFAULT_TEARDOWN_DA_GAS_LIMIT,
6
- DEFAULT_TEARDOWN_L2_GAS_LIMIT,
3
+ MAX_PRIVATE_LOGS_PER_TX,
7
4
  NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP,
8
5
  } from '@aztec/constants';
9
6
  import { BlockNumber } from '@aztec/foundation/branded-types';
@@ -14,15 +11,18 @@ import { TestDateProvider } from '@aztec/foundation/timer';
14
11
  import type { KeyStore } from '@aztec/key-store';
15
12
  import {
16
13
  AddressStore,
14
+ CapsuleService,
17
15
  CapsuleStore,
16
+ type ContractStore,
17
+ type ExecutionHooks,
18
18
  NoteStore,
19
- ORACLE_VERSION,
19
+ ORACLE_VERSION_MAJOR,
20
20
  PrivateEventStore,
21
21
  RecipientTaggingStore,
22
22
  SenderAddressBookStore,
23
23
  SenderTaggingStore,
24
+ composeHooks,
24
25
  enrichPublicSimulationError,
25
- syncState,
26
26
  } from '@aztec/pxe/server';
27
27
  import {
28
28
  ExecutionNoteCache,
@@ -63,6 +63,7 @@ import {
63
63
  PrivateToPublicAccumulatedData,
64
64
  PublicCallRequest,
65
65
  } from '@aztec/stdlib/kernel';
66
+ import { hashPublicKey } from '@aztec/stdlib/keys';
66
67
  import { ChonkProof } from '@aztec/stdlib/proofs';
67
68
  import { makeGlobalVariables } from '@aztec/stdlib/testing';
68
69
  import { MerkleTreeId } from '@aztec/stdlib/trees';
@@ -79,14 +80,13 @@ import {
79
80
  collectNested,
80
81
  } from '@aztec/stdlib/tx';
81
82
  import type { UInt64 } from '@aztec/stdlib/types';
82
- import { ForkCheckpoint } from '@aztec/world-state';
83
+ import { ForkCheckpoint } from '@aztec/world-state/native';
83
84
 
84
85
  import { DEFAULT_ADDRESS } from '../constants.js';
85
86
  import type { TXEStateMachine } from '../state_machine/index.js';
86
- import type { TXEAccountStore } from '../util/txe_account_store.js';
87
- import type { TXEContractStore } from '../util/txe_contract_store.js';
88
- import { TXEPublicContractDataSource } from '../util/txe_public_contract_data_source.js';
89
87
  import { getSingleTxBlockRequestHash, insertTxEffectIntoWorldTrees, makeTXEBlock } from '../utils/block_creation.js';
88
+ import type { TXEAccountStore } from '../utils/txe_account_store.js';
89
+ import { TXEPublicContractDataSource } from '../utils/txe_public_contract_data_source.js';
90
90
  import type { ITxeExecutionOracle } from './interfaces.js';
91
91
 
92
92
  export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracle {
@@ -97,7 +97,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
97
97
 
98
98
  constructor(
99
99
  private stateMachine: TXEStateMachine,
100
- private contractStore: TXEContractStore,
100
+ private contractStore: ContractStore,
101
101
  private noteStore: NoteStore,
102
102
  private keyStore: KeyStore,
103
103
  private addressStore: AddressStore,
@@ -107,7 +107,6 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
107
107
  private senderAddressBookStore: SenderAddressBookStore,
108
108
  private capsuleStore: CapsuleStore,
109
109
  private privateEventStore: PrivateEventStore,
110
- private jobId: string,
111
110
  private nextBlockTimestamp: bigint,
112
111
  private version: Fr,
113
112
  private chainId: Fr,
@@ -117,49 +116,62 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
117
116
  this.logger.debug('Entering Top Level Context');
118
117
  }
119
118
 
120
- utilityAssertCompatibleOracleVersion(version: number): void {
121
- if (version !== ORACLE_VERSION) {
119
+ private contractOracleVersion: { major: number; minor: number } | undefined;
120
+
121
+ assertCompatibleOracleVersion(major: number, minor: number): void {
122
+ if (major !== ORACLE_VERSION_MAJOR) {
123
+ const hint =
124
+ major > ORACLE_VERSION_MAJOR
125
+ ? 'The contract was compiled with a newer version of Aztec.nr than this aztec cli version supports. Upgrade your aztec cli version to a compatible version.'
126
+ : 'The contract was compiled with an older version of Aztec.nr than this aztec cli version supports. Recompile the contract with a compatible version of Aztec.nr.';
122
127
  throw new Error(
123
- `Incompatible oracle version. TXE is using version '${ORACLE_VERSION}', but got a request for '${version}'.`,
128
+ `Incompatible aztec cli version: ${hint} See https://docs.aztec.network/errors/8 (expected oracle major version ${ORACLE_VERSION_MAJOR}, got ${major})`,
124
129
  );
125
130
  }
131
+ this.contractOracleVersion = { major, minor };
132
+ }
133
+
134
+ // Prefixed with "nonOracleFunction" as it is not used as an oracle handler.
135
+ nonOracleFunctionGetContractOracleVersion(): { major: number; minor: number } | undefined {
136
+ return this.contractOracleVersion;
126
137
  }
127
138
 
128
139
  // This is typically only invoked in private contexts, but it is convenient to also have it in top-level for testing
129
140
  // setup.
130
- utilityGetRandomField(): Fr {
141
+ getRandomField(): Fr {
131
142
  return Fr.random();
132
143
  }
133
144
 
134
145
  // We instruct users to debug contracts via this oracle, so it makes sense that they'd expect it to also work in tests
135
- utilityDebugLog(level: number, message: string, fields: Fr[]): void {
146
+ log(level: number, message: string, fields: Fr[]): Promise<void> {
136
147
  if (!LogLevels[level]) {
137
- throw new Error(`Invalid debug log level: ${level}`);
148
+ throw new Error(`Invalid log level: ${level}`);
138
149
  }
139
150
  const levelName = LogLevels[level];
140
151
 
141
152
  this.logger[levelName](`${applyStringFormatting(message, fields)}`, { module: `${this.logger.module}:debug_log` });
153
+ return Promise.resolve();
142
154
  }
143
155
 
144
- txeGetDefaultAddress(): AztecAddress {
156
+ getDefaultAddress(): AztecAddress {
145
157
  return DEFAULT_ADDRESS;
146
158
  }
147
159
 
148
- async txeGetNextBlockNumber(): Promise<BlockNumber> {
160
+ async getNextBlockNumber(): Promise<BlockNumber> {
149
161
  return BlockNumber((await this.getLastBlockNumber()) + 1);
150
162
  }
151
163
 
152
- txeGetNextBlockTimestamp(): Promise<bigint> {
164
+ getNextBlockTimestamp(): Promise<bigint> {
153
165
  return Promise.resolve(this.nextBlockTimestamp);
154
166
  }
155
167
 
156
- async txeGetLastBlockTimestamp() {
157
- return (await this.stateMachine.node.getBlockHeader('latest'))!.globalVariables.timestamp;
168
+ async getLastBlockTimestamp() {
169
+ return (await this.stateMachine.node.getBlockData('latest'))!.header.globalVariables.timestamp;
158
170
  }
159
171
 
160
- async txeGetLastTxEffects() {
172
+ async getLastTxEffects() {
161
173
  const latestBlockNumber = await this.stateMachine.archiver.getBlockNumber();
162
- const block = await this.stateMachine.archiver.getBlock(latestBlockNumber);
174
+ const block = await this.stateMachine.archiver.getBlock({ number: latestBlockNumber });
163
175
 
164
176
  if (block!.body.txEffects.length != 1) {
165
177
  // Note that calls like env.mine() will result in blocks with no transactions, hitting this
@@ -168,10 +180,39 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
168
180
 
169
181
  const txEffects = block!.body.txEffects[0];
170
182
 
171
- return { txHash: txEffects.txHash, noteHashes: txEffects.noteHashes, nullifiers: txEffects.nullifiers };
183
+ const privateLogs = txEffects.privateLogs;
184
+ if (privateLogs.length > MAX_PRIVATE_LOGS_PER_TX) {
185
+ throw new Error(`${privateLogs.length} private logs exceed max ${MAX_PRIVATE_LOGS_PER_TX}`);
186
+ }
187
+
188
+ return {
189
+ txHash: txEffects.txHash,
190
+ noteHashes: txEffects.noteHashes,
191
+ nullifiers: txEffects.nullifiers,
192
+ privateLogs,
193
+ };
172
194
  }
173
195
 
174
- async txeGetPrivateEvents(selector: EventSelector, contractAddress: AztecAddress, scope: AztecAddress) {
196
+ async syncContractNonOracleMethod(contractAddress: AztecAddress, scope: AztecAddress, jobId: string) {
197
+ if (contractAddress.equals(DEFAULT_ADDRESS)) {
198
+ this.logger.debug(`Skipping sync in getPrivateEvents because the events correspond to the default address.`);
199
+ return;
200
+ }
201
+
202
+ const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
203
+ await this.stateMachine.contractSyncService.ensureContractSynced(
204
+ contractAddress,
205
+ null,
206
+ async (call, execScopes) => {
207
+ await this.executeUtilityCall(call, execScopes, jobId);
208
+ },
209
+ blockHeader,
210
+ jobId,
211
+ [scope],
212
+ );
213
+ }
214
+
215
+ async getPrivateEvents(selector: EventSelector, contractAddress: AztecAddress, scope: AztecAddress) {
175
216
  return (
176
217
  await this.privateEventStore.getPrivateEvents(selector, {
177
218
  contractAddress,
@@ -182,7 +223,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
182
223
  ).map(e => e.packedEvent);
183
224
  }
184
225
 
185
- async txeAdvanceBlocksBy(blocks: number) {
226
+ async advanceBlocksBy(blocks: number) {
186
227
  this.logger.debug(`time traveling ${blocks} blocks`);
187
228
 
188
229
  for (let i = 0; i < blocks; i++) {
@@ -190,37 +231,45 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
190
231
  }
191
232
  }
192
233
 
193
- txeAdvanceTimestampBy(duration: UInt64) {
234
+ advanceTimestampBy(duration: UInt64) {
194
235
  this.logger.debug(`time traveling ${duration} seconds`);
195
236
  this.nextBlockTimestamp += duration;
196
237
  }
197
238
 
198
- async txeDeploy(artifact: ContractArtifact, instance: ContractInstanceWithAddress, secret: Fr) {
239
+ private deploymentNullifier(address: AztecAddress): Promise<Fr> {
240
+ return siloNullifier(AztecAddress.fromNumber(CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS), address.toField());
241
+ }
242
+
243
+ async deploy(artifact: ContractArtifact, instance: ContractInstanceWithAddress, secret: Fr) {
199
244
  // Emit deployment nullifier
200
245
  await this.mineBlock({
201
- nullifiers: [
202
- await siloNullifier(
203
- AztecAddress.fromNumber(CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS),
204
- instance.address.toField(),
205
- ),
206
- ],
246
+ nullifiers: [await this.deploymentNullifier(instance.address)],
207
247
  });
208
248
 
209
249
  if (!secret.equals(Fr.ZERO)) {
210
- await this.txeAddAccount(artifact, instance, secret);
250
+ await this.addAccount(artifact, instance, secret);
211
251
  } else {
212
252
  await this.contractStore.addContractInstance(instance);
213
- await this.contractStore.addContractArtifact(instance.currentContractClassId, artifact);
253
+ await this.contractStore.addContractArtifact(artifact);
214
254
  this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
215
255
  }
216
256
  }
217
257
 
218
- async txeAddAccount(artifact: ContractArtifact, instance: ContractInstanceWithAddress, secret: Fr) {
258
+ /**
259
+ * Mines a single block containing only the deployment nullifiers for the contracts at the given addresses.
260
+ */
261
+ async mineDeploymentNullifiers(addresses: AztecAddress[]) {
262
+ await this.mineBlock({
263
+ nullifiers: await Promise.all(addresses.map(address => this.deploymentNullifier(address))),
264
+ });
265
+ }
266
+
267
+ async addAccount(artifact: ContractArtifact, instance: ContractInstanceWithAddress, secret: Fr) {
219
268
  const partialAddress = await computePartialAddress(instance);
220
269
 
221
270
  this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
222
271
  await this.contractStore.addContractInstance(instance);
223
- await this.contractStore.addContractArtifact(instance.currentContractClassId, artifact);
272
+ await this.contractStore.addContractArtifact(artifact);
224
273
 
225
274
  const completeAddress = await this.keyStore.addAccount(secret, partialAddress);
226
275
  await this.accountStore.setAccount(completeAddress.address, completeAddress);
@@ -230,7 +279,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
230
279
  return completeAddress;
231
280
  }
232
281
 
233
- async txeCreateAccount(secret: Fr) {
282
+ async createAccount(secret: Fr) {
234
283
  // This is a foot gun !
235
284
  const completeAddress = await this.keyStore.addAccount(secret, secret);
236
285
  await this.accountStore.setAccount(completeAddress.address, completeAddress);
@@ -240,20 +289,21 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
240
289
  return completeAddress;
241
290
  }
242
291
 
243
- async txeAddAuthWitness(address: AztecAddress, messageHash: Fr) {
292
+ async addAuthWitness(address: AztecAddress, messageHash: Fr) {
244
293
  const account = await this.accountStore.getAccount(address);
245
- const privateKey = await this.keyStore.getMasterSecretKey(account.publicKeys.masterIncomingViewingPublicKey);
294
+ const ivpkMHash = await hashPublicKey(account.publicKeys.ivpkM);
295
+ const privateKey = await this.keyStore.getMasterSecretKey(ivpkMHash);
246
296
 
247
297
  const schnorr = new Schnorr();
248
- const signature = await schnorr.constructSignature(messageHash.toBuffer(), privateKey);
298
+ const signature = await schnorr.constructSignature(messageHash, privateKey);
249
299
 
250
- const authWitness = new AuthWitness(messageHash, [...signature.toBuffer()]);
300
+ const authWitness = new AuthWitness(messageHash, signature.toLimbFields());
251
301
 
252
302
  this.authwits.set(authWitness.requestHash.toString(), authWitness);
253
303
  }
254
304
 
255
305
  async mineBlock(options: { nullifiers?: Fr[] } = {}) {
256
- const blockNumber = await this.txeGetNextBlockNumber();
306
+ const blockNumber = await this.getNextBlockNumber();
257
307
 
258
308
  const txEffect = TxEffect.empty();
259
309
  txEffect.nullifiers = [getSingleTxBlockRequestHash(blockNumber), ...(options.nullifiers ?? [])];
@@ -277,13 +327,17 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
277
327
  await this.stateMachine.handleL2Block(block);
278
328
  }
279
329
 
280
- async txePrivateCallNewFlow(
281
- from: AztecAddress,
330
+ async privateCallNewFlow(
331
+ from: AztecAddress | undefined,
282
332
  targetContractAddress: AztecAddress = AztecAddress.zero(),
283
333
  functionSelector: FunctionSelector = FunctionSelector.empty(),
284
334
  args: Fr[],
285
335
  argsHash: Fr = Fr.zero(),
286
336
  isStaticCall: boolean = false,
337
+ additionalScopes: AztecAddress[] = [],
338
+ jobId: string,
339
+ authorizedUtilityCallTargets: AztecAddress[],
340
+ gasSettings: GasSettings,
287
341
  ) {
288
342
  this.logger.verbose(
289
343
  `Executing external function ${await this.contractStore.getDebugFunctionName(targetContractAddress, functionSelector)}@${targetContractAddress} isStaticCall=${isStaticCall}`,
@@ -297,30 +351,27 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
297
351
  throw new Error(message);
298
352
  }
299
353
 
354
+ const scopes = from === undefined ? additionalScopes : [from, ...additionalScopes];
355
+
300
356
  // Sync notes before executing private function to discover notes from previous transactions
301
- const utilityExecutor = async (call: FunctionCall) => {
302
- await this.executeUtilityCall(call);
357
+ const utilityExecutor = async (call: FunctionCall, execScopes: AztecAddress[]) => {
358
+ await this.executeUtilityCall(call, execScopes, jobId);
303
359
  };
304
360
 
305
361
  const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
306
- await syncState(
362
+ await this.stateMachine.contractSyncService.ensureContractSynced(
307
363
  targetContractAddress,
308
- this.contractStore,
309
364
  functionSelector,
310
365
  utilityExecutor,
311
- this.noteStore,
312
- this.stateMachine.node,
313
366
  blockHeader,
314
- this.jobId,
367
+ jobId,
368
+ scopes,
315
369
  );
316
370
 
317
- const blockNumber = await this.txeGetNextBlockNumber();
371
+ const blockNumber = await this.getNextBlockNumber();
318
372
 
319
- const callContext = new CallContext(from, targetContractAddress, functionSelector, isStaticCall);
320
-
321
- const gasLimits = new Gas(DEFAULT_DA_GAS_LIMIT, DEFAULT_L2_GAS_LIMIT);
322
- const teardownGasLimits = new Gas(DEFAULT_TEARDOWN_DA_GAS_LIMIT, DEFAULT_TEARDOWN_L2_GAS_LIMIT);
323
- const gasSettings = new GasSettings(gasLimits, teardownGasLimits, GasFees.empty(), GasFees.empty());
373
+ const msgSender = from ?? AztecAddress.NULL_MSG_SENDER;
374
+ const callContext = new CallContext(msgSender, targetContractAddress, functionSelector, isStaticCall);
324
375
 
325
376
  const txContext = new TxContext(this.chainId, this.version, gasSettings);
326
377
 
@@ -335,42 +386,45 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
335
386
 
336
387
  const simulator = new WASMSimulator();
337
388
 
338
- const privateExecutionOracle = new PrivateExecutionOracle(
389
+ const privateExecutionOracle = new PrivateExecutionOracle({
339
390
  argsHash,
340
391
  txContext,
341
392
  callContext,
342
- /** Header of a block whose state is used during private execution (not the block the transaction is included in). */
343
- blockHeader,
393
+ anchorBlockHeader: blockHeader,
344
394
  utilityExecutor,
345
- /** List of transient auth witnesses to be used during this simulation */
346
- Array.from(this.authwits.values()),
347
- /** List of transient auth witnesses to be used during this simulation */
348
- [],
349
- HashedValuesCache.create([new HashedValues(args, argsHash)]),
395
+ authWitnesses: Array.from(this.authwits.values()),
396
+ capsules: [],
397
+ executionCache: HashedValuesCache.create([new HashedValues(args, argsHash)]),
350
398
  noteCache,
351
399
  taggingIndexCache,
352
- this.contractStore,
353
- this.noteStore,
354
- this.keyStore,
355
- this.addressStore,
356
- this.stateMachine.node,
357
- this.senderTaggingStore,
358
- this.recipientTaggingStore,
359
- this.senderAddressBookStore,
360
- this.capsuleStore,
361
- this.privateEventStore,
362
- this.jobId,
363
- 0, // totalPublicArgsCount
364
- minRevertibleSideEffectCounter, // (start) sideEffectCounter
365
- undefined, // log
366
- undefined, // scopes
367
- /**
368
- * In TXE, the typical transaction entrypoint is skipped, so we need to simulate the actions that such a
369
- * contract would perform, including setting senderForTags.
370
- */
371
- from,
400
+ contractStore: this.contractStore,
401
+ noteStore: this.noteStore,
402
+ keyStore: this.keyStore,
403
+ addressStore: this.addressStore,
404
+ aztecNode: this.stateMachine.node,
405
+ senderTaggingStore: this.senderTaggingStore,
406
+ recipientTaggingStore: this.recipientTaggingStore,
407
+ senderAddressBookStore: this.senderAddressBookStore,
408
+ capsuleService: new CapsuleService(this.capsuleStore, scopes),
409
+ privateEventStore: this.privateEventStore,
410
+ contractSyncService: this.stateMachine.contractSyncService,
411
+ jobId,
412
+ totalPublicCalldataCount: 0,
413
+ sideEffectCounter: minRevertibleSideEffectCounter,
414
+ scopes,
415
+ // In TXE, the typical transaction entrypoint is skipped, so we need to simulate the actions that such a
416
+ // contract would perform, including setting senderForTags.
417
+ senderForTags: from,
372
418
  simulator,
373
- );
419
+ messageContextService: this.stateMachine.messageContextService,
420
+ l2TipsStore: this.stateMachine.l2TipsProvider,
421
+ hooks: composeHooks({
422
+ authorizeUtilityCall: this.buildAuthorizeUtilityCallHook(
423
+ isStaticCall ? 'private view' : 'private',
424
+ authorizedUtilityCallTargets,
425
+ ),
426
+ }),
427
+ });
374
428
 
375
429
  // Note: This is a slight modification of simulator.run without any of the checks. Maybe we should modify simulator.run with a boolean value to skip checks.
376
430
  let result: PrivateExecutionResult;
@@ -392,7 +446,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
392
446
  );
393
447
  const publicFunctionsCalldata = await Promise.all(
394
448
  publicCallRequests.map(async r => {
395
- const calldata = await privateExecutionOracle.privateLoadFromExecutionCache(r.calldataHash);
449
+ const calldata = await privateExecutionOracle.getHashPreimage(r.calldataHash);
396
450
  return new HashedValues(calldata, r.calldataHash);
397
451
  }),
398
452
  );
@@ -409,7 +463,8 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
409
463
  // We pass the non-zero minRevertibleSideEffectCounter to make sure the side effects are split correctly.
410
464
  const { publicInputs } = await generateSimulatedProvingResult(
411
465
  result,
412
- this.contractStore,
466
+ (addr, sel) => this.contractStore.getDebugFunctionName(addr, sel),
467
+ this.stateMachine.node,
413
468
  minRevertibleSideEffectCounter,
414
469
  );
415
470
 
@@ -476,11 +531,17 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
476
531
  }
477
532
  }
478
533
 
534
+ // Walk the nested private-call tree and collect every offchain effect the transaction emitted.
535
+ // PXE stores these on each `PrivateCallExecutionResult` and they never reach TXE via the
536
+ // `aztec_utl_emitOffchainEffect` foreign-call path (that path only fires at the top-level), so
537
+ // we pull them out here and the RPC wrapper will hand them to `TXESession` for buffering.
538
+ const offchainEffects = collectNested([executionResult], r => r.offchainEffects.map(e => e.data));
539
+
479
540
  if (isStaticCall) {
480
541
  await checkpoint!.revert();
481
542
 
482
543
  await forkedWorldTrees.close();
483
- return executionResult.returnValues ?? [];
544
+ return { returnValues: executionResult.returnValues ?? [], offchainEffects };
484
545
  }
485
546
 
486
547
  const txEffect = TxEffect.empty();
@@ -502,26 +563,21 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
502
563
 
503
564
  await forkedWorldTrees.close();
504
565
 
505
- return executionResult.returnValues ?? [];
566
+ return { returnValues: executionResult.returnValues ?? [], offchainEffects };
506
567
  }
507
568
 
508
- async txePublicCallNewFlow(
509
- from: AztecAddress,
569
+ async publicCallNewFlow(
570
+ from: AztecAddress | undefined,
510
571
  targetContractAddress: AztecAddress,
511
572
  calldata: Fr[],
512
573
  isStaticCall: boolean,
574
+ gasSettings: GasSettings,
513
575
  ) {
514
576
  this.logger.verbose(
515
577
  `Executing public function ${await this.contractStore.getDebugFunctionName(targetContractAddress, FunctionSelector.fromField(calldata[0]))}@${targetContractAddress} isStaticCall=${isStaticCall}`,
516
578
  );
517
579
 
518
- const blockNumber = await this.txeGetNextBlockNumber();
519
-
520
- const gasLimits = new Gas(DEFAULT_DA_GAS_LIMIT, DEFAULT_L2_GAS_LIMIT);
521
-
522
- const teardownGasLimits = new Gas(DEFAULT_TEARDOWN_DA_GAS_LIMIT, DEFAULT_TEARDOWN_L2_GAS_LIMIT);
523
-
524
- const gasSettings = new GasSettings(gasLimits, teardownGasLimits, GasFees.empty(), GasFees.empty());
580
+ const blockNumber = await this.getNextBlockNumber();
525
581
 
526
582
  const txContext = new TxContext(this.chainId, this.version, gasSettings);
527
583
 
@@ -574,7 +630,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
574
630
  // may require producing reverts.
575
631
  const revertibleAccumulatedData = PrivateToPublicAccumulatedData.empty();
576
632
  revertibleAccumulatedData.publicCallRequests[0] = new PublicCallRequest(
577
- from,
633
+ from ?? AztecAddress.NULL_MSG_SENDER,
578
634
  targetContractAddress,
579
635
  isStaticCall,
580
636
  calldataHash,
@@ -592,7 +648,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
592
648
  constantData,
593
649
  /*gasUsed=*/ new Gas(0, 0),
594
650
  /*feePayer=*/ AztecAddress.zero(),
595
- /*includeByTimestamp=*/ 0n,
651
+ /*expirationTimestamp=*/ 0n,
596
652
  inputsForPublic,
597
653
  undefined,
598
654
  );
@@ -660,10 +716,12 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
660
716
  return returnValues ?? [];
661
717
  }
662
718
 
663
- async txeSimulateUtilityFunction(
719
+ async executeUtilityFunction(
664
720
  targetContractAddress: AztecAddress,
665
721
  functionSelector: FunctionSelector,
666
722
  args: Fr[],
723
+ jobId: string,
724
+ authorizedUtilityCallTargets: AztecAddress[],
667
725
  ) {
668
726
  const artifact = await this.contractStore.getFunctionArtifact(targetContractAddress, functionSelector);
669
727
  if (!artifact) {
@@ -672,34 +730,37 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
672
730
 
673
731
  // Sync notes before executing utility function to discover notes from previous transactions
674
732
  const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
675
- await syncState(
733
+ await this.stateMachine.contractSyncService.ensureContractSynced(
676
734
  targetContractAddress,
677
- this.contractStore,
678
735
  functionSelector,
679
- async call => {
680
- await this.executeUtilityCall(call);
736
+ async (call, execScopes) => {
737
+ await this.executeUtilityCall(call, execScopes, jobId);
681
738
  },
682
- this.noteStore,
683
- this.stateMachine.node,
684
739
  blockHeader,
685
- this.jobId,
740
+ jobId,
741
+ await this.keyStore.getAccounts(),
686
742
  );
687
743
 
688
- const call = new FunctionCall(
689
- artifact.name,
690
- targetContractAddress,
691
- functionSelector,
692
- FunctionType.UTILITY,
693
- false,
694
- false,
744
+ const call = FunctionCall.from({
745
+ name: artifact.name,
746
+ to: targetContractAddress,
747
+ selector: functionSelector,
748
+ type: FunctionType.UTILITY,
749
+ hideMsgSender: false,
750
+ isStatic: false,
695
751
  args,
696
- [],
697
- );
752
+ returnTypes: [],
753
+ });
698
754
 
699
- return this.executeUtilityCall(call);
755
+ return this.executeUtilityCall(call, await this.keyStore.getAccounts(), jobId, authorizedUtilityCallTargets);
700
756
  }
701
757
 
702
- private async executeUtilityCall(call: FunctionCall): Promise<Fr[]> {
758
+ private async executeUtilityCall(
759
+ call: FunctionCall,
760
+ scopes: AztecAddress[],
761
+ jobId: string,
762
+ authorizedUtilityCallTargets: AztecAddress[] = [],
763
+ ): Promise<Fr[]> {
703
764
  const entryPointArtifact = await this.contractStore.getFunctionArtifactWithDebugMetadata(call.to, call.selector);
704
765
  if (entryPointArtifact.functionType !== FunctionType.UTILITY) {
705
766
  throw new Error(`Cannot run ${entryPointArtifact.functionType} function as utility`);
@@ -712,23 +773,36 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
712
773
 
713
774
  try {
714
775
  const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
715
- const oracle = new UtilityExecutionOracle(
716
- call.to,
717
- [],
718
- [],
776
+ const simulator = new WASMSimulator();
777
+ const utilityExecutor = async (syncCall: FunctionCall, execScopes: AztecAddress[]) => {
778
+ await this.executeUtilityCall(syncCall, execScopes, jobId);
779
+ };
780
+ const oracle = new UtilityExecutionOracle({
781
+ contractAddress: call.to,
782
+ authWitnesses: [],
783
+ capsules: [],
719
784
  anchorBlockHeader,
720
- this.contractStore,
721
- this.noteStore,
722
- this.keyStore,
723
- this.addressStore,
724
- this.stateMachine.node,
725
- this.recipientTaggingStore,
726
- this.senderAddressBookStore,
727
- this.capsuleStore,
728
- this.privateEventStore,
729
- this.jobId,
730
- );
731
- const acirExecutionResult = await new WASMSimulator()
785
+ contractStore: this.contractStore,
786
+ noteStore: this.noteStore,
787
+ keyStore: this.keyStore,
788
+ addressStore: this.addressStore,
789
+ aztecNode: this.stateMachine.node,
790
+ recipientTaggingStore: this.recipientTaggingStore,
791
+ senderAddressBookStore: this.senderAddressBookStore,
792
+ capsuleService: new CapsuleService(this.capsuleStore, scopes),
793
+ privateEventStore: this.privateEventStore,
794
+ messageContextService: this.stateMachine.messageContextService,
795
+ contractSyncService: this.stateMachine.contractSyncService,
796
+ l2TipsStore: this.stateMachine.l2TipsProvider,
797
+ jobId,
798
+ scopes,
799
+ simulator,
800
+ hooks: composeHooks({
801
+ authorizeUtilityCall: this.buildAuthorizeUtilityCallHook('utility', authorizedUtilityCallTargets),
802
+ }),
803
+ utilityExecutor,
804
+ });
805
+ const acirExecutionResult = await simulator
732
806
  .executeUserCircuit(toACVMWitness(0, call.args), entryPointArtifact, new Oracle(oracle).toACIRCallback())
733
807
  .catch((err: Error) => {
734
808
  err.message = resolveAssertionMessageFromError(err, entryPointArtifact);
@@ -743,10 +817,10 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
743
817
  );
744
818
  });
745
819
 
746
- this.logger.verbose(`Utility simulation for ${call.to}.${call.selector} completed`);
820
+ this.logger.verbose(`Utility execution for ${call.to}.${call.selector} completed`);
747
821
  return witnessMapToFields(acirExecutionResult.returnWitness);
748
822
  } catch (err) {
749
- throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during utility simulation'));
823
+ throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during utility execution'));
750
824
  }
751
825
  }
752
826
 
@@ -756,7 +830,20 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
756
830
  }
757
831
 
758
832
  private async getLastBlockNumber(): Promise<BlockNumber> {
759
- const header = await this.stateMachine.node.getBlockHeader('latest');
760
- return header ? header.globalVariables.blockNumber : BlockNumber.ZERO;
833
+ const block = await this.stateMachine.node.getBlock('latest');
834
+ return block ? block.header.globalVariables.blockNumber : BlockNumber.ZERO;
835
+ }
836
+
837
+ private buildAuthorizeUtilityCallHook(
838
+ callerContext: 'private' | 'private view' | 'utility',
839
+ authorizedTargets: AztecAddress[],
840
+ ): ExecutionHooks['authorizeUtilityCall'] | undefined {
841
+ if (authorizedTargets.length === 0) {
842
+ return undefined;
843
+ }
844
+ return req =>
845
+ Promise.resolve({
846
+ authorized: req.callerContext === callerContext && authorizedTargets.some(t => t.equals(req.target)),
847
+ });
761
848
  }
762
849
  }