@aztec/txe 2.1.0-rc.9 → 3.0.0-devnet.2

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 (71) hide show
  1. package/dest/bin/index.js +1 -1
  2. package/dest/index.d.ts.map +1 -1
  3. package/dest/index.js +5 -2
  4. package/dest/oracle/interfaces.d.ts +54 -0
  5. package/dest/oracle/interfaces.d.ts.map +1 -0
  6. package/dest/oracle/interfaces.js +3 -0
  7. package/dest/oracle/txe_oracle_public_context.d.ts +7 -7
  8. package/dest/oracle/txe_oracle_public_context.d.ts.map +1 -1
  9. package/dest/oracle/txe_oracle_public_context.js +29 -31
  10. package/dest/oracle/txe_oracle_top_level_context.d.ts +56 -0
  11. package/dest/oracle/txe_oracle_top_level_context.d.ts.map +1 -0
  12. package/dest/oracle/txe_oracle_top_level_context.js +423 -0
  13. package/dest/{txe_service/txe_service.d.ts → rpc_translator.d.ts} +34 -28
  14. package/dest/rpc_translator.d.ts.map +1 -0
  15. package/dest/{txe_service/txe_service.js → rpc_translator.js} +143 -115
  16. package/dest/state_machine/archiver.d.ts +5 -1
  17. package/dest/state_machine/archiver.d.ts.map +1 -1
  18. package/dest/state_machine/archiver.js +8 -1
  19. package/dest/state_machine/dummy_p2p_client.d.ts +1 -0
  20. package/dest/state_machine/dummy_p2p_client.d.ts.map +1 -1
  21. package/dest/state_machine/dummy_p2p_client.js +3 -0
  22. package/dest/state_machine/global_variable_builder.d.ts +1 -14
  23. package/dest/state_machine/global_variable_builder.d.ts.map +1 -1
  24. package/dest/state_machine/global_variable_builder.js +3 -22
  25. package/dest/state_machine/index.d.ts.map +1 -1
  26. package/dest/state_machine/index.js +4 -3
  27. package/dest/txe_session.d.ts +34 -44
  28. package/dest/txe_session.d.ts.map +1 -1
  29. package/dest/txe_session.js +197 -82
  30. package/dest/util/encoding.d.ts +1 -1
  31. package/dest/util/txe_contract_data_provider.d.ts +2 -1
  32. package/dest/util/txe_contract_data_provider.d.ts.map +1 -1
  33. package/dest/util/txe_contract_data_provider.js +1 -1
  34. package/dest/util/txe_public_contract_data_source.d.ts +4 -3
  35. package/dest/util/txe_public_contract_data_source.d.ts.map +1 -1
  36. package/dest/util/txe_public_contract_data_source.js +13 -11
  37. package/dest/utils/block_creation.d.ts +13 -0
  38. package/dest/utils/block_creation.d.ts.map +1 -0
  39. package/dest/utils/block_creation.js +24 -0
  40. package/dest/utils/tx_effect_creation.d.ts +5 -0
  41. package/dest/utils/tx_effect_creation.d.ts.map +1 -0
  42. package/dest/utils/tx_effect_creation.js +16 -0
  43. package/package.json +15 -15
  44. package/src/bin/index.ts +1 -1
  45. package/src/index.ts +5 -8
  46. package/src/oracle/interfaces.ts +83 -0
  47. package/src/oracle/txe_oracle_public_context.ts +36 -69
  48. package/src/oracle/txe_oracle_top_level_context.ts +658 -0
  49. package/src/{txe_service/txe_service.ts → rpc_translator.ts} +181 -115
  50. package/src/state_machine/archiver.ts +8 -2
  51. package/src/state_machine/dummy_p2p_client.ts +4 -0
  52. package/src/state_machine/global_variable_builder.ts +6 -41
  53. package/src/state_machine/index.ts +6 -4
  54. package/src/txe_session.ts +301 -90
  55. package/src/util/txe_contract_data_provider.ts +2 -1
  56. package/src/util/txe_public_contract_data_source.ts +13 -11
  57. package/src/utils/block_creation.ts +62 -0
  58. package/src/utils/tx_effect_creation.ts +37 -0
  59. package/dest/oracle/txe_oracle.d.ts +0 -124
  60. package/dest/oracle/txe_oracle.d.ts.map +0 -1
  61. package/dest/oracle/txe_oracle.js +0 -770
  62. package/dest/oracle/txe_typed_oracle.d.ts +0 -42
  63. package/dest/oracle/txe_typed_oracle.d.ts.map +0 -1
  64. package/dest/oracle/txe_typed_oracle.js +0 -83
  65. package/dest/txe_constants.d.ts +0 -2
  66. package/dest/txe_constants.d.ts.map +0 -1
  67. package/dest/txe_constants.js +0 -7
  68. package/dest/txe_service/txe_service.d.ts.map +0 -1
  69. package/src/oracle/txe_oracle.ts +0 -1287
  70. package/src/oracle/txe_typed_oracle.ts +0 -142
  71. package/src/txe_constants.ts +0 -9
@@ -1,37 +1,24 @@
1
- import { AztecAddress, Fr } from '@aztec/aztec.js';
1
+ import { Fr } from '@aztec/foundation/fields';
2
2
  import { createLogger } from '@aztec/foundation/log';
3
3
  import { KeyStore } from '@aztec/key-store';
4
4
  import { openTmpStore } from '@aztec/kv-store/lmdb-v2';
