@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.
- package/dest/bin/index.js +3 -5
- package/dest/index.js +112 -64
- package/dest/node/txe_node.js +292 -338
- package/dest/oracle/txe_oracle.js +208 -147
- package/dest/txe_service/txe_service.js +194 -118
- package/dest/util/encoding.js +16 -7
- package/dest/util/expected_failure_error.js +1 -2
- package/dest/util/txe_database.js +5 -9
- package/dest/util/txe_public_contract_data_source.js +21 -12
- package/dest/util/txe_world_state_db.js +7 -8
- package/package.json +14 -15
- package/src/index.ts +109 -35
- package/src/node/txe_node.ts +4 -0
- package/src/oracle/txe_oracle.ts +8 -29
- package/src/txe_service/txe_service.ts +14 -46
- package/src/util/encoding.ts +3 -3
- package/dest/bin/index.d.ts +0 -3
- package/dest/bin/index.d.ts.map +0 -1
- package/dest/index.d.ts +0 -8
- package/dest/index.d.ts.map +0 -1
- package/dest/node/txe_node.d.ts +0 -354
- package/dest/node/txe_node.d.ts.map +0 -1
- package/dest/oracle/txe_oracle.d.ts +0 -132
- package/dest/oracle/txe_oracle.d.ts.map +0 -1
- package/dest/txe_service/txe_service.d.ts +0 -204
- package/dest/txe_service/txe_service.d.ts.map +0 -1
- package/dest/util/encoding.d.ts +0 -29
- package/dest/util/encoding.d.ts.map +0 -1
- package/dest/util/expected_failure_error.d.ts +0 -4
- package/dest/util/expected_failure_error.d.ts.map +0 -1
- package/dest/util/txe_database.d.ts +0 -10
- package/dest/util/txe_database.d.ts.map +0 -1
- package/dest/util/txe_public_contract_data_source.d.ts +0 -18
- package/dest/util/txe_public_contract_data_source.d.ts.map +0 -1
- package/dest/util/txe_world_state_db.d.ts +0 -16
- 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
|
-
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
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,
|
|
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
|
-
|
|
23
|
-
|
|
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
|
|
35
|
-
case 'reset':
|
|
36
|
-
|
|
37
|
-
this.logger.debug(`Called reset on session ${sessionId}, yeeting it out of existence`);
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
case 'deploy':
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
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
|
-
|
|
97
|
-
|
|
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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
|