@aztec/txe 0.74.0 → 0.75.0-commit.c03ba01a2a4122e43e90d5133ba017e54b90e9d2

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 (36) hide show
  1. package/dest/bin/index.js +3 -5
  2. package/dest/index.js +112 -64
  3. package/dest/node/txe_node.js +292 -338
  4. package/dest/oracle/txe_oracle.js +208 -147
  5. package/dest/txe_service/txe_service.js +194 -118
  6. package/dest/util/encoding.js +16 -7
  7. package/dest/util/expected_failure_error.js +1 -2
  8. package/dest/util/txe_database.js +5 -9
  9. package/dest/util/txe_public_contract_data_source.js +21 -12
  10. package/dest/util/txe_world_state_db.js +7 -8
  11. package/package.json +14 -15
  12. package/src/index.ts +109 -35
  13. package/src/node/txe_node.ts +4 -0
  14. package/src/oracle/txe_oracle.ts +8 -29
  15. package/src/txe_service/txe_service.ts +14 -46
  16. package/src/util/encoding.ts +3 -3
  17. package/dest/bin/index.d.ts +0 -3
  18. package/dest/bin/index.d.ts.map +0 -1
  19. package/dest/index.d.ts +0 -8
  20. package/dest/index.d.ts.map +0 -1
  21. package/dest/node/txe_node.d.ts +0 -354
  22. package/dest/node/txe_node.d.ts.map +0 -1
  23. package/dest/oracle/txe_oracle.d.ts +0 -132
  24. package/dest/oracle/txe_oracle.d.ts.map +0 -1
  25. package/dest/txe_service/txe_service.d.ts +0 -204
  26. package/dest/txe_service/txe_service.d.ts.map +0 -1
  27. package/dest/util/encoding.d.ts +0 -29
  28. package/dest/util/encoding.d.ts.map +0 -1
  29. package/dest/util/expected_failure_error.d.ts +0 -4
  30. package/dest/util/expected_failure_error.d.ts.map +0 -1
  31. package/dest/util/txe_database.d.ts +0 -10
  32. package/dest/util/txe_database.d.ts.map +0 -1
  33. package/dest/util/txe_public_contract_data_source.d.ts +0 -18
  34. package/dest/util/txe_public_contract_data_source.d.ts.map +0 -1
  35. package/dest/util/txe_world_state_db.d.ts +0 -16
  36. package/dest/util/txe_world_state_db.d.ts.map +0 -1
package/dest/bin/index.js CHANGED
@@ -4,21 +4,19 @@ import { startHttpRpcServer } from '@aztec/foundation/json-rpc/server';
4
4
  import { createTXERpcServer } from '../index.js';
