@aztec/txe 0.0.1-commit.4d3c002 → 0.0.1-commit.4d9804df

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 (168) hide show
  1. package/dest/AuthRegistry-QVGDDH5X.js +3 -0
  2. package/dest/AuthRegistry-QVGDDH5X.js.map +7 -0
  3. package/dest/ContractClassRegistry-VWR3F42P.js +3 -0
  4. package/dest/ContractClassRegistry-VWR3F42P.js.map +7 -0
  5. package/dest/ContractInstanceRegistry-FHIWE33X.js +3 -0
  6. package/dest/ContractInstanceRegistry-FHIWE33X.js.map +7 -0
  7. package/dest/FeeJuice-SAOWVGG7.js +3 -0
  8. package/dest/FeeJuice-SAOWVGG7.js.map +7 -0
  9. package/dest/HandshakeRegistry-GY5CPEPS.js +3 -0
  10. package/dest/HandshakeRegistry-GY5CPEPS.js.map +7 -0
  11. package/dest/MultiCallEntrypoint-QG5H33ZZ.js +3 -0
  12. package/dest/MultiCallEntrypoint-QG5H33ZZ.js.map +7 -0
  13. package/dest/SchnorrAccount-NME3E45O.js +3 -0
  14. package/dest/SchnorrAccount-NME3E45O.js.map +7 -0
  15. package/dest/SchnorrInitializerlessAccount-WTGXU6SW.js +3 -0
  16. package/dest/SchnorrInitializerlessAccount-WTGXU6SW.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 +53 -0
  20. package/dest/bin/index.js +3 -30
  21. package/dest/bin/index.js.map +7 -0
  22. package/dest/bin/oracle_test_server.d.ts +3 -0
  23. package/dest/bin/oracle_test_server.d.ts.map +1 -0
  24. package/dest/bin/oracle_test_server.js +41 -0
  25. package/dest/chunk-32UHX7YY.js +3 -0
  26. package/dest/chunk-32UHX7YY.js.map +7 -0
  27. package/dest/chunk-GSUKUCKV.js +260 -0
  28. package/dest/chunk-GSUKUCKV.js.map +7 -0
  29. package/dest/chunk-UP4KKUVA.js +304 -0
  30. package/dest/chunk-UP4KKUVA.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 +72 -190
  40. package/dest/metafile.json +38759 -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 +47 -9
  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 +16 -0
  50. package/dest/oracle/test-resolver/default_fixtures.d.ts.map +1 -0
  51. package/dest/oracle/test-resolver/default_fixtures.js +200 -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 +26 -2
  59. package/dest/oracle/txe_oracle_public_context.d.ts.map +1 -1
  60. package/dest/oracle/txe_oracle_public_context.js +49 -1
  61. package/dest/oracle/txe_oracle_registry.d.ts +172 -0
  62. package/dest/oracle/txe_oracle_registry.d.ts.map +1 -0
  63. package/dest/oracle/txe_oracle_registry.js +767 -0
  64. package/dest/oracle/txe_oracle_top_level_context.d.ts +58 -18
  65. package/dest/oracle/txe_oracle_top_level_context.d.ts.map +1 -1
  66. package/dest/oracle/txe_oracle_top_level_context.js +555 -301
  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 +115 -233
  77. package/dest/rpc_translator.d.ts.map +1 -1
  78. package/dest/rpc_translator.js +791 -647
  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 +4 -3
  82. package/dest/state_machine/archiver.d.ts.map +1 -1
  83. package/dest/state_machine/archiver.js +25 -16
  84. package/dest/state_machine/dummy_p2p_client.d.ts +14 -6
  85. package/dest/state_machine/dummy_p2p_client.d.ts.map +1 -1
  86. package/dest/state_machine/dummy_p2p_client.js +20 -2
  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 +11 -7
  91. package/dest/state_machine/index.d.ts.map +1 -1
  92. package/dest/state_machine/index.js +50 -14
  93. package/dest/state_machine/mock_epoch_cache.d.ts +1 -2
  94. package/dest/state_machine/mock_epoch_cache.d.ts.map +1 -1
  95. package/dest/state_machine/mock_epoch_cache.js +0 -3
  96. package/dest/state_machine/synchronizer.d.ts +10 -2
  97. package/dest/state_machine/synchronizer.d.ts.map +1 -1
  98. package/dest/state_machine/synchronizer.js +19 -6
  99. package/dest/txe_session.d.ts +90 -20
  100. package/dest/txe_session.d.ts.map +1 -1
  101. package/dest/txe_session.js +316 -63
  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 +2 -2
  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/{util → utils}/txe_public_contract_data_source.js +7 -4
  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 +67 -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 -227
  133. package/src/msgpackr_fr_extension.ts +23 -0
  134. package/src/oracle/interfaces.ts +47 -8
  135. package/src/oracle/tagging_secret_strategy.ts +25 -0
  136. package/src/oracle/test-resolver/default_fixtures.ts +271 -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 +62 -0
  140. package/src/oracle/txe_oracle_registry.ts +556 -0
  141. package/src/oracle/txe_oracle_top_level_context.ts +356 -112
  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 +890 -938
  146. package/src/state_machine/archiver.ts +37 -17
  147. package/src/state_machine/dummy_p2p_client.ts +38 -9
  148. package/src/state_machine/global_variable_builder.ts +12 -17
  149. package/src/state_machine/index.ts +62 -32
  150. package/src/state_machine/mock_epoch_cache.ts +0 -4
  151. package/src/state_machine/synchronizer.ts +27 -6
  152. package/src/txe_session.ts +548 -76
  153. package/src/utils/block_creation.ts +2 -1
  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/{util → utils}/txe_public_contract_data_source.ts +6 -4
  158. package/src/worker.ts +98 -0
  159. package/dest/util/encoding.d.ts +0 -788
  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_public_contract_data_source.d.ts +0 -20
  164. package/dest/util/txe_public_contract_data_source.d.ts.map +0 -1
  165. /package/dest/{util → utils}/expected_failure_error.js +0 -0
  166. /package/dest/{util → utils}/txe_account_store.js +0 -0
  167. /package/src/{util → utils}/expected_failure_error.ts +0 -0
  168. /package/src/{util → utils}/txe_account_store.ts +0 -0
