@aztec/txe 0.0.1-commit.2ed92850 → 0.0.1-commit.3100065

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