@aztec/txe 0.0.1-commit.a072138 → 0.0.1-commit.a4600f49

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 (170) hide show
  1. package/dest/AuthRegistry-HMC7WEOJ.js +3 -0
  2. package/dest/AuthRegistry-HMC7WEOJ.js.map +7 -0
  3. package/dest/ContractClassRegistry-TXCDCFNC.js +3 -0
  4. package/dest/ContractClassRegistry-TXCDCFNC.js.map +7 -0
  5. package/dest/ContractInstanceRegistry-2TZHWOTT.js +3 -0
  6. package/dest/ContractInstanceRegistry-2TZHWOTT.js.map +7 -0
  7. package/dest/FeeJuice-FDF3J2Q5.js +3 -0
  8. package/dest/FeeJuice-FDF3J2Q5.js.map +7 -0
  9. package/dest/HandshakeRegistry-C7JF4R54.js +3 -0
  10. package/dest/HandshakeRegistry-C7JF4R54.js.map +7 -0
  11. package/dest/MultiCallEntrypoint-IGLO227K.js +3 -0
  12. package/dest/MultiCallEntrypoint-IGLO227K.js.map +7 -0
  13. package/dest/SchnorrAccount-KCIHUCXS.js +3 -0
  14. package/dest/SchnorrAccount-KCIHUCXS.js.map +7 -0
  15. package/dest/SchnorrInitializerlessAccount-PVR6XUSN.js +3 -0
  16. package/dest/SchnorrInitializerlessAccount-PVR6XUSN.js.map +7 -0
  17. package/dest/bin/check_txe_oracle_version.d.ts +2 -0
  18. package/dest/bin/check_txe_oracle_version.d.ts.map +1 -0
  19. package/dest/bin/check_txe_oracle_version.js +61 -0
  20. package/dest/bin/index.js +3 -30
  21. package/dest/bin/index.js.map +7 -0
  22. package/dest/bin/oracle_test_server.d.ts +3 -0
  23. package/dest/bin/oracle_test_server.d.ts.map +1 -0
  24. package/dest/bin/oracle_test_server.js +41 -0
  25. package/dest/chunk-32UHX7YY.js +3 -0
  26. package/dest/chunk-32UHX7YY.js.map +7 -0
  27. package/dest/chunk-6AVNR3XX.js +304 -0
  28. package/dest/chunk-6AVNR3XX.js.map +7 -0
  29. package/dest/chunk-CJEH2W44.js +260 -0
  30. package/dest/chunk-CJEH2W44.js.map +7 -0
  31. package/dest/constants.d.ts +5 -1
  32. package/dest/constants.d.ts.map +1 -1
  33. package/dest/constants.js +9 -1
  34. package/dest/dispatcher_pool.d.ts +67 -0
  35. package/dest/dispatcher_pool.d.ts.map +1 -0
  36. package/dest/dispatcher_pool.js +286 -0
  37. package/dest/index.d.ts +51 -7
  38. package/dest/index.d.ts.map +1 -1
  39. package/dest/index.js +73 -157
  40. package/dest/metafile.json +38497 -0
  41. package/dest/msgpackr_fr_extension.d.ts +2 -0
  42. package/dest/msgpackr_fr_extension.d.ts.map +1 -0
  43. package/dest/msgpackr_fr_extension.js +21 -0
  44. package/dest/oracle/interfaces.d.ts +61 -30
  45. package/dest/oracle/interfaces.d.ts.map +1 -1
  46. package/dest/oracle/test-resolver/default_fixtures.d.ts +9 -0
  47. package/dest/oracle/test-resolver/default_fixtures.d.ts.map +1 -0
  48. package/dest/oracle/test-resolver/default_fixtures.js +207 -0
  49. package/dest/oracle/test-resolver/index.d.ts +9 -0
  50. package/dest/oracle/test-resolver/index.d.ts.map +1 -0
  51. package/dest/oracle/test-resolver/index.js +32 -0
  52. package/dest/oracle/test-resolver/resolver.d.ts +48 -0
  53. package/dest/oracle/test-resolver/resolver.d.ts.map +1 -0
  54. package/dest/oracle/test-resolver/resolver.js +181 -0
  55. package/dest/oracle/txe_oracle_public_context.d.ts +38 -14
  56. package/dest/oracle/txe_oracle_public_context.d.ts.map +1 -1
  57. package/dest/oracle/txe_oracle_public_context.js +61 -13
  58. package/dest/oracle/txe_oracle_registry.d.ts +169 -0
  59. package/dest/oracle/txe_oracle_registry.d.ts.map +1 -0
  60. package/dest/oracle/txe_oracle_registry.js +745 -0
  61. package/dest/oracle/txe_oracle_top_level_context.d.ts +55 -29
  62. package/dest/oracle/txe_oracle_top_level_context.d.ts.map +1 -1
  63. package/dest/oracle/txe_oracle_top_level_context.js +582 -275
  64. package/dest/oracle/txe_oracle_version.d.ts +17 -0
  65. package/dest/oracle/txe_oracle_version.d.ts.map +1 -0
  66. package/dest/oracle/txe_oracle_version.js +14 -0
  67. package/dest/oracle/txe_private_execution_oracle.d.ts +17 -0
  68. package/dest/oracle/txe_private_execution_oracle.d.ts.map +1 -0
  69. package/dest/oracle/txe_private_execution_oracle.js +15 -0
  70. package/dest/rpc_server.d.ts +14 -0
  71. package/dest/rpc_server.d.ts.map +1 -0
  72. package/dest/rpc_server.js +78 -0
  73. package/dest/rpc_translator.d.ts +112 -228
  74. package/dest/rpc_translator.d.ts.map +1 -1
  75. package/dest/rpc_translator.js +877 -612
  76. package/dest/server.bundle.js +3 -0
  77. package/dest/server.bundle.js.map +7 -0
  78. package/dest/state_machine/archiver.d.ts +6 -5
  79. package/dest/state_machine/archiver.d.ts.map +1 -1
  80. package/dest/state_machine/archiver.js +30 -20
  81. package/dest/state_machine/dummy_p2p_client.d.ts +29 -16
  82. package/dest/state_machine/dummy_p2p_client.d.ts.map +1 -1
  83. package/dest/state_machine/dummy_p2p_client.js +53 -20
  84. package/dest/state_machine/global_variable_builder.d.ts +10 -6
  85. package/dest/state_machine/global_variable_builder.d.ts.map +1 -1
  86. package/dest/state_machine/global_variable_builder.js +8 -5
  87. package/dest/state_machine/index.d.ts +13 -7
  88. package/dest/state_machine/index.d.ts.map +1 -1
  89. package/dest/state_machine/index.js +60 -15
  90. package/dest/state_machine/mock_epoch_cache.d.ts +18 -3
  91. package/dest/state_machine/mock_epoch_cache.d.ts.map +1 -1
  92. package/dest/state_machine/mock_epoch_cache.js +33 -2
  93. package/dest/state_machine/synchronizer.d.ts +14 -6
  94. package/dest/state_machine/synchronizer.d.ts.map +1 -1
  95. package/dest/state_machine/synchronizer.js +22 -9
  96. package/dest/txe_session.d.ts +89 -16
  97. package/dest/txe_session.d.ts.map +1 -1
  98. package/dest/txe_session.js +370 -55
  99. package/dest/utils/block_creation.d.ts +2 -2
  100. package/dest/utils/block_creation.d.ts.map +1 -1
  101. package/dest/utils/block_creation.js +5 -3
  102. package/dest/utils/encoding.d.ts +192 -0
  103. package/dest/utils/encoding.d.ts.map +1 -0
  104. package/dest/{util → utils}/encoding.js +7 -2
  105. package/dest/{util → utils}/expected_failure_error.d.ts +1 -1
  106. package/dest/utils/expected_failure_error.d.ts.map +1 -0
  107. package/dest/utils/tx_effect_creation.d.ts +1 -1
  108. package/dest/utils/tx_effect_creation.d.ts.map +1 -1
  109. package/dest/utils/tx_effect_creation.js +0 -1
  110. package/dest/{util → utils}/txe_account_store.d.ts +1 -1
  111. package/dest/utils/txe_account_store.d.ts.map +1 -0
  112. package/dest/utils/txe_artifact_resolver.d.ts +37 -0
  113. package/dest/utils/txe_artifact_resolver.d.ts.map +1 -0
  114. package/dest/utils/txe_artifact_resolver.js +161 -0
  115. package/dest/utils/txe_public_contract_data_source.d.ts +20 -0
  116. package/dest/utils/txe_public_contract_data_source.d.ts.map +1 -0
  117. package/dest/utils/txe_public_contract_data_source.js +51 -0
  118. package/dest/worker.bundle.js +3 -0
  119. package/dest/worker.bundle.js.map +7 -0
  120. package/dest/worker.d.ts +2 -0
  121. package/dest/worker.d.ts.map +1 -0
  122. package/dest/worker.js +92 -0
  123. package/package.json +38 -21
  124. package/src/bin/check_txe_oracle_version.ts +70 -0
  125. package/src/bin/index.ts +11 -2
  126. package/src/bin/oracle_test_server.ts +51 -0
  127. package/src/constants.ts +11 -1
  128. package/src/dispatcher_pool.ts +317 -0
  129. package/src/index.ts +99 -190
  130. package/src/msgpackr_fr_extension.ts +23 -0
  131. package/src/oracle/interfaces.ts +64 -35
  132. package/src/oracle/test-resolver/default_fixtures.ts +282 -0
  133. package/src/oracle/test-resolver/index.ts +44 -0
  134. package/src/oracle/test-resolver/resolver.ts +245 -0
  135. package/src/oracle/txe_oracle_public_context.ts +74 -12
  136. package/src/oracle/txe_oracle_registry.ts +536 -0
  137. package/src/oracle/txe_oracle_top_level_context.ts +429 -175
  138. package/src/oracle/txe_oracle_version.ts +17 -0
  139. package/src/oracle/txe_private_execution_oracle.ts +30 -0
  140. package/src/rpc_server.ts +87 -0
  141. package/src/rpc_translator.ts +1087 -995
  142. package/src/state_machine/archiver.ts +43 -20
  143. package/src/state_machine/dummy_p2p_client.ts +83 -32
  144. package/src/state_machine/global_variable_builder.ts +12 -11
  145. package/src/state_machine/index.ts +84 -33
  146. package/src/state_machine/mock_epoch_cache.ts +43 -3
  147. package/src/state_machine/synchronizer.ts +31 -10
  148. package/src/txe_session.ts +601 -114
  149. package/src/utils/block_creation.ts +5 -2
  150. package/src/{util → utils}/encoding.ts +8 -2
  151. package/src/utils/tx_effect_creation.ts +0 -2
  152. package/src/utils/txe_artifact_resolver.ts +217 -0
  153. package/src/utils/txe_public_contract_data_source.ts +60 -0
  154. package/src/worker.ts +98 -0
  155. package/dest/util/encoding.d.ts +0 -720
  156. package/dest/util/encoding.d.ts.map +0 -1
  157. package/dest/util/expected_failure_error.d.ts.map +0 -1
  158. package/dest/util/txe_account_store.d.ts.map +0 -1
  159. package/dest/util/txe_contract_store.d.ts +0 -12
  160. package/dest/util/txe_contract_store.d.ts.map +0 -1
  161. package/dest/util/txe_contract_store.js +0 -22
  162. package/dest/util/txe_public_contract_data_source.d.ts +0 -21
  163. package/dest/util/txe_public_contract_data_source.d.ts.map +0 -1
  164. package/dest/util/txe_public_contract_data_source.js +0 -67
  165. package/src/util/txe_contract_store.ts +0 -36
  166. package/src/util/txe_public_contract_data_source.ts +0 -86
  167. /package/dest/{util → utils}/expected_failure_error.js +0 -0
  168. /package/dest/{util → utils}/txe_account_store.js +0 -0
  169. /package/src/{util → utils}/expected_failure_error.ts +0 -0
  170. /package/src/{util → utils}/txe_account_store.ts +0 -0
