@ethernity-cloud/sdk-js 1.7.14 → 1.7.15
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/README.md +5 -0
- package/cas/config.js +12 -1
- package/nodenithy/run/etny-securelock-test.yaml.tpl +3 -0
- package/nodenithy/run.js +2 -1
- package/package.json +3 -2
- package/pynithy/run/etny-securelock-test.yaml.tpl +3 -0
- package/pynithy/run.js +2 -1
- package/run.js +9 -31
- package/runReport.js +45 -0
package/README.md
CHANGED
|
@@ -182,6 +182,11 @@ sets the enclave heap (default `1024M`).
|
|
|
182
182
|
`--network`/`--securelock`/`--trustedzone`; the signing key is `PRIVATE_KEY`
|
|
183
183
|
(or `ECLD_PRIVATE_KEY`) — a funded `0x` key that pays for the order. Resources
|
|
184
184
|
are tunable with `--task-price`/`--cpu`/`--memory`/`--storage`/`--bandwidth`/`--duration`/`--validators`.
|
|
185
|
+
`--input <file>` / `--input-text <string>` send the task's input dataset, read
|
|
186
|
+
as `___etny_data_set___`; it travels encrypted, and the trustedzone checks it
|
|
187
|
+
against the sha256 the request carries. Exit code 0 on a `SUCCESS` task result,
|
|
188
|
+
1 otherwise; a task that raised in the enclave prints its task code (e.g.
|
|
189
|
+
`4 (BASE_EXCEPTION)`) and the enclave's error report as its result.
|
|
185
190
|
`--ipfs intake` (the default) delivers the payload to the bootnode's payload
|
|
186
191
|
intake once the request is on chain; `--ipfs <url>` writes and reads through
|
|
187
192
|
that IPFS RPC API instead, with `ECLD_IPFS_TOKEN` (or `IPFS_TOKEN`) as its
|
package/cas/config.js
CHANGED
|
@@ -120,8 +120,19 @@ const renderCompose = (content, cas, unsafe) => content
|
|
|
120
120
|
.map((line) => line.replace(/\s*# __(?:CAS|NO_CAS|SAFE)_ONLY__$/, ''))
|
|
121
121
|
.join('\n');
|
|
122
122
|
|
|
123
|
+
// The securelock session's ESR environment entry. A CAS-provisioned enclave
|
|
124
|
+
// takes its environment from the session, not from the image's ENV, so the
|
|
125
|
+
// registry address the build baked must also be set here; without ESR (or
|
|
126
|
+
// without an address) the entry is a YAML comment.
|
|
127
|
+
const esrSessionEnvironment = (env) => {
|
|
128
|
+
const enabled = /^(1|true|yes)$/i.test(String(env.ESR_ENABLED || '').trim());
|
|
129
|
+
const address = String(env.ESR_CONTRACT_ADDRESS || '').trim();
|
|
130
|
+
if (!enabled || !/^0x[0-9a-fA-F]{40}$/.test(address)) return '# ESR not enabled';
|
|
131
|
+
return `ESR_CONTRACT_ADDRESS: "${address}"`;
|
|
132
|
+
};
|
|
133
|
+
|
|
123
134
|
module.exports = {
|
|
124
135
|
VALIDATOR_REGISTRY, SESSION_REGISTRY, CHAIN, casProvisioned, isMainnetNetwork,
|
|
125
136
|
UNSAFE_NETWORKS, isUnsafeNetwork, TESTNETS, isTestnetNetwork, sessionAttestation,
|
|
126
|
-
nameOnNetwork, sessionTag, renderCompose,
|
|
137
|
+
nameOnNetwork, sessionTag, renderCompose, esrSessionEnvironment,
|
|
127
138
|
};
|
|
@@ -20,6 +20,9 @@ services:
|
|
|
20
20
|
pwd: /
|
|
21
21
|
environment:
|
|
22
22
|
GREETING: hello from ETNY SECURELOCK!!!!
|
|
23
|
+
# A CAS-provisioned enclave takes its environment from this session,
|
|
24
|
+
# not from the image's ENV; run.js fills in the ESR registry address.
|
|
25
|
+
__ESR_ENVIRONMENT__
|
|
23
26
|
|
|
24
27
|
images:
|
|
25
28
|
- name: application_image
|
package/nodenithy/run.js
CHANGED
|
@@ -311,7 +311,8 @@ const main = async () => {
|
|
|
311
311
|
const replacementsSecurelock = {
|
|
312
312
|
PREDECESSOR: PREDECESSOR_HASH_SECURELOCK === 'EMPTY' ? `# predecessor: ${PREDECESSOR_HASH_SECURELOCK}` : `predecessor: ${PREDECESSOR_HASH_SECURELOCK}`,
|
|
313
313
|
MRENCLAVE: process.env.MRENCLAVE_SECURELOCK,
|
|
314
|
-
ENCLAVE_NAME: ENCLAVE_NAME_SECURELOCK
|
|
314
|
+
ENCLAVE_NAME: ENCLAVE_NAME_SECURELOCK,
|
|
315
|
+
ESR_ENVIRONMENT: casConfig.esrSessionEnvironment(process.env)
|
|
315
316
|
};
|
|
316
317
|
if (cas) {
|
|
317
318
|
processYamlTemplate('etny-securelock-test.yaml.tpl', 'etny-securelock-test.yaml', replacementsSecurelock);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ethernity-cloud/sdk-js",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.15",
|
|
4
4
|
"description": "A package to run ethernity cloud build scripts",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "node --test \"test/**/*.test.js\"",
|
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
"test.js",
|
|
33
33
|
"info.js",
|
|
34
34
|
"run.js",
|
|
35
|
+
"runReport.js",
|
|
35
36
|
"network.js",
|
|
36
37
|
"localKubo.js",
|
|
37
38
|
"revert.js",
|
|
@@ -39,7 +40,7 @@
|
|
|
39
40
|
"!**/*.pyc"
|
|
40
41
|
],
|
|
41
42
|
"dependencies": {
|
|
42
|
-
"@ethernity-cloud/runner": "^0.6.
|
|
43
|
+
"@ethernity-cloud/runner": "^0.6.11",
|
|
43
44
|
"acorn": "^8.11.0",
|
|
44
45
|
"adm-zip": "^0.5.14",
|
|
45
46
|
"axios": "^1.7.2",
|
|
@@ -24,6 +24,9 @@ services:
|
|
|
24
24
|
# libraries call os.path.expanduser('~') at startup and abort with
|
|
25
25
|
# "$HOME is not defined" before the enclave emits its public key.
|
|
26
26
|
HOME: /tmp
|
|
27
|
+
# A CAS-provisioned enclave takes its environment from this session,
|
|
28
|
+
# not from the image's ENV; run.js fills in the ESR registry address.
|
|
29
|
+
__ESR_ENVIRONMENT__
|
|
27
30
|
|
|
28
31
|
images:
|
|
29
32
|
- name: application_image
|
package/pynithy/run.js
CHANGED
|
@@ -309,7 +309,8 @@ const main = async () => {
|
|
|
309
309
|
const replacementsSecurelock = {
|
|
310
310
|
PREDECESSOR: PREDECESSOR_HASH_SECURELOCK === 'EMPTY' ? `# predecessor: ${PREDECESSOR_HASH_SECURELOCK}` : `predecessor: ${PREDECESSOR_HASH_SECURELOCK}`,
|
|
311
311
|
MRENCLAVE: process.env.MRENCLAVE_SECURELOCK,
|
|
312
|
-
ENCLAVE_NAME: ENCLAVE_NAME_SECURELOCK
|
|
312
|
+
ENCLAVE_NAME: ENCLAVE_NAME_SECURELOCK,
|
|
313
|
+
ESR_ENVIRONMENT: casConfig.esrSessionEnvironment(process.env)
|
|
313
314
|
};
|
|
314
315
|
if (cas) {
|
|
315
316
|
processYamlTemplate('etny-securelock-test.yaml.tpl', 'etny-securelock-test.yaml', replacementsSecurelock);
|
package/run.js
CHANGED
|
@@ -44,6 +44,7 @@ try { require('dotenv').config(); } catch (e) { /* dotenv optional */ }
|
|
|
44
44
|
const casConfig = require('./cas/config.js');
|
|
45
45
|
const { networkFor, unsafeVariant } = require('./network.js');
|
|
46
46
|
const { PUBLIC_IPFS_HOST } = require('./localKubo.js');
|
|
47
|
+
const { reportRun } = require('./runReport.js');
|
|
47
48
|
|
|
48
49
|
// `--ipfs intake` (the default): the artefacts' CIDs are computed locally and
|
|
49
50
|
// the bytes delivered to the bootnode's payload intake once the DO request is
|
|
@@ -116,20 +117,19 @@ async function main() {
|
|
|
116
117
|
let input = null;
|
|
117
118
|
if (opts.inputFile !== undefined) input = fs.readFileSync(opts.inputFile, 'utf8');
|
|
118
119
|
else if (opts.inputText !== undefined) input = opts.inputText;
|
|
119
|
-
// The
|
|
120
|
-
//
|
|
121
|
-
// ecld-run mirrors ecld-test: input is delivered via the payload call itself.
|
|
120
|
+
// The input is the task's input dataset (runner option inputData): sent
|
|
121
|
+
// sealed for the trustedzone and read in the payload as ___etny_data_set___.
|
|
122
122
|
|
|
123
123
|
// ---- runner (ESM) ----
|
|
124
|
-
let EthernityCloudRunner, ECStatus, ECEvent,
|
|
124
|
+
let EthernityCloudRunner, ECStatus, ECEvent, enums;
|
|
125
125
|
try {
|
|
126
126
|
const runnerMod = await import('@ethernity-cloud/runner');
|
|
127
127
|
EthernityCloudRunner = runnerMod.default || runnerMod.EthernityCloudRunner;
|
|
128
128
|
enums = await import('@ethernity-cloud/runner/enums.js');
|
|
129
|
-
({ ECStatus, ECEvent
|
|
129
|
+
({ ECStatus, ECEvent } = enums);
|
|
130
130
|
} catch (e) {
|
|
131
131
|
console.error('ecld-run: the runner package is not installed or is too old '
|
|
132
|
-
+ '(need @ethernity-cloud/runner >= 0.6.
|
|
132
|
+
+ '(need @ethernity-cloud/runner >= 0.6.11): ' + e.message);
|
|
133
133
|
process.exit(1);
|
|
134
134
|
}
|
|
135
135
|
|
|
@@ -228,10 +228,9 @@ async function main() {
|
|
|
228
228
|
const timeout = new Promise((resolve) => { timer = setTimeout(() => resolve('TIMEOUT'), timeoutMs); });
|
|
229
229
|
|
|
230
230
|
try {
|
|
231
|
-
const runArgs = [resources, securelock, code, opts.node];
|
|
232
|
-
if (trustedzone) runArgs.push(trustedzone);
|
|
233
231
|
// Fire the run; its own promise also settles on completion.
|
|
234
|
-
const runPromise = runner.run(
|
|
232
|
+
const runPromise = runner.run(resources, securelock, code, opts.node, trustedzone || null, { inputData: input })
|
|
233
|
+
.catch((e) => ({ error: e.message }));
|
|
235
234
|
const outcome = await Promise.race([done, timeout, runPromise]);
|
|
236
235
|
clearTimeout(timer);
|
|
237
236
|
|
|
@@ -239,28 +238,7 @@ async function main() {
|
|
|
239
238
|
console.error(`\necld-run: no result after ${opts.timeout}s; the order may still process on-chain.`);
|
|
240
239
|
process.exit(1);
|
|
241
240
|
}
|
|
242
|
-
|
|
243
|
-
console.error(`\nstatus : ERROR`);
|
|
244
|
-
console.error(`error : ${outcome.error}`);
|
|
245
|
-
process.exit(1);
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
// SUCCESS
|
|
249
|
-
const result = await runner.getResult();
|
|
250
|
-
const typed = (runner.getStructuredResult && runner.getStructuredResult()) || null;
|
|
251
|
-
const taskCode = runner.resultTaskCode;
|
|
252
|
-
const taskName = runner.resultTaskCodeName
|
|
253
|
-
|| (ECOrderTaskStatus && taskCode !== undefined ? ECOrderTaskStatus[taskCode] : undefined);
|
|
254
|
-
|
|
255
|
-
if (opts.json) {
|
|
256
|
-
console.log(JSON.stringify({ task_code: taskCode, task_code_name: taskName, value: result, structured: typed }, null, 2));
|
|
257
|
-
} else {
|
|
258
|
-
if (taskName && taskName !== 'SUCCESS') console.log(`task code : ${taskCode} (${taskName})`);
|
|
259
|
-
console.log('result :');
|
|
260
|
-
console.log(result);
|
|
261
|
-
}
|
|
262
|
-
// A non-zero enclave task code is a failed run even though the order landed.
|
|
263
|
-
process.exit(taskCode === undefined || taskCode === 0 ? 0 : 1);
|
|
241
|
+
process.exit(await reportRun(runner, outcome, { json: opts.json }));
|
|
264
242
|
} catch (e) {
|
|
265
243
|
clearTimeout(timer);
|
|
266
244
|
console.error('ecld-run: run failed: ' + (e && e.stack ? e.stack : e));
|
package/runReport.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/* ecld-run's report of a finished run.
|
|
4
|
+
*
|
|
5
|
+
* A run that delivered a result prints it; a task the enclave reported with a
|
|
6
|
+
* non-zero task code (an exception in the dApp, a checksum mismatch, ...)
|
|
7
|
+
* prints that code and its result, which is the enclave's error report. The
|
|
8
|
+
* runner signals such a task with its ERROR event, carrying getLastError().
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Print the outcome of a run and return the exit code.
|
|
13
|
+
* outcome: 'SUCCESS', or { error } from the ERROR event or a rejected run().
|
|
14
|
+
*/
|
|
15
|
+
async function reportRun(runner, outcome, { json = false, out = console.log, err = console.error } = {}) {
|
|
16
|
+
// { code, name } of the enclave's task code, or null when no result came.
|
|
17
|
+
const taskCode = runner.getResultTaskCode();
|
|
18
|
+
const error = outcome && outcome.error;
|
|
19
|
+
if (!taskCode && error) {
|
|
20
|
+
err('\nstatus : ERROR');
|
|
21
|
+
err(`error : ${error}`);
|
|
22
|
+
return 1;
|
|
23
|
+
}
|
|
24
|
+
const result = await runner.getResult();
|
|
25
|
+
const typed = (runner.getStructuredResult && runner.getStructuredResult()) || null;
|
|
26
|
+
if (json) {
|
|
27
|
+
out(JSON.stringify({
|
|
28
|
+
task_code: taskCode ? taskCode.code : undefined,
|
|
29
|
+
task_code_name: taskCode ? taskCode.name : undefined,
|
|
30
|
+
value: result,
|
|
31
|
+
structured: typed,
|
|
32
|
+
}, null, 2));
|
|
33
|
+
} else {
|
|
34
|
+
if (taskCode && taskCode.code !== 0) out(`task code : ${taskCode.code} (${taskCode.name})`);
|
|
35
|
+
out('result :');
|
|
36
|
+
out(result);
|
|
37
|
+
}
|
|
38
|
+
if (taskCode && taskCode.code !== 0) {
|
|
39
|
+
err(`error : ${runner.getLastError() || error || taskCode.name}`);
|
|
40
|
+
return 1;
|
|
41
|
+
}
|
|
42
|
+
return error ? 1 : 0;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
module.exports = { reportRun };
|