@aztec/txe 0.0.1-commit.e558bd1c → 0.0.1-commit.e57c76e

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 (154) hide show
  1. package/dest/ContractClassRegistry-PII7Q556.js +3 -0
  2. package/dest/ContractClassRegistry-PII7Q556.js.map +7 -0
  3. package/dest/ContractInstanceRegistry-3MHLGFNZ.js +3 -0
  4. package/dest/ContractInstanceRegistry-3MHLGFNZ.js.map +7 -0
  5. package/dest/FeeJuice-TQV5AQK7.js +3 -0
  6. package/dest/FeeJuice-TQV5AQK7.js.map +7 -0
  7. package/dest/MultiCallEntrypoint-SBJUIJY7.js +3 -0
  8. package/dest/MultiCallEntrypoint-SBJUIJY7.js.map +7 -0
  9. package/dest/SchnorrAccount-MQXPIZ44.js +3 -0
  10. package/dest/SchnorrAccount-MQXPIZ44.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 +61 -0
  14. package/dest/bin/index.js +3 -30
  15. package/dest/bin/index.js.map +7 -0
  16. package/dest/bin/oracle_test_server.d.ts +3 -0
  17. package/dest/bin/oracle_test_server.d.ts.map +1 -0
  18. package/dest/bin/oracle_test_server.js +41 -0
  19. package/dest/chunk-3VX4QA7B.js +265 -0
  20. package/dest/chunk-3VX4QA7B.js.map +7 -0
  21. package/dest/chunk-BJVAAXNA.js +3 -0
  22. package/dest/chunk-BJVAAXNA.js.map +7 -0
  23. package/dest/chunk-FU3LBVE4.js +304 -0
  24. package/dest/chunk-FU3LBVE4.js.map +7 -0
  25. package/dest/constants.d.ts +5 -1
  26. package/dest/constants.d.ts.map +1 -1
  27. package/dest/constants.js +8 -0
  28. package/dest/dispatcher_pool.d.ts +67 -0
  29. package/dest/dispatcher_pool.d.ts.map +1 -0
  30. package/dest/dispatcher_pool.js +284 -0
  31. package/dest/index.d.ts +185 -7
  32. package/dest/index.d.ts.map +1 -1
  33. package/dest/index.js +71 -157
  34. package/dest/metafile.json +38352 -0
  35. package/dest/msgpackr_fr_extension.d.ts +2 -0
  36. package/dest/msgpackr_fr_extension.d.ts.map +1 -0
  37. package/dest/msgpackr_fr_extension.js +21 -0
  38. package/dest/oracle/interfaces.d.ts +56 -30
  39. package/dest/oracle/interfaces.d.ts.map +1 -1
  40. package/dest/oracle/test-resolver/fixtures.d.ts +43 -0
  41. package/dest/oracle/test-resolver/fixtures.d.ts.map +1 -0
  42. package/dest/oracle/test-resolver/fixtures.js +39 -0
  43. package/dest/oracle/test-resolver/index.d.ts +9 -0
  44. package/dest/oracle/test-resolver/index.d.ts.map +1 -0
  45. package/dest/oracle/test-resolver/index.js +33 -0
  46. package/dest/oracle/test-resolver/resolver.d.ts +34 -0
  47. package/dest/oracle/test-resolver/resolver.d.ts.map +1 -0
  48. package/dest/oracle/test-resolver/resolver.js +114 -0
  49. package/dest/oracle/txe_oracle_public_context.d.ts +38 -14
  50. package/dest/oracle/txe_oracle_public_context.d.ts.map +1 -1
  51. package/dest/oracle/txe_oracle_public_context.js +55 -13
  52. package/dest/oracle/txe_oracle_registry.d.ts +147 -0
  53. package/dest/oracle/txe_oracle_registry.d.ts.map +1 -0
  54. package/dest/oracle/txe_oracle_registry.js +562 -0
  55. package/dest/oracle/txe_oracle_top_level_context.d.ts +45 -26
  56. package/dest/oracle/txe_oracle_top_level_context.d.ts.map +1 -1
  57. package/dest/oracle/txe_oracle_top_level_context.js +241 -85
  58. package/dest/oracle/txe_oracle_version.d.ts +17 -0
  59. package/dest/oracle/txe_oracle_version.d.ts.map +1 -0
  60. package/dest/oracle/txe_oracle_version.js +14 -0
  61. package/dest/oracle/txe_private_execution_oracle.d.ts +17 -0
  62. package/dest/oracle/txe_private_execution_oracle.d.ts.map +1 -0
  63. package/dest/oracle/txe_private_execution_oracle.js +15 -0
  64. package/dest/rpc_server.d.ts +14 -0
  65. package/dest/rpc_server.d.ts.map +1 -0
  66. package/dest/rpc_server.js +78 -0
  67. package/dest/rpc_translator.d.ts +96 -228
  68. package/dest/rpc_translator.d.ts.map +1 -1
  69. package/dest/rpc_translator.js +815 -624
  70. package/dest/server.bundle.js +3 -0
  71. package/dest/server.bundle.js.map +7 -0
  72. package/dest/state_machine/archiver.d.ts +6 -5
  73. package/dest/state_machine/archiver.d.ts.map +1 -1
  74. package/dest/state_machine/archiver.js +30 -21
  75. package/dest/state_machine/dummy_p2p_client.d.ts +24 -15
  76. package/dest/state_machine/dummy_p2p_client.d.ts.map +1 -1
  77. package/dest/state_machine/dummy_p2p_client.js +39 -18
  78. package/dest/state_machine/global_variable_builder.d.ts +9 -4
  79. package/dest/state_machine/global_variable_builder.d.ts.map +1 -1
  80. package/dest/state_machine/global_variable_builder.js +9 -3
  81. package/dest/state_machine/index.d.ts +7 -3
  82. package/dest/state_machine/index.d.ts.map +1 -1
  83. package/dest/state_machine/index.js +23 -5
  84. package/dest/state_machine/mock_epoch_cache.d.ts +18 -3
  85. package/dest/state_machine/mock_epoch_cache.d.ts.map +1 -1
  86. package/dest/state_machine/mock_epoch_cache.js +33 -2
  87. package/dest/state_machine/synchronizer.d.ts +5 -5
  88. package/dest/state_machine/synchronizer.d.ts.map +1 -1
  89. package/dest/state_machine/synchronizer.js +4 -4
  90. package/dest/txe_session.d.ts +80 -15
  91. package/dest/txe_session.d.ts.map +1 -1
  92. package/dest/txe_session.js +236 -42
  93. package/dest/utils/encoding.d.ts +191 -0
  94. package/dest/utils/encoding.d.ts.map +1 -0
  95. package/dest/{util → utils}/encoding.js +7 -2
  96. package/dest/{util → utils}/expected_failure_error.d.ts +1 -1
  97. package/dest/utils/expected_failure_error.d.ts.map +1 -0
  98. package/dest/{util → utils}/txe_account_store.d.ts +1 -1
  99. package/dest/utils/txe_account_store.d.ts.map +1 -0
  100. package/dest/utils/txe_artifact_resolver.d.ts +37 -0
  101. package/dest/utils/txe_artifact_resolver.d.ts.map +1 -0
  102. package/dest/utils/txe_artifact_resolver.js +161 -0
  103. package/dest/utils/txe_public_contract_data_source.d.ts +20 -0
  104. package/dest/utils/txe_public_contract_data_source.d.ts.map +1 -0
  105. package/dest/{util → utils}/txe_public_contract_data_source.js +6 -25
  106. package/dest/worker.bundle.js +3 -0
  107. package/dest/worker.bundle.js.map +7 -0
  108. package/dest/worker.d.ts +2 -0
  109. package/dest/worker.d.ts.map +1 -0
  110. package/dest/worker.js +92 -0
  111. package/package.json +38 -21
  112. package/src/bin/check_txe_oracle_version.ts +70 -0
  113. package/src/bin/index.ts +11 -2
  114. package/src/bin/oracle_test_server.ts +51 -0
  115. package/src/constants.ts +10 -0
  116. package/src/dispatcher_pool.ts +316 -0
  117. package/src/index.ts +97 -190
  118. package/src/msgpackr_fr_extension.ts +23 -0
  119. package/src/oracle/interfaces.ts +58 -35
  120. package/src/oracle/test-resolver/fixtures.ts +84 -0
  121. package/src/oracle/test-resolver/index.ts +45 -0
  122. package/src/oracle/test-resolver/resolver.ts +165 -0
  123. package/src/oracle/txe_oracle_public_context.ts +72 -12
  124. package/src/oracle/txe_oracle_registry.ts +401 -0
  125. package/src/oracle/txe_oracle_top_level_context.ts +279 -144
  126. package/src/oracle/txe_oracle_version.ts +17 -0
  127. package/src/oracle/txe_private_execution_oracle.ts +30 -0
  128. package/src/rpc_server.ts +87 -0
  129. package/src/rpc_translator.ts +1000 -1006
  130. package/src/state_machine/archiver.ts +42 -20
  131. package/src/state_machine/dummy_p2p_client.ts +63 -30
  132. package/src/state_machine/global_variable_builder.ts +18 -3
  133. package/src/state_machine/index.ts +25 -5
  134. package/src/state_machine/mock_epoch_cache.ts +43 -3
  135. package/src/state_machine/synchronizer.ts +5 -5
  136. package/src/txe_session.ts +351 -96
  137. package/src/{util → utils}/encoding.ts +8 -2
  138. package/src/utils/txe_artifact_resolver.ts +217 -0
  139. package/src/{util → utils}/txe_public_contract_data_source.ts +10 -38
  140. package/src/worker.ts +98 -0
  141. package/dest/util/encoding.d.ts +0 -720
  142. package/dest/util/encoding.d.ts.map +0 -1
  143. package/dest/util/expected_failure_error.d.ts.map +0 -1
  144. package/dest/util/txe_account_store.d.ts.map +0 -1
  145. package/dest/util/txe_contract_store.d.ts +0 -12
  146. package/dest/util/txe_contract_store.d.ts.map +0 -1
  147. package/dest/util/txe_contract_store.js +0 -22
  148. package/dest/util/txe_public_contract_data_source.d.ts +0 -21
  149. package/dest/util/txe_public_contract_data_source.d.ts.map +0 -1
  150. package/src/util/txe_contract_store.ts +0 -36
  151. /package/dest/{util → utils}/expected_failure_error.js +0 -0
  152. /package/dest/{util → utils}/txe_account_store.js +0 -0
  153. /package/src/{util → utils}/expected_failure_error.ts +0 -0
  154. /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,13 +11,17 @@ 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