@@ -1,37 +1,45 @@
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';
10
7
  import { Schnorr } from '@aztec/foundation/crypto/schnorr';
11
8
  import { Fr } from '@aztec/foundation/curves/bn254';
9
+ import type { EthAddress } from '@aztec/foundation/eth-address';
12
10
  import { LogLevels, type Logger, applyStringFormatting, createLogger } from '@aztec/foundation/log';
13
11
  import { TestDateProvider } from '@aztec/foundation/timer';
14
12
  import type { KeyStore } from '@aztec/key-store';
15
13
  import {
16
14
  AddressStore,
15
+ AnchoredContractData,
16
+ CapsuleService,
17
17
  CapsuleStore,
18
+ type ContractStore,
19
+ type ExecutionHooks,
20
+ FactService,
21
+ FactStore,
18
22
  NoteStore,
19
- ORACLE_VERSION,
23
+ ORACLE_VERSION_MAJOR,
20
24
  PrivateEventStore,
21
25
  RecipientTaggingStore,
22
- SenderAddressBookStore,
23
26
  SenderTaggingStore,
27
+ TaggingSecretSourcesStore,
28
+ type TaggingSecretStrategy,
29
+ composeHooks,
24
30
  enrichPublicSimulationError,
25
- syncState,
26
31
  } from '@aztec/pxe/server';
27
32
  import {
33
+ CONTRACT_INSTANCE,
28
34
  ExecutionNoteCache,
29
35
  ExecutionTaggingIndexCache,
30
36
  HashedValuesCache,
31
37
  type IMiscOracle,
32
- Oracle,
38
+ type Option,
33
39
  PrivateExecutionOracle,
40
+ TransientArrayService,
34
41
  UtilityExecutionOracle,
42
+ buildACIRCallback,
35
43
  executePrivateFunction,
36
44
  generateSimulatedProvingResult,
37
45
  } from '@aztec/pxe/simulator';
@@ -45,10 +53,10 @@ import {
45
53
  witnessMapToFields,
46
54
  } from '@aztec/simulator/client';
47
55
  import {
48
- CppPublicTxSimulator,
49
56
  GuardedMerkleTreeOperations,
50
57
  PublicContractsDB,
51
58
  PublicProcessor,
59
+ PublicTxSimulator,
52
60
  } from '@aztec/simulator/server';
53
61
  import { type ContractArtifact, EventSelector, FunctionCall, FunctionSelector, FunctionType } from '@aztec/stdlib/abi';
54
62
  import { AuthWitness } from '@aztec/stdlib/auth-witness';
