@aztec/txe 0.0.1-commit.d3ec352c → 0.0.1-commit.d58ff9d0

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 (175) 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 +7 -0
  32. package/dest/constants.d.ts.map +1 -0
  33. package/dest/constants.js +10 -0
  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 +75 -158
  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 +71 -30
  45. package/dest/oracle/interfaces.d.ts.map +1 -1
  46. package/dest/oracle/tagging_secret_strategy.d.ts +12 -0
  47. package/dest/oracle/tagging_secret_strategy.d.ts.map +1 -0
  48. package/dest/oracle/tagging_secret_strategy.js +12 -0
  49. package/dest/oracle/test-resolver/default_fixtures.d.ts +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 +40 -16
  59. package/dest/oracle/txe_oracle_public_context.d.ts.map +1 -1
  60. package/dest/oracle/txe_oracle_public_context.js +69 -23
  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 +79 -30
  65. package/dest/oracle/txe_oracle_top_level_context.d.ts.map +1 -1
  66. package/dest/oracle/txe_oracle_top_level_context.js +653 -285
  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 -216
  77. package/dest/rpc_translator.d.ts.map +1 -1
  78. package/dest/rpc_translator.js +901 -560
  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 +23 -58
  82. package/dest/state_machine/archiver.d.ts.map +1 -1
  83. package/dest/state_machine/archiver.js +76 -112
  84. package/dest/state_machine/dummy_p2p_client.d.ts +31 -17
  85. package/dest/state_machine/dummy_p2p_client.d.ts.map +1 -1
  86. package/dest/state_machine/dummy_p2p_client.js +63 -25
  87. package/dest/state_machine/global_variable_builder.d.ts +10 -5
  88. package/dest/state_machine/global_variable_builder.d.ts.map +1 -1
  89. package/dest/state_machine/global_variable_builder.js +20 -5
  90. package/dest/state_machine/index.d.ts +14 -8
  91. package/dest/state_machine/index.d.ts.map +1 -1
  92. package/dest/state_machine/index.js +84 -27
  93. package/dest/state_machine/mock_epoch_cache.d.ts +24 -8
  94. package/dest/state_machine/mock_epoch_cache.d.ts.map +1 -1
  95. package/dest/state_machine/mock_epoch_cache.js +43 -9
  96. package/dest/state_machine/synchronizer.d.ts +14 -6
  97. package/dest/state_machine/synchronizer.d.ts.map +1 -1
  98. package/dest/state_machine/synchronizer.js +23 -10
  99. package/dest/txe_session.d.ts +102 -20
  100. package/dest/txe_session.d.ts.map +1 -1
  101. package/dest/txe_session.js +442 -75
  102. package/dest/utils/block_creation.d.ts +20 -6
  103. package/dest/utils/block_creation.d.ts.map +1 -1
  104. package/dest/utils/block_creation.js +40 -6
  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 +8 -3
  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 +2 -3
  111. package/dest/utils/tx_effect_creation.d.ts.map +1 -1
  112. package/dest/utils/tx_effect_creation.js +3 -7
  113. package/dest/utils/txe_account_store.d.ts +10 -0
  114. package/dest/utils/txe_account_store.d.ts.map +1 -0
  115. package/dest/{util/txe_account_data_provider.js → utils/txe_account_store.js} +1 -1
  116. package/dest/utils/txe_artifact_resolver.d.ts +37 -0
  117. package/dest/utils/txe_artifact_resolver.d.ts.map +1 -0
  118. package/dest/utils/txe_artifact_resolver.js +161 -0
  119. package/dest/utils/txe_public_contract_data_source.d.ts +20 -0
  120. package/dest/utils/txe_public_contract_data_source.d.ts.map +1 -0
  121. package/dest/utils/txe_public_contract_data_source.js +51 -0
  122. package/dest/worker.bundle.js +3 -0
  123. package/dest/worker.bundle.js.map +7 -0
  124. package/dest/worker.d.ts +2 -0
  125. package/dest/worker.d.ts.map +1 -0
  126. package/dest/worker.js +92 -0
  127. package/package.json +39 -22
  128. package/src/bin/check_txe_oracle_version.ts +67 -0
  129. package/src/bin/index.ts +11 -2
  130. package/src/bin/oracle_test_server.ts +51 -0
  131. package/src/constants.ts +13 -0
  132. package/src/dispatcher_pool.ts +317 -0
  133. package/src/index.ts +113 -201
  134. package/src/msgpackr_fr_extension.ts +23 -0
  135. package/src/oracle/interfaces.ts +77 -35
  136. package/src/oracle/tagging_secret_strategy.ts +25 -0
  137. package/src/oracle/test-resolver/default_fixtures.ts +271 -0
  138. package/src/oracle/test-resolver/index.ts +44 -0
  139. package/src/oracle/test-resolver/resolver.ts +245 -0
  140. package/src/oracle/txe_oracle_public_context.ts +82 -27
  141. package/src/oracle/txe_oracle_registry.ts +556 -0
  142. package/src/oracle/txe_oracle_top_level_context.ts +555 -189
  143. package/src/oracle/txe_oracle_version.ts +17 -0
  144. package/src/oracle/txe_private_execution_oracle.ts +30 -0
  145. package/src/rpc_server.ts +87 -0
  146. package/src/rpc_translator.ts +1115 -923
  147. package/src/state_machine/archiver.ts +81 -132
  148. package/src/state_machine/dummy_p2p_client.ts +96 -38
  149. package/src/state_machine/global_variable_builder.ts +28 -10
  150. package/src/state_machine/index.ts +118 -44
  151. package/src/state_machine/mock_epoch_cache.ts +53 -14
  152. package/src/state_machine/synchronizer.ts +32 -12
  153. package/src/txe_session.ts +727 -123
  154. package/src/utils/block_creation.ts +50 -16
  155. package/src/{util → utils}/encoding.ts +9 -3
  156. package/src/utils/tx_effect_creation.ts +3 -13
  157. package/src/{util/txe_account_data_provider.ts → utils/txe_account_store.ts} +1 -1
  158. package/src/utils/txe_artifact_resolver.ts +217 -0
  159. package/src/utils/txe_public_contract_data_source.ts +60 -0
  160. package/src/worker.ts +98 -0
  161. package/dest/util/encoding.d.ts +0 -121
  162. package/dest/util/encoding.d.ts.map +0 -1
  163. package/dest/util/expected_failure_error.d.ts.map +0 -1
  164. package/dest/util/txe_account_data_provider.d.ts +0 -10
  165. package/dest/util/txe_account_data_provider.d.ts.map +0 -1
  166. package/dest/util/txe_contract_data_provider.d.ts +0 -12
  167. package/dest/util/txe_contract_data_provider.d.ts.map +0 -1
  168. package/dest/util/txe_contract_data_provider.js +0 -22
  169. package/dest/util/txe_public_contract_data_source.d.ts +0 -21
  170. package/dest/util/txe_public_contract_data_source.d.ts.map +0 -1
  171. package/dest/util/txe_public_contract_data_source.js +0 -67
  172. package/src/util/txe_contract_data_provider.ts +0 -36
  173. package/src/util/txe_public_contract_data_source.ts +0 -86
  174. /package/dest/{util → utils}/expected_failure_error.js +0 -0
  175. /package/src/{util → utils}/expected_failure_error.ts +0 -0
