@aztec/txe 5.0.0-private.20260318 → 5.0.0-rc.1

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 (154) hide show
  1. package/dest/AuthRegistry-CPGFQR26.js +3 -0
  2. package/dest/AuthRegistry-CPGFQR26.js.map +7 -0
  3. package/dest/ContractClassRegistry-EHVIHGEK.js +3 -0
  4. package/dest/ContractClassRegistry-EHVIHGEK.js.map +7 -0
  5. package/dest/ContractInstanceRegistry-DWZDXHRG.js +3 -0
  6. package/dest/ContractInstanceRegistry-DWZDXHRG.js.map +7 -0
  7. package/dest/FeeJuice-MI32ZO7B.js +3 -0
  8. package/dest/FeeJuice-MI32ZO7B.js.map +7 -0
  9. package/dest/HandshakeRegistry-3KSP3ITH.js +3 -0
  10. package/dest/HandshakeRegistry-3KSP3ITH.js.map +7 -0
  11. package/dest/MultiCallEntrypoint-IU7HYFYE.js +3 -0
  12. package/dest/MultiCallEntrypoint-IU7HYFYE.js.map +7 -0
  13. package/dest/SchnorrAccount-6TUE7JX4.js +3 -0
  14. package/dest/SchnorrAccount-6TUE7JX4.js.map +7 -0
  15. package/dest/SchnorrInitializerlessAccount-S3DU2DJK.js +3 -0
  16. package/dest/SchnorrInitializerlessAccount-S3DU2DJK.js.map +7 -0
  17. package/dest/bin/check_txe_oracle_version.d.ts +2 -0
  18. package/dest/bin/check_txe_oracle_version.d.ts.map +1 -0
  19. package/dest/bin/check_txe_oracle_version.js +61 -0
  20. package/dest/bin/index.js +3 -30
  21. package/dest/bin/index.js.map +7 -0
  22. package/dest/bin/oracle_test_server.d.ts +3 -0
  23. package/dest/bin/oracle_test_server.d.ts.map +1 -0
  24. package/dest/bin/oracle_test_server.js +41 -0
  25. package/dest/chunk-5U25VAFR.js +265 -0
  26. package/dest/chunk-5U25VAFR.js.map +7 -0
  27. package/dest/chunk-BJVAAXNA.js +3 -0
  28. package/dest/chunk-BJVAAXNA.js.map +7 -0
  29. package/dest/chunk-UPW55EJX.js +304 -0
  30. package/dest/chunk-UPW55EJX.js.map +7 -0
  31. package/dest/constants.d.ts +5 -1
  32. package/dest/constants.d.ts.map +1 -1
  33. package/dest/constants.js +8 -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 +70 -190
  40. package/dest/metafile.json +38829 -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 +33 -8
  45. package/dest/oracle/interfaces.d.ts.map +1 -1
  46. package/dest/oracle/test-resolver/fixtures.d.ts +43 -0
  47. package/dest/oracle/test-resolver/fixtures.d.ts.map +1 -0
  48. package/dest/oracle/test-resolver/fixtures.js +39 -0
  49. package/dest/oracle/test-resolver/index.d.ts +9 -0
  50. package/dest/oracle/test-resolver/index.d.ts.map +1 -0
  51. package/dest/oracle/test-resolver/index.js +33 -0
  52. package/dest/oracle/test-resolver/resolver.d.ts +34 -0
  53. package/dest/oracle/test-resolver/resolver.d.ts.map +1 -0
  54. package/dest/oracle/test-resolver/resolver.js +114 -0
  55. package/dest/oracle/txe_oracle_public_context.d.ts +26 -2
  56. package/dest/oracle/txe_oracle_public_context.d.ts.map +1 -1
  57. package/dest/oracle/txe_oracle_public_context.js +43 -1
  58. package/dest/oracle/txe_oracle_registry.d.ts +14 -0
  59. package/dest/oracle/txe_oracle_registry.d.ts.map +1 -0
  60. package/dest/oracle/txe_oracle_registry.js +562 -0
  61. package/dest/oracle/txe_oracle_top_level_context.d.ts +32 -18
  62. package/dest/oracle/txe_oracle_top_level_context.d.ts.map +1 -1
  63. package/dest/oracle/txe_oracle_top_level_context.js +151 -55
  64. package/dest/oracle/txe_oracle_version.d.ts +17 -0
  65. package/dest/oracle/txe_oracle_version.d.ts.map +1 -0
  66. package/dest/oracle/txe_oracle_version.js +14 -0
  67. package/dest/oracle/txe_private_execution_oracle.d.ts +17 -0
  68. package/dest/oracle/txe_private_execution_oracle.d.ts.map +1 -0
  69. package/dest/oracle/txe_private_execution_oracle.js +15 -0
  70. package/dest/rpc_server.d.ts +14 -0
  71. package/dest/rpc_server.d.ts.map +1 -0
  72. package/dest/rpc_server.js +78 -0
  73. package/dest/rpc_translator.d.ts +103 -230
  74. package/dest/rpc_translator.d.ts.map +1 -1
  75. package/dest/rpc_translator.js +697 -616
  76. package/dest/server.bundle.js +3 -0
  77. package/dest/server.bundle.js.map +7 -0
  78. package/dest/state_machine/archiver.d.ts +4 -3
  79. package/dest/state_machine/archiver.d.ts.map +1 -1
  80. package/dest/state_machine/archiver.js +26 -15
  81. package/dest/state_machine/dummy_p2p_client.d.ts +14 -7
  82. package/dest/state_machine/dummy_p2p_client.d.ts.map +1 -1
  83. package/dest/state_machine/dummy_p2p_client.js +19 -4
  84. package/dest/state_machine/global_variable_builder.d.ts +9 -4
  85. package/dest/state_machine/global_variable_builder.d.ts.map +1 -1
  86. package/dest/state_machine/global_variable_builder.js +9 -3
  87. package/dest/state_machine/index.d.ts +4 -2
  88. package/dest/state_machine/index.d.ts.map +1 -1
  89. package/dest/state_machine/index.js +11 -3
  90. package/dest/state_machine/mock_epoch_cache.d.ts +16 -3
  91. package/dest/state_machine/mock_epoch_cache.d.ts.map +1 -1
  92. package/dest/state_machine/mock_epoch_cache.js +29 -2
  93. package/dest/state_machine/synchronizer.js +1 -1
  94. package/dest/txe_session.d.ts +85 -17
  95. package/dest/txe_session.d.ts.map +1 -1
  96. package/dest/txe_session.js +245 -40
  97. package/dest/utils/encoding.d.ts +191 -0
  98. package/dest/utils/encoding.d.ts.map +1 -0
  99. package/dest/{util → utils}/encoding.js +7 -2
  100. package/dest/{util → utils}/expected_failure_error.d.ts +1 -1
  101. package/dest/utils/expected_failure_error.d.ts.map +1 -0
  102. package/dest/{util → utils}/txe_account_store.d.ts +1 -1
  103. package/dest/utils/txe_account_store.d.ts.map +1 -0
  104. package/dest/utils/txe_artifact_resolver.d.ts +37 -0
  105. package/dest/utils/txe_artifact_resolver.d.ts.map +1 -0
  106. package/dest/utils/txe_artifact_resolver.js +161 -0
  107. package/dest/utils/txe_public_contract_data_source.d.ts +20 -0
  108. package/dest/utils/txe_public_contract_data_source.d.ts.map +1 -0
  109. package/dest/{util → utils}/txe_public_contract_data_source.js +1 -3
  110. package/dest/worker.bundle.js +3 -0
  111. package/dest/worker.bundle.js.map +7 -0
  112. package/dest/worker.d.ts +2 -0
  113. package/dest/worker.d.ts.map +1 -0
  114. package/dest/worker.js +92 -0
  115. package/package.json +38 -21
  116. package/src/bin/check_txe_oracle_version.ts +70 -0
  117. package/src/bin/index.ts +11 -2
  118. package/src/bin/oracle_test_server.ts +51 -0
  119. package/src/constants.ts +10 -0
  120. package/src/dispatcher_pool.ts +317 -0
  121. package/src/index.ts +97 -227
  122. package/src/msgpackr_fr_extension.ts +23 -0
  123. package/src/oracle/interfaces.ts +29 -7
  124. package/src/oracle/test-resolver/fixtures.ts +84 -0
  125. package/src/oracle/test-resolver/index.ts +45 -0
  126. package/src/oracle/test-resolver/resolver.ts +165 -0
  127. package/src/oracle/txe_oracle_public_context.ts +60 -0
  128. package/src/oracle/txe_oracle_registry.ts +401 -0
  129. package/src/oracle/txe_oracle_top_level_context.ts +185 -64
  130. package/src/oracle/txe_oracle_version.ts +17 -0
  131. package/src/oracle/txe_private_execution_oracle.ts +30 -0
  132. package/src/rpc_server.ts +87 -0
  133. package/src/rpc_translator.ts +767 -892
  134. package/src/state_machine/archiver.ts +38 -16
  135. package/src/state_machine/dummy_p2p_client.ts +35 -11
  136. package/src/state_machine/global_variable_builder.ts +18 -3
  137. package/src/state_machine/index.ts +17 -5
  138. package/src/state_machine/mock_epoch_cache.ts +38 -3
  139. package/src/state_machine/synchronizer.ts +1 -1
  140. package/src/txe_session.ts +437 -50
  141. package/src/{util → utils}/encoding.ts +8 -2
  142. package/src/utils/txe_artifact_resolver.ts +217 -0
  143. package/src/{util → utils}/txe_public_contract_data_source.ts +0 -2
  144. package/src/worker.ts +98 -0
  145. package/dest/util/encoding.d.ts +0 -720
  146. package/dest/util/encoding.d.ts.map +0 -1
  147. package/dest/util/expected_failure_error.d.ts.map +0 -1
  148. package/dest/util/txe_account_store.d.ts.map +0 -1
  149. package/dest/util/txe_public_contract_data_source.d.ts +0 -20
  150. package/dest/util/txe_public_contract_data_source.d.ts.map +0 -1
  151. /package/dest/{util → utils}/expected_failure_error.js +0 -0
  152. /package/dest/{util → utils}/txe_account_store.js +0 -0
  153. /package/src/{util → utils}/expected_failure_error.ts +0 -0
  154. /package/src/{util → utils}/txe_account_store.ts +0 -0
