@aztec/txe 0.0.1-commit.3469e52 → 0.0.1-commit.350e0a4d

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-2RDAZOGB.js +3 -0
  2. package/dest/AuthRegistry-2RDAZOGB.js.map +7 -0
  3. package/dest/ContractClassRegistry-L5F3G33N.js +3 -0
  4. package/dest/ContractClassRegistry-L5F3G33N.js.map +7 -0
  5. package/dest/ContractInstanceRegistry-IJOBAWAC.js +3 -0
  6. package/dest/ContractInstanceRegistry-IJOBAWAC.js.map +7 -0
  7. package/dest/FeeJuice-J3XDQPFS.js +3 -0
  8. package/dest/FeeJuice-J3XDQPFS.js.map +7 -0
  9. package/dest/HandshakeRegistry-QGWZJYVS.js +3 -0
  10. package/dest/HandshakeRegistry-QGWZJYVS.js.map +7 -0
  11. package/dest/MultiCallEntrypoint-WZHPRFJ6.js +3 -0
  12. package/dest/MultiCallEntrypoint-WZHPRFJ6.js.map +7 -0
  13. package/dest/SchnorrAccount-II4XD6MI.js +3 -0
  14. package/dest/SchnorrAccount-II4XD6MI.js.map +7 -0
  15. package/dest/SchnorrInitializerlessAccount-FXIOXUQQ.js +3 -0
  16. package/dest/SchnorrInitializerlessAccount-FXIOXUQQ.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-OMH3BDML.js +304 -0
  28. package/dest/chunk-OMH3BDML.js.map +7 -0
  29. package/dest/chunk-R3ZWQEFL.js +260 -0
  30. package/dest/chunk-R3ZWQEFL.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 +38140 -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 +40 -16
  56. package/dest/oracle/txe_oracle_public_context.d.ts.map +1 -1
  57. package/dest/oracle/txe_oracle_public_context.js +65 -17
  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 +322 -104
  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 -222
  74. package/dest/rpc_translator.d.ts.map +1 -1
  75. package/dest/rpc_translator.js +877 -600
  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 +7 -6
  79. package/dest/state_machine/archiver.d.ts.map +1 -1
  80. package/dest/state_machine/archiver.js +31 -22
  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 +75 -21
  90. package/dest/state_machine/mock_epoch_cache.d.ts +21 -4
  91. package/dest/state_machine/mock_epoch_cache.d.ts.map +1 -1
  92. package/dest/state_machine/mock_epoch_cache.js +35 -3
  93. package/dest/state_machine/synchronizer.d.ts +9 -6
  94. package/dest/state_machine/synchronizer.d.ts.map +1 -1
  95. package/dest/state_machine/synchronizer.js +10 -6
  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 +366 -58
  99. package/dest/utils/block_creation.d.ts +6 -6
  100. package/dest/utils/block_creation.d.ts.map +1 -1
  101. package/dest/utils/block_creation.js +9 -7
  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 +80 -20
  136. package/src/oracle/txe_oracle_registry.ts +536 -0
  137. package/src/oracle/txe_oracle_top_level_context.ts +430 -168
  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 -974
  142. package/src/state_machine/archiver.ts +45 -26
  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 +105 -40
  146. package/src/state_machine/mock_epoch_cache.ts +45 -4
  147. package/src/state_machine/synchronizer.ts +13 -7
  148. package/src/txe_session.ts +609 -128
  149. package/src/utils/block_creation.ts +10 -7
  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,36 +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
31
  } from '@aztec/pxe/server';
26
32
  import {
33
+ CONTRACT_INSTANCE,
27
34
  ExecutionNoteCache,
28
35
  ExecutionTaggingIndexCache,
29
36
  HashedValuesCache,
30
37
  type IMiscOracle,
31
- Oracle,
38
+ type Option,
32
39
  PrivateExecutionOracle,
40
+ TransientArrayService,
33
41
  UtilityExecutionOracle,
42
+ buildACIRCallback,
34
43
  executePrivateFunction,
35
44
  generateSimulatedProvingResult,
36
45
  } from '@aztec/pxe/simulator';
@@ -44,10 +53,10 @@ import {
44
53
  witnessMapToFields,
45
54
  } from '@aztec/simulator/client';
46
55
  import {
47
- CppPublicTxSimulator,
48
56
  GuardedMerkleTreeOperations,
49
57
  PublicContractsDB,
50
58
  PublicProcessor,
59
+ PublicTxSimulator,
51
60
  } from '@aztec/simulator/server';
52
61
  import { type ContractArtifact, EventSelector, FunctionCall, FunctionSelector, FunctionType } from '@aztec/stdlib/abi';
53
62
  import { AuthWitness } from '@aztec/stdlib/auth-witness';