@@ -1,31 +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
- import { Schnorr } from '@aztec/foundation/crypto';
11
- import { Fr } from '@aztec/foundation/fields';
7
+ import { Schnorr } from '@aztec/foundation/crypto/schnorr';
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
- AddressDataProvider,
17
- ORACLE_VERSION,
18
- PXEOracleInterface,
14
+ AddressStore,
15
+ AnchoredContractData,
16
+ CapsuleService,
17
+ CapsuleStore,
18
+ type ContractStore,
19
+ type ExecutionHooks,
20
+ FactService,
21
+ FactStore,
22
+ NoteStore,
23
+ ORACLE_VERSION_MAJOR,
24
+ PrivateEventStore,
25
+ RecipientTaggingStore,
26
+ SenderTaggingStore,
27
+ TaggingSecretSourcesStore,
28
+ type TaggingSecretStrategy,
29
+ composeHooks,
19
30
  enrichPublicSimulationError,
20
31
  } from '@aztec/pxe/server';
21
32
  import {
33
+ CONTRACT_INSTANCE,
22
34
  ExecutionNoteCache,
23
35
  ExecutionTaggingIndexCache,
24
36
  HashedValuesCache,
25
37
  type IMiscOracle,
26
- Oracle,
38
+ type Option,
27
39
  PrivateExecutionOracle,
40
+ TransientArrayService,
28
41
  UtilityExecutionOracle,
42
+ buildACIRCallback,
29
43
  executePrivateFunction,
30
44
  generateSimulatedProvingResult,
31
45
  } from '@aztec/pxe/simulator';
@@ -39,16 +53,15 @@ import {
39
53
  witnessMapToFields,
40
54
  } from '@aztec/simulator/client';
41
55
  import {
42
- CppPublicTxSimulator,
43
56
  GuardedMerkleTreeOperations,
44
57
  PublicContractsDB,
45
58
  PublicProcessor,
59
+ PublicTxSimulator,
46
60
  } from '@aztec/simulator/server';
47
- import { type ContractArtifact, FunctionSelector, FunctionType } from '@aztec/stdlib/abi';
61
+ import { type ContractArtifact, EventSelector, FunctionCall, FunctionSelector, FunctionType } from '@aztec/stdlib/abi';
48
62
  import { AuthWitness } from '@aztec/stdlib/auth-witness';
49
63
  import { PublicSimulatorConfig } from '@aztec/stdlib/avm';
50
64
  import { AztecAddress } from '@aztec/stdlib/aztec-address';
51
- import { Body, L2Block } from '@aztec/stdlib/block';
52
65
  import { type ContractInstanceWithAddress, computePartialAddress } from '@aztec/stdlib/contract';
53
66
  import { Gas, GasFees, GasSettings } from '@aztec/stdlib/gas';
54
67
  import { computeCalldataHash, computeProtocolNullifier, siloNullifier } from '@aztec/stdlib/hash';