@@ -1,11 +1,11 @@
1
- import { CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS, DEFAULT_DA_GAS_LIMIT, DEFAULT_L2_GAS_LIMIT, DEFAULT_TEARDOWN_DA_GAS_LIMIT, DEFAULT_TEARDOWN_L2_GAS_LIMIT, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP } from '@aztec/constants';
1
+ import { CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS, MAX_PRIVATE_LOGS_PER_TX, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP } from '@aztec/constants';
2
2
  import { BlockNumber } from '@aztec/foundation/branded-types';
3
3
  import { Schnorr } from '@aztec/foundation/crypto/schnorr';
4
4
  import { Fr } from '@aztec/foundation/curves/bn254';
5
5
  import { LogLevels, applyStringFormatting, createLogger } from '@aztec/foundation/log';
6
6
  import { TestDateProvider } from '@aztec/foundation/timer';
7
- import { ORACLE_VERSION, enrichPublicSimulationError } from '@aztec/pxe/server';
8
- import { ExecutionNoteCache, ExecutionTaggingIndexCache, HashedValuesCache, Oracle, PrivateExecutionOracle, UtilityExecutionOracle, executePrivateFunction, generateSimulatedProvingResult } from '@aztec/pxe/simulator';
7
+ import { CapsuleService, ORACLE_VERSION_MAJOR, composeHooks, enrichPublicSimulationError } from '@aztec/pxe/server';
8
+ import { ExecutionNoteCache, ExecutionTaggingIndexCache, HashedValuesCache, PrivateExecutionOracle, TransientArrayService, UtilityExecutionOracle, buildACIRCallback, executePrivateFunction, generateSimulatedProvingResult } from '@aztec/pxe/simulator';
9
9
  import { ExecutionError, WASMSimulator, createSimulationError, extractCallStack, resolveAssertionMessageFromError, toACVMWitness, witnessMapToFields } from '@aztec/simulator/client';
10
10
  import { CppPublicTxSimulator, GuardedMerkleTreeOperations, PublicContractsDB, PublicProcessor } from '@aztec/simulator/server';
11
11
  import { FunctionCall, FunctionSelector, FunctionType } from '@aztec/stdlib/abi';
@@ -13,17 +13,18 @@ import { AuthWitness } from '@aztec/stdlib/auth-witness';
13
13
  import { PublicSimulatorConfig } from '@aztec/stdlib/avm';
14
14
  import { AztecAddress } from '@aztec/stdlib/aztec-address';
15
15
  import { computePartialAddress } from '@aztec/stdlib/contract';
16
- import { Gas, GasFees, GasSettings } from '@aztec/stdlib/gas';
16
+ import { Gas, GasFees } from '@aztec/stdlib/gas';
17
17
  import { computeCalldataHash, computeProtocolNullifier, siloNullifier } from '@aztec/stdlib/hash';
18
18
  import { PartialPrivateTailPublicInputsForPublic, PrivateKernelTailCircuitPublicInputs, PrivateToPublicAccumulatedData, PublicCallRequest } from '@aztec/stdlib/kernel';