5
- import { AddressDataProvider, CapsuleDataProvider, NoteDataProvider, PrivateEventDataProvider, TaggingDataProvider } from '@aztec/pxe/server';
6
- import { makeGlobalVariables } from '@aztec/stdlib/testing';
7
- import { TXE } from './oracle/txe_oracle.js';
5
+ import { AddressDataProvider, CapsuleDataProvider, NoteDataProvider, PXEOracleInterface, PrivateEventDataProvider, TaggingDataProvider } from '@aztec/pxe/server';
6
+ import { ExecutionNoteCache, ExecutionTaggingIndexCache, HashedValuesCache, PrivateExecutionOracle, UtilityExecutionOracle } from '@aztec/pxe/simulator';
7
+ import { FunctionSelector } from '@aztec/stdlib/abi';
8
+ import { AztecAddress } from '@aztec/stdlib/aztec-address';
9
+ import { Body, L2Block } from '@aztec/stdlib/block';
10
+ import { GasSettings } from '@aztec/stdlib/gas';
11
+ import { makeAppendOnlyTreeSnapshot, makeGlobalVariables } from '@aztec/stdlib/testing';
12
+ import { CallContext, TxContext } from '@aztec/stdlib/tx';
13
+ import { z } from 'zod';
8
14
  import { TXEOraclePublicContext } from './oracle/txe_oracle_public_context.js';
15
+ import { TXEOracleTopLevelContext } from './oracle/txe_oracle_top_level_context.js';
16
+ import { RPCTranslator } from './rpc_translator.js';
9
17
  import { TXEStateMachine } from './state_machine/index.js';
10
- import { TXEService } from './txe_service/txe_service.js';
11
18
  import { TXEAccountDataProvider } from './util/txe_account_data_provider.js';
12
19
  import { TXEContractDataProvider } from './util/txe_contract_data_provider.js';
13
- /**
14
- * A TXE Session can be ine one of four states, which change as the test progresses and different oracles are called.
15
- * The current state determines which oracles are available.
16
- */ var SessionState = /*#__PURE__*/ function(SessionState) {
17
- /**
18
- * The top-level state is the default state, before any other state has been entered. This is where contracts can be
19
- * deployed, accounts created, blocks mined, etc.
20
- */ SessionState[SessionState["TOP_LEVEL"] = 0] = "TOP_LEVEL";
21
- /**
22
- * The private state is entered via the `private_context` function. In this state the PXE oracles that `#[private]`
23
- * functions use are available, such as those related to note retrieval, notification of side-effects, capsule access,
24
- * etc. */ SessionState[SessionState["PRIVATE"] = 1] = "PRIVATE";
25
- /**
26
- * The public state is entered via the `public_context` function. In this state the AVM opcodes that `#[public]`
27
- * functions execute are resolved as oracles by TXE, since Noir tests are not transpiled. */ SessionState[SessionState["PUBLIC"] = 2] = "PUBLIC";
28
- /**
29
- * The utility state is entered via the `utility_context` function. In this state the PXE oracles that `#[utility]`
30
- * functions use are available, such as those related to (unconstrained) note retrieval, capsule access, public
31
- * storage reads, etc.
32
- */ SessionState[SessionState["UTILITY"] = 3] = "UTILITY";
33
- return SessionState;
34
- }(SessionState || {});
20
+ import { getSingleTxBlockRequestHash, insertTxEffectIntoWorldTrees, makeTXEBlockHeader } from './utils/block_creation.js';
21
+ import { makeTxEffect } from './utils/tx_effect_creation.js';
35
22
  const DEFAULT_ADDRESS = AztecAddress.fromNumber(42);
36
23
  /**
37
24
  * A `TXESession` corresponds to a Noir `#[test]` function, and handles all of its oracle calls, stores test-specific
@@ -40,14 +27,32 @@ const DEFAULT_ADDRESS = AztecAddress.fromNumber(42);
40
27
  logger;
41
28
  stateMachine;
42
29
  oracleHandler;
43
- legacyTXEOracle;
30
+ contractDataProvider;
31
+ keyStore;
32
+ addressDataProvider;
33
+ accountDataProvider;
34
+ chainId;
35
+ version;
36
+ nextBlockTimestamp;
37
+ pxeOracleInterface;
44
38
  state;
45
- constructor(logger, stateMachine, oracleHandler, legacyTXEOracle){
39
+ authwits;
40
+ constructor(logger, stateMachine, oracleHandler, contractDataProvider, keyStore, addressDataProvider, accountDataProvider, chainId, version, nextBlockTimestamp, pxeOracleInterface){
46
41
  this.logger = logger;
47
42
  this.stateMachine = stateMachine;
48
43
  this.oracleHandler = oracleHandler;
49
- this.legacyTXEOracle = legacyTXEOracle;
50
- this.state = 0;
44
+ this.contractDataProvider = contractDataProvider;
45
+ this.keyStore = keyStore;
46
+ this.addressDataProvider = addressDataProvider;
47
+ this.accountDataProvider = accountDataProvider;
48
+ this.chainId = chainId;
49
+ this.version = version;
50
+ this.nextBlockTimestamp = nextBlockTimestamp;
51
+ this.pxeOracleInterface = pxeOracleInterface;
52
+ this.state = {
53
+ name: 'TOP_LEVEL'
54
+ };
55
+ this.authwits = new Map();
51
56
  }
52
57
  static async init(protocolContracts) {
53
58
  const store = await openTmpStore('txe-session');
@@ -65,9 +70,13 @@ const DEFAULT_ADDRESS = AztecAddress.fromNumber(42);
65
70
  await contractDataProvider.addContractInstance(instance);
66
71
  }
67
72
  const stateMachine = await TXEStateMachine.create(store);
68
- const txeOracle = new TXE(keyStore, contractDataProvider, noteDataProvider, capsuleDataProvider, taggingDataProvider, addressDataProvider, privateEventDataProvider, accountDataProvider, DEFAULT_ADDRESS, await stateMachine.synchronizer.nativeWorldStateService.fork(), stateMachine);
69
- await txeOracle.txeAdvanceBlocksBy(1);
70
- return new TXESession(createLogger('txe:session'), stateMachine, txeOracle, txeOracle);
73
+ const nextBlockTimestamp = BigInt(Math.floor(new Date().getTime() / 1000));
74
+ const version = new Fr(await stateMachine.node.getVersion());
75
+ const chainId = new Fr(await stateMachine.node.getChainId());
76
+ const pxeOracleInterface = new PXEOracleInterface(stateMachine.node, keyStore, contractDataProvider, noteDataProvider, capsuleDataProvider, stateMachine.syncDataProvider, taggingDataProvider, addressDataProvider, privateEventDataProvider);
77
+ const topLevelOracleHandler = new TXEOracleTopLevelContext(stateMachine, contractDataProvider, keyStore, addressDataProvider, accountDataProvider, pxeOracleInterface, nextBlockTimestamp, version, chainId, new Map());
78
+ await topLevelOracleHandler.txeAdvanceBlocksBy(1);
79
+ return new TXESession(createLogger('txe:session'), stateMachine, topLevelOracleHandler, contractDataProvider, keyStore, addressDataProvider, accountDataProvider, version, chainId, nextBlockTimestamp, pxeOracleInterface);
71
80
  }
72
81
  /**
73
82
  * Processes an oracle function invoked by the Noir test associated to this session.
@@ -75,64 +84,170 @@ const DEFAULT_ADDRESS = AztecAddress.fromNumber(42);
75
84
  * @param inputs The inputs of the oracle.
76
85
  * @returns The oracle return values.
77
86
  */ processFunction(functionName, inputs) {
78
- return new TXEService(this, this.oracleHandler)[functionName](...inputs);
87
+ try {
88
+ const translator = new RPCTranslator(this, this.oracleHandler);
89
+ // We perform a runtime validation to check that the function name corresponds to a real oracle handler.
90
+ const validatedFunctionName = z.string().refine((fn)=>typeof translator[fn] === 'function' && !fn.startsWith('handlerAs') && fn !== 'constructor').parse(functionName);
91
+ return translator[validatedFunctionName](...inputs);
92
+ } catch (error) {
93
+ if (error instanceof z.ZodError) {
94
+ throw new Error(`${functionName} does not correspond to any oracle handler available on RPCTranslator`);
95
+ } else if (error instanceof Error) {
96
+ throw new Error(`Execution error while processing function ${functionName} in state ${this.state.name}: ${error.message}`);
97
+ } else {
98
+ throw new Error(`Unknown execution error while processing function ${functionName} in state ${this.state.name}`);
99
+ }
100
+ }
79
101
  }