26
  } from '@aztec/pxe/server';
26
27
  import {
@@ -62,6 +63,7 @@ import {
62
63
  PrivateToPublicAccumulatedData,
63
64
  PublicCallRequest,
64
65
  } from '@aztec/stdlib/kernel';
66
+ import { hashPublicKey } from '@aztec/stdlib/keys';
65
67
  import { ChonkProof } from '@aztec/stdlib/proofs';
66
68
  import { makeGlobalVariables } from '@aztec/stdlib/testing';
67
69
  import { MerkleTreeId } from '@aztec/stdlib/trees';
@@ -78,14 +80,14 @@ import {
78
80
  collectNested,
79
81
  } from '@aztec/stdlib/tx';
80
82
  import type { UInt64 } from '@aztec/stdlib/types';
81
- import { ForkCheckpoint } from '@aztec/world-state';
83
+ import { ForkCheckpoint } from '@aztec/world-state/native';
82
84
 
83
- import { DEFAULT_ADDRESS } from '../constants.js';
85
+ import { DEFAULT_ADDRESS, MAX_PRIVATE_EVENTS_PER_TXE_QUERY, MAX_PRIVATE_EVENT_LEN } from '../constants.js';
84
86
  import type { TXEStateMachine } from '../state_machine/index.js';
85
- import type { TXEAccountStore } from '../util/txe_account_store.js';
86
- import type { TXEContractStore } from '../util/txe_contract_store.js';
87
- import { TXEPublicContractDataSource } from '../util/txe_public_contract_data_source.js';
88
87
  import { getSingleTxBlockRequestHash, insertTxEffectIntoWorldTrees, makeTXEBlock } from '../utils/block_creation.js';
88
+ import type { TXEAccountStore } from '../utils/txe_account_store.js';
89
+ import type { TXEArtifactResolver } from '../utils/txe_artifact_resolver.js';
90
+ import { TXEPublicContractDataSource } from '../utils/txe_public_contract_data_source.js';
89
91
  import type { ITxeExecutionOracle } from './interfaces.js';
90
92
 
91
93
  export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracle {
@@ -96,7 +98,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
96
98
 
97
99
  constructor(
98
100
  private stateMachine: TXEStateMachine,
99
- private contractStore: TXEContractStore,
101
+ private contractStore: ContractStore,
100
102
  private noteStore: NoteStore,
101
103
  private keyStore: KeyStore,
102
104
  private addressStore: AddressStore,
@@ -106,59 +108,74 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
106
108
  private senderAddressBookStore: SenderAddressBookStore,
107
109
  private capsuleStore: CapsuleStore,
108
110
  private privateEventStore: PrivateEventStore,
109
- private jobId: string,
110
111
  private nextBlockTimestamp: bigint,
111
112
  private version: Fr,
112
113
  private chainId: Fr,
113
114
  private authwits: Map<string, AuthWitness>,
115
+ private readonly artifactResolver: TXEArtifactResolver,
116
+ private readonly rootPath: string,
117
+ private readonly packageName: string,
114
118
  ) {
115
119
  this.logger = createLogger('txe:top_level_context');
116
120
  this.logger.debug('Entering Top Level Context');
117
121
  }
118
122
 
119
- utilityAssertCompatibleOracleVersion(version: number): void {
120
- if (version !== ORACLE_VERSION) {
123
+ private contractOracleVersion: { major: number; minor: number } | undefined;
124
+
125
+ assertCompatibleOracleVersion(major: number, minor: number): void {
126
+ if (major !== ORACLE_VERSION_MAJOR) {
127
+ const hint =
128
+ major > ORACLE_VERSION_MAJOR
129
+ ? '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.'
130
+ : '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.';
121
131
  throw new Error(
122
- `Incompatible oracle version. TXE is using version '${ORACLE_VERSION}', but got a request for '${version}'.`,
132
+ `Incompatible aztec cli version: ${hint} See https://docs.aztec.network/errors/8 (expected oracle major version ${ORACLE_VERSION_MAJOR}, got ${major})`,
123
133
  );
124
134
  }
135
+ this.contractOracleVersion = { major, minor };
136
+ }
137
+
138
+ // Prefixed with "nonOracleFunction" as it is not used as an oracle handler.
139
+ nonOracleFunctionGetContractOracleVersion(): { major: number; minor: number } | undefined {
140
+ return this.contractOracleVersion;
125
141
  }
126
142
 
127
143
  // This is typically only invoked in private contexts, but it is convenient to also have it in top-level for testing
128
144
  // setup.
129
- utilityGetRandomField(): Fr {
145
+ getRandomField(): Fr {
130
146
  return Fr.random();
131
147
  }
132
148
 
133
149
  // We instruct users to debug contracts via this oracle, so it makes sense that they'd expect it to also work in tests
134
- utilityDebugLog(level: number, message: string, fields: Fr[]): void {
150
+ log(level: number, message: string, _fieldsSize: number, fields: Fr[]): Promise<void> {
135
151
  if (!LogLevels[level]) {
136
- throw new Error(`Invalid debug log level: ${level}`);
152
+ throw new Error(`Invalid log level: ${level}`);
137
153
  }
138
154
  const levelName = LogLevels[level];
139
155
 
140
156
  this.logger[levelName](`${applyStringFormatting(message, fields)}`, { module: `${this.logger.module}:debug_log` });
157
+ return Promise.resolve();
141
158
  }
142
159
 
143
- txeGetDefaultAddress(): AztecAddress {
160
+ getDefaultAddress(): AztecAddress {
144
161
  return DEFAULT_ADDRESS;
145
162
  }
146
163
 
147
- async txeGetNextBlockNumber(): Promise<BlockNumber> {
164
+ async getNextBlockNumber(): Promise<BlockNumber> {
148
165
  return BlockNumber((await this.getLastBlockNumber()) + 1);
149
166
  }
150
167
 
151
- txeGetNextBlockTimestamp(): Promise<bigint> {
168
+ getNextBlockTimestamp(): Promise<bigint> {
152
169
  return Promise.resolve(this.nextBlockTimestamp);
153
170
  }
154
171
 
155
- async txeGetLastBlockTimestamp() {
156
- return (await this.stateMachine.node.getBlockHeader('latest'))!.globalVariables.timestamp;
172
+ async getLastBlockTimestamp() {
173
+ return (await this.stateMachine.node.getBlockData('latest'))!.header.globalVariables.timestamp;
157
174
  }
158
175
 
159
- async txeGetLastTxEffects() {
176
+ async getLastTxEffects() {
160
177
  const latestBlockNumber = await this.stateMachine.archiver.getBlockNumber();
161
- const block = await this.stateMachine.archiver.getBlock(latestBlockNumber);
178
+ const block = await this.stateMachine.archiver.getBlock({ number: latestBlockNumber });
162
179
 
163
180
  if (block!.body.txEffects.length != 1) {
164
181
  // Note that calls like env.mine() will result in blocks with no transactions, hitting this
@@ -167,11 +184,40 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
167
184
 
168
185
  const txEffects = block!.body.txEffects[0];
169
186
 
170
- return { txHash: txEffects.txHash, noteHashes: txEffects.noteHashes, nullifiers: txEffects.nullifiers };
187
+ const privateLogs = txEffects.privateLogs;
188
+ if (privateLogs.length > MAX_PRIVATE_LOGS_PER_TX) {
189
+ throw new Error(`${privateLogs.length} private logs exceed max ${MAX_PRIVATE_LOGS_PER_TX}`);
190
+ }
191
+
192
+ return {
193
+ txHash: txEffects.txHash,
194
+ noteHashes: txEffects.noteHashes,
195
+ nullifiers: txEffects.nullifiers,
196
+ privateLogs,
197
+ };
198
+ }
199
+
200
+ async syncContractNonOracleMethod(contractAddress: AztecAddress, scope: AztecAddress, jobId: string) {
201
+ if (contractAddress.equals(DEFAULT_ADDRESS)) {
202
+ this.logger.debug(`Skipping sync in getPrivateEvents because the events correspond to the default address.`);
203
+ return;
204
+ }
205
+
206
+ const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
207
+ await this.stateMachine.contractSyncService.ensureContractSynced(
208
+ contractAddress,
209
+ null,
210
+ async (call, execScopes) => {
211
+ await this.executeUtilityCall(call, execScopes, jobId);
212
+ },
213
+ blockHeader,
214
+ jobId,
215
+ [scope],
216
+ );
171
217
  }
172
218
 
173
- async txeGetPrivateEvents(selector: EventSelector, contractAddress: AztecAddress, scope: AztecAddress) {
174
- return (
219
+ async getPrivateEvents(selector: EventSelector, contractAddress: AztecAddress, scope: AztecAddress) {
220
+ const events = (
175
221
  await this.privateEventStore.getPrivateEvents(selector, {
176
222
  contractAddress,
177
223
  scopes: [scope],
@@ -179,9 +225,18 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
179
225
  toBlock: (await this.getLastBlockNumber()) + 1,
180
226
  })
181
227
  ).map(e => e.packedEvent);
228
+
229
+ if (events.length > MAX_PRIVATE_EVENTS_PER_TXE_QUERY) {
230
+ throw new Error(`Array of length ${events.length} larger than maxLen ${MAX_PRIVATE_EVENTS_PER_TXE_QUERY}`);
231
+ }
232
+ if (events.some(e => e.length > MAX_PRIVATE_EVENT_LEN)) {
233
+ throw new Error(`Some private event has length larger than maxLen ${MAX_PRIVATE_EVENT_LEN}`);
234
+ }
235
+
236
+ return events;
182
237
  }
183
238
 
184
- async txeAdvanceBlocksBy(blocks: number) {
239
+ async advanceBlocksBy(blocks: number) {
185
240
  this.logger.debug(`time traveling ${blocks} blocks`);
186
241
 
187
242
  for (let i = 0; i < blocks; i++) {
@@ -189,37 +244,81 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
189
244
  }
190
245
  }
191
246
 
192
- txeAdvanceTimestampBy(duration: UInt64) {
247
+ advanceTimestampBy(duration: UInt64) {
193
248
  this.logger.debug(`time traveling ${duration} seconds`);
194
249
  this.nextBlockTimestamp += duration;
195
250
  }
196
251
 
197
- async txeDeploy(artifact: ContractArtifact, instance: ContractInstanceWithAddress, secret: Fr) {
252
+ private deploymentNullifier(address: AztecAddress): Promise<Fr> {
253
+ return siloNullifier(AztecAddress.fromNumber(CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS), address.toField());
254
+ }
255
+
256
+ async deploy(
257
+ contractPath: string,
258
+ initializer: string,
259
+ args: Fr[],
260
+ secret: Fr,
261
+ salt: Fr,
262
+ deployer: AztecAddress,
263
+ ): Promise<Fr[]> {
264
+ const { artifact, instance } = await this.artifactResolver.resolveDeployArtifact({
265
+ rootPath: this.rootPath,
266
+ packageName: this.packageName,
267
+ contractPath,
268
+ initializer,
269
+ args,
270
+ secret,
271
+ salt,
272
+ deployer,
273
+ });
274
+
198
275
  // Emit deployment nullifier
199
276
  await this.mineBlock({
200
- nullifiers: [
201
- await siloNullifier(
202
- AztecAddress.fromNumber(CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS),
203
- instance.address.toField(),
204
- ),
205
- ],
277
+ nullifiers: [await this.deploymentNullifier(instance.address)],
206
278
  });
207
279
 
208
280
  if (!secret.equals(Fr.ZERO)) {
209
- await this.txeAddAccount(artifact, instance, secret);
281
+ await this.registerContractAndAddAccount(artifact, instance, secret);
210
282
  } else {
211
283
  await this.contractStore.addContractInstance(instance);
212
- await this.contractStore.addContractArtifact(instance.currentContractClassId, artifact);
284
+ await this.contractStore.addContractArtifact(artifact);
213
285
  this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
214
286
  }
287
+
288
+ return [
289
+ instance.salt,
290
+ instance.deployer.toField(),
291
+ instance.currentContractClassId,
292
+ instance.initializationHash,
293
+ instance.immutablesHash,
294
+ ...instance.publicKeys.toFields(),
295
+ ];
215
296
  }
216
297
 
217
- async txeAddAccount(artifact: ContractArtifact, instance: ContractInstanceWithAddress, secret: Fr) {
298
+ /**
299
+ * Mines a single block containing only the deployment nullifiers for the contracts at the given addresses.
300
+ */
301
+ async mineDeploymentNullifiers(addresses: AztecAddress[]) {
302
+ await this.mineBlock({
303
+ nullifiers: await Promise.all(addresses.map(address => this.deploymentNullifier(address))),
304
+ });
305
+ }
306
+
307
+ async addAccount(secret: Fr) {
308
+ const { artifact, instance } = await this.artifactResolver.resolveAccountArtifact(secret);
309
+ return this.registerContractAndAddAccount(artifact, instance, secret);
310
+ }
311
+
312
+ private async registerContractAndAddAccount(
313
+ artifact: ContractArtifact,
314
+ instance: ContractInstanceWithAddress,
315
+ secret: Fr,
316
+ ) {
218
317
  const partialAddress = await computePartialAddress(instance);
219
318
 
220
319
  this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
221
320
  await this.contractStore.addContractInstance(instance);
222
- await this.contractStore.addContractArtifact(instance.currentContractClassId, artifact);
321
+ await this.contractStore.addContractArtifact(artifact);
223
322
 
224
323
  const completeAddress = await this.keyStore.addAccount(secret, partialAddress);
225
324
  await this.accountStore.setAccount(completeAddress.address, completeAddress);
@@ -229,7 +328,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
229
328
  return completeAddress;
230
329
  }
231
330
 
232
- async txeCreateAccount(secret: Fr) {
331
+ async createAccount(secret: Fr) {
233
332
  // This is a foot gun !
234
333
  const completeAddress = await this.keyStore.addAccount(secret, secret);
235
334
  await this.accountStore.setAccount(completeAddress.address, completeAddress);
@@ -239,20 +338,21 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
239
338
  return completeAddress;
240
339
  }
241
340
 
242
- async txeAddAuthWitness(address: AztecAddress, messageHash: Fr) {
341
+ async addAuthWitness(address: AztecAddress, messageHash: Fr) {
243
342
  const account = await this.accountStore.getAccount(address);
244
- const privateKey = await this.keyStore.getMasterSecretKey(account.publicKeys.masterIncomingViewingPublicKey);
343
+ const ivpkMHash = await hashPublicKey(account.publicKeys.ivpkM);
344
+ const privateKey = await this.keyStore.getMasterSecretKey(ivpkMHash);
245
345
 
246
346
  const schnorr = new Schnorr();
247
- const signature = await schnorr.constructSignature(messageHash.toBuffer(), privateKey);
347
+ const signature = await schnorr.constructSignature(messageHash, privateKey);
248
348
 
249
- const authWitness = new AuthWitness(messageHash, [...signature.toBuffer()]);
349
+ const authWitness = new AuthWitness(messageHash, signature.toLimbFields());
250
350
 
251
351
  this.authwits.set(authWitness.requestHash.toString(), authWitness);
252
352
  }
253
353
 
254
354
  async mineBlock(options: { nullifiers?: Fr[] } = {}) {
255
- const blockNumber = await this.txeGetNextBlockNumber();
355
+ const blockNumber = await this.getNextBlockNumber();
256
356
 
257
357
  const txEffect = TxEffect.empty();
258
358
  txEffect.nullifiers = [getSingleTxBlockRequestHash(blockNumber), ...(options.nullifiers ?? [])];
@@ -276,13 +376,17 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
276
376
  await this.stateMachine.handleL2Block(block);
277
377
  }
278
378
 
279
- async txePrivateCallNewFlow(
280
- from: AztecAddress,
379
+ async privateCallNewFlow(
380
+ from: AztecAddress | undefined,
281
381
  targetContractAddress: AztecAddress = AztecAddress.zero(),
282
382
  functionSelector: FunctionSelector = FunctionSelector.empty(),
283
383
  args: Fr[],
284
384
  argsHash: Fr = Fr.zero(),
285
385
  isStaticCall: boolean = false,
386
+ additionalScopes: AztecAddress[] = [],
387
+ jobId: string,
388
+ authorizedUtilityCallTargets: AztecAddress[],
389
+ gasSettings: GasSettings,
286
390
  ) {
287
391
  this.logger.verbose(
288
392
  `Executing external function ${await this.contractStore.getDebugFunctionName(targetContractAddress, functionSelector)}@${targetContractAddress} isStaticCall=${isStaticCall}`,
@@ -296,14 +400,11 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
296
400
  throw new Error(message);
297
401
  }
298
402
 
299
- // When `from` is the zero address (used when creating a new contract account for example),
300
- // we disable scope filtering by setting effectiveScopes to undefined. This allows these operations
301
- // to proceed without requiring keys registered for the zero address.
302
- const effectiveScopes = from.isZero() ? undefined : [from];
403
+ const scopes = from === undefined ? additionalScopes : [from, ...additionalScopes];
303
404
 
304
405
  // Sync notes before executing private function to discover notes from previous transactions
305
- const utilityExecutor = async (call: FunctionCall) => {
306
- await this.executeUtilityCall(call, effectiveScopes);
406
+ const utilityExecutor = async (call: FunctionCall, execScopes: AztecAddress[]) => {
407
+ await this.executeUtilityCall(call, execScopes, jobId);
307
408
  };
308
409
 
309
410
  const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
@@ -312,16 +413,14 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
312
413
  functionSelector,
313
414
  utilityExecutor,
314
415
  blockHeader,
315
- this.jobId,
416
+ jobId,
417
+ scopes,
316
418
  );
317
419
 
318
- const blockNumber = await this.txeGetNextBlockNumber();
319
-
320
- const callContext = new CallContext(from, targetContractAddress, functionSelector, isStaticCall);
420
+ const blockNumber = await this.getNextBlockNumber();
321
421
 
322
- const gasLimits = new Gas(DEFAULT_DA_GAS_LIMIT, DEFAULT_L2_GAS_LIMIT);
323
- const teardownGasLimits = new Gas(DEFAULT_TEARDOWN_DA_GAS_LIMIT, DEFAULT_TEARDOWN_L2_GAS_LIMIT);
324
- const gasSettings = new GasSettings(gasLimits, teardownGasLimits, GasFees.empty(), GasFees.empty());
422
+ const msgSender = from ?? AztecAddress.NULL_MSG_SENDER;
423
+ const callContext = new CallContext(msgSender, targetContractAddress, functionSelector, isStaticCall);
325
424
 
326
425
  const txContext = new TxContext(this.chainId, this.version, gasSettings);
327
426
 
@@ -336,43 +435,45 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
336
435
 
337
436
  const simulator = new WASMSimulator();
338
437
 
339
- const privateExecutionOracle = new PrivateExecutionOracle(
438
+ const privateExecutionOracle = new PrivateExecutionOracle({
340
439
  argsHash,
341
440
  txContext,
342
441
  callContext,
343
- /** Header of a block whose state is used during private execution (not the block the transaction is included in). */
344
- blockHeader,
442
+ anchorBlockHeader: blockHeader,
345
443
  utilityExecutor,
346
- /** List of transient auth witnesses to be used during this simulation */
347
- Array.from(this.authwits.values()),
348
- /** List of transient auth witnesses to be used during this simulation */
349
- [],
350
- HashedValuesCache.create([new HashedValues(args, argsHash)]),
444
+ authWitnesses: Array.from(this.authwits.values()),
445
+ capsules: [],
446
+ executionCache: HashedValuesCache.create([new HashedValues(args, argsHash)]),
351
447
  noteCache,
352
448
  taggingIndexCache,
353
- this.contractStore,
354
- this.noteStore,
355
- this.keyStore,
356
- this.addressStore,
357
- this.stateMachine.node,
358
- this.senderTaggingStore,
359
- this.recipientTaggingStore,
360
- this.senderAddressBookStore,
361
- this.capsuleStore,
362
- this.privateEventStore,
363
- this.stateMachine.contractSyncService,
364
- this.jobId,
365
- 0, // totalPublicArgsCount
366
- minRevertibleSideEffectCounter, // (start) sideEffectCounter
367
- undefined, // log
368
- effectiveScopes, // scopes
369
- /**
370
- * In TXE, the typical transaction entrypoint is skipped, so we need to simulate the actions that such a
371
- * contract would perform, including setting senderForTags.
372
- */
373
- from,
449
+ contractStore: this.contractStore,
450
+ noteStore: this.noteStore,
451
+ keyStore: this.keyStore,
452
+ addressStore: this.addressStore,
453
+ aztecNode: this.stateMachine.node,
454
+ senderTaggingStore: this.senderTaggingStore,
455
+ recipientTaggingStore: this.recipientTaggingStore,
456
+ senderAddressBookStore: this.senderAddressBookStore,
457
+ capsuleService: new CapsuleService(this.capsuleStore, scopes),
458
+ privateEventStore: this.privateEventStore,
459
+ contractSyncService: this.stateMachine.contractSyncService,
460
+ jobId,
461
+ totalPublicCalldataCount: 0,
462
+ sideEffectCounter: minRevertibleSideEffectCounter,
463
+ scopes,
464
+ // In TXE, the typical transaction entrypoint is skipped, so we need to simulate the actions that such a
465
+ // contract would perform, including setting senderForTags.
466
+ senderForTags: from,
374
467
  simulator,
375
- );
468
+ messageContextService: this.stateMachine.messageContextService,
469
+ l2TipsStore: this.stateMachine.l2TipsProvider,
470
+ hooks: composeHooks({
471
+ authorizeUtilityCall: this.buildAuthorizeUtilityCallHook(
472
+ isStaticCall ? 'private view' : 'private',
473
+ authorizedUtilityCallTargets,
474
+ ),
475
+ }),
476
+ });
376
477
 
377
478
  // 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.
378
479
  let result: PrivateExecutionResult;
@@ -394,7 +495,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
394
495
  );
395
496
  const publicFunctionsCalldata = await Promise.all(
396
497
  publicCallRequests.map(async r => {
397
- const calldata = await privateExecutionOracle.privateLoadFromExecutionCache(r.calldataHash);
498
+ const calldata = await privateExecutionOracle.getHashPreimage(r.calldataHash);
398
499
  return new HashedValues(calldata, r.calldataHash);
399
500
  }),
400
501
  );
@@ -411,7 +512,8 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
411
512
  // We pass the non-zero minRevertibleSideEffectCounter to make sure the side effects are split correctly.
412
513
  const { publicInputs } = await generateSimulatedProvingResult(
413
514
  result,
414
- this.contractStore,
515
+ (addr, sel) => this.contractStore.getDebugFunctionName(addr, sel),
516
+ this.stateMachine.node,
415
517
  minRevertibleSideEffectCounter,
416
518
  );
417
519
 
@@ -478,11 +580,17 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
478
580
  }
479
581
  }
480
582
 
583
+ // Walk the nested private-call tree and collect every offchain effect the transaction emitted.
584
+ // PXE stores these on each `PrivateCallExecutionResult` and they never reach TXE via the
585
+ // `aztec_utl_emitOffchainEffect` foreign-call path (that path only fires at the top-level), so
586
+ // we pull them out here and the RPC wrapper will hand them to `TXESession` for buffering.
587
+ const offchainEffects = collectNested([executionResult], r => r.offchainEffects.map(e => e.data));
588
+
481
589
  if (isStaticCall) {
482
590
  await checkpoint!.revert();
483
591
 
484
592
  await forkedWorldTrees.close();
485
- return executionResult.returnValues ?? [];
593
+ return { returnValues: executionResult.returnValues ?? [], offchainEffects };
486
594
  }
487
595
 
488
596
  const txEffect = TxEffect.empty();
@@ -504,26 +612,21 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
504
612
 
505
613
  await forkedWorldTrees.close();
506
614
 
507
- return executionResult.returnValues ?? [];
615
+ return { returnValues: executionResult.returnValues ?? [], offchainEffects };
508
616
  }
509
617
 
510
- async txePublicCallNewFlow(
511
- from: AztecAddress,
618
+ async publicCallNewFlow(
619
+ from: AztecAddress | undefined,
512
620
  targetContractAddress: AztecAddress,
513
621
  calldata: Fr[],
514
622
  isStaticCall: boolean,
623
+ gasSettings: GasSettings,
515
624
  ) {
516
625
  this.logger.verbose(
517
626
  `Executing public function ${await this.contractStore.getDebugFunctionName(targetContractAddress, FunctionSelector.fromField(calldata[0]))}@${targetContractAddress} isStaticCall=${isStaticCall}`,
518
627
  );
519
628
 
520
- const blockNumber = await this.txeGetNextBlockNumber();
521
-
522
- const gasLimits = new Gas(DEFAULT_DA_GAS_LIMIT, DEFAULT_L2_GAS_LIMIT);
523
-
524
- const teardownGasLimits = new Gas(DEFAULT_TEARDOWN_DA_GAS_LIMIT, DEFAULT_TEARDOWN_L2_GAS_LIMIT);
525
-
526
- const gasSettings = new GasSettings(gasLimits, teardownGasLimits, GasFees.empty(), GasFees.empty());
629
+ const blockNumber = await this.getNextBlockNumber();
527
630
 
528
631
  const txContext = new TxContext(this.chainId, this.version, gasSettings);
529
632
 
@@ -576,7 +679,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
576
679
  // may require producing reverts.
577
680
  const revertibleAccumulatedData = PrivateToPublicAccumulatedData.empty();
578
681
  revertibleAccumulatedData.publicCallRequests[0] = new PublicCallRequest(
579
- from,
682
+ from ?? AztecAddress.NULL_MSG_SENDER,
580
683
  targetContractAddress,
581
684
  isStaticCall,
582
685
  calldataHash,
@@ -594,7 +697,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
594
697
  constantData,
595
698
  /*gasUsed=*/ new Gas(0, 0),
596
699
  /*feePayer=*/ AztecAddress.zero(),
597
- /*includeByTimestamp=*/ 0n,
700
+ /*expirationTimestamp=*/ 0n,
598
701
  inputsForPublic,
599
702
  undefined,
600
703
  );
@@ -662,10 +765,12 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
662
765
  return returnValues ?? [];
663
766
  }
664
767
 
665
- async txeSimulateUtilityFunction(
768
+ async executeUtilityFunction(
666
769
  targetContractAddress: AztecAddress,
667
770
  functionSelector: FunctionSelector,
668
771
  args: Fr[],
772
+ jobId: string,
773
+ authorizedUtilityCallTargets: AztecAddress[],
669
774
  ) {
670
775
  const artifact = await this.contractStore.getFunctionArtifact(targetContractAddress, functionSelector);
671
776
  if (!artifact) {
@@ -677,28 +782,34 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
677
782
  await this.stateMachine.contractSyncService.ensureContractSynced(
678
783
  targetContractAddress,
679
784
  functionSelector,
680
- async call => {
681
- await this.executeUtilityCall(call);
785
+ async (call, execScopes) => {
786
+ await this.executeUtilityCall(call, execScopes, jobId);
682
787
  },
683
788
  blockHeader,
684
- this.jobId,
789
+ jobId,
790
+ await this.keyStore.getAccounts(),
685
791
  );
686
792
 
687
- const call = new FunctionCall(
688
- artifact.name,
689
- targetContractAddress,
690
- functionSelector,
691
- FunctionType.UTILITY,
692
- false,
693
- false,
793
+ const call = FunctionCall.from({
794
+ name: artifact.name,
795
+ to: targetContractAddress,
796
+ selector: functionSelector,
797
+ type: FunctionType.UTILITY,
798
+ hideMsgSender: false,
799
+ isStatic: false,
694
800
  args,
695
- [],
696
- );
801
+ returnTypes: [],
802
+ });
697
803
 
698
- return this.executeUtilityCall(call);
804
+ return this.executeUtilityCall(call, await this.keyStore.getAccounts(), jobId, authorizedUtilityCallTargets);
699
805
  }
700
806
 
701
- private async executeUtilityCall(call: FunctionCall, scopes?: AztecAddress[]): Promise<Fr[]> {
807
+ private async executeUtilityCall(
808
+ call: FunctionCall,
809
+ scopes: AztecAddress[],
810
+ jobId: string,
811
+ authorizedUtilityCallTargets: AztecAddress[] = [],
812
+ ): Promise<Fr[]> {
702
813
  const entryPointArtifact = await this.contractStore.getFunctionArtifactWithDebugMetadata(call.to, call.selector);
703
814
  if (entryPointArtifact.functionType !== FunctionType.UTILITY) {
704
815
  throw new Error(`Cannot run ${entryPointArtifact.functionType} function as utility`);
@@ -711,25 +822,36 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
711
822
 
712
823
  try {
713
824
  const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
714
- const oracle = new UtilityExecutionOracle(
715
- call.to,
716
- [],
717
- [],
825
+ const simulator = new WASMSimulator();
826
+ const utilityExecutor = async (syncCall: FunctionCall, execScopes: AztecAddress[]) => {
827
+ await this.executeUtilityCall(syncCall, execScopes, jobId);
828
+ };
829
+ const oracle = new UtilityExecutionOracle({
830
+ contractAddress: call.to,
831
+ authWitnesses: [],
832
+ capsules: [],
718
833
  anchorBlockHeader,
719
- this.contractStore,
720
- this.noteStore,
721
- this.keyStore,
722
- this.addressStore,
723
- this.stateMachine.node,
724
- this.recipientTaggingStore,
725
- this.senderAddressBookStore,
726
- this.capsuleStore,
727
- this.privateEventStore,
728
- this.jobId,
729
- undefined, // log
730
- scopes, // scopes - used to filter notes by account
731
- );
732
- const acirExecutionResult = await new WASMSimulator()
834
+ contractStore: this.contractStore,
835
+ noteStore: this.noteStore,
836
+ keyStore: this.keyStore,
837
+ addressStore: this.addressStore,
838
+ aztecNode: this.stateMachine.node,
839
+ recipientTaggingStore: this.recipientTaggingStore,
840
+ senderAddressBookStore: this.senderAddressBookStore,
841
+ capsuleService: new CapsuleService(this.capsuleStore, scopes),
842
+ privateEventStore: this.privateEventStore,
843
+ messageContextService: this.stateMachine.messageContextService,
844
+ contractSyncService: this.stateMachine.contractSyncService,
845
+ l2TipsStore: this.stateMachine.l2TipsProvider,
846
+ jobId,
847
+ scopes,
848
+ simulator,
849
+ hooks: composeHooks({
850
+ authorizeUtilityCall: this.buildAuthorizeUtilityCallHook('utility', authorizedUtilityCallTargets),
851
+ }),
852
+ utilityExecutor,
853
+ });
854
+ const acirExecutionResult = await simulator
733
855
  .executeUserCircuit(toACVMWitness(0, call.args), entryPointArtifact, new Oracle(oracle).toACIRCallback())
734
856
  .catch((err: Error) => {
735
857
  err.message = resolveAssertionMessageFromError(err, entryPointArtifact);
@@ -744,10 +866,10 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
744
866
  );
745
867
  });
746
868
 
747
- this.logger.verbose(`Utility simulation for ${call.to}.${call.selector} completed`);
869
+ this.logger.verbose(`Utility execution for ${call.to}.${call.selector} completed`);
748
870
  return witnessMapToFields(acirExecutionResult.returnWitness);
749
871
  } catch (err) {
750
- throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during utility simulation'));
872
+ throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during utility execution'));
751
873
  }
752
874
  }
753
875
 
@@ -757,7 +879,20 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
757
879
  }
758
880
 
759
881
  private async getLastBlockNumber(): Promise<BlockNumber> {
760
- const header = await this.stateMachine.node.getBlockHeader('latest');
761
- return header ? header.globalVariables.blockNumber : BlockNumber.ZERO;
882
+ const block = await this.stateMachine.node.getBlock('latest');
883
+ return block ? block.header.globalVariables.blockNumber : BlockNumber.ZERO;
884
+ }
885
+
886
+ private buildAuthorizeUtilityCallHook(
887
+ callerContext: 'private' | 'private view' | 'utility',
888
+ authorizedTargets: AztecAddress[],
889
+ ): ExecutionHooks['authorizeUtilityCall'] | undefined {
890
+ if (authorizedTargets.length === 0) {
891
+ return undefined;
892
+ }
893
+ return req =>
894
+ Promise.resolve({
895
+ authorized: req.callerContext === callerContext && authorizedTargets.some(t => t.equals(req.target)),
896
+ });
762
897
  }
763
898
  }