@@ -1,39 +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,
17
16
  CapsuleService,
18
17
  CapsuleStore,
19
18
  type ContractStore,
20
- type ContractSyncService,
19
+ type ExecutionHooks,
20
+ FactService,
21
+ FactStore,
21
22
  NoteStore,
22
- ORACLE_VERSION,
23
+ ORACLE_VERSION_MAJOR,
23
24
  PrivateEventStore,
24
25
  RecipientTaggingStore,
25
- SenderAddressBookStore,
26
26
  SenderTaggingStore,
27
+ TaggingSecretSourcesStore,
28
+ type TaggingSecretStrategy,
29
+ composeHooks,
27
30
  enrichPublicSimulationError,
28
31
  } from '@aztec/pxe/server';
29
32
  import {
33
+ CONTRACT_INSTANCE,
30
34
  ExecutionNoteCache,
31
35
  ExecutionTaggingIndexCache,
32
36
  HashedValuesCache,
33
37
  type IMiscOracle,
34
- Oracle,
38
+ type Option,
35
39
  PrivateExecutionOracle,
40
+ TransientArrayService,
36
41
  UtilityExecutionOracle,
42
+ buildACIRCallback,
37
43
  executePrivateFunction,
38
44
  generateSimulatedProvingResult,
39
45
  } from '@aztec/pxe/simulator';
@@ -47,10 +53,10 @@ import {
47
53
  witnessMapToFields,
48
54
  } from '@aztec/simulator/client';
49
55
  import {
50
- CppPublicTxSimulator,
51
56
  GuardedMerkleTreeOperations,
52
57
  PublicContractsDB,
53
58
  PublicProcessor,
59
+ PublicTxSimulator,
54
60
  } from '@aztec/simulator/server';
55
61
  import { type ContractArtifact, EventSelector, FunctionCall, FunctionSelector, FunctionType } from '@aztec/stdlib/abi';
56
62
  import { AuthWitness } from '@aztec/stdlib/auth-witness';