5
5
  /**
6
6
  * Create and start a new TXE HTTP Server
7
- */
8
- async function main() {
7
+ */ async function main() {
9
8
  const { TXE_PORT = 8080 } = process.env;
10
9
  const logger = createLogger('txe:service');
11
10
  logger.info(`Setting up TXE...`);
12
11
  const txeServer = createTXERpcServer(logger);
13
12
  const { port } = await startHttpRpcServer(txeServer, {
14
13
  port: TXE_PORT,
15
- timeoutMs: 1e3 * 60 * 5,
14
+ timeoutMs: 1e3 * 60 * 5
16
15
  });
17
16
  logger.info(`TXE listening on port ${port}`);
18
17
  }
19
- main().catch(err => {
18
+ main().catch((err)=>{
20
19
  // eslint-disable-next-line no-console
21
20
  console.error(err);
22
21
  process.exit(1);
23
22
  });
24
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvYmluL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFDQSxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDL0MsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sbUNBQW1DLENBQUM7QUFFdkUsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sYUFBYSxDQUFDO0FBRWpEOztHQUVHO0FBQ0gsS0FBSyxVQUFVLElBQUk7SUFDakIsTUFBTSxFQUFFLFFBQVEsR0FBRyxJQUFJLEVBQUUsR0FBRyxPQUFPLENBQUMsR0FBRyxDQUFDO0lBRXhDLE1BQU0sTUFBTSxHQUFHLFlBQVksQ0FBQyxhQUFhLENBQUMsQ0FBQztJQUMzQyxNQUFNLENBQUMsSUFBSSxDQUFDLG1CQUFtQixDQUFDLENBQUM7SUFFakMsTUFBTSxTQUFTLEdBQUcsa0JBQWtCLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDN0MsTUFBTSxFQUFFLElBQUksRUFBRSxHQUFHLE1BQU0sa0JBQWtCLENBQUMsU0FBUyxFQUFFO1FBQ25ELElBQUksRUFBRSxRQUFRO1FBQ2QsU0FBUyxFQUFFLEdBQUcsR0FBRyxFQUFFLEdBQUcsQ0FBQztLQUN4QixDQUFDLENBQUM7SUFFSCxNQUFNLENBQUMsSUFBSSxDQUFDLHlCQUF5QixJQUFJLEVBQUUsQ0FBQyxDQUFDO0FBQy9DLENBQUM7QUFFRCxJQUFJLEVBQUUsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLEVBQUU7SUFDakIsc0NBQXNDO0lBQ3RDLE9BQU8sQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDbkIsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUNsQixDQUFDLENBQUMsQ0FBQyJ9
package/dest/index.js CHANGED
@@ -1,13 +1,13 @@
1
- var _TXEDispatcher_instances, _TXEDispatcher_processDeployInputs;
2
- import { __classPrivateFieldGet } from "tslib";
3
- import { loadContractArtifact } from '@aztec/aztec.js';
4
- import { createTracedJsonRpcServer } from '@aztec/telemetry-client';
1
+ import { SchnorrAccountContractArtifact } from '@aztec/accounts/schnorr';
2
+ import { AztecAddress, Fr, PublicKeys, deriveKeys, getContractInstanceFromDeployParams, loadContractArtifact } from '@aztec/aztec.js';
3
+ import { createSafeJsonRpcServer } from '@aztec/foundation/json-rpc/server';
5
4
  import { readFile, readdir } from 'fs/promises';
6
5
  import { join } from 'path';
7
6
  import { z } from 'zod';
8
7
  import { TXEService } from './txe_service/txe_service.js';
9
- import { ForeignCallArgsSchema, ForeignCallResultSchema, fromArray, toForeignCallResult, } from './util/encoding.js';
8
+ import { ForeignCallArgsSchema, ForeignCallResultSchema, fromArray, fromSingle, toForeignCallResult } from './util/encoding.js';
10
9
  const TXESessions = new Map();
10
+ const TXEArtifactsCache = new Map();
11
11
  const TXEForeignCallInputSchema = z.object({
12
12
  // eslint-disable-next-line camelcase
13
13
  session_id: z.number(),
@@ -16,13 +16,94 @@ const TXEForeignCallInputSchema = z.object({
16
16
  root_path: z.string(),
17
17
  // eslint-disable-next-line camelcase
18
18
  package_name: z.string(),
19
- inputs: ForeignCallArgsSchema,
19
+ inputs: ForeignCallArgsSchema
20
20
  });
21
21
  class TXEDispatcher {
22
- constructor(logger) {
23
- _TXEDispatcher_instances.add(this);
22
+ logger;
23
+ constructor(logger){
24
24
  this.logger = logger;
25
25
  }
26
+ async #processDeployInputs({ inputs, root_path: rootPath, package_name: packageName }) {
27
+ const [pathStr, contractName, initializer] = inputs.slice(0, 3).map((input)=>fromArray(input).map((char)=>String.fromCharCode(char.toNumber())).join(''));
28
+ const decodedArgs = fromArray(inputs[4]);
29
+ const publicKeysHashFr = fromSingle(inputs[5]);
30
+ const cacheKey = `${pathStr}-${contractName}-${initializer}-${decodedArgs.map((arg)=>arg.toString()).join('-')}-${publicKeysHashFr}`;
31
+ let artifact;
32
+ let instance;
33
+ if (TXEArtifactsCache.has(cacheKey)) {
34
+ this.logger.debug(`Using cached artifact for ${cacheKey}`);
35
+ ({ artifact, instance } = TXEArtifactsCache.get(cacheKey));
36
+ } else {
37
+ let artifactPath = '';
38
+ // We're deploying the contract under test
39
+ // env.deploy_self("contractName")
40
+ if (!pathStr) {
41
+ artifactPath = join(rootPath, './target', `${packageName}-${contractName}.json`);
42
+ } else {
43
+ // We're deploying a contract that belongs in a workspace
44
+ // env.deploy("../path/to/workspace/root@packageName", "contractName")
45
+ if (pathStr.includes('@')) {
46
+ const [workspace, pkg] = pathStr.split('@');
47
+ const targetPath = join(rootPath, workspace, './target');
48
+ this.logger.debug(`Looking for compiled artifact in workspace ${targetPath}`);
49
+ artifactPath = join(targetPath, `${pkg}-${contractName}.json`);
50
+ } else {
51
+ // We're deploying a standalone contract
52
+ // env.deploy("../path/to/contract/root", "contractName")
53
+ const targetPath = join(rootPath, pathStr, './target');
54
+ this.logger.debug(`Looking for compiled artifact in ${targetPath}`);
55
+ [artifactPath] = (await readdir(targetPath)).filter((file)=>file.endsWith(`-${contractName}.json`));
56
+ }
57
+ }
58
+ this.logger.debug(`Loading compiled artifact ${artifactPath}`);
59
+ artifact = loadContractArtifact(JSON.parse(await readFile(artifactPath, 'utf-8')));
60
+ this.logger.debug(`Deploy ${artifact.name} with initializer ${initializer}(${decodedArgs}) and public keys hash ${publicKeysHashFr}`);
61
+ instance = await getContractInstanceFromDeployParams(artifact, {
62
+ constructorArgs: decodedArgs,
63
+ skipArgsDecoding: true,
64
+ salt: Fr.ONE,
65
+ // TODO: Modify this to allow for passing public keys.
66
+ publicKeys: PublicKeys.default(),
67
+ constructorArtifact: initializer ? initializer : undefined,
68
+ deployer: AztecAddress.ZERO
69
+ });
70
+ TXEArtifactsCache.set(cacheKey, {
71
+ artifact,
72
+ instance
73
+ });
74
+ }
75
+ inputs.splice(0, 2, artifact, instance);
76
+ }
77
+ async #processAddAccountInputs({ inputs }) {
78
+ const secret = fromSingle(inputs[0]);
79
+ const cacheKey = `SchnorrAccountContract-${secret}`;
80
+ let artifact;
81
+ let instance;
82
+ if (TXEArtifactsCache.has(cacheKey)) {
83
+ this.logger.debug(`Using cached artifact for ${cacheKey}`);
84
+ ({ artifact, instance } = TXEArtifactsCache.get(cacheKey));
85
+ } else {
86
+ const keys = await deriveKeys(secret);
87
+ const args = [
88
+ keys.publicKeys.masterIncomingViewingPublicKey.x,
89
+ keys.publicKeys.masterIncomingViewingPublicKey.y
90
+ ];
91
+ artifact = SchnorrAccountContractArtifact;
92
+ instance = await getContractInstanceFromDeployParams(artifact, {
93
+ constructorArgs: args,
94
+ skipArgsDecoding: true,
95
+ salt: Fr.ONE,
96
+ publicKeys: keys.publicKeys,
97
+ constructorArtifact: 'constructor',
98
+ deployer: AztecAddress.ZERO
99
+ });
100
+ TXEArtifactsCache.set(cacheKey, {
101
+ artifact,
102
+ instance
103
+ });
104
+ }
105
+ inputs.splice(0, 0, artifact, instance);
106
+ }
26
107
  // eslint-disable-next-line camelcase
27
108
  async resolve_foreign_call(callData) {
28
109
  const { session_id: sessionId, function: functionName, inputs } = callData;
@@ -31,71 +112,38 @@ class TXEDispatcher {
31
112
  this.logger.debug(`Creating new session ${sessionId}`);
32
113
  TXESessions.set(sessionId, await TXEService.init(this.logger));
33
114
  }
34
- switch (functionName) {
35
- case 'reset': {
36
- TXESessions.delete(sessionId) &&
37
- this.logger.debug(`Called reset on session ${sessionId}, yeeting it out of existence`);
38
- return toForeignCallResult([]);
39
- }
40
- case 'deploy': {
41
- // Modify inputs and fall through
42
- await __classPrivateFieldGet(this, _TXEDispatcher_instances, "m", _TXEDispatcher_processDeployInputs).call(this, callData);
43
- }
44
- // eslint-disable-next-line no-fallthrough
45
- default: {
46
- const txeService = TXESessions.get(sessionId);
47
- const response = await txeService[functionName](...inputs);
48
- return response;
49
- }
115
+ switch(functionName){
116
+ case 'reset':
117
+ {
118
+ TXESessions.delete(sessionId) && this.logger.debug(`Called reset on session ${sessionId}, yeeting it out of existence`);
119
+ return toForeignCallResult([]);
120
+ }
121
+ case 'deploy':
122
+ {
123
+ await this.#processDeployInputs(callData);
124
+ break;
125
+ }
126
+ case 'addAccount':
127
+ {
128
+ await this.#processAddAccountInputs(callData);
129
+ break;
130
+ }
50
131
  }
132
+ const txeService = TXESessions.get(sessionId);
133
+ const response = await txeService[functionName](...inputs);
134
+ return response;
51
135
  }
52
136
  }
53
- _TXEDispatcher_instances = new WeakSet(), _TXEDispatcher_processDeployInputs = async function _TXEDispatcher_processDeployInputs({ inputs, root_path: rootPath, package_name: packageName }) {
54
- const pathStr = fromArray(inputs[0])
55
- .map(char => String.fromCharCode(char.toNumber()))
56
- .join('');
57
- const contractName = fromArray(inputs[1])
58
- .map(char => String.fromCharCode(char.toNumber()))
59
- .join('');
60
- let artifactPath = '';
61
- // We're deploying the contract under test
62
- // env.deploy_self("contractName")
63
- if (!pathStr) {
64
- artifactPath = join(rootPath, './target', `${packageName}-${contractName}.json`);
65
- }
66
- else {
67
- // We're deploying a contract that belongs in a workspace
68
- // env.deploy("../path/to/workspace/root@packageName", "contractName")
69
- if (pathStr.includes('@')) {
70
- const [workspace, pkg] = pathStr.split('@');
71
- const targetPath = join(rootPath, workspace, './target');
72
- this.logger.debug(`Looking for compiled artifact in workspace ${targetPath}`);
73
- artifactPath = join(targetPath, `${pkg}-${contractName}.json`);
74
- }
75
- else {
76
- // We're deploying a standalone contract
77
- // env.deploy("../path/to/contract/root", "contractName")
78
- const targetPath = join(rootPath, pathStr, './target');
79
- this.logger.debug(`Looking for compiled artifact in ${targetPath}`);
80
- [artifactPath] = (await readdir(targetPath)).filter(file => file.endsWith(`-${contractName}.json`));
81
- }
82
- }
83
- this.logger.debug(`Loading compiled artifact ${artifactPath}`);
84
- const artifact = loadContractArtifact(JSON.parse(await readFile(artifactPath, 'utf-8')));
85
- inputs.splice(0, 2, artifact);
86
- };
87
137
  const TXEDispatcherApiSchema = {
88
138
  // eslint-disable-next-line camelcase
89
- resolve_foreign_call: z.function().args(TXEForeignCallInputSchema).returns(ForeignCallResultSchema),
139
+ resolve_foreign_call: z.function().args(TXEForeignCallInputSchema).returns(ForeignCallResultSchema)
90
140
  };
91
141
  /**
92
142
  * Creates an RPC server that forwards calls to the TXE.
93
143
  * @param logger - Logger to output to
94
144
  * @returns A TXE RPC server.
95
- */
96
- export function createTXERpcServer(logger) {
97
- return createTracedJsonRpcServer(new TXEDispatcher(logger), TXEDispatcherApiSchema, {
98
- http200OnError: true,
145
+ */ export function createTXERpcServer(logger) {
146
+ return createSafeJsonRpcServer(new TXEDispatcher(logger), TXEDispatcherApiSchema, {
147
+ http200OnError: true
99
148
  });
100
149
  }
101
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUd2RCxPQUFPLEVBQUUseUJBQXlCLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUVwRSxPQUFPLEVBQUUsUUFBUSxFQUFFLE9BQU8sRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUNoRCxPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQzVCLE9BQU8sRUFBRSxDQUFDLEVBQUUsTUFBTSxLQUFLLENBQUM7QUFFeEIsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLDhCQUE4QixDQUFDO0FBQzFELE9BQU8sRUFFTCxxQkFBcUIsRUFHckIsdUJBQXVCLEVBQ3ZCLFNBQVMsRUFDVCxtQkFBbUIsR0FDcEIsTUFBTSxvQkFBb0IsQ0FBQztBQUU1QixNQUFNLFdBQVcsR0FBRyxJQUFJLEdBQUcsRUFBc0IsQ0FBQztBQWNsRCxNQUFNLHlCQUF5QixHQUFHLENBQUMsQ0FBQyxNQUFNLENBQUM7SUFDekMscUNBQXFDO0lBQ3JDLFVBQVUsRUFBRSxDQUFDLENBQUMsTUFBTSxFQUFFO0lBQ3RCLFFBQVEsRUFBRSxDQUFDLENBQUMsTUFBTSxFQUErQztJQUNqRSxxQ0FBcUM7SUFDckMsU0FBUyxFQUFFLENBQUMsQ0FBQyxNQUFNLEVBQUU7SUFDckIscUNBQXFDO0lBQ3JDLFlBQVksRUFBRSxDQUFDLENBQUMsTUFBTSxFQUFFO0lBQ3hCLE1BQU0sRUFBRSxxQkFBcUI7Q0FDOUIsQ0FBdUMsQ0FBQztBQUV6QyxNQUFNLGFBQWE7SUFDakIsWUFBb0IsTUFBYzs7UUFBZCxXQUFNLEdBQU4sTUFBTSxDQUFRO0lBQUcsQ0FBQztJQW1DdEMscUNBQXFDO0lBQ3JDLEtBQUssQ0FBQyxvQkFBb0IsQ0FBQyxRQUE2QjtRQUN0RCxNQUFNLEVBQUUsVUFBVSxFQUFF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