80
- async setTopLevelContext() {
81
- if (this.state == 1) {
82
- await this.oracleHandler.txeAdvanceBlocksBy(1);
83
- this.oracleHandler.txeSetContractAddress(DEFAULT_ADDRESS);
84
- } else if (this.state == 2) {
85
- const block = await this.oracleHandler.close();
86
- await this.stateMachine.handleL2Block(block);
87
- this.legacyTXEOracle.baseFork = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
88
- this.legacyTXEOracle.txeSetContractAddress(DEFAULT_ADDRESS);
89
- this.legacyTXEOracle.setBlockNumber(block.number + 1);
90
- this.oracleHandler = this.legacyTXEOracle;
91
- } else if (this.state == 3) {
92
- this.oracleHandler.txeSetContractAddress(DEFAULT_ADDRESS);
93
- } else if (this.state == 0) {
94
- throw new Error(`Expected to be in state other than ${SessionState[0]}`);
95
- } else {
96
- throw new Error(`Unexpected state '${this.state}'`);
102
+ async enterTopLevelState() {
103
+ switch(this.state.name){
104
+ case 'PRIVATE':
105
+ {
106
+ await this.exitPrivateState();
107
+ break;
108
+ }
109
+ case 'PUBLIC':
110
+ {
111
+ await this.exitPublicState();
112
+ break;
113
+ }
114
+ case 'UTILITY':
115
+ {
116
+ this.exitUtilityContext();
117
+ break;
118
+ }
119
+ case 'TOP_LEVEL':
120
+ {
121
+ throw new Error(`Expected to be in state other than TOP_LEVEL`);
122
+ }
123
+ default:
124
+ {
125
+ this.state;
126
+ }
97
127
  }
98
- this.state = 0;
99
- this.logger.debug(`Entered state ${SessionState[this.state]}`);
128
+ this.oracleHandler = new TXEOracleTopLevelContext(this.stateMachine, this.contractDataProvider, this.keyStore, this.addressDataProvider, this.accountDataProvider, this.pxeOracleInterface, this.nextBlockTimestamp, this.version, this.chainId, this.authwits);
129
+ this.state = {
130
+ name: 'TOP_LEVEL'
131
+ };
132
+ this.logger.debug(`Entered state ${this.state.name}`);
100
133
  }
101
- async setPublicContext(contractAddress) {
102
- this.assertInTopLevelState();
134
+ async enterPrivateState(contractAddress = DEFAULT_ADDRESS, anchorBlockNumber) {
135
+ this.exitTopLevelState();
136
+ // There is no automatic message discovery and contract-driven syncing process in inlined private or utility
137
+ // contexts, which means that known nullifiers are also not searched for, since it is during the tagging sync that
138
+ // we perform this. We therefore search for known nullifiers now, as otherwise notes that were nullified would not
139
+ // be removed from the database.
140
+ // TODO(#12553): make the synchronizer sync here instead and remove this
141
+ await this.pxeOracleInterface.syncNoteNullifiers(contractAddress);
142
+ // Private execution has two associated block numbers: the anchor block (i.e. the historical block that is used to
143
+ // build the proof), and the *next* block, i.e. the one we'll create once the execution ends, and which will contain
144
+ // a single transaction with the effects of what was done in the test.
145
+ const anchorBlock = await this.stateMachine.node.getBlockHeader(anchorBlockNumber ?? 'latest');
146
+ const latestBlock = await this.stateMachine.node.getBlockHeader('latest');
147
+ const nextBlockGlobalVariables = makeGlobalVariables(undefined, {
148
+ blockNumber: latestBlock.globalVariables.blockNumber + 1,
149
+ timestamp: this.nextBlockTimestamp,
150
+ version: this.version,
151
+ chainId: this.chainId
152
+ });
153
+ const txRequestHash = getSingleTxBlockRequestHash(nextBlockGlobalVariables.blockNumber);
154
+ const noteCache = new ExecutionNoteCache(txRequestHash);
155
+ const taggingIndexCache = new ExecutionTaggingIndexCache();
156
+ this.oracleHandler = new PrivateExecutionOracle(Fr.ZERO, new TxContext(this.chainId, this.version, GasSettings.empty()), new CallContext(AztecAddress.ZERO, contractAddress, FunctionSelector.empty(), false), anchorBlock, [], [], new HashedValuesCache(), noteCache, taggingIndexCache, this.pxeOracleInterface);
157
+ // We store the note and tagging index caches fed into the PrivateExecutionOracle (along with some other auxiliary
158
+ // data) in order to refer to it later, mimicking the way this object is used by the ContractFunctionSimulator. The
159
+ // difference resides in that the simulator has all information needed in order to run the simulation, while ours
160
+ // will be ongoing as the different oracles will be invoked from the Noir test, until eventually the private
161
+ // execution finishes.
162
+ this.state = {
163
+ name: 'PRIVATE',
164
+ nextBlockGlobalVariables,
165
+ txRequestHash,
166
+ noteCache,
167
+ taggingIndexCache
168
+ };
169
+ this.logger.debug(`Entered state ${this.state.name}`);
170
+ return this.oracleHandler.getPrivateContextInputs();
171
+ }
172
+ async enterPublicState(contractAddress) {
173
+ this.exitTopLevelState();
174
+ // The PublicContext will create a block with a single transaction in it, containing the effects of what was done in
175
+ // the test. The block therefore gets the *next* block number and timestamp.
176
+ const latestBlockNumber = (await this.stateMachine.node.getBlockHeader('latest')).globalVariables.blockNumber;
103
177
  const globalVariables = makeGlobalVariables(undefined, {
104
- blockNumber: await this.legacyTXEOracle.utilityGetBlockNumber(),
105
- timestamp: await this.legacyTXEOracle.utilityGetTimestamp(),
106
- version: await this.legacyTXEOracle.utilityGetVersion(),
107
- chainId: await this.legacyTXEOracle.utilityGetChainId()
178
+ blockNumber: latestBlockNumber + 1,
179
+ timestamp: this.nextBlockTimestamp,
180
+ version: this.version,
181
+ chainId: this.chainId
108
182
  });
109
- const txRequestHash = new Fr(globalVariables.blockNumber + 6969);
110
- this.oracleHandler = new TXEOraclePublicContext(contractAddress ?? DEFAULT_ADDRESS, await this.stateMachine.synchronizer.nativeWorldStateService.fork(), txRequestHash, globalVariables);
111
- this.state = 2;
112
- this.logger.debug(`Entered state ${SessionState[this.state]}`);
183
+ this.oracleHandler = new TXEOraclePublicContext(contractAddress ?? DEFAULT_ADDRESS, await this.stateMachine.synchronizer.nativeWorldStateService.fork(), getSingleTxBlockRequestHash(globalVariables.blockNumber), globalVariables);
184
+ this.state = {
185
+ name: 'PUBLIC'
186
+ };
187
+ this.logger.debug(`Entered state ${this.state.name}`);
188
+ }
189
+ async enterUtilityState(contractAddress = DEFAULT_ADDRESS) {
190
+ this.exitTopLevelState();
191
+ // There is no automatic message discovery and contract-driven syncing process in inlined private or utility
192
+ // contexts, which means that known nullifiers are also not searched for, since it is during the tagging sync that
193
+ // we perform this. We therefore search for known nullifiers now, as otherwise notes that were nullified would not
194
+ // be removed from the database.
195
+ // TODO(#12553): make the synchronizer sync here instead and remove this
196
+ await this.pxeOracleInterface.syncNoteNullifiers(contractAddress);
197
+ this.oracleHandler = new UtilityExecutionOracle(contractAddress, [], [], this.pxeOracleInterface);
198
+ this.state = {
199
+ name: 'UTILITY'
200
+ };
201
+ this.logger.debug(`Entered state ${this.state.name}`);
202
+ }
203
+ exitTopLevelState() {
204
+ if (this.state.name != 'TOP_LEVEL') {
205
+ throw new Error(`Expected to be in state 'TOP_LEVEL', but got '${this.state.name}' instead`);
206
+ }
207
+ // Note that while all public and private contexts do is build a single block that we then process when exiting
208
+ // those, the top level context performs a large number of actions not captured in the following 'close' call. Among
209
+ // others, it will create empty blocks (via `txeAdvanceBlocksBy` and `deploy`), create blocks with transactions via
210
+ // `txePrivateCallNewFlow` and `txePublicCallNewFlow`, add accounts to PXE via `txeAddAccount`, etc. This is a
211
+ // slight inconsistency in the working model of this class, but is not too bad.
212
+ // TODO: it's quite unfortunate that we need to capture the authwits created to later pass them again when the top
213
+ // level context is re-created. This is because authwits create a temporary utility context that'd otherwise reset
214
+ // the authwits if not persisted, so we'd not be able to pass more than one per execution.
215
+ // Ideally authwits would be passed alongside a contract call instead of pre-seeded.
216
+ [this.nextBlockTimestamp, this.authwits] = this.oracleHandler.close();
113
217
  }
114
- async setPrivateContext(contractAddress, historicalBlockNumber) {
115
- this.assertInTopLevelState();
116
- if (contractAddress) {
117
- this.oracleHandler.txeSetContractAddress(contractAddress);
218
+ async exitPrivateState() {
219
+ if (this.state.name != 'PRIVATE') {
220
+ throw new Error(`Expected to be in state 'PRIVATE', but got '${this.state.name}' instead`);
118
221
  }
119
- const privateContextInputs = await this.oracleHandler.txeGetPrivateContextInputs(historicalBlockNumber);
120
- this.state = 1;
121
- this.logger.debug(`Entered state ${SessionState[this.state]}`);
122
- return privateContextInputs;
222
+ this.logger.debug('Exiting Private state, building block with collected side effects', {
223
+ blockNumber: this.state.nextBlockGlobalVariables.blockNumber
224
+ });
225
+ // We rely on the note cache to determine the effects of the transaction. This is incomplete as it doesn't private
226
+ // logs (other effects like enqueued public calls don't need to be considered since those are not allowed).
227
+ const txEffect = await makeTxEffect(this.state.noteCache, this.state.txRequestHash, this.state.nextBlockGlobalVariables.blockNumber);
228
+ // We build a block holding just this transaction
229
+ const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
230
+ await insertTxEffectIntoWorldTrees(txEffect, forkedWorldTrees);
231
+ const block = new L2Block(makeAppendOnlyTreeSnapshot(), await makeTXEBlockHeader(forkedWorldTrees, this.state.nextBlockGlobalVariables), new Body([
232
+ txEffect
233
+ ]));
234
+ await this.stateMachine.handleL2Block(block);
235
+ await forkedWorldTrees.close();
236
+ this.logger.debug('Exited PublicContext with built block', {
237
+ blockNumber: block.number,
238
+ txEffects: block.body.txEffects
239
+ });
123
240
  }
124
- setUtilityContext(contractAddress) {
125
- this.assertInTopLevelState();
126
- if (contractAddress) {
127
- this.oracleHandler.txeSetContractAddress(contractAddress);
241
+ async exitPublicState() {
242
+ if (this.state.name != 'PUBLIC') {
243
+ throw new Error(`Expected to be in state 'PUBLIC', but got '${this.state.name}' instead`);
128
244
  }
129
- this.state = 3;
130
- this.logger.debug(`Entered state ${SessionState[this.state]}`);
131
- return Promise.resolve();
245
+ const block = await this.oracleHandler.close();
246
+ await this.stateMachine.handleL2Block(block);
132
247
  }
133
- assertInTopLevelState() {
134
- if (this.state != 0) {
135
- throw new Error(`Expected to be in state ${SessionState[0]}, but got '${SessionState[this.state]}' instead`);
248
+ exitUtilityContext() {
249
+ if (this.state.name != 'UTILITY') {
250
+ throw new Error(`Expected to be in state 'UTILITY', but got '${this.state.name}' instead`);
136
251
  }
137
252
  }
138
253
  }
@@ -86,11 +86,11 @@ export declare const ForeignCallArgsSchema: z.ZodArray<z.ZodUnion<[z.ZodString,
86
86
  }, "strip", z.ZodTypeAny, {
87
87
  version: 1;
88
88
  salt: Fr;
89
- publicKeys: import("@aztec/stdlib/keys").PublicKeys;
90
89
  deployer: AztecAddress;
91
90
  currentContractClassId: Fr;
92
91
  originalContractClassId: Fr;
93
92
  initializationHash: Fr;
93
+ publicKeys: import("@aztec/stdlib/keys").PublicKeys;
94
94
  }, {
95
95
  version: 1;
96
96
  publicKeys: {
@@ -1,4 +1,5 @@
1
- import { type ContractArtifact, Fr } from '@aztec/aztec.js';
1
+ import type { ContractArtifact } from '@aztec/aztec.js/abi';
2
+ import { Fr } from '@aztec/aztec.js/fields';
2
3
  import { ContractDataProvider } from '@aztec/pxe/server';
3
4
  export type ContractArtifactWithHash = ContractArtifact & {
4
5
  artifactHash: Fr;
@@ -1 +1 @@
1
- {"version":3,"file":"txe_contract_data_provider.d.ts","sourceRoot":"","sources":["../../src/util/txe_contract_data_provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,gBAAgB,EAAE,EAAE,EAAE,MAAM,iBAAiB,CAAC;AAC5D,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAEzD,MAAM,MAAM,wBAAwB,GAAG,gBAAgB,GAAG;IAAE,YAAY,EAAE,EAAE,CAAA;CAAE,CAAC;AAO/E,qBAAa,uBAAwB,SAAQ,oBAAoB;;IAGzC,mBAAmB,CACvC,EAAE,EAAE,EAAE,EACN,QAAQ,EAAE,gBAAgB,GAAG,wBAAwB,GACpD,OAAO,CAAC,IAAI,CAAC;IAOM,mBAAmB,CACvC,eAAe,EAAE,EAAE,GAClB,OAAO,CAAC,gBAAgB,GAAG,wBAAwB,GAAG,SAAS,CAAC;CASpE"}
1
+ {"version":3,"file":"txe_contract_data_provider.d.ts","sourceRoot":"","sources":["../../src/util/txe_contract_data_provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,EAAE,EAAE,MAAM,wBAAwB,CAAC;AAC5C,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAEzD,MAAM,MAAM,wBAAwB,GAAG,gBAAgB,GAAG;IAAE,YAAY,EAAE,EAAE,CAAA;CAAE,CAAC;AAO/E,qBAAa,uBAAwB,SAAQ,oBAAoB;;IAGzC,mBAAmB,CACvC,EAAE,EAAE,EAAE,EACN,QAAQ,EAAE,gBAAgB,GAAG,wBAAwB,GACpD,OAAO,CAAC,IAAI,CAAC;IAOM,mBAAmB,CACvC,eAAe,EAAE,EAAE,GAClB,OAAO,CAAC,gBAAgB,GAAG,wBAAwB,GAAG,SAAS,CAAC;CASpE"}
@@ -1,4 +1,4 @@
1
- import { Fr } from '@aztec/aztec.js';
1
+ import { Fr } from '@aztec/aztec.js/fields';
2
2
  import { ContractDataProvider } from '@aztec/pxe/server';
3
3
  /*
4
4
  * A contract data provider that stores contract artifacts with their hashes. Since
@@ -1,12 +1,13 @@
1
1
  import { Fr } from '@aztec/foundation/fields';
2
+ import type { ContractDataProvider } from '@aztec/pxe/server';
2
3
  import { type ContractArtifact, FunctionSelector } from '@aztec/stdlib/abi';
3
4
  import type { AztecAddress } from '@aztec/stdlib/aztec-address';
4
5
  import { type ContractClassPublic, type ContractDataSource, type ContractInstanceWithAddress } from '@aztec/stdlib/contract';
5
- import type { TXE } from '../oracle/txe_oracle.js';
6
6
  export declare class TXEPublicContractDataSource implements ContractDataSource {
7
7
  #private;
8
- private txeOracle;
9
- constructor(txeOracle: TXE);
8
+ private blockNumber;
9
+ private contractDataProvider;
10
+ constructor(blockNumber: number, contractDataProvider: ContractDataProvider);
10
11
  getBlockNumber(): Promise<number>;
11
12
  getContractClass(id: Fr): Promise<ContractClassPublic | undefined>;
12
13
  getBytecodeCommitment(id: Fr): Promise<Fr | undefined>;
@@ -1 +1 @@
1
- {"version":3,"file":"txe_public_contract_data_source.d.ts","sourceRoot":"","sources":["../../src/util/txe_public_contract_data_source.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,0BAA0B,CAAC;AAC9C,OAAO,EAAE,KAAK,gBAAgB,EAAE,gBAAgB,EAAgB,MAAM,mBAAmB,CAAC;AAC1F,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,EACL,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACvB,KAAK,2BAA2B,EAIjC,MAAM,wBAAwB,CAAC;AAEhC,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,yBAAyB,CAAC;AAEnD,qBAAa,2BAA4B,YAAW,kBAAkB;;IAExD,OAAO,CAAC,SAAS;gBAAT,SAAS,EAAE,GAAG;IAElC,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC;IAI3B,gBAAgB,CAAC,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,mBAAmB,GAAG,SAAS,CAAC;IAkClE,qBAAqB,CAAC,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,EAAE,GAAG,SAAS,CAAC;IAKtD,WAAW,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,2BAA2B,GAAG,SAAS,CAAC;IAK1F,mBAAmB,IAAI,OAAO,CAAC,EAAE,EAAE,CAAC;IAI9B,mBAAmB,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,gBAAgB,GAAG,SAAS,CAAC;IAKjF,oBAAoB,CAAC,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAI1G,kCAAkC,CAAC,WAAW,EAAE,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;CAGnE"}
1
+ {"version":3,"file":"txe_public_contract_data_source.d.ts","sourceRoot":"","sources":["../../src/util/txe_public_contract_data_source.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,0BAA0B,CAAC;AAC9C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAC9D,OAAO,EAAE,KAAK,gBAAgB,EAAE,gBAAgB,EAAgB,MAAM,mBAAmB,CAAC;AAC1F,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,EACL,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACvB,KAAK,2BAA2B,EAIjC,MAAM,wBAAwB,CAAC;AAEhC,qBAAa,2BAA4B,YAAW,kBAAkB;;IAGlE,OAAO,CAAC,WAAW;IACnB,OAAO,CAAC,oBAAoB;gBADpB,WAAW,EAAE,MAAM,EACnB,oBAAoB,EAAE,oBAAoB;IAGpD,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC;IAI3B,gBAAgB,CAAC,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,mBAAmB,GAAG,SAAS,CAAC;IAkClE,qBAAqB,CAAC,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,EAAE,GAAG,SAAS,CAAC;IAKtD,WAAW,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,2BAA2B,GAAG,SAAS,CAAC;IAK1F,mBAAmB,IAAI,OAAO,CAAC,EAAE,EAAE,CAAC;IAI9B,mBAAmB,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,gBAAgB,GAAG,SAAS,CAAC;IAKjF,oBAAoB,CAAC,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAI1G,kCAAkC,CAAC,WAAW,EAAE,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;CAGnE"}
@@ -2,21 +2,23 @@ import { Fr } from '@aztec/foundation/fields';
2
2
  import { FunctionType } from '@aztec/stdlib/abi';
3
3
  import { computePrivateFunctionsRoot, computePublicBytecodeCommitment, getContractClassPrivateFunctionFromArtifact } from '@aztec/stdlib/contract';
4
4
  export class TXEPublicContractDataSource {
5
- txeOracle;
5
+ blockNumber;
6
+ contractDataProvider;
6
7
  #privateFunctionsRoot;
7
- constructor(txeOracle){
8
- this.txeOracle = txeOracle;
8
+ constructor(blockNumber, contractDataProvider){
9
+ this.blockNumber = blockNumber;
10
+ this.contractDataProvider = contractDataProvider;
9
11
  this.#privateFunctionsRoot = new Map();
10
12
  }
11
13
  getBlockNumber() {
12
- return this.txeOracle.utilityGetBlockNumber();
14
+ return Promise.resolve(this.blockNumber);
13
15
  }
14
16
  async getContractClass(id) {
15
- const contractClass = await this.txeOracle.getContractDataProvider().getContractClass(id);
17
+ const contractClass = await this.contractDataProvider.getContractClass(id);
16
18
  if (!contractClass) {
17
19
  return;
18
20
  }
19
- const artifact = await this.txeOracle.getContractDataProvider().getContractArtifact(id);
21
+ const artifact = await this.contractDataProvider.getContractArtifact(id);
20
22
  if (!artifact) {
21
23
  return;
22
24
  }
@@ -39,11 +41,11 @@ export class TXEPublicContractDataSource {
39
41
  };
40
42
  }
41
43
  async getBytecodeCommitment(id) {
42
- const contractClass = await this.txeOracle.getContractDataProvider().getContractClass(id);
44
+ const contractClass = await this.contractDataProvider.getContractClass(id);
43
45
  return contractClass && computePublicBytecodeCommitment(contractClass.packedBytecode);
44
46
  }
45
47
  async getContract(address) {
46
- const instance = await this.txeOracle.getContractDataProvider().getContractInstance(address);
48
+ const instance = await this.contractDataProvider.getContractInstance(address);
47
49
  return instance && {
48
50
  ...instance,
49
51
  address
@@ -53,11 +55,11 @@ export class TXEPublicContractDataSource {
53
55
  throw new Error('Method not implemented.');
54
56
  }
55
57
  async getContractArtifact(address) {
56
- const instance = await this.txeOracle.getContractDataProvider().getContractInstance(address);
57
- return instance && this.txeOracle.getContractDataProvider().getContractArtifact(instance.currentContractClassId);
58
+ const instance = await this.contractDataProvider.getContractInstance(address);
59
+ return instance && this.contractDataProvider.getContractArtifact(instance.currentContractClassId);
58
60
  }
59
61
  async getDebugFunctionName(address, selector) {
60
- return await this.txeOracle.getContractDataProvider().getDebugFunctionName(address, selector);
62
+ return await this.contractDataProvider.getDebugFunctionName(address, selector);
61
63
  }
62
64
  registerContractFunctionSignatures(_signatures) {
63
65
  return Promise.resolve();
@@ -0,0 +1,13 @@
1
+ import { Fr } from '@aztec/foundation/fields';
2
+ import { L2BlockHeader } from '@aztec/stdlib/block';
3
+ import { type MerkleTreeWriteOperations } from '@aztec/stdlib/trees';
4
+ import { GlobalVariables, TxEffect } from '@aztec/stdlib/tx';
5
+ /**
6
+ * Returns a transaction request hash that is valid for transactions that are the only ones in a block.
7
+ * @param blockNumber The number for the block in which there is a single transaction.
8
+ * @returns The transaction request hash.
9
+ */
10
+ export declare function getSingleTxBlockRequestHash(blockNumber: number): Fr;
11
+ export declare function insertTxEffectIntoWorldTrees(txEffect: TxEffect, worldTrees: MerkleTreeWriteOperations): Promise<void>;
12
+ export declare function makeTXEBlockHeader(worldTrees: MerkleTreeWriteOperations, globalVariables: GlobalVariables): Promise<L2BlockHeader>;
13
+ //# sourceMappingURL=block_creation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"block_creation.d.ts","sourceRoot":"","sources":["../../src/utils/block_creation.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,EAAE,EAAE,MAAM,0BAA0B,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEpD,OAAO,EAAwC,KAAK,yBAAyB,EAAE,MAAM,qBAAqB,CAAC;AAC3G,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE7D;;;;GAIG;AACH,wBAAgB,2BAA2B,CAAC,WAAW,EAAE,MAAM,GAAG,EAAE,CAEnE;AAED,wBAAsB,4BAA4B,CAChD,QAAQ,EAAE,QAAQ,EAClB,UAAU,EAAE,yBAAyB,GACpC,OAAO,CAAC,IAAI,CAAC,CAkBf;AAED,wBAAsB,kBAAkB,CACtC,UAAU,EAAE,yBAAyB,EACrC,eAAe,EAAE,eAAe,GAC/B,OAAO,CAAC,aAAa,CAAC,CAaxB"}
@@ -0,0 +1,24 @@
1
+ import { MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, NULLIFIER_SUBTREE_HEIGHT, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP } from '@aztec/constants';
2
+ import { padArrayEnd } from '@aztec/foundation/collection';
3
+ import { Fr } from '@aztec/foundation/fields';
4
+ import { L2BlockHeader } from '@aztec/stdlib/block';
5
+ import { makeContentCommitment } from '@aztec/stdlib/testing';
6
+ import { AppendOnlyTreeSnapshot, MerkleTreeId } from '@aztec/stdlib/trees';
7
+ /**
8
+ * Returns a transaction request hash that is valid for transactions that are the only ones in a block.
9
+ * @param blockNumber The number for the block in which there is a single transaction.
10
+ * @returns The transaction request hash.
11
+ */ export function getSingleTxBlockRequestHash(blockNumber) {
12
+ return new Fr(blockNumber + 9999); // Why does this need to be a high number? Why do small numbered nullifiers already exist?
13
+ }
14
+ export async function insertTxEffectIntoWorldTrees(txEffect, worldTrees) {
15
+ await worldTrees.appendLeaves(MerkleTreeId.NOTE_HASH_TREE, padArrayEnd(txEffect.noteHashes, Fr.ZERO, MAX_NOTE_HASHES_PER_TX));
16
+ await worldTrees.batchInsert(MerkleTreeId.NULLIFIER_TREE, padArrayEnd(txEffect.nullifiers, Fr.ZERO, MAX_NULLIFIERS_PER_TX).map((nullifier)=>nullifier.toBuffer()), NULLIFIER_SUBTREE_HEIGHT);
17
+ await worldTrees.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, padArrayEnd(txEffect.l2ToL1Msgs, Fr.ZERO, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP));
18
+ // We do not need to add public data writes because we apply them as we go.
19
+ }
20
+ export async function makeTXEBlockHeader(worldTrees, globalVariables) {
21
+ const stateReference = await worldTrees.getStateReference();
22
+ const archiveInfo = await worldTrees.getTreeInfo(MerkleTreeId.ARCHIVE);
23
+ return new L2BlockHeader(new AppendOnlyTreeSnapshot(new Fr(archiveInfo.root), Number(archiveInfo.size)), makeContentCommitment(), stateReference, globalVariables, Fr.ZERO, Fr.ZERO, Fr.ZERO);
24
+ }
@@ -0,0 +1,5 @@
1
+ import { Fr } from '@aztec/foundation/fields';
2
+ import type { ExecutionNoteCache } from '@aztec/pxe/simulator';
3
+ import { TxEffect } from '@aztec/stdlib/tx';
4
+ export declare function makeTxEffect(noteCache: ExecutionNoteCache, txRequestHash: Fr, txBlockNumber: number): Promise<TxEffect>;
5
+ //# sourceMappingURL=tx_effect_creation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tx_effect_creation.d.ts","sourceRoot":"","sources":["../../src/utils/tx_effect_creation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,0BAA0B,CAAC;AAC9C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAE/D,OAAO,EAAE,QAAQ,EAAU,MAAM,kBAAkB,CAAC;AAEpD,wBAAsB,YAAY,CAChC,SAAS,EAAE,kBAAkB,EAC7B,aAAa,EAAE,EAAE,EACjB,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,QAAQ,CAAC,CA2BnB"}
@@ -0,0 +1,16 @@
1
+ import { Fr } from '@aztec/foundation/fields';
2
+ import { computeNoteHashNonce, computeUniqueNoteHash, siloNoteHash } from '@aztec/stdlib/hash';
3
+ import { TxEffect, TxHash } from '@aztec/stdlib/tx';
4
+ export async function makeTxEffect(noteCache, txRequestHash, txBlockNumber) {
5
+ const txEffect = TxEffect.empty();
6
+ const { usedTxRequestHashForNonces } = noteCache.finish();
7
+ const nonceGenerator = usedTxRequestHashForNonces ? txRequestHash : noteCache.getAllNullifiers()[0];
8
+ txEffect.noteHashes = await Promise.all(noteCache.getAllNotes().map(async (pendingNote, i)=>computeUniqueNoteHash(await computeNoteHashNonce(nonceGenerator, i), await siloNoteHash(pendingNote.note.contractAddress, pendingNote.noteHashForConsumption))));
9
+ // Nullifiers are already siloed
10
+ txEffect.nullifiers = noteCache.getAllNullifiers();
11
+ if (usedTxRequestHashForNonces) {
12
+ txEffect.nullifiers.unshift(txRequestHash);
13
+ }
14
+ txEffect.txHash = new TxHash(new Fr(txBlockNumber));
15
+ return txEffect;
16
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aztec/txe",
3
- "version": "2.1.0-rc.9",
3
+ "version": "3.0.0-devnet.2",
4
4
  "type": "module",
5
5
  "exports": "./dest/index.js",
6
6
  "bin": "./dest/bin/index.js",
@@ -61,20 +61,20 @@
61
61
  ]
62
62
  },
63
63
  "dependencies": {
64
- "@aztec/accounts": "2.1.0-rc.9",
65
- "@aztec/archiver": "2.1.0-rc.9",
66
- "@aztec/aztec-node": "2.1.0-rc.9",
67
- "@aztec/aztec.js": "2.1.0-rc.9",
68
- "@aztec/bb-prover": "2.1.0-rc.9",
69
- "@aztec/constants": "2.1.0-rc.9",
70
- "@aztec/foundation": "2.1.0-rc.9",
71
- "@aztec/key-store": "2.1.0-rc.9",
72
- "@aztec/kv-store": "2.1.0-rc.9",
73
- "@aztec/protocol-contracts": "2.1.0-rc.9",
74
- "@aztec/pxe": "2.1.0-rc.9",
75
- "@aztec/simulator": "2.1.0-rc.9",
76
- "@aztec/stdlib": "2.1.0-rc.9",
77
- "@aztec/world-state": "2.1.0-rc.9",
64
+ "@aztec/accounts": "3.0.0-devnet.2",
65
+ "@aztec/archiver": "3.0.0-devnet.2",
66
+ "@aztec/aztec-node": "3.0.0-devnet.2",
67
+ "@aztec/aztec.js": "3.0.0-devnet.2",
68
+ "@aztec/bb-prover": "3.0.0-devnet.2",
69
+ "@aztec/constants": "3.0.0-devnet.2",
70
+ "@aztec/foundation": "3.0.0-devnet.2",
71
+ "@aztec/key-store": "3.0.0-devnet.2",
72
+ "@aztec/kv-store": "3.0.0-devnet.2",
73
+ "@aztec/protocol-contracts": "3.0.0-devnet.2",
74
+ "@aztec/pxe": "3.0.0-devnet.2",
75
+ "@aztec/simulator": "3.0.0-devnet.2",
76
+ "@aztec/stdlib": "3.0.0-devnet.2",
77
+ "@aztec/world-state": "3.0.0-devnet.2",
78
78
  "zod": "^3.23.8"
79
79
  },
80
80
  "devDependencies": {
package/src/bin/index.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env -S node --no-warnings
2
- import { createLogger } from '@aztec/aztec.js';
2
+ import { createLogger } from '@aztec/aztec.js/log';
3
3
  import { startHttpRpcServer } from '@aztec/foundation/json-rpc/server';
4
4
 
5
5
  import { createTXERpcServer } from '../index.js';
package/src/index.ts CHANGED
@@ -1,14 +1,12 @@
1
1
  import { SchnorrAccountContractArtifact } from '@aztec/accounts/schnorr';
2
+ import { type NoirCompiledContract, loadContractArtifact } from '@aztec/aztec.js/abi';
3
+ import { AztecAddress } from '@aztec/aztec.js/addresses';
2
4
  import {
3
- AztecAddress,
4
5
  type ContractInstanceWithAddress,
5
- Fr,
6
- type NoirCompiledContract,
7
- PublicKeys,
8
- deriveKeys,
9
6
  getContractInstanceFromInstantiationParams,
10
- loadContractArtifact,
11
- } from '@aztec/aztec.js';
7
+ } from '@aztec/aztec.js/contracts';
8
+ import { Fr } from '@aztec/aztec.js/fields';
9
+ import { PublicKeys, deriveKeys } from '@aztec/aztec.js/keys';
12
10
  import { createSafeJsonRpcServer } from '@aztec/foundation/json-rpc/server';
13
11
  import type { Logger } from '@aztec/foundation/log';
14
12
  import { type ProtocolContract, protocolContractNames } from '@aztec/protocol-contracts';
@@ -55,7 +53,6 @@ type TXEForeignCallInput = {
55
53
  inputs: ForeignCallArgs;
56
54
  };
57
55
 
58
- // TODO: why does the zod validation in the txe dispatcher not reject invalid function names?
59
56
  const TXEForeignCallInputSchema = z.object({
60
57
  // eslint-disable-next-line camelcase
61
58
  session_id: z.number().int().nonnegative(),