@@ -65,6 +71,10 @@ import {
65
71
  PrivateToPublicAccumulatedData,
66
72
  PublicCallRequest,
67
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';
68
78
  import { ChonkProof } from '@aztec/stdlib/proofs';
69
79
  import { makeGlobalVariables } from '@aztec/stdlib/testing';
70
80
  import { MerkleTreeId } from '@aztec/stdlib/trees';
@@ -81,14 +91,16 @@ import {
81
91
  collectNested,
82
92
  } from '@aztec/stdlib/tx';
83
93
  import type { UInt64 } from '@aztec/stdlib/types';
84
- import { ForkCheckpoint } from '@aztec/world-state';
94
+ import { ForkCheckpoint } from '@aztec/world-state/native';
85
95
 
86
- import { DEFAULT_ADDRESS } from '../constants.js';
96
+ import { DEFAULT_ADDRESS, MAX_PRIVATE_EVENTS_PER_TXE_QUERY, MAX_PRIVATE_EVENT_LEN } from '../constants.js';
87
97
  import type { TXEStateMachine } from '../state_machine/index.js';
88
- import type { TXEAccountStore } from '../util/txe_account_store.js';
89
- import { TXEPublicContractDataSource } from '../util/txe_public_contract_data_source.js';
90
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';
91
102
  import type { ITxeExecutionOracle } from './interfaces.js';
103
+ import { type TXETaggingSecretStrategies, makeResolveTaggingSecretStrategyHook } from './tagging_secret_strategy.js';
92
104
 
93
105
  export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracle {
94
106
  isMisc = true as const;
@@ -105,29 +117,42 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
105
117
  private accountStore: TXEAccountStore,
106
118
  private senderTaggingStore: SenderTaggingStore,
107
119
  private recipientTaggingStore: RecipientTaggingStore,
108
- private senderAddressBookStore: SenderAddressBookStore,
120
+ private taggingSecretSourcesStore: TaggingSecretSourcesStore,
109
121
  private capsuleStore: CapsuleStore,
122
+ private factStore: FactStore,
110
123
  private privateEventStore: PrivateEventStore,
111
124
  private nextBlockTimestamp: bigint,
112
125
  private version: Fr,
113
126
  private chainId: Fr,
114
127
  private authwits: Map<string, AuthWitness>,
115
- private readonly contractSyncService: ContractSyncService,
128
+ private taggingSecretStrategies: TXETaggingSecretStrategies,
129
+ private authorizeAllUtilityCallTargets: boolean,
130
+ private readonly artifactResolver: TXEArtifactResolver,
131
+ private readonly rootPath: string,
132
+ private readonly packageName: string,
116
133
  ) {
117
134
  this.logger = createLogger('txe:top_level_context');
118
135
  this.logger.debug('Entering Top Level Context');
119
136
  }
120
137
 
121
- assertCompatibleOracleVersion(version: number): void {
122
- if (version !== ORACLE_VERSION) {
138
+ private contractOracleVersion: { major: number; minor: number } | undefined;
139
+
140
+ assertCompatibleOracleVersion(major: number, minor: number): void {
141
+ if (major !== ORACLE_VERSION_MAJOR) {
123
142
  const hint =
124
- version > ORACLE_VERSION
143
+ major > ORACLE_VERSION_MAJOR
125
144
  ? 'The contract was compiled with a newer version of Aztec.nr than this aztec cli version supports. Upgrade your aztec cli version to a compatible version.'
126
145
  : '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.';
127
146
  throw new Error(
128
- `Incompatible aztec cli version: ${hint} See https://docs.aztec.network/errors/8 (expected oracle version ${ORACLE_VERSION}, got ${version})`,
147
+ `Incompatible aztec cli version: ${hint} See https://docs.aztec.network/errors/8 (expected oracle major version ${ORACLE_VERSION_MAJOR}, got ${major})`,
129
148
  );
130
149
  }
150
+ this.contractOracleVersion = { major, minor };
151
+ }
152
+
153
+ // Prefixed with "nonOracleFunction" as it is not used as an oracle handler.
154
+ nonOracleFunctionGetContractOracleVersion(): { major: number; minor: number } | undefined {
155
+ return this.contractOracleVersion;
131
156
  }
132
157
 
133
158
  // This is typically only invoked in private contexts, but it is convenient to also have it in top-level for testing
@@ -137,7 +162,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
137
162
  }
138
163
 
139
164
  // We instruct users to debug contracts via this oracle, so it makes sense that they'd expect it to also work in tests
140
- log(level: number, message: string, fields: Fr[]): Promise<void> {
165
+ log(level: number, message: string, _fieldsSize: number, fields: Fr[]): Promise<void> {
141
166
  if (!LogLevels[level]) {
142
167
  throw new Error(`Invalid log level: ${level}`);
143
168
  }
@@ -160,12 +185,12 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
160
185
  }
161
186
 
162
187
  async getLastBlockTimestamp() {
163
- return (await this.stateMachine.node.getBlockHeader('latest'))!.globalVariables.timestamp;
188
+ return (await this.stateMachine.node.getBlockData('latest'))!.header.globalVariables.timestamp;
164
189
  }
165
190
 
166
- async getLastTxEffects() {
191
+ async getLastTxEffects(): Promise<{ txHash: TxHash; noteHashes: Fr[]; nullifiers: Fr[]; privateLogs: PrivateLog[] }> {
167
192
  const latestBlockNumber = await this.stateMachine.archiver.getBlockNumber();
168
- const block = await this.stateMachine.archiver.getBlock(latestBlockNumber);
193
+ const block = await this.stateMachine.archiver.getBlock({ number: latestBlockNumber });
169
194
 
170
195
  if (block!.body.txEffects.length != 1) {
171
196
  // Note that calls like env.mine() will result in blocks with no transactions, hitting this
@@ -174,7 +199,17 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
174
199
 
175
200
  const txEffects = block!.body.txEffects[0];
176
201
 
177
- return { txHash: txEffects.txHash, noteHashes: txEffects.noteHashes, nullifiers: txEffects.nullifiers };
202
+ const privateLogs = txEffects.privateLogs;
203
+ if (privateLogs.length > MAX_PRIVATE_LOGS_PER_TX) {
204
+ throw new Error(`${privateLogs.length} private logs exceed max ${MAX_PRIVATE_LOGS_PER_TX}`);
205
+ }
206
+
207
+ return {
208
+ txHash: txEffects.txHash,
209
+ noteHashes: txEffects.noteHashes,
210
+ nullifiers: txEffects.nullifiers,
211
+ privateLogs,
212
+ };
178
213
  }
179
214
 
180
215
  async syncContractNonOracleMethod(contractAddress: AztecAddress, scope: AztecAddress, jobId: string) {
@@ -188,7 +223,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
188
223
  contractAddress,
189
224
  null,
190
225
  async (call, execScopes) => {
191
- await this.executeUtilityCall(call, execScopes, jobId);
226
+ await this.executeUtilityCall(call, { scopes: execScopes, jobId });
192
227
  },
193
228
  blockHeader,
194
229
  jobId,
@@ -197,7 +232,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
197
232
  }
198
233
 
199
234
  async getPrivateEvents(selector: EventSelector, contractAddress: AztecAddress, scope: AztecAddress) {
200
- return (
235
+ const events = (
201
236
  await this.privateEventStore.getPrivateEvents(selector, {
202
237
  contractAddress,
203
238
  scopes: [scope],
@@ -205,6 +240,15 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
205
240
  toBlock: (await this.getLastBlockNumber()) + 1,
206
241
  })
207
242
  ).map(e => e.packedEvent);
243
+
244
+ if (events.length > MAX_PRIVATE_EVENTS_PER_TXE_QUERY) {
245
+ throw new Error(`Array of length ${events.length} larger than maxLen ${MAX_PRIVATE_EVENTS_PER_TXE_QUERY}`);
246
+ }
247
+ if (events.some(e => e.length > MAX_PRIVATE_EVENT_LEN)) {
248
+ throw new Error(`Some private event has length larger than maxLen ${MAX_PRIVATE_EVENT_LEN}`);
249
+ }
250
+
251
+ return events;
208
252
  }
209
253
 
210
254
  async advanceBlocksBy(blocks: number) {
@@ -220,34 +264,71 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
220
264
  this.nextBlockTimestamp += duration;
221
265
  }
222
266
 
223
- async deploy(artifact: ContractArtifact, instance: ContractInstanceWithAddress, secret: Fr) {
267
+ private deploymentNullifier(address: AztecAddress): Promise<Fr> {
268
+ return siloNullifier(AztecAddress.fromNumberUnsafe(CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS), address.toField());
269
+ }
270
+
271
+ async deploy(
272
+ contractPath: string,
273
+ initializer: string,
274
+ args: Fr[],
275
+ secret: Fr,
276
+ salt: Fr,
277
+ deployer: AztecAddress,
278
+ ): Promise<Fr[]> {
279
+ const { artifact, instance } = await this.artifactResolver.resolveDeployArtifact({
280
+ rootPath: this.rootPath,
281
+ packageName: this.packageName,
282
+ contractPath,
283
+ initializer,
284
+ args,
285
+ secret,
286
+ salt,
287
+ deployer,
288
+ });
289
+
224
290
  // Emit deployment nullifier
225
291
  await this.mineBlock({
226
- nullifiers: [
227
- await siloNullifier(
228
- AztecAddress.fromNumber(CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS),
229
- instance.address.toField(),
230
- ),
231
- ],
292
+ nullifiers: [await this.deploymentNullifier(instance.address)],
232
293
  });
233
294
 
234
295
  if (!secret.equals(Fr.ZERO)) {
235
- await this.addAccount(artifact, instance, secret);
296
+ await this.registerContractAndAddAccount(artifact, instance, secret);
236
297
  } else {
237
298
  await this.contractStore.addContractInstance(instance);
238
299
  await this.contractStore.addContractArtifact(artifact);
239
300
  this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
240
301
  }
302
+
303
+ return CONTRACT_INSTANCE.serialization!.fn(instance).flat();
304
+ }
305
+
306
+ /**
307
+ * Mines a single block containing only the deployment nullifiers for the contracts at the given addresses.
308
+ */
309
+ async mineDeploymentNullifiers(addresses: AztecAddress[]) {
310
+ await this.mineBlock({
311
+ nullifiers: await Promise.all(addresses.map(address => this.deploymentNullifier(address))),
312
+ });
313
+ }
314
+
315
+ async addAccount(secret: Fr) {
316
+ const { artifact, instance } = await this.artifactResolver.resolveAccountArtifact(secret);
317
+ return this.registerContractAndAddAccount(artifact, instance, secret);
241
318
  }
242
319
 
243
- async addAccount(artifact: ContractArtifact, instance: ContractInstanceWithAddress, secret: Fr) {
320
+ private async registerContractAndAddAccount(
321
+ artifact: ContractArtifact,
322
+ instance: ContractInstanceWithAddress,
323
+ secret: Fr,
324
+ ) {
244
325
  const partialAddress = await computePartialAddress(instance);
245
326
 
246
327
  this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
247
328
  await this.contractStore.addContractInstance(instance);
248
329
  await this.contractStore.addContractArtifact(artifact);
249
330
 
250
- const completeAddress = await this.keyStore.addAccount(secret, partialAddress);
331
+ const completeAddress = await this.keyStore.addAccount(await deriveKeys(secret), partialAddress);
251
332
  await this.accountStore.setAccount(completeAddress.address, completeAddress);
252
333
  await this.addressStore.addCompleteAddress(completeAddress);
253
334
  this.logger.debug(`Created account ${completeAddress.address}`);
@@ -255,9 +336,8 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
255
336
  return completeAddress;
256
337
  }
257
338
 
258
- async createAccount(secret: Fr) {
259
- // This is a foot gun !
260
- const completeAddress = await this.keyStore.addAccount(secret, secret);
339
+ async createAccount(secret: Fr, partialAddress: Fr) {
340
+ const completeAddress = await this.keyStore.addAccount(await deriveKeys(secret), partialAddress);
261
341
  await this.accountStore.setAccount(completeAddress.address, completeAddress);
262
342
  await this.addressStore.addCompleteAddress(completeAddress);
263
343
  this.logger.debug(`Created account ${completeAddress.address}`);
@@ -267,17 +347,57 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
267
347
 
268
348
  async addAuthWitness(address: AztecAddress, messageHash: Fr) {
269
349
  const account = await this.accountStore.getAccount(address);
270
- 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);
271
352
 
272
353
  const schnorr = new Schnorr();
273
- const signature = await schnorr.constructSignature(messageHash.toBuffer(), privateKey);
354
+ const signature = await schnorr.constructSignature(messageHash, privateKey);
274
355
 
275
- const authWitness = new AuthWitness(messageHash, [...signature.toBuffer()]);
356
+ const authWitness = new AuthWitness(messageHash, signature.toLimbFields());
276
357
 
277
358
  this.authwits.set(authWitness.requestHash.toString(), authWitness);
278
359
  }
279
360
 
280
- async mineBlock(options: { nullifiers?: Fr[] } = {}) {
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
+ setAuthorizeAllUtilityCallTargets(authorizeAll: boolean): void {
377
+ this.authorizeAllUtilityCallTargets = authorizeAll;
378
+ }
379
+
380
+ async sendL1ToL2Message(content: Fr, secretHash: Fr, sender: EthAddress, recipient: AztecAddress): Promise<Fr> {
381
+ // Messages are appended to the tree, so the next free slot is simply the current tree size.
382
+ const { size } = await this.stateMachine.synchronizer
383
+ .getCommitted()
384
+ .getTreeInfo(MerkleTreeId.L1_TO_L2_MESSAGE_TREE);
385
+ const leafIndex = new Fr(size);
386
+
387
+ const message = new L1ToL2Message(
388
+ new L1Actor(sender, this.chainId.toNumber()),
389
+ new L2Actor(recipient, this.version.toNumber()),
390
+ content,
391
+ secretHash,
392
+ leafIndex,
393
+ );
394
+
395
+ await this.mineBlock({ l1ToL2Messages: [message.hash()] });
396
+
397
+ return leafIndex;
398
+ }
399
+
400
+ async mineBlock(options: { nullifiers?: Fr[]; l1ToL2Messages?: Fr[] } = {}) {
281
401
  const blockNumber = await this.getNextBlockNumber();
282
402
 
283
403
  const txEffect = TxEffect.empty();
@@ -285,7 +405,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
285
405
  txEffect.txHash = new TxHash(new Fr(blockNumber));
286
406
 
287
407
  const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
288
- await insertTxEffectIntoWorldTrees(txEffect, forkedWorldTrees);
408
+ await insertTxEffectIntoWorldTrees(txEffect, forkedWorldTrees, options.l1ToL2Messages ?? []);
289
409
 
290
410
  const globals = makeGlobalVariables(undefined, {
291
411
  blockNumber,
@@ -299,23 +419,33 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
299
419
 
300
420
  this.logger.info(`Created block ${blockNumber} with timestamp ${block.header.globalVariables.timestamp}`);
301
421
 
302
- await this.stateMachine.handleL2Block(block);
422
+ await this.stateMachine.handleL2Block(block, options.l1ToL2Messages ?? []);
303
423
  }
304
424
 
305
425
  async privateCallNewFlow(
306
- from: AztecAddress,
426
+ from: AztecAddress | undefined,
307
427
  targetContractAddress: AztecAddress = AztecAddress.zero(),
308
428
  functionSelector: FunctionSelector = FunctionSelector.empty(),
309
429
  args: Fr[],
310
430
  argsHash: Fr = Fr.zero(),
311
431
  isStaticCall: boolean = false,
432
+ additionalScopes: AztecAddress[] = [],
312
433
  jobId: string,
434
+ authorizedUtilityCallTargets: AztecAddress[],
435
+ gasSettings: GasSettings,
313
436
  ) {
437
+ const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
438
+ const anchoredContractData = new AnchoredContractData(
439
+ this.contractStore,
440
+ this.stateMachine.contractClassService,
441
+ blockHeader,
442
+ );
443
+
314
444
  this.logger.verbose(
315
- `Executing external function ${await this.contractStore.getDebugFunctionName(targetContractAddress, functionSelector)}@${targetContractAddress} isStaticCall=${isStaticCall}`,
445
+ `Executing external function ${await anchoredContractData.getDebugFunctionName(targetContractAddress, functionSelector)}@${targetContractAddress} isStaticCall=${isStaticCall}`,
316
446
  );
317
447
 
318
- const artifact = await this.contractStore.getFunctionArtifact(targetContractAddress, functionSelector);
448
+ const artifact = await anchoredContractData.getFunctionArtifact(targetContractAddress, functionSelector);
319
449
  if (!artifact) {
320
450
  const message = functionSelector.equals(await FunctionSelector.fromSignature('verify_private_authwit(Field)'))
321
451
  ? 'Found no account contract artifact for a private authwit check - use `create_contract_account` instead of `create_light_account` for authwit support.'
@@ -323,32 +453,26 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
323
453
  throw new Error(message);
324
454
  }
325
455
 
326
- // When `from` is the zero address (e.g. when deploying a new account contract), we return an
327
- // empty scope list which acts as deny-all: no notes are visible and no keys are accessible.
328
- const effectiveScopes = from.isZero() ? [] : [from];
456
+ const scopes = from === undefined ? additionalScopes : [from, ...additionalScopes];
329
457
 
330
458
  // Sync notes before executing private function to discover notes from previous transactions
331
459
  const utilityExecutor = async (call: FunctionCall, execScopes: AztecAddress[]) => {
332
- await this.executeUtilityCall(call, execScopes, jobId);
460
+ await this.executeUtilityCall(call, { scopes: execScopes, jobId });
333
461
  };
334
462
 
335
- const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
336
463
  await this.stateMachine.contractSyncService.ensureContractSynced(
337
464
  targetContractAddress,
338
465
  functionSelector,
339
466
  utilityExecutor,
340
467
  blockHeader,
341
468
  jobId,
342
- effectiveScopes,
469
+ scopes,
343
470
  );
344
471
 
345
472
  const blockNumber = await this.getNextBlockNumber();
346
473
 
347
- const callContext = new CallContext(from, targetContractAddress, functionSelector, isStaticCall);
348
-
349
- const gasLimits = new Gas(DEFAULT_DA_GAS_LIMIT, DEFAULT_L2_GAS_LIMIT);
350
- const teardownGasLimits = new Gas(DEFAULT_TEARDOWN_DA_GAS_LIMIT, DEFAULT_TEARDOWN_L2_GAS_LIMIT);
351
- const gasSettings = new GasSettings(gasLimits, teardownGasLimits, GasFees.empty(), GasFees.empty());
474
+ const msgSender = from ?? AztecAddress.NULL_MSG_SENDER;
475
+ const callContext = new CallContext(msgSender, targetContractAddress, functionSelector, isStaticCall);
352
476
 
353
477
  const txContext = new TxContext(this.chainId, this.version, gasSettings);
354
478
 
@@ -363,9 +487,11 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
363
487
 
364
488
  const simulator = new WASMSimulator();
365
489
 
490
+ const transientArrayService = new TransientArrayService();
366
491
  const privateExecutionOracle = new PrivateExecutionOracle({
367
492
  argsHash,
368
493
  txContext,
494
+ txRequestSalt: Fr.ZERO,
369
495
  callContext,
370
496
  anchorBlockHeader: blockHeader,
371
497
  utilityExecutor,
@@ -374,26 +500,36 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
374
500
  executionCache: HashedValuesCache.create([new HashedValues(args, argsHash)]),
375
501
  noteCache,
376
502
  taggingIndexCache,
377
- contractStore: this.contractStore,
503
+ anchoredContractData,
378
504
  noteStore: this.noteStore,
379
505
  keyStore: this.keyStore,
380
506
  addressStore: this.addressStore,
381
507
  aztecNode: this.stateMachine.node,
382
508
  senderTaggingStore: this.senderTaggingStore,
383
509
  recipientTaggingStore: this.recipientTaggingStore,
384
- senderAddressBookStore: this.senderAddressBookStore,
385
- capsuleService: new CapsuleService(this.capsuleStore, effectiveScopes),
510
+ taggingSecretSourcesStore: this.taggingSecretSourcesStore,
511
+ capsuleService: new CapsuleService(this.capsuleStore, scopes),
512
+ factService: new FactService(this.factStore, scopes),
386
513
  privateEventStore: this.privateEventStore,
387
514
  contractSyncService: this.stateMachine.contractSyncService,
388
515
  jobId,
389
516
  totalPublicCalldataCount: 0,
390
517
  sideEffectCounter: minRevertibleSideEffectCounter,
391
- scopes: effectiveScopes,
518
+ scopes,
392
519
  // In TXE, the typical transaction entrypoint is skipped, so we need to simulate the actions that such a
393
520
  // contract would perform, including setting senderForTags.
394
521
  senderForTags: from,
395
522
  simulator,
396
- messageContextService: this.stateMachine.messageContextService,
523
+ txResolver: this.stateMachine.txResolver,
524
+ l2TipsStore: this.stateMachine.l2TipsProvider,
525
+ hooks: composeHooks({
526
+ authorizeUtilityCall: this.buildAuthorizeUtilityCallHook(
527
+ isStaticCall ? 'private view' : 'private',
528
+ authorizedUtilityCallTargets,
529
+ ),
530
+ resolveTaggingSecretStrategy: makeResolveTaggingSecretStrategyHook(this.taggingSecretStrategies),
531
+ }),
532
+ transientArrayService,
397
533
  });
398
534
 
399
535
  // 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.
@@ -421,7 +557,6 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
421
557
  }),
422
558
  );
423
559
 
424
- noteCache.finish();
425
560
  const nonceGenerator = noteCache.getNonceGenerator();
426
561
  result = new PrivateExecutionResult(executionResult, nonceGenerator, publicFunctionsCalldata);
427
562
  } catch (err) {
@@ -433,7 +568,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
433
568
  // We pass the non-zero minRevertibleSideEffectCounter to make sure the side effects are split correctly.
434
569
  const { publicInputs } = await generateSimulatedProvingResult(
435
570
  result,
436
- (addr, sel) => this.contractStore.getDebugFunctionName(addr, sel),
571
+ (addr, sel) => anchoredContractData.getDebugFunctionName(addr, sel),
437
572
  this.stateMachine.node,
438
573
  minRevertibleSideEffectCounter,
439
574
  );
@@ -445,7 +580,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
445
580
  globals.version = this.version;
446
581
  globals.gasFees = GasFees.empty();
447
582
 
448
- const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
583
+ await using forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
449
584
 
450
585
  const bindings = this.logger.getBindings();
451
586
  const contractsDB = new PublicContractsDB(
@@ -460,11 +595,20 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
460
595
  collectStatistics: false,
461
596
  collectCallMetadata: true,
462
597
  });
598
+ // The AVM simulator reads this fork's contracts DB, scoped by fork id, for each simulation.
599
+ const forkId = forkedWorldTrees.getRevision().forkId;
463
600
  const processor = new PublicProcessor(
464
601
  globals,
465
602
  guardedMerkleTrees,
466
603
  contractsDB,
467
- new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config, bindings),
604
+ new PublicTxSimulator(
605
+ this.stateMachine.synchronizer.avmSimulator,
606
+ globals,
607
+ contractsDB,
608
+ forkId,
609
+ config,
610
+ bindings,
611
+ ),
468
612
  new TestDateProvider(),
469
613
  undefined,
470
614
  createLogger('simulator:public-processor', bindings),
@@ -492,7 +636,13 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
492
636
  } else if (!processedTx.revertCode.isOK()) {
493
637
  if (processedTx.revertReason) {
494
638
  try {
495
- await enrichPublicSimulationError(processedTx.revertReason, this.contractStore, this.logger);
639
+ await enrichPublicSimulationError(
640
+ processedTx.revertReason,
641
+ this.contractStore,
642
+ this.stateMachine.contractClassService,
643
+ await this.stateMachine.anchorBlockStore.getBlockHeader(),
644
+ this.logger,
645
+ );
496
646
  // eslint-disable-next-line no-empty
497
647
  } catch {}
498
648
  throw new Error(`Contract execution has reverted: ${processedTx.revertReason.getMessage()}`);
@@ -501,11 +651,15 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
501
651
  }
502
652
  }
503
653
 
654
+ // Walk the nested private-call tree and collect every offchain effect the transaction emitted.
655
+ // PXE stores these on each `PrivateCallExecutionResult` and they never reach TXE via the
656
+ // `aztec_utl_emitOffchainEffect` foreign-call path (that path only fires at the top-level), so
657
+ // we pull them out here and the RPC wrapper will hand them to `TXESession` for buffering.
658
+ const offchainEffects = collectNested([executionResult], r => r.offchainEffects.map(e => e.data));
659
+
504
660
  if (isStaticCall) {
505
661
  await checkpoint!.revert();
506
-
507
- await forkedWorldTrees.close();
508
- return executionResult.returnValues ?? [];
662
+ return { returnValues: executionResult.returnValues ?? [], offchainEffects };
509
663
  }
510
664
 
511
665
  const txEffect = TxEffect.empty();
@@ -525,33 +679,31 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
525
679
 
526
680
  await this.stateMachine.handleL2Block(l2Block);
527
681
 
528
- await forkedWorldTrees.close();
529
-
530
- return executionResult.returnValues ?? [];
682
+ return { returnValues: executionResult.returnValues ?? [], offchainEffects };
531
683
  }
532
684
 
533
685
  async publicCallNewFlow(
534
- from: AztecAddress,
686
+ from: AztecAddress | undefined,
535
687
  targetContractAddress: AztecAddress,
536
688
  calldata: Fr[],
537
689
  isStaticCall: boolean,
690
+ gasSettings: GasSettings,
538
691
  ) {
692
+ const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
693
+ const anchoredContractData = new AnchoredContractData(
694
+ this.contractStore,
695
+ this.stateMachine.contractClassService,
696
+ anchorBlockHeader,
697
+ );
698
+
539
699
  this.logger.verbose(
540
- `Executing public function ${await this.contractStore.getDebugFunctionName(targetContractAddress, FunctionSelector.fromField(calldata[0]))}@${targetContractAddress} isStaticCall=${isStaticCall}`,
700
+ `Executing public function ${await anchoredContractData.getDebugFunctionName(targetContractAddress, FunctionSelector.fromField(calldata[0]))}@${targetContractAddress} isStaticCall=${isStaticCall}`,
541
701
  );
542
702
 
543
703
  const blockNumber = await this.getNextBlockNumber();
544
704
 
545
- const gasLimits = new Gas(DEFAULT_DA_GAS_LIMIT, DEFAULT_L2_GAS_LIMIT);
546
-
547
- const teardownGasLimits = new Gas(DEFAULT_TEARDOWN_DA_GAS_LIMIT, DEFAULT_TEARDOWN_L2_GAS_LIMIT);
548
-
549
- const gasSettings = new GasSettings(gasLimits, teardownGasLimits, GasFees.empty(), GasFees.empty());
550
-
551
705
  const txContext = new TxContext(this.chainId, this.version, gasSettings);
552
706
 
553
- const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
554
-
555
707
  const calldataHash = await computeCalldataHash(calldata);
556
708
  const calldataHashedValues = new HashedValues(calldata, calldataHash);
557
709
 
@@ -562,7 +714,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
562
714
  globals.version = this.version;
563
715
  globals.gasFees = GasFees.empty();
564
716
 
565
- const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
717
+ await using forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
566
718
 
567
719
  const bindings2 = this.logger.getBindings();
568
720
  const contractsDB = new PublicContractsDB(
@@ -577,7 +729,16 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
577
729
  collectStatistics: false,
578
730
  collectCallMetadata: true,
579
731
  });
580
- const simulator = new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config, bindings2);
732
+ // The AVM simulator reads this fork's contracts DB, scoped by fork id, for each simulation.
733
+ const forkId2 = forkedWorldTrees.getRevision().forkId;
734
+ const simulator = new PublicTxSimulator(
735
+ this.stateMachine.synchronizer.avmSimulator,
736
+ globals,
737
+ contractsDB,
738
+ forkId2,
739
+ config,
740
+ bindings2,
741
+ );
581
742
  const processor = new PublicProcessor(
582
743
  globals,
583
744
  guardedMerkleTrees,
@@ -599,7 +760,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
599
760
  // may require producing reverts.
600
761
  const revertibleAccumulatedData = PrivateToPublicAccumulatedData.empty();
601
762
  revertibleAccumulatedData.publicCallRequests[0] = new PublicCallRequest(
602
- from,
763
+ from ?? AztecAddress.NULL_MSG_SENDER,
603
764
  targetContractAddress,
604
765
  isStaticCall,
605
766
  calldataHash,
@@ -644,7 +805,13 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
644
805
  } else if (!processedTx.revertCode.isOK()) {
645
806
  if (processedTx.revertReason) {
646
807
  try {
647
- await enrichPublicSimulationError(processedTx.revertReason, this.contractStore, this.logger);
808
+ await enrichPublicSimulationError(
809
+ processedTx.revertReason,
810
+ this.contractStore,
811
+ this.stateMachine.contractClassService,
812
+ anchorBlockHeader,
813
+ this.logger,
814
+ );
648
815
  // eslint-disable-next-line no-empty
649
816
  } catch {}
650
817
  throw new Error(`Contract execution has reverted: ${processedTx.revertReason.getMessage()}`);
@@ -657,9 +824,6 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
657
824
 
658
825
  if (isStaticCall) {
659
826
  await checkpoint!.revert();
660
-
661
- await forkedWorldTrees.close();
662
-
663
827
  return returnValues ?? [];
664
828
  }
665
829
 
@@ -680,29 +844,35 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
680
844
 
681
845
  await this.stateMachine.handleL2Block(l2Block);
682
846
 
683
- await forkedWorldTrees.close();
684
-
685
847
  return returnValues ?? [];
686
848
  }
687
849
 
688
850
  async executeUtilityFunction(
851
+ from: AztecAddress | undefined,
689
852
  targetContractAddress: AztecAddress,
690
853
  functionSelector: FunctionSelector,
691
854
  args: Fr[],
692
855
  jobId: string,
856
+ authorizedUtilityCallTargets: AztecAddress[],
693
857
  ) {
694
- const artifact = await this.contractStore.getFunctionArtifact(targetContractAddress, functionSelector);
858
+ const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
859
+ const anchoredContractData = new AnchoredContractData(
860
+ this.contractStore,
861
+ this.stateMachine.contractClassService,
862
+ blockHeader,
863
+ );
864
+
865
+ const artifact = await anchoredContractData.getFunctionArtifact(targetContractAddress, functionSelector);
695
866
  if (!artifact) {
696
867
  throw new Error(`Cannot call ${functionSelector} as there is no artifact found at ${targetContractAddress}.`);
697
868
  }
698
869
 
699
870
  // Sync notes before executing utility function to discover notes from previous transactions
700
- const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
701
871
  await this.stateMachine.contractSyncService.ensureContractSynced(
702
872
  targetContractAddress,
703
873
  functionSelector,
704
874
  async (call, execScopes) => {
705
- await this.executeUtilityCall(call, execScopes, jobId);
875
+ await this.executeUtilityCall(call, { scopes: execScopes, jobId });
706
876
  },
707
877
  blockHeader,
708
878
  jobId,
@@ -720,11 +890,34 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
720
890
  returnTypes: [],
721
891
  });
722
892
 
723
- return this.executeUtilityCall(call, await this.keyStore.getAccounts(), jobId);
893
+ return this.executeUtilityCall(call, {
894
+ from,
895
+ scopes: await this.keyStore.getAccounts(),
896
+ jobId,
897
+ authorizedUtilityCallTargets,
898
+ });
724
899
  }
725
900
 
726
- private async executeUtilityCall(call: FunctionCall, scopes: AztecAddress[], jobId: string): Promise<Fr[]> {
727
- const entryPointArtifact = await this.contractStore.getFunctionArtifactWithDebugMetadata(call.to, call.selector);
901
+ private async executeUtilityCall(
902
+ call: FunctionCall,
903
+ {
904
+ from = AztecAddress.NULL_MSG_SENDER,
905
+ scopes,
906
+ jobId,
907
+ authorizedUtilityCallTargets = [],
908
+ }: { from?: AztecAddress; scopes: AztecAddress[]; jobId: string; authorizedUtilityCallTargets?: AztecAddress[] },
909
+ ): Promise<Fr[]> {
910
+ const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
911
+ const anchoredContractData = new AnchoredContractData(
912
+ this.contractStore,
913
+ this.stateMachine.contractClassService,
914
+ anchorBlockHeader,
915
+ );
916
+
917
+ const entryPointArtifact = await anchoredContractData.getFunctionArtifactWithDebugMetadata(call.to, call.selector);
918
+ if (!entryPointArtifact) {
919
+ throw new Error(`Cannot run function ${call.selector} on ${call.to}: the contract is not registered.`);
920
+ }
728
921
  if (entryPointArtifact.functionType !== FunctionType.UTILITY) {
729
922
  throw new Error(`Cannot run ${entryPointArtifact.functionType} function as utility`);
730
923
  }
@@ -735,28 +928,45 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
735
928
  });
736
929
 
737
930
  try {
738
- const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
931
+ const simulator = new WASMSimulator();
932
+ const utilityExecutor = async (syncCall: FunctionCall, execScopes: AztecAddress[]) => {
933
+ await this.executeUtilityCall(syncCall, { scopes: execScopes, jobId });
934
+ };
739
935
  const oracle = new UtilityExecutionOracle({
740
- contractAddress: call.to,
936
+ callContext: CallContext.from({
937
+ msgSender: from,
938
+ contractAddress: call.to,
939
+ functionSelector: call.selector,
940
+ isStaticCall: true,
941
+ }),
741
942
  authWitnesses: [],
742
943
  capsules: [],
743
944
  anchorBlockHeader,
744
- contractStore: this.contractStore,
945
+ anchoredContractData,
745
946
  noteStore: this.noteStore,
746
947
  keyStore: this.keyStore,
747
948
  addressStore: this.addressStore,
748
949
  aztecNode: this.stateMachine.node,
749
950
  recipientTaggingStore: this.recipientTaggingStore,
750
- senderAddressBookStore: this.senderAddressBookStore,
951
+ taggingSecretSourcesStore: this.taggingSecretSourcesStore,
751
952
  capsuleService: new CapsuleService(this.capsuleStore, scopes),
953
+ factService: new FactService(this.factStore, scopes),
752
954
  privateEventStore: this.privateEventStore,
753
- messageContextService: this.stateMachine.messageContextService,
754
- contractSyncService: this.contractSyncService,
955
+ txResolver: this.stateMachine.txResolver,
956
+ contractSyncService: this.stateMachine.contractSyncService,
957
+ l2TipsStore: this.stateMachine.l2TipsProvider,
755
958
  jobId,
756
959
  scopes,
960
+ simulator,
961
+ hooks: composeHooks({
962
+ authorizeUtilityCall: this.buildAuthorizeUtilityCallHook('utility', authorizedUtilityCallTargets),
963
+ }),
964
+ utilityExecutor,
965
+ // Execution-tree root (top-level utility run or contract sync): own store; nested frames inherit it.
966
+ transientArrayService: new TransientArrayService(),
757
967
  });
758
- const acirExecutionResult = await new WASMSimulator()
759
- .executeUserCircuit(toACVMWitness(0, call.args), entryPointArtifact, new Oracle(oracle).toACIRCallback())
968
+ const acirExecutionResult = await simulator
969
+ .executeUserCircuit(toACVMWitness(0, call.args), entryPointArtifact, buildACIRCallback(oracle))
760
970
  .catch((err: Error) => {
761
971
  err.message = resolveAssertionMessageFromError(err, entryPointArtifact);
762
972
  throw new ExecutionError(
@@ -777,13 +987,47 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
777
987
  }
778
988
  }
779
989
 
780
- close(): [bigint, Map<string, AuthWitness>] {
990
+ close(): {
991
+ nextBlockTimestamp: bigint;
992
+ authwits: Map<string, AuthWitness>;
993
+ taggingSecretStrategies: TXETaggingSecretStrategies;
994
+ authorizeAllUtilityCallTargets: boolean;
995
+ } {
781
996
  this.logger.debug('Exiting Top Level Context');
782
- return [this.nextBlockTimestamp, this.authwits];
997
+ return {
998
+ nextBlockTimestamp: this.nextBlockTimestamp,
999
+ authwits: this.authwits,
1000
+ taggingSecretStrategies: this.taggingSecretStrategies,
1001
+ authorizeAllUtilityCallTargets: this.authorizeAllUtilityCallTargets,
1002
+ };
783
1003
  }
784
1004
 
785
1005
  private async getLastBlockNumber(): Promise<BlockNumber> {
786
- const header = await this.stateMachine.node.getBlockHeader('latest');
787
- return header ? header.globalVariables.blockNumber : BlockNumber.ZERO;
1006
+ const block = await this.stateMachine.node.getBlock('latest');
1007
+ return block ? block.header.globalVariables.blockNumber : BlockNumber.ZERO;
1008
+ }
1009
+
1010
+ private buildAuthorizeUtilityCallHook(
1011
+ callerContext: 'private' | 'private view' | 'utility',
1012
+ authorizedTargets: AztecAddress[],
1013
+ ): ExecutionHooks['authorizeUtilityCall'] | undefined {
1014
+ if (this.authorizeAllUtilityCallTargets) {
1015
+ return authorizeAllUtilityCallsHook;
1016
+ }
1017
+ if (authorizedTargets.length === 0) {
1018
+ return undefined;
1019
+ }
1020
+ return req =>
1021
+ Promise.resolve({
1022
+ authorized: req.callerContext === callerContext && authorizedTargets.some(t => t.equals(req.target)),
1023
+ });
788
1024
  }
789
1025
  }
1026
+
1027
+ /**
1028
+ * An `authorizeUtilityCall` hook that authorizes every cross-contract utility call.
1029
+ *
1030
+ * Backs the `aztec_txe_setAuthorizeAllUtilityCallTargets` oracle.
1031
+ */
1032
+ export const authorizeAllUtilityCallsHook: NonNullable<ExecutionHooks['authorizeUtilityCall']> = () =>
1033
+ Promise.resolve({ authorized: true });