@@ -62,6 +71,9 @@ import {
62
71
  PrivateToPublicAccumulatedData,
63
72
  PublicCallRequest,
64
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';
65
77
  import { ChonkProof } from '@aztec/stdlib/proofs';
66
78
  import { makeGlobalVariables } from '@aztec/stdlib/testing';
67
79
  import { MerkleTreeId } from '@aztec/stdlib/trees';
@@ -78,14 +90,14 @@ import {
78
90
  collectNested,
79
91
  } from '@aztec/stdlib/tx';
80
92
  import type { UInt64 } from '@aztec/stdlib/types';
81
- import { ForkCheckpoint } from '@aztec/world-state';
93
+ import { ForkCheckpoint } from '@aztec/world-state/native';
82
94
 
83
- import { DEFAULT_ADDRESS } from '../constants.js';
95
+ import { DEFAULT_ADDRESS, MAX_PRIVATE_EVENTS_PER_TXE_QUERY, MAX_PRIVATE_EVENT_LEN } from '../constants.js';
84
96
  import type { TXEStateMachine } from '../state_machine/index.js';
85
- import type { TXEAccountStore } from '../util/txe_account_store.js';
86
- import type { TXEContractStore } from '../util/txe_contract_store.js';
87
- import { TXEPublicContractDataSource } from '../util/txe_public_contract_data_source.js';
88
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';
89
101
  import type { ITxeExecutionOracle } from './interfaces.js';
90
102
 
91
103
  export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracle {
@@ -96,69 +108,86 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
96
108
 
97
109
  constructor(
98
110
  private stateMachine: TXEStateMachine,
99
- private contractStore: TXEContractStore,
111
+ private contractStore: ContractStore,
100
112
  private noteStore: NoteStore,
101
113
  private keyStore: KeyStore,
102
114
  private addressStore: AddressStore,
103
115
  private accountStore: TXEAccountStore,
104
116
  private senderTaggingStore: SenderTaggingStore,
105
117
  private recipientTaggingStore: RecipientTaggingStore,
106
- private senderAddressBookStore: SenderAddressBookStore,
118
+ private taggingSecretSourcesStore: TaggingSecretSourcesStore,
107
119
  private capsuleStore: CapsuleStore,
120
+ private factStore: FactStore,
108
121
  private privateEventStore: PrivateEventStore,
109
- private jobId: string,
110
122
  private nextBlockTimestamp: bigint,
111
123
  private version: Fr,
112
124
  private chainId: Fr,
113
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,
114
130
  ) {
115
131
  this.logger = createLogger('txe:top_level_context');
116
132
  this.logger.debug('Entering Top Level Context');
117
133
  }
118
134
 
119
- utilityAssertCompatibleOracleVersion(version: number): void {
120
- 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.';
121
143
  throw new Error(
122
- `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})`,
123
145
  );
124
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;
125
153
  }
126
154
 
127
155
  // This is typically only invoked in private contexts, but it is convenient to also have it in top-level for testing
128
156
  // setup.
129
- utilityGetRandomField(): Fr {
157
+ getRandomField(): Fr {
130
158
  return Fr.random();
131
159
  }
132
160
 
133
161
  // We instruct users to debug contracts via this oracle, so it makes sense that they'd expect it to also work in tests
134
- utilityDebugLog(level: number, message: string, fields: Fr[]): void {
162
+ log(level: number, message: string, _fieldsSize: number, fields: Fr[]): Promise<void> {
135
163
  if (!LogLevels[level]) {
136
- throw new Error(`Invalid debug log level: ${level}`);
164
+ throw new Error(`Invalid log level: ${level}`);
137
165
  }
138
166
  const levelName = LogLevels[level];
139
167
 
140
168
  this.logger[levelName](`${applyStringFormatting(message, fields)}`, { module: `${this.logger.module}:debug_log` });
169
+ return Promise.resolve();
141
170
  }
142
171
 
143
- txeGetDefaultAddress(): AztecAddress {
172
+ getDefaultAddress(): AztecAddress {
144
173
  return DEFAULT_ADDRESS;
145
174
  }
146
175
 
147
- async txeGetNextBlockNumber(): Promise<BlockNumber> {
176
+ async getNextBlockNumber(): Promise<BlockNumber> {
148
177
  return BlockNumber((await this.getLastBlockNumber()) + 1);
149
178
  }
150
179
 
151
- txeGetNextBlockTimestamp(): Promise<bigint> {
180
+ getNextBlockTimestamp(): Promise<bigint> {
152
181
  return Promise.resolve(this.nextBlockTimestamp);
153
182
  }
154
183
 
155
- async txeGetLastBlockTimestamp() {
156
- return (await this.stateMachine.node.getBlockHeader('latest'))!.globalVariables.timestamp;
184
+ async getLastBlockTimestamp() {
185
+ return (await this.stateMachine.node.getBlockData('latest'))!.header.globalVariables.timestamp;
157
186
  }
158
187
 
159
- async txeGetLastTxEffects() {
188
+ async getLastTxEffects(): Promise<{ txHash: TxHash; noteHashes: Fr[]; nullifiers: Fr[]; privateLogs: PrivateLog[] }> {
160
189
  const latestBlockNumber = await this.stateMachine.archiver.getBlockNumber();
161
- const block = await this.stateMachine.archiver.getBlock(latestBlockNumber);
190
+ const block = await this.stateMachine.archiver.getBlock({ number: latestBlockNumber });
162
191
 
163
192
  if (block!.body.txEffects.length != 1) {
164
193
  // Note that calls like env.mine() will result in blocks with no transactions, hitting this
@@ -167,11 +196,40 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
167
196
 
168
197
  const txEffects = block!.body.txEffects[0];
169
198
 
170
- 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
+ };
210
+ }
211
+
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
+ );
171
229
  }
172
230
 
173
- async txeGetPrivateEvents(selector: EventSelector, contractAddress: AztecAddress, scope: AztecAddress) {
174
- return (
231
+ async getPrivateEvents(selector: EventSelector, contractAddress: AztecAddress, scope: AztecAddress) {
232
+ const events = (
175
233
  await this.privateEventStore.getPrivateEvents(selector, {
176
234
  contractAddress,
177
235
  scopes: [scope],
@@ -179,9 +237,18 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
179
237
  toBlock: (await this.getLastBlockNumber()) + 1,
180
238
  })
181
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;
182
249
  }
183
250
 
184
- async txeAdvanceBlocksBy(blocks: number) {
251
+ async advanceBlocksBy(blocks: number) {
185
252
  this.logger.debug(`time traveling ${blocks} blocks`);
186
253
 
187
254
  for (let i = 0; i < blocks; i++) {
@@ -189,39 +256,76 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
189
256
  }
190
257
  }
191
258
 
192
- txeAdvanceTimestampBy(duration: UInt64) {
259
+ advanceTimestampBy(duration: UInt64) {
193
260
  this.logger.debug(`time traveling ${duration} seconds`);
194
261
  this.nextBlockTimestamp += duration;
195
262
  }
196
263
 
197
- 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
+
198
287
  // Emit deployment nullifier
199
288
  await this.mineBlock({
200
- nullifiers: [
201
- await siloNullifier(
202
- AztecAddress.fromNumber(CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS),
203
- instance.address.toField(),
204
- ),
205
- ],
289
+ nullifiers: [await this.deploymentNullifier(instance.address)],
206
290
  });
207
291
 
208
292
  if (!secret.equals(Fr.ZERO)) {
209
- await this.txeAddAccount(artifact, instance, secret);
293
+ await this.registerContractAndAddAccount(artifact, instance, secret);
210
294
  } else {
211
295
  await this.contractStore.addContractInstance(instance);
212
- await this.contractStore.addContractArtifact(instance.currentContractClassId, artifact);
296
+ await this.contractStore.addContractArtifact(artifact);
213
297
  this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
214
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
+ });
310
+ }
311
+
312
+ async addAccount(secret: Fr) {
313
+ const { artifact, instance } = await this.artifactResolver.resolveAccountArtifact(secret);
314
+ return this.registerContractAndAddAccount(artifact, instance, secret);
215
315
  }
216
316
 
217
- async txeAddAccount(artifact: ContractArtifact, instance: ContractInstanceWithAddress, secret: Fr) {
317
+ private async registerContractAndAddAccount(
318
+ artifact: ContractArtifact,
319
+ instance: ContractInstanceWithAddress,
320
+ secret: Fr,
321
+ ) {
218
322
  const partialAddress = await computePartialAddress(instance);
219
323
 
220
324
  this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
221
325
  await this.contractStore.addContractInstance(instance);
222
- await this.contractStore.addContractArtifact(instance.currentContractClassId, artifact);
326
+ await this.contractStore.addContractArtifact(artifact);
223
327
 
224
- const completeAddress = await this.keyStore.addAccount(secret, partialAddress);
328
+ const completeAddress = await this.keyStore.addAccount(await deriveKeys(secret), partialAddress);
225
329
  await this.accountStore.setAccount(completeAddress.address, completeAddress);
226
330
  await this.addressStore.addCompleteAddress(completeAddress);
227
331
  this.logger.debug(`Created account ${completeAddress.address}`);
@@ -229,9 +333,9 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
229
333
  return completeAddress;
230
334
  }
231
335
 
232
- async txeCreateAccount(secret: Fr) {
336
+ async createAccount(secret: Fr) {
233
337
  // This is a foot gun !
234
- const completeAddress = await this.keyStore.addAccount(secret, secret);
338
+ const completeAddress = await this.keyStore.addAccount(await deriveKeys(secret), secret);
235
339
  await this.accountStore.setAccount(completeAddress.address, completeAddress);
236
340
  await this.addressStore.addCompleteAddress(completeAddress);
237
341
  this.logger.debug(`Created account ${completeAddress.address}`);
@@ -239,27 +343,52 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
239
343
  return completeAddress;
240
344
  }
241
345
 
242
- async txeAddAuthWitness(address: AztecAddress, messageHash: Fr) {
346
+ async addAuthWitness(address: AztecAddress, messageHash: Fr) {
243
347
  const account = await this.accountStore.getAccount(address);
244
- 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);
245
350
 
246
351
  const schnorr = new Schnorr();
247
- const signature = await schnorr.constructSignature(messageHash.toBuffer(), privateKey);
352
+ const signature = await schnorr.constructSignature(messageHash, privateKey);
248
353
 
249
- const authWitness = new AuthWitness(messageHash, [...signature.toBuffer()]);
354
+ const authWitness = new AuthWitness(messageHash, signature.toLimbFields());
250
355
 
251
356
  this.authwits.set(authWitness.requestHash.toString(), authWitness);
252
357
  }
253
358
 
254
- async mineBlock(options: { nullifiers?: Fr[] } = {}) {
255
- 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();
256
385
 
257
386
  const txEffect = TxEffect.empty();
258
387
  txEffect.nullifiers = [getSingleTxBlockRequestHash(blockNumber), ...(options.nullifiers ?? [])];
259
388
  txEffect.txHash = new TxHash(new Fr(blockNumber));
260
389
 
261
390
  const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
262
- await insertTxEffectIntoWorldTrees(txEffect, forkedWorldTrees);
391
+ await insertTxEffectIntoWorldTrees(txEffect, forkedWorldTrees, options.l1ToL2Messages ?? []);
263
392
 
264
393
  const globals = makeGlobalVariables(undefined, {
265
394
  blockNumber,
@@ -273,22 +402,33 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
273
402
 
274
403
  this.logger.info(`Created block ${blockNumber} with timestamp ${block.header.globalVariables.timestamp}`);
275
404
 
276
- await this.stateMachine.handleL2Block(block);
405
+ await this.stateMachine.handleL2Block(block, options.l1ToL2Messages ?? []);
277
406
  }
278
407
 
279
- async txePrivateCallNewFlow(
280
- from: AztecAddress,
408
+ async privateCallNewFlow(
409
+ from: AztecAddress | undefined,
281
410
  targetContractAddress: AztecAddress = AztecAddress.zero(),
282
411
  functionSelector: FunctionSelector = FunctionSelector.empty(),
283
412
  args: Fr[],
284
413
  argsHash: Fr = Fr.zero(),
285
414
  isStaticCall: boolean = false,
415
+ additionalScopes: AztecAddress[] = [],
416
+ jobId: string,
417
+ authorizedUtilityCallTargets: AztecAddress[],
418
+ gasSettings: GasSettings,
286
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
+
287
427
  this.logger.verbose(
288
- `Executing external function ${await this.contractStore.getDebugFunctionName(targetContractAddress, functionSelector)}@${targetContractAddress} isStaticCall=${isStaticCall}`,
428
+ `Executing external function ${await anchoredContractData.getDebugFunctionName(targetContractAddress, functionSelector)}@${targetContractAddress} isStaticCall=${isStaticCall}`,
289
429
  );
290
430
 
291
- const artifact = await this.contractStore.getFunctionArtifact(targetContractAddress, functionSelector);
431
+ const artifact = await anchoredContractData.getFunctionArtifact(targetContractAddress, functionSelector);
292
432
  if (!artifact) {
293
433
  const message = functionSelector.equals(await FunctionSelector.fromSignature('verify_private_authwit(Field)'))
294
434
  ? 'Found no account contract artifact for a private authwit check - use `create_contract_account` instead of `create_light_account` for authwit support.'
@@ -296,25 +436,29 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
296
436
  throw new Error(message);
297
437
  }
298
438
 
439
+ const scopes = from === undefined ? additionalScopes : [from, ...additionalScopes];
440
+
299
441
  // Sync notes before executing private function to discover notes from previous transactions
300
- const utilityExecutor = async (call: FunctionCall) => {
301
- await this.executeUtilityCall(call);
442
+ const utilityExecutor = async (call: FunctionCall, execScopes: AztecAddress[]) => {
443
+ await this.executeUtilityCall(call, { scopes: execScopes, jobId });
302
444
  };
303
445
 
304
- await this.contractStore.syncPrivateState(targetContractAddress, functionSelector, utilityExecutor);
305
-
306
- const blockNumber = await this.txeGetNextBlockNumber();
446
+ await this.stateMachine.contractSyncService.ensureContractSynced(
447
+ targetContractAddress,
448
+ functionSelector,
449
+ utilityExecutor,
450
+ blockHeader,
451
+ jobId,
452
+ scopes,
453
+ );
307
454
 
308
- const callContext = new CallContext(from, targetContractAddress, functionSelector, isStaticCall);
455
+ const blockNumber = await this.getNextBlockNumber();
309
456
 
310
- const gasLimits = new Gas(DEFAULT_DA_GAS_LIMIT, DEFAULT_L2_GAS_LIMIT);
311
- const teardownGasLimits = new Gas(DEFAULT_TEARDOWN_DA_GAS_LIMIT, DEFAULT_TEARDOWN_L2_GAS_LIMIT);
312
- 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);
313
459
 
314
460
  const txContext = new TxContext(this.chainId, this.version, gasSettings);
315
461
 
316
- const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
317
-
318
462
  const protocolNullifier = await computeProtocolNullifier(getSingleTxBlockRequestHash(blockNumber));
319
463
  const noteCache = new ExecutionNoteCache(protocolNullifier);
320
464
  // In production, the account contract sets the min revertible counter before calling the app function.
@@ -326,43 +470,53 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
326
470
 
327
471
  const simulator = new WASMSimulator();
328
472
 
329
- const privateExecutionOracle = new PrivateExecutionOracle(
473
+ const transientArrayService = new TransientArrayService();
474
+ const taggingSecretStrategy = this.taggingSecretStrategy;
475
+ const privateExecutionOracle = new PrivateExecutionOracle({
330
476
  argsHash,
331
477
  txContext,
478
+ txRequestSalt: Fr.ZERO,
332
479
  callContext,
333
- /** Header of a block whose state is used during private execution (not the block the transaction is included in). */
334
- blockHeader,
480
+ anchorBlockHeader: blockHeader,
335
481
  utilityExecutor,
336
- /** List of transient auth witnesses to be used during this simulation */
337
- Array.from(this.authwits.values()),
338
- /** List of transient auth witnesses to be used during this simulation */
339
- [],
340
- HashedValuesCache.create([new HashedValues(args, argsHash)]),
482
+ authWitnesses: Array.from(this.authwits.values()),
483
+ capsules: [],
484
+ executionCache: HashedValuesCache.create([new HashedValues(args, argsHash)]),
341
485
  noteCache,
342
486
  taggingIndexCache,
343
- this.contractStore,
344
- this.noteStore,
345
- this.keyStore,
346
- this.addressStore,
347
- this.stateMachine.node,
348
- this.stateMachine.anchorBlockStore,
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
 
@@ -414,7 +568,11 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
414
568
 
415
569
  const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
416
570
 
417
- const contractsDB = new PublicContractsDB(new TXEPublicContractDataSource(blockNumber, this.contractStore));
571
+ const bindings = this.logger.getBindings();
572
+ const contractsDB = new PublicContractsDB(
573
+ new TXEPublicContractDataSource(blockNumber, this.contractStore),
574
+ bindings,
575
+ );
418
576
  const guardedMerkleTrees = new GuardedMerkleTreeOperations(forkedWorldTrees);
419
577
  const config = PublicSimulatorConfig.from({
420
578
  skipFeeEnforcement: true,
@@ -427,8 +585,10 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
427
585
  globals,
428
586
  guardedMerkleTrees,
429
587
  contractsDB,
430
- new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config),
588
+ new PublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config, bindings),
431
589
  new TestDateProvider(),
590
+ undefined,
591
+ createLogger('simulator:public-processor', bindings),
432
592
  );
433
593
 
434
594
  const tx = await Tx.create({
@@ -453,7 +613,13 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
453
613
  } else if (!processedTx.revertCode.isOK()) {
454
614
  if (processedTx.revertReason) {
455
615
  try {
456
- await enrichPublicSimulationError(processedTx.revertReason, this.contractStore, this.logger);
616
+ await enrichPublicSimulationError(
617
+ processedTx.revertReason,
618
+ this.contractStore,
619
+ this.stateMachine.contractClassService,
620
+ await this.stateMachine.anchorBlockStore.getBlockHeader(),
621
+ this.logger,
622
+ );
457
623
  // eslint-disable-next-line no-empty
458
624
  } catch {}
459
625
  throw new Error(`Contract execution has reverted: ${processedTx.revertReason.getMessage()}`);
@@ -462,11 +628,17 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
462
628
  }
463
629
  }
464
630
 
631
+ // Walk the nested private-call tree and collect every offchain effect the transaction emitted.
632
+ // PXE stores these on each `PrivateCallExecutionResult` and they never reach TXE via the
633
+ // `aztec_utl_emitOffchainEffect` foreign-call path (that path only fires at the top-level), so
634
+ // we pull them out here and the RPC wrapper will hand them to `TXESession` for buffering.
635
+ const offchainEffects = collectNested([executionResult], r => r.offchainEffects.map(e => e.data));
636
+
465
637
  if (isStaticCall) {
466
638
  await checkpoint!.revert();
467
639
 
468
640
  await forkedWorldTrees.close();
469
- return executionResult.returnValues ?? [];
641
+ return { returnValues: executionResult.returnValues ?? [], offchainEffects };
470
642
  }
471
643
 
472
644
  const txEffect = TxEffect.empty();
@@ -488,31 +660,31 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
488
660
 
489
661
  await forkedWorldTrees.close();
490
662
 
491
- return executionResult.returnValues ?? [];
663
+ return { returnValues: executionResult.returnValues ?? [], offchainEffects };
492
664
  }
493
665
 
494
- async txePublicCallNewFlow(
495
- from: AztecAddress,
666
+ async publicCallNewFlow(
667
+ from: AztecAddress | undefined,
496
668
  targetContractAddress: AztecAddress,
497
669
  calldata: Fr[],
498
670
  isStaticCall: boolean,
671
+ gasSettings: GasSettings,
499
672
  ) {
500
- this.logger.verbose(
501
- `Executing public function ${await this.contractStore.getDebugFunctionName(targetContractAddress, FunctionSelector.fromField(calldata[0]))}@${targetContractAddress} isStaticCall=${isStaticCall}`,
673
+ const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
674
+ const anchoredContractData = new AnchoredContractData(
675
+ this.contractStore,
676
+ this.stateMachine.contractClassService,
677
+ anchorBlockHeader,
502
678
  );
503
679
 
504
- const blockNumber = await this.txeGetNextBlockNumber();
505
-
506
- const gasLimits = new Gas(DEFAULT_DA_GAS_LIMIT, DEFAULT_L2_GAS_LIMIT);
507
-
508
- const teardownGasLimits = new Gas(DEFAULT_TEARDOWN_DA_GAS_LIMIT, DEFAULT_TEARDOWN_L2_GAS_LIMIT);
680
+ this.logger.verbose(
681
+ `Executing public function ${await anchoredContractData.getDebugFunctionName(targetContractAddress, FunctionSelector.fromField(calldata[0]))}@${targetContractAddress} isStaticCall=${isStaticCall}`,
682
+ );
509
683
 
510
- const gasSettings = new GasSettings(gasLimits, teardownGasLimits, GasFees.empty(), GasFees.empty());
684
+ const blockNumber = await this.getNextBlockNumber();
511
685
 
512
686
  const txContext = new TxContext(this.chainId, this.version, gasSettings);
513
687
 
514
- const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
515
-
516
688
  const calldataHash = await computeCalldataHash(calldata);
517
689
  const calldataHashedValues = new HashedValues(calldata, calldataHash);
518
690
 
@@ -525,7 +697,11 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
525
697
 
526
698
  const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
527
699
 
528
- const contractsDB = new PublicContractsDB(new TXEPublicContractDataSource(blockNumber, this.contractStore));
700
+ const bindings2 = this.logger.getBindings();
701
+ const contractsDB = new PublicContractsDB(
702
+ new TXEPublicContractDataSource(blockNumber, this.contractStore),
703
+ bindings2,
704
+ );
529
705
  const guardedMerkleTrees = new GuardedMerkleTreeOperations(forkedWorldTrees);
530
706
  const config = PublicSimulatorConfig.from({
531
707
  skipFeeEnforcement: true,
@@ -534,8 +710,16 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
534
710
  collectStatistics: false,
535
711
  collectCallMetadata: true,
536
712
  });
537
- const simulator = new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config);
538
- const processor = new PublicProcessor(globals, guardedMerkleTrees, contractsDB, simulator, new TestDateProvider());
713
+ const simulator = new PublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config, bindings2);
714
+ const processor = new PublicProcessor(
715
+ globals,
716
+ guardedMerkleTrees,
717
+ contractsDB,
718
+ simulator,
719
+ new TestDateProvider(),
720
+ undefined,
721
+ createLogger('simulator:public-processor', bindings2),
722
+ );
539
723
 
540
724
  // We're simulating a scenario in which private execution immediately enqueues a public call and halts. The private
541
725
  // kernel init would in this case inject a nullifier with the transaction request hash as a non-revertible
@@ -548,7 +732,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
548
732
  // may require producing reverts.
549
733
  const revertibleAccumulatedData = PrivateToPublicAccumulatedData.empty();
550
734
  revertibleAccumulatedData.publicCallRequests[0] = new PublicCallRequest(
551
- from,
735
+ from ?? AztecAddress.NULL_MSG_SENDER,
552
736
  targetContractAddress,
553
737
  isStaticCall,
554
738
  calldataHash,
@@ -566,7 +750,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
566
750
  constantData,
567
751
  /*gasUsed=*/ new Gas(0, 0),
568
752
  /*feePayer=*/ AztecAddress.zero(),
569
- /*includeByTimestamp=*/ 0n,
753
+ /*expirationTimestamp=*/ 0n,
570
754
  inputsForPublic,
571
755
  undefined,
572
756
  );
@@ -593,7 +777,13 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
593
777
  } else if (!processedTx.revertCode.isOK()) {
594
778
  if (processedTx.revertReason) {
595
779
  try {
596
- await enrichPublicSimulationError(processedTx.revertReason, this.contractStore, this.logger);
780
+ await enrichPublicSimulationError(
781
+ processedTx.revertReason,
782
+ this.contractStore,
783
+ this.stateMachine.contractClassService,
784
+ anchorBlockHeader,
785
+ this.logger,
786
+ );
597
787
  // eslint-disable-next-line no-empty
598
788
  } catch {}
599
789
  throw new Error(`Contract execution has reverted: ${processedTx.revertReason.getMessage()}`);
@@ -634,37 +824,77 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
634
824
  return returnValues ?? [];
635
825
  }
636
826
 
637
- async txeSimulateUtilityFunction(
827
+ async executeUtilityFunction(
828
+ from: AztecAddress | undefined,
638
829
  targetContractAddress: AztecAddress,
639
830
  functionSelector: FunctionSelector,
640
831
  args: Fr[],
832
+ jobId: string,
833
+ authorizedUtilityCallTargets: AztecAddress[],
641
834
  ) {
642
- const artifact = await this.contractStore.getFunctionArtifact(targetContractAddress, functionSelector);
835
+ const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
836
+ const anchoredContractData = new AnchoredContractData(
837
+ this.contractStore,
838
+ this.stateMachine.contractClassService,
839
+ blockHeader,
840
+ );
841
+
842
+ const artifact = await anchoredContractData.getFunctionArtifact(targetContractAddress, functionSelector);
643
843
  if (!artifact) {
644
844
  throw new Error(`Cannot call ${functionSelector} as there is no artifact found at ${targetContractAddress}.`);
645
845
  }
646
846
 
647
847
  // Sync notes before executing utility function to discover notes from previous transactions
648
- await this.contractStore.syncPrivateState(targetContractAddress, functionSelector, async call => {
649
- await this.executeUtilityCall(call);
650
- });
651
-
652
- const call = new FunctionCall(
653
- artifact.name,
848
+ await this.stateMachine.contractSyncService.ensureContractSynced(
654
849
  targetContractAddress,
655
850
  functionSelector,
656
- FunctionType.UTILITY,
657
- false,
658
- false,
659
- args,
660
- [],
851
+ async (call, execScopes) => {
852
+ await this.executeUtilityCall(call, { scopes: execScopes, jobId });
853
+ },
854
+ blockHeader,
855
+ jobId,
856
+ await this.keyStore.getAccounts(),
661
857
  );
662
858
 
663
- return this.executeUtilityCall(call);
859
+ const call = FunctionCall.from({
860
+ name: artifact.name,
861
+ to: targetContractAddress,
862
+ selector: functionSelector,
863
+ type: FunctionType.UTILITY,
864
+ hideMsgSender: false,
865
+ isStatic: false,
866
+ args,
867
+ returnTypes: [],
868
+ });
869
+
870
+ return this.executeUtilityCall(call, {
871
+ from,
872
+ scopes: await this.keyStore.getAccounts(),
873
+ jobId,
874
+ authorizedUtilityCallTargets,
875
+ });
664
876
  }
665
877
 
666
- private async executeUtilityCall(call: FunctionCall): Promise<Fr[]> {
667
- const entryPointArtifact = await this.contractStore.getFunctionArtifactWithDebugMetadata(call.to, call.selector);
878
+ private async executeUtilityCall(
879
+ call: FunctionCall,
880
+ {
881
+ from = AztecAddress.NULL_MSG_SENDER,
882
+ scopes,
883
+ jobId,
884
+ authorizedUtilityCallTargets = [],
885
+ }: { from?: AztecAddress; scopes: AztecAddress[]; jobId: string; authorizedUtilityCallTargets?: AztecAddress[] },
886
+ ): Promise<Fr[]> {
887
+ const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
888
+ const anchoredContractData = new AnchoredContractData(
889
+ this.contractStore,
890
+ this.stateMachine.contractClassService,
891
+ anchorBlockHeader,
892
+ );
893
+
894
+ const entryPointArtifact = await anchoredContractData.getFunctionArtifactWithDebugMetadata(call.to, call.selector);
895
+ if (!entryPointArtifact) {
896
+ throw new Error(`Cannot run function ${call.selector} on ${call.to}: the contract is not registered.`);
897
+ }
668
898
  if (entryPointArtifact.functionType !== FunctionType.UTILITY) {
669
899
  throw new Error(`Cannot run ${entryPointArtifact.functionType} function as utility`);
670
900
  }
@@ -675,26 +905,45 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
675
905
  });
676
906
 
677
907
  try {
678
- const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
679
- const oracle = new UtilityExecutionOracle(
680
- call.to,
681
- [],
682
- [],
908
+ const simulator = new WASMSimulator();
909
+ const utilityExecutor = async (syncCall: FunctionCall, execScopes: AztecAddress[]) => {
910
+ await this.executeUtilityCall(syncCall, { scopes: execScopes, jobId });
911
+ };
912
+ const oracle = new UtilityExecutionOracle({
913
+ callContext: CallContext.from({
914
+ msgSender: from,
915
+ contractAddress: call.to,
916
+ functionSelector: call.selector,
917
+ isStaticCall: true,
918
+ }),
919
+ authWitnesses: [],
920
+ capsules: [],
683
921
  anchorBlockHeader,
684
- this.contractStore,
685
- this.noteStore,
686
- this.keyStore,
687
- this.addressStore,
688
- this.stateMachine.node,
689
- this.stateMachine.anchorBlockStore,
690
- this.recipientTaggingStore,
691
- this.senderAddressBookStore,
692
- this.capsuleStore,
693
- this.privateEventStore,
694
- this.jobId,
695
- );
696
- const acirExecutionResult = await new WASMSimulator()
697
- .executeUserCircuit(toACVMWitness(0, call.args), entryPointArtifact, new Oracle(oracle).toACIRCallback())
922
+ anchoredContractData,
923
+ noteStore: this.noteStore,
924
+ keyStore: this.keyStore,
925
+ addressStore: this.addressStore,
926
+ aztecNode: this.stateMachine.node,
927
+ recipientTaggingStore: this.recipientTaggingStore,
928
+ taggingSecretSourcesStore: this.taggingSecretSourcesStore,
929
+ capsuleService: new CapsuleService(this.capsuleStore, scopes),
930
+ factService: new FactService(this.factStore, scopes),
931
+ privateEventStore: this.privateEventStore,
932
+ txResolver: this.stateMachine.txResolver,
933
+ contractSyncService: this.stateMachine.contractSyncService,
934
+ l2TipsStore: this.stateMachine.l2TipsProvider,
935
+ jobId,
936
+ scopes,
937
+ simulator,
938
+ hooks: composeHooks({
939
+ authorizeUtilityCall: this.buildAuthorizeUtilityCallHook('utility', authorizedUtilityCallTargets),
940
+ }),
941
+ utilityExecutor,
942
+ // Execution-tree root (top-level utility run or contract sync): own store; nested frames inherit it.
943
+ transientArrayService: new TransientArrayService(),
944
+ });
945
+ const acirExecutionResult = await simulator
946
+ .executeUserCircuit(toACVMWitness(0, call.args), entryPointArtifact, buildACIRCallback(oracle))
698
947
  .catch((err: Error) => {
699
948
  err.message = resolveAssertionMessageFromError(err, entryPointArtifact);
700
949
  throw new ExecutionError(
@@ -708,20 +957,33 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
708
957
  );
709
958
  });
710
959
 
711
- this.logger.verbose(`Utility simulation for ${call.to}.${call.selector} completed`);
960
+ this.logger.verbose(`Utility execution for ${call.to}.${call.selector} completed`);
712
961
  return witnessMapToFields(acirExecutionResult.returnWitness);
713
962
  } catch (err) {
714
- throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during utility simulation'));
963
+ throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during utility execution'));
715
964
  }
716
965
  }
717
966
 
718
- close(): [bigint, Map<string, AuthWitness>] {
967
+ close(): [bigint, Map<string, AuthWitness>, TaggingSecretStrategy | undefined] {
719
968
  this.logger.debug('Exiting Top Level Context');
720
- return [this.nextBlockTimestamp, this.authwits];
969
+ return [this.nextBlockTimestamp, this.authwits, this.taggingSecretStrategy];
721
970
  }
722
971
 
723
972
  private async getLastBlockNumber(): Promise<BlockNumber> {
724
- const header = await this.stateMachine.node.getBlockHeader('latest');
725
- return header ? header.globalVariables.blockNumber : BlockNumber.ZERO;
973
+ const block = await this.stateMachine.node.getBlock('latest');
974
+ return block ? block.header.globalVariables.blockNumber : BlockNumber.ZERO;
975
+ }
976
+
977
+ private buildAuthorizeUtilityCallHook(
978
+ callerContext: 'private' | 'private view' | 'utility',
979
+ authorizedTargets: AztecAddress[],
980
+ ): ExecutionHooks['authorizeUtilityCall'] | undefined {
981
+ if (authorizedTargets.length === 0) {
982
+ return undefined;
983
+ }
984
+ return req =>
985
+ Promise.resolve({
986
+ authorized: req.callerContext === callerContext && authorizedTargets.some(t => t.equals(req.target)),
987
+ });
726
988
  }
727
989
  }