19
+ import { hashPublicKey } from '@aztec/stdlib/keys';
19
20
  import { ChonkProof } from '@aztec/stdlib/proofs';
20
21
  import { makeGlobalVariables } from '@aztec/stdlib/testing';
21
22
  import { MerkleTreeId } from '@aztec/stdlib/trees';
22
23
  import { CallContext, HashedValues, PrivateExecutionResult, Tx, TxConstantData, TxContext, TxEffect, TxHash, collectNested } from '@aztec/stdlib/tx';
23
- import { ForkCheckpoint } from '@aztec/world-state';
24
- import { DEFAULT_ADDRESS } from '../constants.js';
25
- import { TXEPublicContractDataSource } from '../util/txe_public_contract_data_source.js';
24
+ import { ForkCheckpoint } from '@aztec/world-state/native';
25
+ import { DEFAULT_ADDRESS, MAX_PRIVATE_EVENTS_PER_TXE_QUERY, MAX_PRIVATE_EVENT_LEN } from '../constants.js';
26
26
  import { getSingleTxBlockRequestHash, insertTxEffectIntoWorldTrees, makeTXEBlock } from '../utils/block_creation.js';
27
+ import { TXEPublicContractDataSource } from '../utils/txe_public_contract_data_source.js';
27
28
  export class TXEOracleTopLevelContext {
28
29
  stateMachine;
29
30
  contractStore;
@@ -40,10 +41,13 @@ export class TXEOracleTopLevelContext {
40
41
  version;
41
42
  chainId;
42
43
  authwits;
44
+ artifactResolver;
45
+ rootPath;
46
+ packageName;
43
47
  isMisc;
44
48
  isTxe;
45
49
  logger;
46
- constructor(stateMachine, contractStore, noteStore, keyStore, addressStore, accountStore, senderTaggingStore, recipientTaggingStore, senderAddressBookStore, capsuleStore, privateEventStore, nextBlockTimestamp, version, chainId, authwits){
50
+ constructor(stateMachine, contractStore, noteStore, keyStore, addressStore, accountStore, senderTaggingStore, recipientTaggingStore, senderAddressBookStore, capsuleStore, privateEventStore, nextBlockTimestamp, version, chainId, authwits, artifactResolver, rootPath, packageName){
47
51
  this.stateMachine = stateMachine;
48
52
  this.contractStore = contractStore;
49
53
  this.noteStore = noteStore;
@@ -59,15 +63,28 @@ export class TXEOracleTopLevelContext {
59
63
  this.version = version;
60
64
  this.chainId = chainId;
61
65
  this.authwits = authwits;
66
+ this.artifactResolver = artifactResolver;
67
+ this.rootPath = rootPath;
68
+ this.packageName = packageName;
62
69
  this.isMisc = true;
63
70
  this.isTxe = true;
64
71
  this.logger = createLogger('txe:top_level_context');
65
72
  this.logger.debug('Entering Top Level Context');
66
73
  }
67
- assertCompatibleOracleVersion(version) {
68
- if (version !== ORACLE_VERSION) {
69
- throw new Error(`Incompatible oracle version. TXE is using version '${ORACLE_VERSION}', but got a request for '${version}'.`);
74
+ contractOracleVersion;
75
+ assertCompatibleOracleVersion(major, minor) {
76
+ if (major !== ORACLE_VERSION_MAJOR) {
77
+ const hint = major > ORACLE_VERSION_MAJOR ? '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.' : '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.';
78
+ throw new Error(`Incompatible aztec cli version: ${hint} See https://docs.aztec.network/errors/8 (expected oracle major version ${ORACLE_VERSION_MAJOR}, got ${major})`);
70
79
  }
80
+ this.contractOracleVersion = {
81
+ major,
82
+ minor
83
+ };
84
+ }
85
+ // Prefixed with "nonOracleFunction" as it is not used as an oracle handler.
86
+ nonOracleFunctionGetContractOracleVersion() {
87
+ return this.contractOracleVersion;
71
88
  }
72
89
  // This is typically only invoked in private contexts, but it is convenient to also have it in top-level for testing
73
90
  // setup.
@@ -75,7 +92,7 @@ export class TXEOracleTopLevelContext {
75
92
  return Fr.random();
76
93
  }
77
94
  // We instruct users to debug contracts via this oracle, so it makes sense that they'd expect it to also work in tests
78
- log(level, message, fields) {
95
+ log(level, message, _fieldsSize, fields) {
79
96
  if (!LogLevels[level]) {
80
97
  throw new Error(`Invalid log level: ${level}`);
81
98
  }
@@ -95,20 +112,27 @@ export class TXEOracleTopLevelContext {
95
112
  return Promise.resolve(this.nextBlockTimestamp);
96
113
  }
97
114
  async getLastBlockTimestamp() {
98
- return (await this.stateMachine.node.getBlockHeader('latest')).globalVariables.timestamp;
115
+ return (await this.stateMachine.node.getBlockData('latest')).header.globalVariables.timestamp;
99
116
  }
100
117
  async getLastTxEffects() {
101
118
  const latestBlockNumber = await this.stateMachine.archiver.getBlockNumber();
102
- const block = await this.stateMachine.archiver.getBlock(latestBlockNumber);
119
+ const block = await this.stateMachine.archiver.getBlock({
120
+ number: latestBlockNumber
121
+ });
103
122
  if (block.body.txEffects.length != 1) {
104
123
  // Note that calls like env.mine() will result in blocks with no transactions, hitting this
105
124
  throw new Error(`Expected a single transaction in the last block, found ${block.body.txEffects.length}`);
106
125
  }
107
126
  const txEffects = block.body.txEffects[0];
127
+ const privateLogs = txEffects.privateLogs;
128
+ if (privateLogs.length > MAX_PRIVATE_LOGS_PER_TX) {
129
+ throw new Error(`${privateLogs.length} private logs exceed max ${MAX_PRIVATE_LOGS_PER_TX}`);
130
+ }
108
131
  return {
109
132
  txHash: txEffects.txHash,
110
133
  noteHashes: txEffects.noteHashes,
111
- nullifiers: txEffects.nullifiers
134
+ nullifiers: txEffects.nullifiers,
135
+ privateLogs
112
136
  };
113
137
  }
114
138
  async syncContractNonOracleMethod(contractAddress, scope, jobId) {
@@ -124,7 +148,7 @@ export class TXEOracleTopLevelContext {
124
148
  ]);
125
149
  }
126
150
  async getPrivateEvents(selector, contractAddress, scope) {
127
- return (await this.privateEventStore.getPrivateEvents(selector, {
151
+ const events = (await this.privateEventStore.getPrivateEvents(selector, {
128
152
  contractAddress,
129
153
  scopes: [
130
154
  scope
@@ -132,6 +156,13 @@ export class TXEOracleTopLevelContext {
132
156
  fromBlock: 0,
133
157
  toBlock: await this.getLastBlockNumber() + 1
134
158
  })).map((e)=>e.packedEvent);
159
+ if (events.length > MAX_PRIVATE_EVENTS_PER_TXE_QUERY) {
160
+ throw new Error(`Array of length ${events.length} larger than maxLen ${MAX_PRIVATE_EVENTS_PER_TXE_QUERY}`);
161
+ }
162
+ if (events.some((e)=>e.length > MAX_PRIVATE_EVENT_LEN)) {
163
+ throw new Error(`Some private event has length larger than maxLen ${MAX_PRIVATE_EVENT_LEN}`);
164
+ }
165
+ return events;
135
166
  }
136
167
  async advanceBlocksBy(blocks) {
137
168
  this.logger.debug(`time traveling ${blocks} blocks`);
@@ -143,22 +174,54 @@ export class TXEOracleTopLevelContext {
143
174
  this.logger.debug(`time traveling ${duration} seconds`);
144
175
  this.nextBlockTimestamp += duration;
145
176
  }
146
- async deploy(artifact, instance, secret) {
177
+ deploymentNullifier(address) {
178
+ return siloNullifier(AztecAddress.fromNumber(CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS), address.toField());
179
+ }
180
+ async deploy(contractPath, initializer, args, secret, salt, deployer) {
181
+ const { artifact, instance } = await this.artifactResolver.resolveDeployArtifact({
182
+ rootPath: this.rootPath,
183
+ packageName: this.packageName,
184
+ contractPath,
185
+ initializer,
186
+ args,
187
+ secret,
188
+ salt,
189
+ deployer
190
+ });
147
191
  // Emit deployment nullifier
148
192
  await this.mineBlock({
149
193
  nullifiers: [
150
- await siloNullifier(AztecAddress.fromNumber(CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS), instance.address.toField())
194
+ await this.deploymentNullifier(instance.address)
151
195
  ]
152
196
  });
153
197
  if (!secret.equals(Fr.ZERO)) {
154
- await this.addAccount(artifact, instance, secret);
198
+ await this.registerContractAndAddAccount(artifact, instance, secret);
155
199
  } else {
156
200
  await this.contractStore.addContractInstance(instance);
157
201
  await this.contractStore.addContractArtifact(artifact);
158
202
  this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
159
203
  }
204
+ return [
205
+ instance.salt,
206
+ instance.deployer.toField(),
207
+ instance.currentContractClassId,
208
+ instance.initializationHash,
209
+ instance.immutablesHash,
210
+ ...instance.publicKeys.toFields()
211
+ ];
160
212
  }
161
- async addAccount(artifact, instance, secret) {
213
+ /**
214
+ * Mines a single block containing only the deployment nullifiers for the contracts at the given addresses.
215
+ */ async mineDeploymentNullifiers(addresses) {
216
+ await this.mineBlock({
217
+ nullifiers: await Promise.all(addresses.map((address)=>this.deploymentNullifier(address)))
218
+ });
219
+ }
220
+ async addAccount(secret) {
221
+ const { artifact, instance } = await this.artifactResolver.resolveAccountArtifact(secret);
222
+ return this.registerContractAndAddAccount(artifact, instance, secret);
223
+ }
224
+ async registerContractAndAddAccount(artifact, instance, secret) {
162
225
  const partialAddress = await computePartialAddress(instance);
163
226
  this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
164
227
  await this.contractStore.addContractInstance(instance);
@@ -179,12 +242,11 @@ export class TXEOracleTopLevelContext {
179
242
  }
180
243
  async addAuthWitness(address, messageHash) {
181
244
  const account = await this.accountStore.getAccount(address);
182
- const privateKey = await this.keyStore.getMasterSecretKey(account.publicKeys.masterIncomingViewingPublicKey);
245
+ const ivpkMHash = await hashPublicKey(account.publicKeys.ivpkM);
246
+ const privateKey = await this.keyStore.getMasterSecretKey(ivpkMHash);
183
247
  const schnorr = new Schnorr();
184
- const signature = await schnorr.constructSignature(messageHash.toBuffer(), privateKey);
185
- const authWitness = new AuthWitness(messageHash, [
186
- ...signature.toBuffer()
187
- ]);
248
+ const signature = await schnorr.constructSignature(messageHash, privateKey);
249
+ const authWitness = new AuthWitness(messageHash, signature.toLimbFields());
188
250
  this.authwits.set(authWitness.requestHash.toString(), authWitness);
189
251
  }
190
252
  async mineBlock(options = {}) {
@@ -210,29 +272,26 @@ export class TXEOracleTopLevelContext {
210
272
  this.logger.info(`Created block ${blockNumber} with timestamp ${block.header.globalVariables.timestamp}`);
211
273
  await this.stateMachine.handleL2Block(block);
212
274
  }
213
- async privateCallNewFlow(from, targetContractAddress = AztecAddress.zero(), functionSelector = FunctionSelector.empty(), args, argsHash = Fr.zero(), isStaticCall = false, jobId) {
275
+ async privateCallNewFlow(from, targetContractAddress = AztecAddress.zero(), functionSelector = FunctionSelector.empty(), args, argsHash = Fr.zero(), isStaticCall = false, additionalScopes = [], jobId, authorizedUtilityCallTargets, gasSettings) {
214
276
  this.logger.verbose(`Executing external function ${await this.contractStore.getDebugFunctionName(targetContractAddress, functionSelector)}@${targetContractAddress} isStaticCall=${isStaticCall}`);
215
277
  const artifact = await this.contractStore.getFunctionArtifact(targetContractAddress, functionSelector);
216
278
  if (!artifact) {
217
279
  const message = functionSelector.equals(await FunctionSelector.fromSignature('verify_private_authwit(Field)')) ? 'Found no account contract artifact for a private authwit check - use `create_contract_account` instead of `create_light_account` for authwit support.' : 'Function Artifact does not exist';
218
280
  throw new Error(message);
219
281
  }
220
- // When `from` is the zero address (e.g. when deploying a new account contract), we return an
221
- // empty scope list which acts as deny-all: no notes are visible and no keys are accessible.
222
- const effectiveScopes = from.isZero() ? [] : [
223
- from
282
+ const scopes = from === undefined ? additionalScopes : [
283
+ from,
284
+ ...additionalScopes
224
285
  ];
225
286
  // Sync notes before executing private function to discover notes from previous transactions
226
287
  const utilityExecutor = async (call, execScopes)=>{
227
288
  await this.executeUtilityCall(call, execScopes, jobId);
228
289
  };
229
290
  const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
230
- await this.stateMachine.contractSyncService.ensureContractSynced(targetContractAddress, functionSelector, utilityExecutor, blockHeader, jobId, effectiveScopes);
291
+ await this.stateMachine.contractSyncService.ensureContractSynced(targetContractAddress, functionSelector, utilityExecutor, blockHeader, jobId, scopes);
231
292
  const blockNumber = await this.getNextBlockNumber();
232
- const callContext = new CallContext(from, targetContractAddress, functionSelector, isStaticCall);
233
- const gasLimits = new Gas(DEFAULT_DA_GAS_LIMIT, DEFAULT_L2_GAS_LIMIT);
234
- const teardownGasLimits = new Gas(DEFAULT_TEARDOWN_DA_GAS_LIMIT, DEFAULT_TEARDOWN_L2_GAS_LIMIT);
235
- const gasSettings = new GasSettings(gasLimits, teardownGasLimits, GasFees.empty(), GasFees.empty());
293
+ const msgSender = from ?? AztecAddress.NULL_MSG_SENDER;
294
+ const callContext = new CallContext(msgSender, targetContractAddress, functionSelector, isStaticCall);
236
295
  const txContext = new TxContext(this.chainId, this.version, gasSettings);
237
296
  const protocolNullifier = await computeProtocolNullifier(getSingleTxBlockRequestHash(blockNumber));
238
297
  const noteCache = new ExecutionNoteCache(protocolNullifier);
@@ -243,6 +302,7 @@ export class TXEOracleTopLevelContext {
243
302
  await noteCache.setMinRevertibleSideEffectCounter(minRevertibleSideEffectCounter);
244
303
  const taggingIndexCache = new ExecutionTaggingIndexCache();
245
304
  const simulator = new WASMSimulator();
305
+ const transientArrayService = new TransientArrayService();
246
306
  const privateExecutionOracle = new PrivateExecutionOracle({
247
307
  argsHash,
248
308
  txContext,
@@ -264,18 +324,23 @@ export class TXEOracleTopLevelContext {
264
324
  senderTaggingStore: this.senderTaggingStore,
265
325
  recipientTaggingStore: this.recipientTaggingStore,
266
326
  senderAddressBookStore: this.senderAddressBookStore,
267
- capsuleStore: this.capsuleStore,
327
+ capsuleService: new CapsuleService(this.capsuleStore, scopes),
268
328
  privateEventStore: this.privateEventStore,
269
329
  contractSyncService: this.stateMachine.contractSyncService,
270
330
  jobId,
271
331
  totalPublicCalldataCount: 0,
272
332
  sideEffectCounter: minRevertibleSideEffectCounter,
273
- scopes: effectiveScopes,
333
+ scopes,
274
334
  // In TXE, the typical transaction entrypoint is skipped, so we need to simulate the actions that such a
275
335
  // contract would perform, including setting senderForTags.
276
336
  senderForTags: from,
277
337
  simulator,
278
- messageContextService: this.stateMachine.messageContextService
338
+ messageContextService: this.stateMachine.messageContextService,
339
+ l2TipsStore: this.stateMachine.l2TipsProvider,
340
+ hooks: composeHooks({
341
+ authorizeUtilityCall: this.buildAuthorizeUtilityCallHook(isStaticCall ? 'private view' : 'private', authorizedUtilityCallTargets)
342
+ }),
343
+ transientArrayService
279
344
  });
280
345
  // 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.
281
346
  let result;
@@ -288,7 +353,7 @@ export class TXEOracleTopLevelContext {
288
353
  r.publicInputs.publicTeardownCallRequest
289
354
  ]));
290
355
  const publicFunctionsCalldata = await Promise.all(publicCallRequests.map(async (r)=>{
291
- const calldata = await privateExecutionOracle.loadFromExecutionCache(r.calldataHash);
356
+ const calldata = await privateExecutionOracle.getHashPreimage(r.calldataHash);
292
357
  return new HashedValues(calldata, r.calldataHash);
293
358
  }));
294
359
  noteCache.finish();
@@ -347,10 +412,20 @@ export class TXEOracleTopLevelContext {
347
412
  throw new Error('Contract execution has reverted');
348
413
  }
349
414
  }
415
+ // Walk the nested private-call tree and collect every offchain effect the transaction emitted.
416
+ // PXE stores these on each `PrivateCallExecutionResult` and they never reach TXE via the
417
+ // `aztec_utl_emitOffchainEffect` foreign-call path (that path only fires at the top-level), so
418
+ // we pull them out here and the RPC wrapper will hand them to `TXESession` for buffering.
419
+ const offchainEffects = collectNested([
420
+ executionResult
421
+ ], (r)=>r.offchainEffects.map((e)=>e.data));
350
422
  if (isStaticCall) {
351
423
  await checkpoint.revert();
352
424
  await forkedWorldTrees.close();
353
- return executionResult.returnValues ?? [];
425
+ return {
426
+ returnValues: executionResult.returnValues ?? [],
427
+ offchainEffects
428
+ };
354
429
  }
355
430
  const txEffect = TxEffect.empty();
356
431
  txEffect.noteHashes = processedTx.txEffect.noteHashes;
@@ -366,14 +441,14 @@ export class TXEOracleTopLevelContext {
366
441
  ]);
367
442
  await this.stateMachine.handleL2Block(l2Block);
368
443
  await forkedWorldTrees.close();
369
- return executionResult.returnValues ?? [];
444
+ return {
445
+ returnValues: executionResult.returnValues ?? [],
446
+ offchainEffects
447
+ };
370
448
  }
371
- async publicCallNewFlow(from, targetContractAddress, calldata, isStaticCall) {
449
+ async publicCallNewFlow(from, targetContractAddress, calldata, isStaticCall, gasSettings) {
372
450
  this.logger.verbose(`Executing public function ${await this.contractStore.getDebugFunctionName(targetContractAddress, FunctionSelector.fromField(calldata[0]))}@${targetContractAddress} isStaticCall=${isStaticCall}`);
373
451
  const blockNumber = await this.getNextBlockNumber();
374
- const gasLimits = new Gas(DEFAULT_DA_GAS_LIMIT, DEFAULT_L2_GAS_LIMIT);
375
- const teardownGasLimits = new Gas(DEFAULT_TEARDOWN_DA_GAS_LIMIT, DEFAULT_TEARDOWN_L2_GAS_LIMIT);
376
- const gasSettings = new GasSettings(gasLimits, teardownGasLimits, GasFees.empty(), GasFees.empty());
377
452
  const txContext = new TxContext(this.chainId, this.version, gasSettings);
378
453
  const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
379
454
  const calldataHash = await computeCalldataHash(calldata);
@@ -406,7 +481,7 @@ export class TXEOracleTopLevelContext {
406
481
  // The enqueued public call itself we make be revertible so that the public execution is itself revertible, as tests
407
482
  // may require producing reverts.
408
483
  const revertibleAccumulatedData = PrivateToPublicAccumulatedData.empty();
409
- revertibleAccumulatedData.publicCallRequests[0] = new PublicCallRequest(from, targetContractAddress, isStaticCall, calldataHash);
484
+ revertibleAccumulatedData.publicCallRequests[0] = new PublicCallRequest(from ?? AztecAddress.NULL_MSG_SENDER, targetContractAddress, isStaticCall, calldataHash);
410
485
  const inputsForPublic = new PartialPrivateTailPublicInputsForPublic(nonRevertibleAccumulatedData, revertibleAccumulatedData, PublicCallRequest.empty());
411
486
  const constantData = new TxConstantData(anchorBlockHeader, txContext, Fr.zero(), Fr.zero());
412
487
  const txData = new PrivateKernelTailCircuitPublicInputs(constantData, /*gasUsed=*/ new Gas(0, 0), /*feePayer=*/ AztecAddress.zero(), /*expirationTimestamp=*/ 0n, inputsForPublic, undefined);
@@ -462,7 +537,7 @@ export class TXEOracleTopLevelContext {
462
537
  await forkedWorldTrees.close();
463
538
  return returnValues ?? [];
464
539
  }
465
- async executeUtilityFunction(targetContractAddress, functionSelector, args, jobId) {
540
+ async executeUtilityFunction(targetContractAddress, functionSelector, args, jobId, authorizedUtilityCallTargets) {
466
541
  const artifact = await this.contractStore.getFunctionArtifact(targetContractAddress, functionSelector);
467
542
  if (!artifact) {
468
543
  throw new Error(`Cannot call ${functionSelector} as there is no artifact found at ${targetContractAddress}.`);
@@ -471,7 +546,7 @@ export class TXEOracleTopLevelContext {
471
546
  const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
472
547
  await this.stateMachine.contractSyncService.ensureContractSynced(targetContractAddress, functionSelector, async (call, execScopes)=>{
473
548
  await this.executeUtilityCall(call, execScopes, jobId);
474
- }, blockHeader, jobId, 'ALL_SCOPES');
549
+ }, blockHeader, jobId, await this.keyStore.getAccounts());
475
550
  const call = FunctionCall.from({
476
551
  name: artifact.name,
477
552
  to: targetContractAddress,
@@ -482,9 +557,9 @@ export class TXEOracleTopLevelContext {
482
557
  args,
483
558
  returnTypes: []
484
559
  });
485
- return this.executeUtilityCall(call, 'ALL_SCOPES', jobId);
560
+ return this.executeUtilityCall(call, await this.keyStore.getAccounts(), jobId, authorizedUtilityCallTargets);
486
561
  }
487
- async executeUtilityCall(call, scopes, jobId) {
562
+ async executeUtilityCall(call, scopes, jobId, authorizedUtilityCallTargets = []) {
488
563
  const entryPointArtifact = await this.contractStore.getFunctionArtifactWithDebugMetadata(call.to, call.selector);
489
564
  if (entryPointArtifact.functionType !== FunctionType.UTILITY) {
490
565
  throw new Error(`Cannot run ${entryPointArtifact.functionType} function as utility`);
@@ -495,6 +570,10 @@ export class TXEOracleTopLevelContext {
495
570
  });
496
571
  try {
497
572
  const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
573
+ const simulator = new WASMSimulator();
574
+ const utilityExecutor = async (syncCall, execScopes)=>{
575
+ await this.executeUtilityCall(syncCall, execScopes, jobId);
576
+ };
498
577
  const oracle = new UtilityExecutionOracle({
499
578
  contractAddress: call.to,
500
579
  authWitnesses: [],
@@ -507,13 +586,22 @@ export class TXEOracleTopLevelContext {
507
586
  aztecNode: this.stateMachine.node,
508
587
  recipientTaggingStore: this.recipientTaggingStore,
509
588
  senderAddressBookStore: this.senderAddressBookStore,
510
- capsuleStore: this.capsuleStore,
589
+ capsuleService: new CapsuleService(this.capsuleStore, scopes),
511
590
  privateEventStore: this.privateEventStore,
512
591
  messageContextService: this.stateMachine.messageContextService,
592
+ contractSyncService: this.stateMachine.contractSyncService,
593
+ l2TipsStore: this.stateMachine.l2TipsProvider,
513
594
  jobId,
514
- scopes
595
+ scopes,
596
+ simulator,
597
+ hooks: composeHooks({
598
+ authorizeUtilityCall: this.buildAuthorizeUtilityCallHook('utility', authorizedUtilityCallTargets)
599
+ }),
600
+ utilityExecutor,
601
+ // Execution-tree root (top-level utility run or contract sync): own store; nested frames inherit it.
602
+ transientArrayService: new TransientArrayService()
515
603
  });
516
- const acirExecutionResult = await new WASMSimulator().executeUserCircuit(toACVMWitness(0, call.args), entryPointArtifact, new Oracle(oracle).toACIRCallback()).catch((err)=>{
604
+ const acirExecutionResult = await simulator.executeUserCircuit(toACVMWitness(0, call.args), entryPointArtifact, buildACIRCallback(oracle)).catch((err)=>{
517
605
  err.message = resolveAssertionMessageFromError(err, entryPointArtifact);
518
606
  throw new ExecutionError(err.message, {
519
607
  contractAddress: call.to,
@@ -536,7 +624,15 @@ export class TXEOracleTopLevelContext {
536
624
  ];
537
625
  }
538
626
  async getLastBlockNumber() {
539
- const header = await this.stateMachine.node.getBlockHeader('latest');
540
- return header ? header.globalVariables.blockNumber : BlockNumber.ZERO;
627
+ const block = await this.stateMachine.node.getBlock('latest');
628
+ return block ? block.header.globalVariables.blockNumber : BlockNumber.ZERO;
629
+ }
630
+ buildAuthorizeUtilityCallHook(callerContext, authorizedTargets) {
631
+ if (authorizedTargets.length === 0) {
632
+ return undefined;
633
+ }
634
+ return (req)=>Promise.resolve({
635
+ authorized: req.callerContext === callerContext && authorizedTargets.some((t)=>t.equals(req.target))
636
+ });
541
637
  }
542
638
  }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * The TXE oracle version constants are used to check that the oracle interface used for tests is in sync between
3
+ * TXE and Aztec.nr. This is separate from the contract oracle version in `pxe/src/oracle_version.ts`, which covers
4
+ * oracles used during contract execution by PXE.
5
+ *
6
+ * The Noir counterparts are in `noir-projects/aztec-nr/aztec/src/test/helpers/txe_oracles.nr`.
7
+ */
8
+ export declare const TXE_ORACLE_VERSION_MAJOR = 1;
9
+ export declare const TXE_ORACLE_VERSION_MINOR = 2;
10
+ /**
11
+ * This hash is computed from the TXE oracle interfaces (IAvmExecutionOracle and ITxeExecutionOracle) and is used to
12
+ * detect when those interfaces change. When it does, bump:
13
+ * - TXE_ORACLE_VERSION_MAJOR (and reset MINOR to 0) for breaking changes, or
14
+ * - TXE_ORACLE_VERSION_MINOR for additive changes (new oracle method added).
15
+ */
16
+ export declare const TXE_ORACLE_INTERFACE_HASH = "9e5f6ad5fd170d1de5ddd417f19cce47b17382567e08360dc6a783154828e218";
17
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHhlX29yYWNsZV92ZXJzaW9uLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvb3JhY2xlL3R4ZV9vcmFjbGVfdmVyc2lvbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7O0dBTUc7QUFDSCxlQUFPLE1BQU0sd0JBQXdCLElBQUksQ0FBQztBQUMxQyxlQUFPLE1BQU0sd0JBQXdCLElBQUksQ0FBQztBQUUxQzs7Ozs7R0FLRztBQUNILGVBQU8sTUFBTSx5QkFBeUIscUVBQXFFLENBQUMifQ==
@@ -0,0 +1 @@
1
+ {"version":3,"file":"txe_oracle_version.d.ts","sourceRoot":"","sources":["../../src/oracle/txe_oracle_version.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,eAAO,MAAM,wBAAwB,IAAI,CAAC;AAC1C,eAAO,MAAM,wBAAwB,IAAI,CAAC;AAE1C;;;;;GAKG;AACH,eAAO,MAAM,yBAAyB,qEAAqE,CAAC"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * The TXE oracle version constants are used to check that the oracle interface used for tests is in sync between
3
+ * TXE and Aztec.nr. This is separate from the contract oracle version in `pxe/src/oracle_version.ts`, which covers
4
+ * oracles used during contract execution by PXE.
5
+ *
6
+ * The Noir counterparts are in `noir-projects/aztec-nr/aztec/src/test/helpers/txe_oracles.nr`.
7
+ */ export const TXE_ORACLE_VERSION_MAJOR = 1;
8
+ export const TXE_ORACLE_VERSION_MINOR = 2;
9
+ /**
10
+ * This hash is computed from the TXE oracle interfaces (IAvmExecutionOracle and ITxeExecutionOracle) and is used to
11
+ * detect when those interfaces change. When it does, bump:
12
+ * - TXE_ORACLE_VERSION_MAJOR (and reset MINOR to 0) for breaking changes, or
13
+ * - TXE_ORACLE_VERSION_MINOR for additive changes (new oracle method added).
14
+ */ export const TXE_ORACLE_INTERFACE_HASH = '9e5f6ad5fd170d1de5ddd417f19cce47b17382567e08360dc6a783154828e218';
@@ -0,0 +1,17 @@
1
+ import type { Fr } from '@aztec/foundation/curves/bn254';
2
+ import { PrivateExecutionOracle } from '@aztec/pxe/simulator';
3
+ import type { FunctionSelector } from '@aztec/stdlib/abi';
4
+ import type { AztecAddress } from '@aztec/stdlib/aztec-address';
5
+ /**
6
+ * TXE-specific subclass of PrivateExecutionOracle that forbids operations not supported in
7
+ * TestEnvironment::private_context. TXE uses dedicated oracle flows (e.g. private_call) instead.
8
+ */
9
+ export declare class TXEPrivateExecutionOracle extends PrivateExecutionOracle {
10
+ callPrivateFunction(_targetContractAddress: AztecAddress, _functionSelector: FunctionSelector, _argsHash: Fr, _sideEffectCounter: number, _isStaticCall: boolean): Promise<{
11
+ endSideEffectCounter: Fr;
12
+ returnsHash: Fr;
13
+ }>;
14
+ assertValidPublicCalldata(_calldataHash: Fr): Promise<void>;
15
+ notifyRevertiblePhaseStart(_minRevertibleSideEffectCounter: number): Promise<void>;
16
+ }
17
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHhlX3ByaXZhdGVfZXhlY3V0aW9uX29yYWNsZS5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL29yYWNsZS90eGVfcHJpdmF0ZV9leGVjdXRpb25fb3JhY2xlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxFQUFFLEVBQUUsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBQ3pELE9BQU8sRUFBRSxzQkFBc0IsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQzlELE9BQU8sS0FBSyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDMUQsT0FBTyxLQUFLLEVBQUUsWUFBWSxFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFFaEU7OztHQUdHO0FBQ0gscUJBQWEseUJBQTBCLFNBQVEsc0JBQXNCO0lBQzFELG1CQUFtQixDQUMxQixzQkFBc0IsRUFBRSxZQUFZLEVBQ3BDLGlCQUFpQixFQUFFLGdCQUFnQixFQUNuQyxTQUFTLEVBQUUsRUFBRSxFQUNiLGtCQUFrQixFQUFFLE1BQU0sRUFDMUIsYUFBYSxFQUFFLE9BQU8sR0FDckIsT0FBTyxDQUFDO1FBQUUsb0JBQW9CLEVBQUUsRUFBRSxDQUFDO1FBQUMsV0FBVyxFQUFFLEVBQUUsQ0FBQTtLQUFFLENBQUMsQ0FJeEQ7SUFFUSx5QkFBeUIsQ0FBQyxhQUFhLEVBQUUsRUFBRSxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FFbkU7SUFFUSwwQkFBMEIsQ0FBQywrQkFBK0IsRUFBRSxNQUFNLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUUxRjtDQUNGIn0=
@@ -0,0 +1 @@
1
+ {"version":3,"file":"txe_private_execution_oracle.d.ts","sourceRoot":"","sources":["../../src/oracle/txe_private_execution_oracle.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,gCAAgC,CAAC;AACzD,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAEhE;;;GAGG;AACH,qBAAa,yBAA0B,SAAQ,sBAAsB;IAC1D,mBAAmB,CAC1B,sBAAsB,EAAE,YAAY,EACpC,iBAAiB,EAAE,gBAAgB,EACnC,SAAS,EAAE,EAAE,EACb,kBAAkB,EAAE,MAAM,EAC1B,aAAa,EAAE,OAAO,GACrB,OAAO,CAAC;QAAE,oBAAoB,EAAE,EAAE,CAAC;QAAC,WAAW,EAAE,EAAE,CAAA;KAAE,CAAC,CAIxD;IAEQ,yBAAyB,CAAC,aAAa,EAAE,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAEnE;IAEQ,0BAA0B,CAAC,+BAA+B,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE1F;CACF"}
@@ -0,0 +1,15 @@
1
+ import { PrivateExecutionOracle } from '@aztec/pxe/simulator';
2
+ /**
3
+ * TXE-specific subclass of PrivateExecutionOracle that forbids operations not supported in
4
+ * TestEnvironment::private_context. TXE uses dedicated oracle flows (e.g. private_call) instead.
5
+ */ export class TXEPrivateExecutionOracle extends PrivateExecutionOracle {
6
+ callPrivateFunction(_targetContractAddress, _functionSelector, _argsHash, _sideEffectCounter, _isStaticCall) {
7
+ throw new Error('Contract calls are forbidden inside a `TestEnvironment::private_context`, use `private_call` instead');
8
+ }
9
+ assertValidPublicCalldata(_calldataHash) {
10
+ throw new Error('Enqueueing public calls is not supported in TestEnvironment::private_context');
11
+ }
12
+ notifyRevertiblePhaseStart(_minRevertibleSideEffectCounter) {
13
+ throw new Error('Enqueueing public calls is not supported in TestEnvironment::private_context');
14
+ }
15
+ }
@@ -0,0 +1,14 @@
1
+ import type { Logger } from '@aztec/foundation/log';
2
+ /**
3
+ * Creates the TXE RPC server. With `TXE_WORKERS=1` oracle calls run on the main thread (no
4
+ * worker_threads, no IPC overhead). With any other value oracle calls are
5
+ * routed to a pool of worker threads sized to that value, sticky by `session_id`.
6
+ *
7
+ * Each incoming TCP socket is tagged with the `session_id` of the first oracle call it carries —
8
+ * nargo uses one HTTP client per test, so the socket-to-session mapping is 1:1. When the socket
9
+ * closes (end of test), the dispatcher disposes the session and frees its world state + LMDB.
10
+ *
11
+ * Lives in its own module so the worker bundle does not pull in the HTTP server stack.
12
+ */
13
+ export declare function createTXERpcServer(logger: Logger): Promise<import("@aztec/foundation/json-rpc/server").SafeJsonRpcServer>;
14
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicnBjX3NlcnZlci5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL3JwY19zZXJ2ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxLQUFLLEVBQUUsTUFBTSxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFlcEQ7Ozs7Ozs7Ozs7R0FVRztBQUNILHdCQUFzQixrQkFBa0IsQ0FBQyxNQUFNLEVBQUUsTUFBTSwwRUE0Q3REIn0=
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rpc_server.d.ts","sourceRoot":"","sources":["../src/rpc_server.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAepD;;;;;;;;;;GAUG;AACH,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,MAAM,0EA4CtD"}
@@ -0,0 +1,78 @@
1
+ import { createSafeJsonRpcServer } from '@aztec/foundation/json-rpc/server';
2
+ import { TXEDispatcherPool, buildSharedContractStore } from './dispatcher_pool.js';
3
+ import { TXEDispatcher, TXEDispatcherApiSchema } from './index.js';
4
+ /**
5
+ * Symbol used to tag an incoming TCP socket with the `session_id` it has been associated with.
6
+ * Hidden under a Symbol so we don't risk colliding with anything koa or http core adds.
7
+ */ const SESSION_SYMBOL = Symbol('txeSessionId');
8
+ /**
9
+ * Creates the TXE RPC server. With `TXE_WORKERS=1` oracle calls run on the main thread (no
10
+ * worker_threads, no IPC overhead). With any other value oracle calls are
11
+ * routed to a pool of worker threads sized to that value, sticky by `session_id`.
12
+ *
13
+ * Each incoming TCP socket is tagged with the `session_id` of the first oracle call it carries —
14
+ * nargo uses one HTTP client per test, so the socket-to-session mapping is 1:1. When the socket
15
+ * closes (end of test), the dispatcher disposes the session and frees its world state + LMDB.
16
+ *
17
+ * Lives in its own module so the worker bundle does not pull in the HTTP server stack.
18
+ */ export async function createTXERpcServer(logger) {
19
+ const workerCount = Number(process.env.TXE_WORKERS);
20
+ let dispatcher;
21
+ if (workerCount === 1) {
22
+ const { dataDir, schnorrClassId } = await buildSharedContractStore();
23
+ dispatcher = new TXEDispatcher(logger, {
24
+ contractStoreSourceDir: dataDir,
25
+ schnorrClassId
26
+ });
27
+ } else {
28
+ dispatcher = new TXEDispatcherPool(logger, {
29
+ workers: Number.isFinite(workerCount) && workerCount > 1 ? workerCount : undefined
30
+ });
31
+ }
32
+ const server = createSafeJsonRpcServer(dispatcher, TXEDispatcherApiSchema, {
33
+ http200OnError: true,
34
+ middlewares: [
35
+ async (ctx, next)=>{
36
+ // The body parser runs further down the chain, so `ctx.request.body` is populated only
37
+ // after `next()` resolves.
38
+ await next();
39
+ const socket = ctx.req.socket;
40
+ if (socket[SESSION_SYMBOL] !== undefined) {
41
+ return;
42
+ }
43
+ const body = ctx.request.body;
44
+ const sessionId = body && typeof body === 'object' && 'params' in body ? extractSessionId(body.params) : undefined;
45
+ if (sessionId === undefined) {
46
+ return;
47
+ }
48
+ socket[SESSION_SYMBOL] = sessionId;
49
+ logger.debug(`Tagged socket with session`, {
50
+ sessionId,
51
+ remoteAddress: socket.remoteAddress,
52
+ remotePort: socket.remotePort
53
+ });
54
+ socket.once('close', ()=>{
55
+ logger.debug(`Disposing session on socket close`, {
56
+ sessionId
57
+ });
58
+ void dispatcher.disposeSession(sessionId);
59
+ });
60
+ }
61
+ ]
62
+ });
63
+ return server;
64
+ }
65
+ // Extracts `session_id` from a JSON-RPC `params` array. Always a `number` because session_id
66
+ // comes off `JSON.parse`, which never produces BigInt; values above MAX_SAFE_INTEGER lose
67
+ // precision but still work as a Map key.
68
+ function extractSessionId(params) {
69
+ if (!Array.isArray(params) || params.length === 0) {
70
+ return undefined;
71
+ }
72
+ const first = params[0];
73
+ if (first && typeof first === 'object' && 'session_id' in first) {
74
+ const sid = first.session_id;
75
+ return typeof sid === 'number' ? sid : undefined;
76
+ }
77
+ return undefined;
78
+ }