@@ -63,6 +71,9 @@ import {
63
71
  PrivateToPublicAccumulatedData,
64
72
  PublicCallRequest,
65
73
  } from '@aztec/stdlib/kernel';
74
+ import { deriveKeys, hashPublicKey } from '@aztec/stdlib/keys';
75
+ import type { PrivateLog } from '@aztec/stdlib/logs';
76
+ import { L1Actor, L1ToL2Message, L2Actor } from '@aztec/stdlib/messaging';
66
77
  import { ChonkProof } from '@aztec/stdlib/proofs';
67
78
  import { makeGlobalVariables } from '@aztec/stdlib/testing';
68
79
  import { MerkleTreeId } from '@aztec/stdlib/trees';
@@ -79,14 +90,14 @@ import {
79
90
  collectNested,
80
91
  } from '@aztec/stdlib/tx';
81
92
  import type { UInt64 } from '@aztec/stdlib/types';
82
- import { ForkCheckpoint } from '@aztec/world-state';
93
+ import { ForkCheckpoint } from '@aztec/world-state/native';
83
94
 
84
- import { DEFAULT_ADDRESS } from '../constants.js';
95
+ import { DEFAULT_ADDRESS, MAX_PRIVATE_EVENTS_PER_TXE_QUERY, MAX_PRIVATE_EVENT_LEN } from '../constants.js';
85
96
  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
97
  import { getSingleTxBlockRequestHash, insertTxEffectIntoWorldTrees, makeTXEBlock } from '../utils/block_creation.js';
98
+ import type { TXEAccountStore } from '../utils/txe_account_store.js';
99
+ import type { TXEArtifactResolver } from '../utils/txe_artifact_resolver.js';
100
+ import { TXEPublicContractDataSource } from '../utils/txe_public_contract_data_source.js';
90
101
  import type { ITxeExecutionOracle } from './interfaces.js';
91
102
 