@@ -58,8 +71,12 @@ import {
58
71
  PrivateToPublicAccumulatedData,
59
72
  PublicCallRequest,
60
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';
61
78
  import { ChonkProof } from '@aztec/stdlib/proofs';
62
- import { makeAppendOnlyTreeSnapshot, makeGlobalVariables } from '@aztec/stdlib/testing';
79
+ import { makeGlobalVariables } from '@aztec/stdlib/testing';
63
80
  import { MerkleTreeId } from '@aztec/stdlib/trees';
64
81
  import {
65
82
  CallContext,
@@ -74,18 +91,16 @@ import {
74
91
  collectNested,
75
92
  } from '@aztec/stdlib/tx';
76
93
  import type { UInt64 } from '@aztec/stdlib/types';
77
- import { ForkCheckpoint } from '@aztec/world-state';
94
+ import { ForkCheckpoint } from '@aztec/world-state/native';
78
95
 
96
+ import { DEFAULT_ADDRESS, MAX_PRIVATE_EVENTS_PER_TXE_QUERY, MAX_PRIVATE_EVENT_LEN } from '../constants.js';
79
97
  import type { TXEStateMachine } from '../state_machine/index.js';
80
- import type { TXEAccountDataProvider } from '../util/txe_account_data_provider.js';
81
- import type { TXEContractDataProvider } from '../util/txe_contract_data_provider.js';
82
- import { TXEPublicContractDataSource } from '../util/txe_public_contract_data_source.js';
83
- import {
84
- getSingleTxBlockRequestHash,
85
- insertTxEffectIntoWorldTrees,
86
- makeTXEBlockHeader,
87
- } from '../utils/block_creation.js';
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';
88
102
  import type { ITxeExecutionOracle } from './interfaces.js';
103
+ import { type TXETaggingSecretStrategies, makeResolveTaggingSecretStrategyHook } from './tagging_secret_strategy.js';
89
104
 
90
105
  export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracle {
91
106
  isMisc = true as const;
@@ -95,58 +110,87 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
95
110
 
96
111
  constructor(
97
112
  private stateMachine: TXEStateMachine,
98
- private contractDataProvider: TXEContractDataProvider,
113
+ private contractStore: ContractStore,
114
+ private noteStore: NoteStore,
99
115
  private keyStore: KeyStore,
100
- private addressDataProvider: AddressDataProvider,
101
- private accountDataProvider: TXEAccountDataProvider,
102
- private pxeOracleInterface: PXEOracleInterface,
116
+ private addressStore: AddressStore,
117
+ private accountStore: TXEAccountStore,
118
+ private senderTaggingStore: SenderTaggingStore,
119
+ private recipientTaggingStore: RecipientTaggingStore,
120
+ private taggingSecretSourcesStore: TaggingSecretSourcesStore,
121
+ private capsuleStore: CapsuleStore,
122
+ private factStore: FactStore,
123
+ private privateEventStore: PrivateEventStore,
103
124
  private nextBlockTimestamp: bigint,
104
125
  private version: Fr,
105
126
  private chainId: Fr,
106
127
  private authwits: Map<string, AuthWitness>,
128
+ private taggingSecretStrategies: TXETaggingSecretStrategies,
129
+ private authorizeAllUtilityCallTargets: boolean,
130
+ private readonly artifactResolver: TXEArtifactResolver,
131
+ private readonly rootPath: string,
132
+ private readonly packageName: string,
107
133
  ) {
108
134
  this.logger = createLogger('txe:top_level_context');
109
135
  this.logger.debug('Entering Top Level Context');
110
136
  }
111
137
 
112
- utilityAssertCompatibleOracleVersion(version: number): void {
113
- 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) {
142
+ const hint =
143
+ major > ORACLE_VERSION_MAJOR
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.'
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.';
114
146
  throw new Error(
115
- `Incompatible oracle version. TXE is using version '${ORACLE_VERSION}', but got a request for '${version}'.`,
147
+ `Incompatible aztec cli version: ${hint} See https://docs.aztec.network/errors/8 (expected oracle major version ${ORACLE_VERSION_MAJOR}, got ${major})`,
116
148
  );
117
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;
118
156
  }
119
157
 
120
158
  // This is typically only invoked in private contexts, but it is convenient to also have it in top-level for testing
121
159
  // setup.
122
- utilityGetRandomField(): Fr {
160
+ getRandomField(): Fr {
123
161
  return Fr.random();
124
162
  }
125
163
 
126
164
  // We instruct users to debug contracts via this oracle, so it makes sense that they'd expect it to also work in tests
127
- utilityDebugLog(level: number, message: string, fields: Fr[]): void {
165
+ log(level: number, message: string, _fieldsSize: number, fields: Fr[]): Promise<void> {
128
166
  if (!LogLevels[level]) {
129
- throw new Error(`Invalid debug log level: ${level}`);
167
+ throw new Error(`Invalid log level: ${level}`);
130
168
  }
131
169
  const levelName = LogLevels[level];
132
170
 
133
171
  this.logger[levelName](`${applyStringFormatting(message, fields)}`, { module: `${this.logger.module}:debug_log` });
172
+ return Promise.resolve();
134
173
  }
135
174
 
136
- async txeGetNextBlockNumber(): Promise<BlockNumber> {
175
+ getDefaultAddress(): AztecAddress {
176
+ return DEFAULT_ADDRESS;
177
+ }
178
+
179
+ async getNextBlockNumber(): Promise<BlockNumber> {
137
180
  return BlockNumber((await this.getLastBlockNumber()) + 1);
138
181
  }
139
182
 
140
- txeGetNextBlockTimestamp(): Promise<bigint> {
183
+ getNextBlockTimestamp(): Promise<bigint> {
141
184
  return Promise.resolve(this.nextBlockTimestamp);
142
185
  }
143
186
 
144
- async txeGetLastBlockTimestamp() {
145
- return (await this.stateMachine.node.getBlockHeader('latest'))!.globalVariables.timestamp;
187
+ async getLastBlockTimestamp() {
188
+ return (await this.stateMachine.node.getBlockData('latest'))!.header.globalVariables.timestamp;
146
189
  }
147
190
 
148
- async txeGetLastTxEffects() {
149
- const block = await this.stateMachine.archiver.getBlock('latest');
191
+ async getLastTxEffects(): Promise<{ txHash: TxHash; noteHashes: Fr[]; nullifiers: Fr[]; privateLogs: PrivateLog[] }> {
192
+ const latestBlockNumber = await this.stateMachine.archiver.getBlockNumber();
193
+ const block = await this.stateMachine.archiver.getBlock({ number: latestBlockNumber });
150
194
 
151
195
  if (block!.body.txEffects.length != 1) {
152
196
  // Note that calls like env.mine() will result in blocks with no transactions, hitting this
@@ -155,10 +199,59 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
155
199
 
156
200
  const txEffects = block!.body.txEffects[0];
157
201
 
158
- 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
+ };
159
213
  }
160
214
 
161
- async txeAdvanceBlocksBy(blocks: number) {
215
+ async syncContractNonOracleMethod(contractAddress: AztecAddress, scope: AztecAddress, jobId: string) {
216
+ if (contractAddress.equals(DEFAULT_ADDRESS)) {
217
+ this.logger.debug(`Skipping sync in getPrivateEvents because the events correspond to the default address.`);
218
+ return;
219
+ }
220
+
221
+ const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
222
+ await this.stateMachine.contractSyncService.ensureContractSynced(
223
+ contractAddress,
224
+ null,
225
+ async (call, execScopes) => {
226
+ await this.executeUtilityCall(call, { scopes: execScopes, jobId });
227
+ },
228
+ blockHeader,
229
+ jobId,
230
+ [scope],
231
+ );
232
+ }
233
+
234
+ async getPrivateEvents(selector: EventSelector, contractAddress: AztecAddress, scope: AztecAddress) {
235
+ const events = (
236
+ await this.privateEventStore.getPrivateEvents(selector, {
237
+ contractAddress,
238
+ scopes: [scope],
239
+ fromBlock: 0,
240
+ toBlock: (await this.getLastBlockNumber()) + 1,
241
+ })
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;
252
+ }
253
+
254
+ async advanceBlocksBy(blocks: number) {
162
255
  this.logger.debug(`time traveling ${blocks} blocks`);
163
256
 
164
257
  for (let i = 0; i < blocks; i++) {
@@ -166,112 +259,193 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
166
259
  }
167
260
  }
168
261
 
169
- txeAdvanceTimestampBy(duration: UInt64) {
262
+ advanceTimestampBy(duration: UInt64) {
170
263
  this.logger.debug(`time traveling ${duration} seconds`);
171
264
  this.nextBlockTimestamp += duration;
172
265
  }
173
266
 
174
- async txeDeploy(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
+
175
290
  // Emit deployment nullifier
176
291
  await this.mineBlock({
177
- nullifiers: [
178
- await siloNullifier(
179
- AztecAddress.fromNumber(CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS),
180
- instance.address.toField(),
181
- ),
182
- ],
292
+ nullifiers: [await this.deploymentNullifier(instance.address)],
183
293
  });
184
294
 
185
295
  if (!secret.equals(Fr.ZERO)) {
186
- await this.txeAddAccount(artifact, instance, secret);
296
+ await this.registerContractAndAddAccount(artifact, instance, secret);
187
297
  } else {
188
- await this.contractDataProvider.addContractInstance(instance);
189
- await this.contractDataProvider.addContractArtifact(instance.currentContractClassId, artifact);
298
+ await this.contractStore.addContractInstance(instance);
299
+ await this.contractStore.addContractArtifact(artifact);
190
300
  this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
191
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);
192
318
  }
193
319
 
194
- async txeAddAccount(artifact: ContractArtifact, instance: ContractInstanceWithAddress, secret: Fr) {
320
+ private async registerContractAndAddAccount(
321
+ artifact: ContractArtifact,
322
+ instance: ContractInstanceWithAddress,
323
+ secret: Fr,
324
+ ) {
195
325
  const partialAddress = await computePartialAddress(instance);
196
326
 
197
327
  this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
198
- await this.contractDataProvider.addContractInstance(instance);
199
- await this.contractDataProvider.addContractArtifact(instance.currentContractClassId, artifact);
328
+ await this.contractStore.addContractInstance(instance);
329
+ await this.contractStore.addContractArtifact(artifact);
200
330
 
201
- const completeAddress = await this.keyStore.addAccount(secret, partialAddress);
202
- await this.accountDataProvider.setAccount(completeAddress.address, completeAddress);
203
- await this.addressDataProvider.addCompleteAddress(completeAddress);
331
+ const completeAddress = await this.keyStore.addAccount(await deriveKeys(secret), partialAddress);
332
+ await this.accountStore.setAccount(completeAddress.address, completeAddress);
333
+ await this.addressStore.addCompleteAddress(completeAddress);
204
334
  this.logger.debug(`Created account ${completeAddress.address}`);
205
335
 
206
336
  return completeAddress;
207
337
  }
208
338
 
209
- async txeCreateAccount(secret: Fr) {
210
- // This is a footgun !
211
- const completeAddress = await this.keyStore.addAccount(secret, secret);
212
- await this.accountDataProvider.setAccount(completeAddress.address, completeAddress);
213
- await this.addressDataProvider.addCompleteAddress(completeAddress);
339
+ async createAccount(secret: Fr, partialAddress: Fr) {
340
+ const completeAddress = await this.keyStore.addAccount(await deriveKeys(secret), partialAddress);
341
+ await this.accountStore.setAccount(completeAddress.address, completeAddress);
342
+ await this.addressStore.addCompleteAddress(completeAddress);
214
343
  this.logger.debug(`Created account ${completeAddress.address}`);
215
344
 
216
345
  return completeAddress;
217
346
  }
218
347
 
219
- async txeAddAuthWitness(address: AztecAddress, messageHash: Fr) {
220
- const account = await this.accountDataProvider.getAccount(address);
221
- const privateKey = await this.keyStore.getMasterSecretKey(account.publicKeys.masterIncomingViewingPublicKey);
348
+ async addAuthWitness(address: AztecAddress, messageHash: Fr) {
349
+ const account = await this.accountStore.getAccount(address);
350
+ const ivpkMHash = await hashPublicKey(account.publicKeys.ivpkM);
351
+ const privateKey = await this.keyStore.getMasterSecretKey(ivpkMHash);
222
352
 
223
353
  const schnorr = new Schnorr();
224
- const signature = await schnorr.constructSignature(messageHash.toBuffer(), privateKey);
354
+ const signature = await schnorr.constructSignature(messageHash, privateKey);
225
355
 
226
- const authWitness = new AuthWitness(messageHash, [...signature.toBuffer()]);
356
+ const authWitness = new AuthWitness(messageHash, signature.toLimbFields());
227
357
 
228
358
  this.authwits.set(authWitness.requestHash.toString(), authWitness);
229
359
  }
230
360
 
231
- async mineBlock(options: { nullifiers?: Fr[] } = {}) {
232
- const blockNumber = await this.txeGetNextBlockNumber();
361
+ setTaggingSecretStrategies(
362
+ unconstrainedStrategy: Option<TaggingSecretStrategy>,
363
+ constrainedStrategy: Option<TaggingSecretStrategy>,
364
+ ): void {
365
+ const apply = (mode: AppTaggingSecretKind, strategy: Option<TaggingSecretStrategy>) => {
366
+ if (strategy.isSome()) {
367
+ this.taggingSecretStrategies.set(mode, strategy.value);
368
+ } else {
369
+ this.taggingSecretStrategies.delete(mode);
370
+ }
371
+ };
372
+ apply(AppTaggingSecretKind.UNCONSTRAINED, unconstrainedStrategy);
373
+ apply(AppTaggingSecretKind.CONSTRAINED, constrainedStrategy);
374
+ }
375
+
376
+ 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[] } = {}) {
401
+ const blockNumber = await this.getNextBlockNumber();
233
402
 
234
403
  const txEffect = TxEffect.empty();
235
404
  txEffect.nullifiers = [getSingleTxBlockRequestHash(blockNumber), ...(options.nullifiers ?? [])];
236
405
  txEffect.txHash = new TxHash(new Fr(blockNumber));
237
406
 
238
407
  const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
239
- await insertTxEffectIntoWorldTrees(txEffect, forkedWorldTrees);
240
-
241
- const block = new L2Block(
242
- makeAppendOnlyTreeSnapshot(),
243
- await makeTXEBlockHeader(
244
- forkedWorldTrees,
245
- makeGlobalVariables(undefined, {
246
- blockNumber,
247
- timestamp: this.nextBlockTimestamp,
248
- version: this.version,
249
- chainId: this.chainId,
250
- }),
251
- ),
252
- new Body([txEffect]),
253
- );
408
+ await insertTxEffectIntoWorldTrees(txEffect, forkedWorldTrees, options.l1ToL2Messages ?? []);
409
+
410
+ const globals = makeGlobalVariables(undefined, {
411
+ blockNumber,
412
+ timestamp: this.nextBlockTimestamp,
413
+ version: this.version,
414
+ chainId: this.chainId,
415
+ });
416
+ const block = await makeTXEBlock(forkedWorldTrees, globals, [txEffect]);
254
417
 
255
418
  await forkedWorldTrees.close();
256
419
 
257
420
  this.logger.info(`Created block ${blockNumber} with timestamp ${block.header.globalVariables.timestamp}`);
258
421
 
259
- await this.stateMachine.handleL2Block(block);
422
+ await this.stateMachine.handleL2Block(block, options.l1ToL2Messages ?? []);
260
423
  }
261
424
 
262
- async txePrivateCallNewFlow(
263
- from: AztecAddress,
425
+ async privateCallNewFlow(
426
+ from: AztecAddress | undefined,
264
427
  targetContractAddress: AztecAddress = AztecAddress.zero(),
265
428
  functionSelector: FunctionSelector = FunctionSelector.empty(),
266
429
  args: Fr[],
267
430
  argsHash: Fr = Fr.zero(),
268
431
  isStaticCall: boolean = false,
432
+ additionalScopes: AztecAddress[] = [],
433
+ jobId: string,
434
+ authorizedUtilityCallTargets: AztecAddress[],
435
+ gasSettings: GasSettings,
269
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
+
270
444
  this.logger.verbose(
271
- `Executing external function ${await this.contractDataProvider.getDebugFunctionName(targetContractAddress, functionSelector)}@${targetContractAddress} isStaticCall=${isStaticCall}`,
445
+ `Executing external function ${await anchoredContractData.getDebugFunctionName(targetContractAddress, functionSelector)}@${targetContractAddress} isStaticCall=${isStaticCall}`,
272
446
  );
273
447
 
274
- const artifact = await this.contractDataProvider.getFunctionArtifact(targetContractAddress, functionSelector);
448
+ const artifact = await anchoredContractData.getFunctionArtifact(targetContractAddress, functionSelector);
275
449
  if (!artifact) {
276
450
  const message = functionSelector.equals(await FunctionSelector.fromSignature('verify_private_authwit(Field)'))
277
451
  ? 'Found no account contract artifact for a private authwit check - use `create_contract_account` instead of `create_light_account` for authwit support.'
@@ -279,51 +453,84 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
279
453
  throw new Error(message);
280
454
  }
281
455
 
282
- const blockNumber = await this.txeGetNextBlockNumber();
456
+ const scopes = from === undefined ? additionalScopes : [from, ...additionalScopes];
283
457
 
284
- const callContext = new CallContext(from, targetContractAddress, functionSelector, isStaticCall);
458
+ // Sync notes before executing private function to discover notes from previous transactions
459
+ const utilityExecutor = async (call: FunctionCall, execScopes: AztecAddress[]) => {
460
+ await this.executeUtilityCall(call, { scopes: execScopes, jobId });
461
+ };
285
462
 
286
- const gasLimits = new Gas(DEFAULT_DA_GAS_LIMIT, DEFAULT_L2_GAS_LIMIT);
463
+ await this.stateMachine.contractSyncService.ensureContractSynced(
464
+ targetContractAddress,
465
+ functionSelector,
466
+ utilityExecutor,
467
+ blockHeader,
468
+ jobId,
469
+ scopes,
470
+ );
287
471
 
288
- const teardownGasLimits = new Gas(DEFAULT_TEARDOWN_DA_GAS_LIMIT, DEFAULT_TEARDOWN_L2_GAS_LIMIT);
472
+ const blockNumber = await this.getNextBlockNumber();
289
473
 
290
- 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);
291
476
 
292
477
  const txContext = new TxContext(this.chainId, this.version, gasSettings);
293
478
 
294
- const blockHeader = await this.pxeOracleInterface.getAnchorBlockHeader();
295
-
296
479
  const protocolNullifier = await computeProtocolNullifier(getSingleTxBlockRequestHash(blockNumber));
297
480
  const noteCache = new ExecutionNoteCache(protocolNullifier);
481
+ // In production, the account contract sets the min revertible counter before calling the app function.
482
+ // Since TXE bypasses the account contract, we simulate this by setting minRevertibleSideEffectCounter to 1,
483
+ // marking all side effects as revertible.
484
+ const minRevertibleSideEffectCounter = 1;
485
+ await noteCache.setMinRevertibleSideEffectCounter(minRevertibleSideEffectCounter);
298
486
  const taggingIndexCache = new ExecutionTaggingIndexCache();
299
487
 
300
488
  const simulator = new WASMSimulator();
301
489
 
302
- const privateExecutionOracle = new PrivateExecutionOracle(
490
+ const transientArrayService = new TransientArrayService();
491
+ const privateExecutionOracle = new PrivateExecutionOracle({
303
492
  argsHash,
304
493
  txContext,
494
+ txRequestSalt: Fr.ZERO,
305
495
  callContext,
306
- /** Header of a block whose state is used during private execution (not the block the transaction is included in). */
307
- blockHeader,
308
- /** List of transient auth witnesses to be used during this simulation */
309
- Array.from(this.authwits.values()),
310
- /** List of transient auth witnesses to be used during this simulation */
311
- [],
312
- HashedValuesCache.create([new HashedValues(args, argsHash)]),
496
+ anchorBlockHeader: blockHeader,
497
+ utilityExecutor,
498
+ authWitnesses: Array.from(this.authwits.values()),
499
+ capsules: [],
500
+ executionCache: HashedValuesCache.create([new HashedValues(args, argsHash)]),
313
501
  noteCache,
314
502
  taggingIndexCache,
315
- this.pxeOracleInterface,
316
- 0,
317
- 1,
318
- undefined, // log
319
- undefined, // scopes
320
- /**
321
- * In TXE, the typical transaction entrypoint is skipped, so we need to simulate the actions that such a
322
- * contract would perform, including setting senderForTags.
323
- */
324
- from,
503
+ anchoredContractData,
504
+ noteStore: this.noteStore,
505
+ keyStore: this.keyStore,
506
+ addressStore: this.addressStore,
507
+ aztecNode: this.stateMachine.node,
508
+ senderTaggingStore: this.senderTaggingStore,
509
+ recipientTaggingStore: this.recipientTaggingStore,
510
+ taggingSecretSourcesStore: this.taggingSecretSourcesStore,
511
+ capsuleService: new CapsuleService(this.capsuleStore, scopes),
512
+ factService: new FactService(this.factStore, scopes),
513
+ privateEventStore: this.privateEventStore,
514
+ contractSyncService: this.stateMachine.contractSyncService,
515
+ jobId,
516
+ totalPublicCalldataCount: 0,
517
+ sideEffectCounter: minRevertibleSideEffectCounter,
518
+ scopes,
519
+ // In TXE, the typical transaction entrypoint is skipped, so we need to simulate the actions that such a
520
+ // contract would perform, including setting senderForTags.
521
+ senderForTags: from,
325
522
  simulator,
326
- );
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,
533
+ });
327
534
 
328
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.
329
536
  let result: PrivateExecutionResult;
@@ -345,24 +552,26 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
345
552
  );
346
553
  const publicFunctionsCalldata = await Promise.all(
347
554
  publicCallRequests.map(async r => {
348
- const calldata = await privateExecutionOracle.privateLoadFromExecutionCache(r.calldataHash);
555
+ const calldata = await privateExecutionOracle.getHashPreimage(r.calldataHash);
349
556
  return new HashedValues(calldata, r.calldataHash);
350
557
  }),
351
558
  );
352
559
 
353
- // TXE's top level context does not track side effect counters, and as such, minRevertibleSideEffectCounter is always 0.
354
- // This has the unfortunate consequence of always producing revertible nullifiers, which means we
355
- // must set the firstNullifierHint to Fr.ZERO so the txRequestHash is always used as nonce generator
356
- result = new PrivateExecutionResult(executionResult, Fr.ZERO, publicFunctionsCalldata);
560
+ const nonceGenerator = noteCache.getNonceGenerator();
561
+ result = new PrivateExecutionResult(executionResult, nonceGenerator, publicFunctionsCalldata);
357
562
  } catch (err) {
358
563
  throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during private execution'));
359
564
  }
360
565
 
361
- // According to the protocol rules, the nonce generator for the note hashes
362
- // can either be the first nullifier in the tx or the hash of the initial tx request
363
- // if there are none.
364
- const nonceGenerator = result.firstNullifier.equals(Fr.ZERO) ? protocolNullifier : result.firstNullifier;
365
- const { publicInputs } = await generateSimulatedProvingResult(result, nonceGenerator, this.contractDataProvider);
566
+ // According to the protocol rules, there must be at least one nullifier in the tx. The first nullifier is used as
567
+ // the nonce generator for the note hashes.
568
+ // We pass the non-zero minRevertibleSideEffectCounter to make sure the side effects are split correctly.
569
+ const { publicInputs } = await generateSimulatedProvingResult(
570
+ result,
571
+ (addr, sel) => anchoredContractData.getDebugFunctionName(addr, sel),
572
+ this.stateMachine.node,
573
+ minRevertibleSideEffectCounter,
574
+ );
366
575
 
367
576
  const globals = makeGlobalVariables();
368
577
  globals.blockNumber = blockNumber;
@@ -371,9 +580,13 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
371
580
  globals.version = this.version;
372
581
  globals.gasFees = GasFees.empty();
373
582
 
374
- const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
583
+ await using forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
375
584
 
376
- const contractsDB = new PublicContractsDB(new TXEPublicContractDataSource(blockNumber, this.contractDataProvider));
585
+ const bindings = this.logger.getBindings();
586
+ const contractsDB = new PublicContractsDB(
587
+ new TXEPublicContractDataSource(blockNumber, this.contractStore),
588
+ bindings,
589
+ );
377
590
  const guardedMerkleTrees = new GuardedMerkleTreeOperations(forkedWorldTrees);
378
591
  const config = PublicSimulatorConfig.from({
379
592
  skipFeeEnforcement: true,
@@ -382,12 +595,23 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
382
595
  collectStatistics: false,
383
596
  collectCallMetadata: true,
384
597
  });
598
+ // The AVM simulator reads this fork's contracts DB, scoped by fork id, for each simulation.
599
+ const forkId = forkedWorldTrees.getRevision().forkId;
385
600
  const processor = new PublicProcessor(
386
601
  globals,
387
602
  guardedMerkleTrees,
388
603
  contractsDB,
389
- new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config),
604
+ new PublicTxSimulator(
605
+ this.stateMachine.synchronizer.avmSimulator,
606
+ globals,
607
+ contractsDB,
608
+ forkId,
609
+ config,
610
+ bindings,
611
+ ),
390
612
  new TestDateProvider(),
613
+ undefined,
614
+ createLogger('simulator:public-processor', bindings),
391
615
  );
392
616
 
393
617
  const tx = await Tx.create({
@@ -412,7 +636,13 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
412
636
  } else if (!processedTx.revertCode.isOK()) {
413
637
  if (processedTx.revertReason) {
414
638
  try {
415
- await enrichPublicSimulationError(processedTx.revertReason, this.contractDataProvider, 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
+ );
416
646
  // eslint-disable-next-line no-empty
417
647
  } catch {}
418
648
  throw new Error(`Contract execution has reverted: ${processedTx.revertReason.getMessage()}`);
@@ -421,11 +651,15 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
421
651
  }
422
652
  }
423
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
+
424
660
  if (isStaticCall) {
425
661
  await checkpoint!.revert();
426
-
427
- await forkedWorldTrees.close();
428
- return executionResult.returnValues ?? [];
662
+ return { returnValues: executionResult.returnValues ?? [], offchainEffects };
429
663
  }
430
664
 
431
665
  const txEffect = TxEffect.empty();
@@ -441,43 +675,35 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
441
675
  const l1ToL2Messages = Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(0).map(Fr.zero);
442
676
  await forkedWorldTrees.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, l1ToL2Messages);
443
677
 
444
- const body = new Body([txEffect]);
445
-
446
- const l2Block = new L2Block(
447
- makeAppendOnlyTreeSnapshot(),
448
- await makeTXEBlockHeader(forkedWorldTrees, globals),
449
- body,
450
- );
678
+ const l2Block = await makeTXEBlock(forkedWorldTrees, globals, [txEffect]);
451
679
 
452
680
  await this.stateMachine.handleL2Block(l2Block);
453
681
 
454
- await forkedWorldTrees.close();
455
-
456
- return executionResult.returnValues ?? [];
682
+ return { returnValues: executionResult.returnValues ?? [], offchainEffects };
457
683
  }
458
684
 
459
- async txePublicCallNewFlow(
460
- from: AztecAddress,
685
+ async publicCallNewFlow(
686
+ from: AztecAddress | undefined,
461
687
  targetContractAddress: AztecAddress,
462
688
  calldata: Fr[],
463
689
  isStaticCall: boolean,
690
+ gasSettings: GasSettings,
464
691
  ) {
465
- this.logger.verbose(
466
- `Executing public function ${await this.contractDataProvider.getDebugFunctionName(targetContractAddress, FunctionSelector.fromField(calldata[0]))}@${targetContractAddress} isStaticCall=${isStaticCall}`,
692
+ const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
693
+ const anchoredContractData = new AnchoredContractData(
694
+ this.contractStore,
695
+ this.stateMachine.contractClassService,
696
+ anchorBlockHeader,
467
697
  );
468
698
 
469
- const blockNumber = await this.txeGetNextBlockNumber();
470
-
471
- const gasLimits = new Gas(DEFAULT_DA_GAS_LIMIT, DEFAULT_L2_GAS_LIMIT);
472
-
473
- const teardownGasLimits = new Gas(DEFAULT_TEARDOWN_DA_GAS_LIMIT, DEFAULT_TEARDOWN_L2_GAS_LIMIT);
699
+ this.logger.verbose(
700
+ `Executing public function ${await anchoredContractData.getDebugFunctionName(targetContractAddress, FunctionSelector.fromField(calldata[0]))}@${targetContractAddress} isStaticCall=${isStaticCall}`,
701
+ );
474
702
 
475
- const gasSettings = new GasSettings(gasLimits, teardownGasLimits, GasFees.empty(), GasFees.empty());
703
+ const blockNumber = await this.getNextBlockNumber();
476
704
 
477
705
  const txContext = new TxContext(this.chainId, this.version, gasSettings);
478
706
 
479
- const anchorBlockHeader = await this.pxeOracleInterface.getAnchorBlockHeader();
480
-
481
707
  const calldataHash = await computeCalldataHash(calldata);
482
708
  const calldataHashedValues = new HashedValues(calldata, calldataHash);
483
709
 
@@ -488,9 +714,13 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
488
714
  globals.version = this.version;
489
715
  globals.gasFees = GasFees.empty();
490
716
 
491
- const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
717
+ await using forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
492
718
 
493
- const contractsDB = new PublicContractsDB(new TXEPublicContractDataSource(blockNumber, this.contractDataProvider));
719
+ const bindings2 = this.logger.getBindings();
720
+ const contractsDB = new PublicContractsDB(
721
+ new TXEPublicContractDataSource(blockNumber, this.contractStore),
722
+ bindings2,
723
+ );
494
724
  const guardedMerkleTrees = new GuardedMerkleTreeOperations(forkedWorldTrees);
495
725
  const config = PublicSimulatorConfig.from({
496
726
  skipFeeEnforcement: true,
@@ -499,8 +729,25 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
499
729
  collectStatistics: false,
500
730
  collectCallMetadata: true,
501
731
  });
502
- const simulator = new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config);
503
- const processor = new PublicProcessor(globals, guardedMerkleTrees, contractsDB, simulator, new TestDateProvider());
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
+ );
742
+ const processor = new PublicProcessor(
743
+ globals,
744
+ guardedMerkleTrees,
745
+ contractsDB,
746
+ simulator,
747
+ new TestDateProvider(),
748
+ undefined,
749
+ createLogger('simulator:public-processor', bindings2),
750
+ );
504
751
 
505
752
  // We're simulating a scenario in which private execution immediately enqueues a public call and halts. The private
506
753
  // kernel init would in this case inject a nullifier with the transaction request hash as a non-revertible
@@ -513,7 +760,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
513
760
  // may require producing reverts.
514
761
  const revertibleAccumulatedData = PrivateToPublicAccumulatedData.empty();
515
762
  revertibleAccumulatedData.publicCallRequests[0] = new PublicCallRequest(
516
- from,
763
+ from ?? AztecAddress.NULL_MSG_SENDER,
517
764
  targetContractAddress,
518
765
  isStaticCall,
519
766
  calldataHash,
@@ -531,7 +778,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
531
778
  constantData,
532
779
  /*gasUsed=*/ new Gas(0, 0),
533
780
  /*feePayer=*/ AztecAddress.zero(),
534
- /*includeByTimestamp=*/ 0n,
781
+ /*expirationTimestamp=*/ 0n,
535
782
  inputsForPublic,
536
783
  undefined,
537
784
  );
@@ -558,7 +805,13 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
558
805
  } else if (!processedTx.revertCode.isOK()) {
559
806
  if (processedTx.revertReason) {
560
807
  try {
561
- await enrichPublicSimulationError(processedTx.revertReason, this.contractDataProvider, this.logger);
808
+ await enrichPublicSimulationError(
809
+ processedTx.revertReason,
810
+ this.contractStore,
811
+ this.stateMachine.contractClassService,
812
+ anchorBlockHeader,
813
+ this.logger,
814
+ );
562
815
  // eslint-disable-next-line no-empty
563
816
  } catch {}
564
817
  throw new Error(`Contract execution has reverted: ${processedTx.revertReason.getMessage()}`);
@@ -571,9 +824,6 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
571
824
 
572
825
  if (isStaticCall) {
573
826
  await checkpoint!.revert();
574
-
575
- await forkedWorldTrees.close();
576
-
577
827
  return returnValues ?? [];
578
828
  }
579
829
 
@@ -590,38 +840,84 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
590
840
  const l1ToL2Messages = Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(0).map(Fr.zero);
591
841
  await forkedWorldTrees.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, l1ToL2Messages);
592
842
 
593
- const body = new Body([txEffect]);
594
-
595
- const l2Block = new L2Block(
596
- makeAppendOnlyTreeSnapshot(),
597
- await makeTXEBlockHeader(forkedWorldTrees, globals),
598
- body,
599
- );
843
+ const l2Block = await makeTXEBlock(forkedWorldTrees, globals, [txEffect]);
600
844
 
601
845
  await this.stateMachine.handleL2Block(l2Block);
602
846
 
603
- await forkedWorldTrees.close();
604
-
605
847
  return returnValues ?? [];
606
848
  }
607
849
 
608
- async txeSimulateUtilityFunction(
850
+ async executeUtilityFunction(
851
+ from: AztecAddress | undefined,
609
852
  targetContractAddress: AztecAddress,
610
853
  functionSelector: FunctionSelector,
611
854
  args: Fr[],
855
+ jobId: string,
856
+ authorizedUtilityCallTargets: AztecAddress[],
612
857
  ) {
613
- const artifact = await this.contractDataProvider.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);
614
866
  if (!artifact) {
615
867
  throw new Error(`Cannot call ${functionSelector} as there is no artifact found at ${targetContractAddress}.`);
616
868
  }
617
869
 
618
- const call = {
870
+ // Sync notes before executing utility function to discover notes from previous transactions
871
+ await this.stateMachine.contractSyncService.ensureContractSynced(
872
+ targetContractAddress,
873
+ functionSelector,
874
+ async (call, execScopes) => {
875
+ await this.executeUtilityCall(call, { scopes: execScopes, jobId });
876
+ },
877
+ blockHeader,
878
+ jobId,
879
+ await this.keyStore.getAccounts(),
880
+ );
881
+
882
+ const call = FunctionCall.from({
619
883
  name: artifact.name,
620
- selector: functionSelector,
621
884
  to: targetContractAddress,
622
- };
885
+ selector: functionSelector,
886
+ type: FunctionType.UTILITY,
887
+ hideMsgSender: false,
888
+ isStatic: false,
889
+ args,
890
+ returnTypes: [],
891
+ });
623
892
 
624
- const entryPointArtifact = await this.pxeOracleInterface.getFunctionArtifact(call.to, call.selector);
893
+ return this.executeUtilityCall(call, {
894
+ from,
895
+ scopes: await this.keyStore.getAccounts(),
896
+ jobId,
897
+ authorizedUtilityCallTargets,
898
+ });
899
+ }
900
+
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
+ }
625
921
  if (entryPointArtifact.functionType !== FunctionType.UTILITY) {
626
922
  throw new Error(`Cannot run ${entryPointArtifact.functionType} function as utility`);
627
923
  }
@@ -632,9 +928,45 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
632
928
  });
633
929
 
634
930
  try {
635
- const oracle = new UtilityExecutionOracle(call.to, [], [], this.pxeOracleInterface);
636
- const acirExecutionResult = await new WASMSimulator()
637
- .executeUserCircuit(toACVMWitness(0, args), entryPointArtifact, new Oracle(oracle).toACIRCallback())
931
+ const simulator = new WASMSimulator();
932
+ const utilityExecutor = async (syncCall: FunctionCall, execScopes: AztecAddress[]) => {
933
+ await this.executeUtilityCall(syncCall, { scopes: execScopes, jobId });
934
+ };
935
+ const oracle = new UtilityExecutionOracle({
936
+ callContext: CallContext.from({
937
+ msgSender: from,
938
+ contractAddress: call.to,
939
+ functionSelector: call.selector,
940
+ isStaticCall: true,
941
+ }),
942
+ authWitnesses: [],
943
+ capsules: [],
944
+ anchorBlockHeader,
945
+ anchoredContractData,
946
+ noteStore: this.noteStore,
947
+ keyStore: this.keyStore,
948
+ addressStore: this.addressStore,
949
+ aztecNode: this.stateMachine.node,
950
+ recipientTaggingStore: this.recipientTaggingStore,
951
+ taggingSecretSourcesStore: this.taggingSecretSourcesStore,
952
+ capsuleService: new CapsuleService(this.capsuleStore, scopes),
953
+ factService: new FactService(this.factStore, scopes),
954
+ privateEventStore: this.privateEventStore,
955
+ txResolver: this.stateMachine.txResolver,
956
+ contractSyncService: this.stateMachine.contractSyncService,
957
+ l2TipsStore: this.stateMachine.l2TipsProvider,
958
+ jobId,
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(),
967
+ });
968
+ const acirExecutionResult = await simulator
969
+ .executeUserCircuit(toACVMWitness(0, call.args), entryPointArtifact, buildACIRCallback(oracle))
638
970
  .catch((err: Error) => {
639
971
  err.message = resolveAssertionMessageFromError(err, entryPointArtifact);
640
972
  throw new ExecutionError(
@@ -648,20 +980,54 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
648
980
  );
649
981
  });
650
982
 
651
- this.logger.verbose(`Utility simulation for ${call.to}.${call.selector} completed`);
983
+ this.logger.verbose(`Utility execution for ${call.to}.${call.selector} completed`);
652
984
  return witnessMapToFields(acirExecutionResult.returnWitness);
653
985
  } catch (err) {
654
- throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during utility simulation'));
986
+ throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during utility execution'));
655
987
  }
656
988
  }
657
989
 
658
- close(): [bigint, Map<string, AuthWitness>] {
990
+ close(): {
991
+ nextBlockTimestamp: bigint;
992
+ authwits: Map<string, AuthWitness>;
993
+ taggingSecretStrategies: TXETaggingSecretStrategies;
994
+ authorizeAllUtilityCallTargets: boolean;
995
+ } {
659
996
  this.logger.debug('Exiting Top Level Context');
660
- return [this.nextBlockTimestamp, this.authwits];
997
+ return {
998
+ nextBlockTimestamp: this.nextBlockTimestamp,
999
+ authwits: this.authwits,
1000
+ taggingSecretStrategies: this.taggingSecretStrategies,
1001
+ authorizeAllUtilityCallTargets: this.authorizeAllUtilityCallTargets,
1002
+ };
661
1003
  }
662
1004
 
663
1005
  private async getLastBlockNumber(): Promise<BlockNumber> {
664
- const header = await this.stateMachine.node.getBlockHeader('latest');
665
- 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
+ });
666
1024
  }
667
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 });