@aztec/txe 0.0.1-commit.b655e406 → 0.0.1-commit.b8a057fa

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