92
103
  export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracle {
@@ -97,69 +108,86 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
97
108
 
98
109
  constructor(
99
110
  private stateMachine: TXEStateMachine,
100
- private contractStore: TXEContractStore,
111
+ private contractStore: ContractStore,
101
112
  private noteStore: NoteStore,
102
113
  private keyStore: KeyStore,
103
114
  private addressStore: AddressStore,
104
115
  private accountStore: TXEAccountStore,
105
116
  private senderTaggingStore: SenderTaggingStore,
106
117
  private recipientTaggingStore: RecipientTaggingStore,
107
- private senderAddressBookStore: SenderAddressBookStore,
118
+ private taggingSecretSourcesStore: TaggingSecretSourcesStore,
108
119
  private capsuleStore: CapsuleStore,
120
+ private factStore: FactStore,
109
121
  private privateEventStore: PrivateEventStore,
110
- private jobId: string,
111
122
  private nextBlockTimestamp: bigint,
112
123
  private version: Fr,
113
124
  private chainId: Fr,
114
125
  private authwits: Map<string, AuthWitness>,
126
+ private taggingSecretStrategy: TaggingSecretStrategy | undefined,
127
+ private readonly artifactResolver: TXEArtifactResolver,
128
+ private readonly rootPath: string,
129
+ private readonly packageName: string,
115
130
  ) {
116
131
  this.logger = createLogger('txe:top_level_context');
117
132
  this.logger.debug('Entering Top Level Context');
118
133
  }
119
134
 
120
- utilityAssertCompatibleOracleVersion(version: number): void {
121
- if (version !== ORACLE_VERSION) {
135
+ private contractOracleVersion: { major: number; minor: number } | undefined;
136
+
137
+ assertCompatibleOracleVersion(major: number, minor: number): void {
138
+ if (major !== ORACLE_VERSION_MAJOR) {
139
+ const hint =
140
+ major > ORACLE_VERSION_MAJOR
141
+ ? '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.'
142
+ : '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
143
  throw new Error(
123
- `Incompatible oracle version. TXE is using version '${ORACLE_VERSION}', but got a request for '${version}'.`,
144
+ `Incompatible aztec cli version: ${hint} See https://docs.aztec.network/errors/8 (expected oracle major version ${ORACLE_VERSION_MAJOR}, got ${major})`,
124
145
  );
125
146
  }
147
+ this.contractOracleVersion = { major, minor };
148
+ }
149
+
150
+ // Prefixed with "nonOracleFunction" as it is not used as an oracle handler.
151
+ nonOracleFunctionGetContractOracleVersion(): { major: number; minor: number } | undefined {
152
+ return this.contractOracleVersion;
126
153
  }
127
154
 
128
155
  // This is typically only invoked in private contexts, but it is convenient to also have it in top-level for testing
129
156
  // setup.
130
- utilityGetRandomField(): Fr {
157
+ getRandomField(): Fr {
131
158
  return Fr.random();
132
159
  }
133
160
 
134
161
  // 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 {
162
+ log(level: number, message: string, _fieldsSize: number, fields: Fr[]): Promise<void> {
136
163
  if (!LogLevels[level]) {
137
- throw new Error(`Invalid debug log level: ${level}`);
164
+ throw new Error(`Invalid log level: ${level}`);
138
165
  }
139
166
  const levelName = LogLevels[level];
140
167
 
141
168
  this.logger[levelName](`${applyStringFormatting(message, fields)}`, { module: `${this.logger.module}:debug_log` });
169
+ return Promise.resolve();
142
170
  }
143
171
 
144
- txeGetDefaultAddress(): AztecAddress {
172
+ getDefaultAddress(): AztecAddress {
145
173
  return DEFAULT_ADDRESS;
146
174
  }
147
175
 
148
- async txeGetNextBlockNumber(): Promise<BlockNumber> {
176
+ async getNextBlockNumber(): Promise<BlockNumber> {
149
177
  return BlockNumber((await this.getLastBlockNumber()) + 1);
150
178
  }
151
179
 
152
- txeGetNextBlockTimestamp(): Promise<bigint> {
180
+ getNextBlockTimestamp(): Promise<bigint> {
153
181
  return Promise.resolve(this.nextBlockTimestamp);
154
182
  }
155
183
 
156
- async txeGetLastBlockTimestamp() {
157
- return (await this.stateMachine.node.getBlockHeader('latest'))!.globalVariables.timestamp;
184
+ async getLastBlockTimestamp() {
185
+ return (await this.stateMachine.node.getBlockData('latest'))!.header.globalVariables.timestamp;
158
186
  }
159
187
 
160
- async txeGetLastTxEffects() {
188
+ async getLastTxEffects(): Promise<{ txHash: TxHash; noteHashes: Fr[]; nullifiers: Fr[]; privateLogs: PrivateLog[] }> {
161
189
  const latestBlockNumber = await this.stateMachine.archiver.getBlockNumber();
162
- const block = await this.stateMachine.archiver.getBlock(latestBlockNumber);
190
+ const block = await this.stateMachine.archiver.getBlock({ number: latestBlockNumber });
163
191
 
164
192
  if (block!.body.txEffects.length != 1) {
165
193
  // Note that calls like env.mine() will result in blocks with no transactions, hitting this
@@ -168,11 +196,40 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
168
196
 
169
197
  const txEffects = block!.body.txEffects[0];
170
198
 
171
- return { txHash: txEffects.txHash, noteHashes: txEffects.noteHashes, nullifiers: txEffects.nullifiers };
199
+ const privateLogs = txEffects.privateLogs;
200
+ if (privateLogs.length > MAX_PRIVATE_LOGS_PER_TX) {
201
+ throw new Error(`${privateLogs.length} private logs exceed max ${MAX_PRIVATE_LOGS_PER_TX}`);
202
+ }
203
+
204
+ return {
205
+ txHash: txEffects.txHash,
206
+ noteHashes: txEffects.noteHashes,
207
+ nullifiers: txEffects.nullifiers,
208
+ privateLogs,
209
+ };
172
210
  }
173
211
 
174
- async txeGetPrivateEvents(selector: EventSelector, contractAddress: AztecAddress, scope: AztecAddress) {
175
- return (
212
+ async syncContractNonOracleMethod(contractAddress: AztecAddress, scope: AztecAddress, jobId: string) {
213
+ if (contractAddress.equals(DEFAULT_ADDRESS)) {
214
+ this.logger.debug(`Skipping sync in getPrivateEvents because the events correspond to the default address.`);
215
+ return;
216
+ }
217
+
218
+ const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
219
+ await this.stateMachine.contractSyncService.ensureContractSynced(
220
+ contractAddress,
221
+ null,
222
+ async (call, execScopes) => {
223
+ await this.executeUtilityCall(call, { scopes: execScopes, jobId });
224
+ },
225
+ blockHeader,
226
+ jobId,
227
+ [scope],
228
+ );
229
+ }
230
+
231
+ async getPrivateEvents(selector: EventSelector, contractAddress: AztecAddress, scope: AztecAddress) {
232
+ const events = (
176
233
  await this.privateEventStore.getPrivateEvents(selector, {
177
234
  contractAddress,
178
235
  scopes: [scope],
@@ -180,9 +237,18 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
180
237
  toBlock: (await this.getLastBlockNumber()) + 1,
181
238
  })
182
239
  ).map(e => e.packedEvent);
240
+
241
+ if (events.length > MAX_PRIVATE_EVENTS_PER_TXE_QUERY) {
242
+ throw new Error(`Array of length ${events.length} larger than maxLen ${MAX_PRIVATE_EVENTS_PER_TXE_QUERY}`);
243
+ }
244
+ if (events.some(e => e.length > MAX_PRIVATE_EVENT_LEN)) {
245
+ throw new Error(`Some private event has length larger than maxLen ${MAX_PRIVATE_EVENT_LEN}`);
246
+ }
247
+
248
+ return events;
183
249
  }
184
250
 
185
- async txeAdvanceBlocksBy(blocks: number) {
251
+ async advanceBlocksBy(blocks: number) {
186
252
  this.logger.debug(`time traveling ${blocks} blocks`);
187
253
 
188
254
  for (let i = 0; i < blocks; i++) {
@@ -190,39 +256,76 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
190
256
  }
191
257
  }
192
258
 
193
- txeAdvanceTimestampBy(duration: UInt64) {
259
+ advanceTimestampBy(duration: UInt64) {
194
260
  this.logger.debug(`time traveling ${duration} seconds`);
195
261
  this.nextBlockTimestamp += duration;
196
262
  }
197
263
 
198
- async txeDeploy(artifact: ContractArtifact, instance: ContractInstanceWithAddress, secret: Fr) {
264
+ private deploymentNullifier(address: AztecAddress): Promise<Fr> {
265
+ return siloNullifier(AztecAddress.fromNumberUnsafe(CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS), address.toField());
266
+ }
267
+
268
+ async deploy(
269
+ contractPath: string,
270
+ initializer: string,
271
+ args: Fr[],
272
+ secret: Fr,
273
+ salt: Fr,
274
+ deployer: AztecAddress,
275
+ ): Promise<Fr[]> {
276
+ const { artifact, instance } = await this.artifactResolver.resolveDeployArtifact({
277
+ rootPath: this.rootPath,
278
+ packageName: this.packageName,
279
+ contractPath,
280
+ initializer,
281
+ args,
282
+ secret,
283
+ salt,
284
+ deployer,
285
+ });
286
+
199
287
  // Emit deployment nullifier
200
288
  await this.mineBlock({
201
- nullifiers: [
202
- await siloNullifier(
203
- AztecAddress.fromNumber(CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS),
204
- instance.address.toField(),
205
- ),
206
- ],
289
+ nullifiers: [await this.deploymentNullifier(instance.address)],
207
290
  });
208
291
 
209
292
  if (!secret.equals(Fr.ZERO)) {
210
- await this.txeAddAccount(artifact, instance, secret);
293
+ await this.registerContractAndAddAccount(artifact, instance, secret);
211
294
  } else {
212
295
  await this.contractStore.addContractInstance(instance);
213
- await this.contractStore.addContractArtifact(instance.currentContractClassId, artifact);
296
+ await this.contractStore.addContractArtifact(artifact);
214
297
  this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
215
298
  }
299
+
300
+ return CONTRACT_INSTANCE.serialization!.fn(instance).flat();
301
+ }
302
+
303
+ /**
304
+ * Mines a single block containing only the deployment nullifiers for the contracts at the given addresses.
305
+ */
306
+ async mineDeploymentNullifiers(addresses: AztecAddress[]) {
307
+ await this.mineBlock({
308
+ nullifiers: await Promise.all(addresses.map(address => this.deploymentNullifier(address))),
309
+ });
216
310
  }
217
311
 
218
- async txeAddAccount(artifact: ContractArtifact, instance: ContractInstanceWithAddress, secret: Fr) {
312
+ async addAccount(secret: Fr) {
313
+ const { artifact, instance } = await this.artifactResolver.resolveAccountArtifact(secret);
314
+ return this.registerContractAndAddAccount(artifact, instance, secret);
315
+ }
316
+
317
+ private async registerContractAndAddAccount(
318
+ artifact: ContractArtifact,
319
+ instance: ContractInstanceWithAddress,
320
+ secret: Fr,
321
+ ) {
219
322
  const partialAddress = await computePartialAddress(instance);
220
323
 
221
324
  this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
222
325
  await this.contractStore.addContractInstance(instance);
223
- await this.contractStore.addContractArtifact(instance.currentContractClassId, artifact);
326
+ await this.contractStore.addContractArtifact(artifact);
224
327
 
225
- const completeAddress = await this.keyStore.addAccount(secret, partialAddress);
328
+ const completeAddress = await this.keyStore.addAccount(await deriveKeys(secret), partialAddress);
226
329
  await this.accountStore.setAccount(completeAddress.address, completeAddress);
227
330
  await this.addressStore.addCompleteAddress(completeAddress);
228
331
  this.logger.debug(`Created account ${completeAddress.address}`);
@@ -230,9 +333,9 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
230
333
  return completeAddress;
231
334
  }
232
335
 
233
- async txeCreateAccount(secret: Fr) {
336
+ async createAccount(secret: Fr) {
234
337
  // This is a foot gun !
235
- const completeAddress = await this.keyStore.addAccount(secret, secret);
338
+ const completeAddress = await this.keyStore.addAccount(await deriveKeys(secret), secret);
236
339
  await this.accountStore.setAccount(completeAddress.address, completeAddress);
237
340
  await this.addressStore.addCompleteAddress(completeAddress);
238
341
  this.logger.debug(`Created account ${completeAddress.address}`);
@@ -240,27 +343,52 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
240
343
  return completeAddress;
241
344
  }
242
345
 
243
- async txeAddAuthWitness(address: AztecAddress, messageHash: Fr) {
346
+ async addAuthWitness(address: AztecAddress, messageHash: Fr) {
244
347
  const account = await this.accountStore.getAccount(address);
245
- const privateKey = await this.keyStore.getMasterSecretKey(account.publicKeys.masterIncomingViewingPublicKey);
348
+ const ivpkMHash = await hashPublicKey(account.publicKeys.ivpkM);
349
+ const privateKey = await this.keyStore.getMasterSecretKey(ivpkMHash);
246
350
 
247
351
  const schnorr = new Schnorr();
248
- const signature = await schnorr.constructSignature(messageHash.toBuffer(), privateKey);
352
+ const signature = await schnorr.constructSignature(messageHash, privateKey);
249
353
 
250
- const authWitness = new AuthWitness(messageHash, [...signature.toBuffer()]);
354
+ const authWitness = new AuthWitness(messageHash, signature.toLimbFields());
251
355
 
252
356
  this.authwits.set(authWitness.requestHash.toString(), authWitness);
253
357
  }
254
358
 
255
- async mineBlock(options: { nullifiers?: Fr[] } = {}) {
256
- const blockNumber = await this.txeGetNextBlockNumber();
359
+ setTaggingSecretStrategy(strategy: Option<TaggingSecretStrategy>): void {
360
+ this.taggingSecretStrategy = strategy.value;
361
+ }
362
+
363
+ async sendL1ToL2Message(content: Fr, secretHash: Fr, sender: EthAddress, recipient: AztecAddress): Promise<Fr> {
364
+ // Messages are appended to the tree, so the next free slot is simply the current tree size.
365
+ const { size } = await this.stateMachine.synchronizer
366
+ .getCommitted()
367
+ .getTreeInfo(MerkleTreeId.L1_TO_L2_MESSAGE_TREE);
368
+ const leafIndex = new Fr(size);
369
+
370
+ const message = new L1ToL2Message(
371
+ new L1Actor(sender, this.chainId.toNumber()),
372
+ new L2Actor(recipient, this.version.toNumber()),
373
+ content,
374
+ secretHash,
375
+ leafIndex,
376
+ );
377
+
378
+ await this.mineBlock({ l1ToL2Messages: [message.hash()] });
379
+
380
+ return leafIndex;
381
+ }
382
+
383
+ async mineBlock(options: { nullifiers?: Fr[]; l1ToL2Messages?: Fr[] } = {}) {
384
+ const blockNumber = await this.getNextBlockNumber();
257
385
 
258
386
  const txEffect = TxEffect.empty();
259
387
  txEffect.nullifiers = [getSingleTxBlockRequestHash(blockNumber), ...(options.nullifiers ?? [])];
260
388
  txEffect.txHash = new TxHash(new Fr(blockNumber));
261
389
 
262
390
  const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
263
- await insertTxEffectIntoWorldTrees(txEffect, forkedWorldTrees);
391
+ await insertTxEffectIntoWorldTrees(txEffect, forkedWorldTrees, options.l1ToL2Messages ?? []);
264
392
 
265
393
  const globals = makeGlobalVariables(undefined, {
266
394
  blockNumber,
@@ -274,22 +402,33 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
274
402
 
275
403
  this.logger.info(`Created block ${blockNumber} with timestamp ${block.header.globalVariables.timestamp}`);
276
404
 
277
- await this.stateMachine.handleL2Block(block);
405
+ await this.stateMachine.handleL2Block(block, options.l1ToL2Messages ?? []);
278
406
  }
279
407
 
280
- async txePrivateCallNewFlow(
281
- from: AztecAddress,
408
+ async privateCallNewFlow(
409
+ from: AztecAddress | undefined,
282
410
  targetContractAddress: AztecAddress = AztecAddress.zero(),
283
411
  functionSelector: FunctionSelector = FunctionSelector.empty(),
284
412
  args: Fr[],
285
413
  argsHash: Fr = Fr.zero(),
286
414
  isStaticCall: boolean = false,
415
+ additionalScopes: AztecAddress[] = [],
416
+ jobId: string,
417
+ authorizedUtilityCallTargets: AztecAddress[],
418
+ gasSettings: GasSettings,
287
419
  ) {
420
+ const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
421
+ const anchoredContractData = new AnchoredContractData(
422
+ this.contractStore,
423
+ this.stateMachine.contractClassService,
424
+ blockHeader,
425
+ );
426
+
288
427
  this.logger.verbose(
289
- `Executing external function ${await this.contractStore.getDebugFunctionName(targetContractAddress, functionSelector)}@${targetContractAddress} isStaticCall=${isStaticCall}`,
428
+ `Executing external function ${await anchoredContractData.getDebugFunctionName(targetContractAddress, functionSelector)}@${targetContractAddress} isStaticCall=${isStaticCall}`,
290
429
  );
291
430
 
292
- const artifact = await this.contractStore.getFunctionArtifact(targetContractAddress, functionSelector);
431
+ const artifact = await anchoredContractData.getFunctionArtifact(targetContractAddress, functionSelector);
293
432
  if (!artifact) {
294
433
  const message = functionSelector.equals(await FunctionSelector.fromSignature('verify_private_authwit(Field)'))
295
434
  ? 'Found no account contract artifact for a private authwit check - use `create_contract_account` instead of `create_light_account` for authwit support.'
@@ -297,25 +436,29 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
297
436
  throw new Error(message);
298
437
  }
299
438
 
439
+ const scopes = from === undefined ? additionalScopes : [from, ...additionalScopes];
440
+
300
441
  // Sync notes before executing private function to discover notes from previous transactions
301
- const utilityExecutor = async (call: FunctionCall) => {
302
- await this.executeUtilityCall(call);
442
+ const utilityExecutor = async (call: FunctionCall, execScopes: AztecAddress[]) => {
443
+ await this.executeUtilityCall(call, { scopes: execScopes, jobId });
303
444
  };
304
445
 
305
- await syncState(targetContractAddress, this.contractStore, functionSelector, utilityExecutor);
306
-
307
- const blockNumber = await this.txeGetNextBlockNumber();
446
+ await this.stateMachine.contractSyncService.ensureContractSynced(
447
+ targetContractAddress,
448
+ functionSelector,
449
+ utilityExecutor,
450
+ blockHeader,
451
+ jobId,
452
+ scopes,
453
+ );
308
454
 
309
- const callContext = new CallContext(from, targetContractAddress, functionSelector, isStaticCall);
455
+ const blockNumber = await this.getNextBlockNumber();
310
456
 
311
- const gasLimits = new Gas(DEFAULT_DA_GAS_LIMIT, DEFAULT_L2_GAS_LIMIT);
312
- const teardownGasLimits = new Gas(DEFAULT_TEARDOWN_DA_GAS_LIMIT, DEFAULT_TEARDOWN_L2_GAS_LIMIT);
313
- const gasSettings = new GasSettings(gasLimits, teardownGasLimits, GasFees.empty(), GasFees.empty());
457
+ const msgSender = from ?? AztecAddress.NULL_MSG_SENDER;
458
+ const callContext = new CallContext(msgSender, targetContractAddress, functionSelector, isStaticCall);
314
459
 
315
460
  const txContext = new TxContext(this.chainId, this.version, gasSettings);
316
461
 
317
- const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
318
-
319
462
  const protocolNullifier = await computeProtocolNullifier(getSingleTxBlockRequestHash(blockNumber));
320
463
  const noteCache = new ExecutionNoteCache(protocolNullifier);
321
464
  // In production, the account contract sets the min revertible counter before calling the app function.
@@ -327,42 +470,53 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
327
470
 
328
471
  const simulator = new WASMSimulator();
329
472
 
330
- const privateExecutionOracle = new PrivateExecutionOracle(
473
+ const transientArrayService = new TransientArrayService();
474
+ const taggingSecretStrategy = this.taggingSecretStrategy;
475
+ const privateExecutionOracle = new PrivateExecutionOracle({
331
476
  argsHash,
332
477
  txContext,
478
+ txRequestSalt: Fr.ZERO,
333
479
  callContext,
334
- /** Header of a block whose state is used during private execution (not the block the transaction is included in). */
335
- blockHeader,
480
+ anchorBlockHeader: blockHeader,
336
481
  utilityExecutor,
337
- /** List of transient auth witnesses to be used during this simulation */
338
- Array.from(this.authwits.values()),
339
- /** List of transient auth witnesses to be used during this simulation */
340
- [],
341
- HashedValuesCache.create([new HashedValues(args, argsHash)]),
482
+ authWitnesses: Array.from(this.authwits.values()),
483
+ capsules: [],
484
+ executionCache: HashedValuesCache.create([new HashedValues(args, argsHash)]),
342
485
  noteCache,
343
486
  taggingIndexCache,
344
- this.contractStore,
345
- this.noteStore,
346
- this.keyStore,
347
- this.addressStore,
348
- this.stateMachine.node,
349
- this.senderTaggingStore,
350
- this.recipientTaggingStore,
351
- this.senderAddressBookStore,
352
- this.capsuleStore,
353
- this.privateEventStore,
354
- this.jobId,
355
- 0, // totalPublicArgsCount
356
- minRevertibleSideEffectCounter, // (start) sideEffectCounter
357
- undefined, // log
358
- undefined, // scopes
359
- /**
360
- * In TXE, the typical transaction entrypoint is skipped, so we need to simulate the actions that such a
361
- * contract would perform, including setting senderForTags.
362
- */
363
- from,
487
+ anchoredContractData,
488
+ noteStore: this.noteStore,
489
+ keyStore: this.keyStore,
490
+ addressStore: this.addressStore,
491
+ aztecNode: this.stateMachine.node,
492
+ senderTaggingStore: this.senderTaggingStore,
493
+ recipientTaggingStore: this.recipientTaggingStore,
494
+ taggingSecretSourcesStore: this.taggingSecretSourcesStore,
495
+ capsuleService: new CapsuleService(this.capsuleStore, scopes),
496
+ factService: new FactService(this.factStore, scopes),
497
+ privateEventStore: this.privateEventStore,
498
+ contractSyncService: this.stateMachine.contractSyncService,
499
+ jobId,
500
+ totalPublicCalldataCount: 0,
501
+ sideEffectCounter: minRevertibleSideEffectCounter,
502
+ scopes,
503
+ // In TXE, the typical transaction entrypoint is skipped, so we need to simulate the actions that such a
504
+ // contract would perform, including setting senderForTags.
505
+ senderForTags: from,
364
506
  simulator,
365
- );
507
+ txResolver: this.stateMachine.txResolver,
508
+ l2TipsStore: this.stateMachine.l2TipsProvider,
509
+ hooks: composeHooks({
510
+ authorizeUtilityCall: this.buildAuthorizeUtilityCallHook(
511
+ isStaticCall ? 'private view' : 'private',
512
+ authorizedUtilityCallTargets,
513
+ ),
514
+ // Only configure the hook when a strategy was explicitly set, so that otherwise the default tagging secret
515
+ // strategy is exercised.
516
+ resolveTaggingSecretStrategy: taggingSecretStrategy ? () => Promise.resolve(taggingSecretStrategy) : undefined,
517
+ }),
518
+ transientArrayService,
519
+ });
366
520
 
367
521
  // 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.
368
522
  let result: PrivateExecutionResult;
@@ -384,12 +538,11 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
384
538
  );
385
539
  const publicFunctionsCalldata = await Promise.all(
386
540
  publicCallRequests.map(async r => {
387
- const calldata = await privateExecutionOracle.privateLoadFromExecutionCache(r.calldataHash);
541
+ const calldata = await privateExecutionOracle.getHashPreimage(r.calldataHash);
388
542
  return new HashedValues(calldata, r.calldataHash);
389
543
  }),
390
544
  );
391
545
 
392
- noteCache.finish();
393
546
  const nonceGenerator = noteCache.getNonceGenerator();
394
547
  result = new PrivateExecutionResult(executionResult, nonceGenerator, publicFunctionsCalldata);
395
548
  } catch (err) {
@@ -401,7 +554,8 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
401
554
  // We pass the non-zero minRevertibleSideEffectCounter to make sure the side effects are split correctly.
402
555
  const { publicInputs } = await generateSimulatedProvingResult(
403
556
  result,
404
- this.contractStore,
557
+ (addr, sel) => anchoredContractData.getDebugFunctionName(addr, sel),
558
+ this.stateMachine.node,
405
559
  minRevertibleSideEffectCounter,
406
560
  );
407
561
 
@@ -412,7 +566,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
412
566
  globals.version = this.version;
413
567
  globals.gasFees = GasFees.empty();
414
568
 
415
- const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
569
+ await using forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
416
570
 
417
571
  const bindings = this.logger.getBindings();
418
572
  const contractsDB = new PublicContractsDB(
@@ -427,11 +581,20 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
427
581
  collectStatistics: false,
428
582
  collectCallMetadata: true,
429
583
  });
584
+ // The AVM simulator reads this fork's contracts DB, scoped by fork id, for each simulation.
585
+ const forkId = forkedWorldTrees.getRevision().forkId;
430
586
  const processor = new PublicProcessor(
431
587
  globals,
432
588
  guardedMerkleTrees,
433
589
  contractsDB,
434
- new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config, bindings),
590
+ new PublicTxSimulator(
591
+ this.stateMachine.synchronizer.avmSimulator,
592
+ globals,
593
+ contractsDB,
594
+ forkId,
595
+ config,
596
+ bindings,
597
+ ),
435
598
  new TestDateProvider(),
436
599
  undefined,
437
600
  createLogger('simulator:public-processor', bindings),
@@ -459,7 +622,13 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
459
622
  } else if (!processedTx.revertCode.isOK()) {
460
623
  if (processedTx.revertReason) {
461
624
  try {
462
- await enrichPublicSimulationError(processedTx.revertReason, this.contractStore, this.logger);
625
+ await enrichPublicSimulationError(
626
+ processedTx.revertReason,
627
+ this.contractStore,
628
+ this.stateMachine.contractClassService,
629
+ await this.stateMachine.anchorBlockStore.getBlockHeader(),
630
+ this.logger,
631
+ );
463
632
  // eslint-disable-next-line no-empty
464
633
  } catch {}
465
634
  throw new Error(`Contract execution has reverted: ${processedTx.revertReason.getMessage()}`);
@@ -468,11 +637,15 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
468
637
  }
469
638
  }
470
639
 
640
+ // Walk the nested private-call tree and collect every offchain effect the transaction emitted.
641
+ // PXE stores these on each `PrivateCallExecutionResult` and they never reach TXE via the
642
+ // `aztec_utl_emitOffchainEffect` foreign-call path (that path only fires at the top-level), so
643
+ // we pull them out here and the RPC wrapper will hand them to `TXESession` for buffering.
644
+ const offchainEffects = collectNested([executionResult], r => r.offchainEffects.map(e => e.data));
645
+
471
646
  if (isStaticCall) {
472
647
  await checkpoint!.revert();
473
-
474
- await forkedWorldTrees.close();
475
- return executionResult.returnValues ?? [];
648
+ return { returnValues: executionResult.returnValues ?? [], offchainEffects };
476
649
  }
477
650
 
478
651
  const txEffect = TxEffect.empty();
@@ -492,33 +665,31 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
492
665
 
493
666
  await this.stateMachine.handleL2Block(l2Block);
494
667
 
495
- await forkedWorldTrees.close();
496
-
497
- return executionResult.returnValues ?? [];
668
+ return { returnValues: executionResult.returnValues ?? [], offchainEffects };
498
669
  }
499
670
 
500
- async txePublicCallNewFlow(
501
- from: AztecAddress,
671
+ async publicCallNewFlow(
672
+ from: AztecAddress | undefined,
502
673
  targetContractAddress: AztecAddress,
503
674
  calldata: Fr[],
504
675
  isStaticCall: boolean,
676
+ gasSettings: GasSettings,
505
677
  ) {
506
- this.logger.verbose(
507
- `Executing public function ${await this.contractStore.getDebugFunctionName(targetContractAddress, FunctionSelector.fromField(calldata[0]))}@${targetContractAddress} isStaticCall=${isStaticCall}`,
678
+ const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
679
+ const anchoredContractData = new AnchoredContractData(
680
+ this.contractStore,
681
+ this.stateMachine.contractClassService,
682
+ anchorBlockHeader,
508
683
  );
509
684
 
510
- const blockNumber = await this.txeGetNextBlockNumber();
511
-
512
- const gasLimits = new Gas(DEFAULT_DA_GAS_LIMIT, DEFAULT_L2_GAS_LIMIT);
513
-
514
- const teardownGasLimits = new Gas(DEFAULT_TEARDOWN_DA_GAS_LIMIT, DEFAULT_TEARDOWN_L2_GAS_LIMIT);
685
+ this.logger.verbose(
686
+ `Executing public function ${await anchoredContractData.getDebugFunctionName(targetContractAddress, FunctionSelector.fromField(calldata[0]))}@${targetContractAddress} isStaticCall=${isStaticCall}`,
687
+ );
515
688
 
516
- const gasSettings = new GasSettings(gasLimits, teardownGasLimits, GasFees.empty(), GasFees.empty());
689
+ const blockNumber = await this.getNextBlockNumber();
517
690
 
518
691
  const txContext = new TxContext(this.chainId, this.version, gasSettings);
519
692
 
520
- const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
521
-
522
693
  const calldataHash = await computeCalldataHash(calldata);
523
694
  const calldataHashedValues = new HashedValues(calldata, calldataHash);
524
695
 
@@ -529,7 +700,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
529
700
  globals.version = this.version;
530
701
  globals.gasFees = GasFees.empty();
531
702
 
532
- const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
703
+ await using forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
533
704
 
534
705
  const bindings2 = this.logger.getBindings();
535
706
  const contractsDB = new PublicContractsDB(
@@ -544,7 +715,16 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
544
715
  collectStatistics: false,
545
716
  collectCallMetadata: true,
546
717
  });
547
- const simulator = new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config, bindings2);
718
+ // The AVM simulator reads this fork's contracts DB, scoped by fork id, for each simulation.
719
+ const forkId2 = forkedWorldTrees.getRevision().forkId;
720
+ const simulator = new PublicTxSimulator(
721
+ this.stateMachine.synchronizer.avmSimulator,
722
+ globals,
723
+ contractsDB,
724
+ forkId2,
725
+ config,
726
+ bindings2,
727
+ );
548
728
  const processor = new PublicProcessor(
549
729
  globals,
550
730
  guardedMerkleTrees,
@@ -566,7 +746,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
566
746
  // may require producing reverts.
567
747
  const revertibleAccumulatedData = PrivateToPublicAccumulatedData.empty();
568
748
  revertibleAccumulatedData.publicCallRequests[0] = new PublicCallRequest(
569
- from,
749
+ from ?? AztecAddress.NULL_MSG_SENDER,
570
750
  targetContractAddress,
571
751
  isStaticCall,
572
752
  calldataHash,
@@ -584,7 +764,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
584
764
  constantData,
585
765
  /*gasUsed=*/ new Gas(0, 0),
586
766
  /*feePayer=*/ AztecAddress.zero(),
587
- /*includeByTimestamp=*/ 0n,
767
+ /*expirationTimestamp=*/ 0n,
588
768
  inputsForPublic,
589
769
  undefined,
590
770
  );
@@ -611,7 +791,13 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
611
791
  } else if (!processedTx.revertCode.isOK()) {
612
792
  if (processedTx.revertReason) {
613
793
  try {
614
- await enrichPublicSimulationError(processedTx.revertReason, this.contractStore, this.logger);
794
+ await enrichPublicSimulationError(
795
+ processedTx.revertReason,
796
+ this.contractStore,
797
+ this.stateMachine.contractClassService,
798
+ anchorBlockHeader,
799
+ this.logger,
800
+ );
615
801
  // eslint-disable-next-line no-empty
616
802
  } catch {}
617
803
  throw new Error(`Contract execution has reverted: ${processedTx.revertReason.getMessage()}`);
@@ -624,9 +810,6 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
624
810
 
625
811
  if (isStaticCall) {
626
812
  await checkpoint!.revert();
627
-
628
- await forkedWorldTrees.close();
629
-
630
813
  return returnValues ?? [];
631
814
  }
632
815
 
@@ -647,42 +830,80 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
647
830
 
648
831
  await this.stateMachine.handleL2Block(l2Block);
649
832
 
650
- await forkedWorldTrees.close();
651
-
652
833
  return returnValues ?? [];
653
834
  }
654
835
 
655
- async txeSimulateUtilityFunction(
836
+ async executeUtilityFunction(
837
+ from: AztecAddress | undefined,
656
838
  targetContractAddress: AztecAddress,
657
839
  functionSelector: FunctionSelector,
658
840
  args: Fr[],
841
+ jobId: string,
842
+ authorizedUtilityCallTargets: AztecAddress[],
659
843
  ) {
660
- const artifact = await this.contractStore.getFunctionArtifact(targetContractAddress, functionSelector);
844
+ const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
845
+ const anchoredContractData = new AnchoredContractData(
846
+ this.contractStore,
847
+ this.stateMachine.contractClassService,
848
+ blockHeader,
849
+ );
850
+
851
+ const artifact = await anchoredContractData.getFunctionArtifact(targetContractAddress, functionSelector);
661
852
  if (!artifact) {
662
853
  throw new Error(`Cannot call ${functionSelector} as there is no artifact found at ${targetContractAddress}.`);
663
854
  }
664
855
 
665
856
  // Sync notes before executing utility function to discover notes from previous transactions
666
- await syncState(targetContractAddress, this.contractStore, functionSelector, async call => {
667
- await this.executeUtilityCall(call);
668
- });
669
-
670
- const call = new FunctionCall(
671
- artifact.name,
857
+ await this.stateMachine.contractSyncService.ensureContractSynced(
672
858
  targetContractAddress,
673
859
  functionSelector,
674
- FunctionType.UTILITY,
675
- false,
676
- false,
677
- args,
678
- [],
860
+ async (call, execScopes) => {
861
+ await this.executeUtilityCall(call, { scopes: execScopes, jobId });
862
+ },
863
+ blockHeader,
864
+ jobId,
865
+ await this.keyStore.getAccounts(),
679
866
  );
680
867
 
681
- return this.executeUtilityCall(call);
868
+ const call = FunctionCall.from({
869
+ name: artifact.name,
870
+ to: targetContractAddress,
871
+ selector: functionSelector,
872
+ type: FunctionType.UTILITY,
873
+ hideMsgSender: false,
874
+ isStatic: false,
875
+ args,
876
+ returnTypes: [],
877
+ });
878
+
879
+ return this.executeUtilityCall(call, {
880
+ from,
881
+ scopes: await this.keyStore.getAccounts(),
882
+ jobId,
883
+ authorizedUtilityCallTargets,
884
+ });
682
885
  }
683
886
 
684
- private async executeUtilityCall(call: FunctionCall): Promise<Fr[]> {
685
- const entryPointArtifact = await this.contractStore.getFunctionArtifactWithDebugMetadata(call.to, call.selector);
887
+ private async executeUtilityCall(
888
+ call: FunctionCall,
889
+ {
890
+ from = AztecAddress.NULL_MSG_SENDER,
891
+ scopes,
892
+ jobId,
893
+ authorizedUtilityCallTargets = [],
894
+ }: { from?: AztecAddress; scopes: AztecAddress[]; jobId: string; authorizedUtilityCallTargets?: AztecAddress[] },
895
+ ): Promise<Fr[]> {
896
+ const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
897
+ const anchoredContractData = new AnchoredContractData(
898
+ this.contractStore,
899
+ this.stateMachine.contractClassService,
900
+ anchorBlockHeader,
901
+ );
902
+
903
+ const entryPointArtifact = await anchoredContractData.getFunctionArtifactWithDebugMetadata(call.to, call.selector);
904
+ if (!entryPointArtifact) {
905
+ throw new Error(`Cannot run function ${call.selector} on ${call.to}: the contract is not registered.`);
906
+ }
686
907
  if (entryPointArtifact.functionType !== FunctionType.UTILITY) {
687
908
  throw new Error(`Cannot run ${entryPointArtifact.functionType} function as utility`);
688
909
  }
@@ -693,25 +914,45 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
693
914
  });
694
915
 
695
916
  try {
696
- const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
697
- const oracle = new UtilityExecutionOracle(
698
- call.to,
699
- [],
700
- [],
917
+ const simulator = new WASMSimulator();
918
+ const utilityExecutor = async (syncCall: FunctionCall, execScopes: AztecAddress[]) => {
919
+ await this.executeUtilityCall(syncCall, { scopes: execScopes, jobId });
920
+ };
921
+ const oracle = new UtilityExecutionOracle({
922
+ callContext: CallContext.from({
923
+ msgSender: from,
924
+ contractAddress: call.to,
925
+ functionSelector: call.selector,
926
+ isStaticCall: true,
927
+ }),
928
+ authWitnesses: [],
929
+ capsules: [],
701
930
  anchorBlockHeader,
702
- this.contractStore,
703
- this.noteStore,
704
- this.keyStore,
705
- this.addressStore,
706
- this.stateMachine.node,
707
- this.recipientTaggingStore,
708
- this.senderAddressBookStore,
709
- this.capsuleStore,
710
- this.privateEventStore,
711
- this.jobId,
712
- );
713
- const acirExecutionResult = await new WASMSimulator()
714
- .executeUserCircuit(toACVMWitness(0, call.args), entryPointArtifact, new Oracle(oracle).toACIRCallback())
931
+ anchoredContractData,
932
+ noteStore: this.noteStore,
933
+ keyStore: this.keyStore,
934
+ addressStore: this.addressStore,
935
+ aztecNode: this.stateMachine.node,
936
+ recipientTaggingStore: this.recipientTaggingStore,
937
+ taggingSecretSourcesStore: this.taggingSecretSourcesStore,
938
+ capsuleService: new CapsuleService(this.capsuleStore, scopes),
939
+ factService: new FactService(this.factStore, scopes),
940
+ privateEventStore: this.privateEventStore,
941
+ txResolver: this.stateMachine.txResolver,
942
+ contractSyncService: this.stateMachine.contractSyncService,
943
+ l2TipsStore: this.stateMachine.l2TipsProvider,
944
+ jobId,
945
+ scopes,
946
+ simulator,
947
+ hooks: composeHooks({
948
+ authorizeUtilityCall: this.buildAuthorizeUtilityCallHook('utility', authorizedUtilityCallTargets),
949
+ }),
950
+ utilityExecutor,
951
+ // Execution-tree root (top-level utility run or contract sync): own store; nested frames inherit it.
952
+ transientArrayService: new TransientArrayService(),
953
+ });
954
+ const acirExecutionResult = await simulator
955
+ .executeUserCircuit(toACVMWitness(0, call.args), entryPointArtifact, buildACIRCallback(oracle))
715
956
  .catch((err: Error) => {
716
957
  err.message = resolveAssertionMessageFromError(err, entryPointArtifact);
717
958
  throw new ExecutionError(
@@ -725,20 +966,33 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
725
966
  );
726
967
  });
727
968
 
728
- this.logger.verbose(`Utility simulation for ${call.to}.${call.selector} completed`);
969
+ this.logger.verbose(`Utility execution for ${call.to}.${call.selector} completed`);
729
970
  return witnessMapToFields(acirExecutionResult.returnWitness);
730
971
  } catch (err) {
731
- throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during utility simulation'));
972
+ throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during utility execution'));
732
973
  }
733
974
  }
734
975
 
735
- close(): [bigint, Map<string, AuthWitness>] {
976
+ close(): [bigint, Map<string, AuthWitness>, TaggingSecretStrategy | undefined] {
736
977
  this.logger.debug('Exiting Top Level Context');
737
- return [this.nextBlockTimestamp, this.authwits];
978
+ return [this.nextBlockTimestamp, this.authwits, this.taggingSecretStrategy];
738
979
  }
739
980
 
740
981
  private async getLastBlockNumber(): Promise<BlockNumber> {
741
- const header = await this.stateMachine.node.getBlockHeader('latest');
742
- return header ? header.globalVariables.blockNumber : BlockNumber.ZERO;
982
+ const block = await this.stateMachine.node.getBlock('latest');
983
+ return block ? block.header.globalVariables.blockNumber : BlockNumber.ZERO;
984
+ }
985
+
986
+ private buildAuthorizeUtilityCallHook(
987
+ callerContext: 'private' | 'private view' | 'utility',
988
+ authorizedTargets: AztecAddress[],
989
+ ): ExecutionHooks['authorizeUtilityCall'] | undefined {
990
+ if (authorizedTargets.length === 0) {
991
+ return undefined;
992
+ }
993
+ return req =>
994
+ Promise.resolve({
995
+ authorized: req.callerContext === callerContext && authorizedTargets.some(t => t.equals(req.target)),
996
+ });
743
997
  }
744
998
  }