@ethernity-cloud/sdk-js 1.5.1 → 1.5.4
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/nodenithy/build/securelock/src/ecld_state.js +43 -3
- package/nodenithy/build/securelock/src/etny_exec.js +19 -14
- package/nodenithy/build/securelock/src/task_status.js +2 -0
- package/nodenithy/build/trustedzone/src/etny_exec.js +19 -14
- package/nodenithy/build/validator/src/etny_exec.js +19 -14
- package/nodenithy/run/image_registry.js +371 -371
- package/package.json +50 -50
- package/pynithy/run/image_registry.js +371 -371
|
@@ -60,6 +60,7 @@ function configure({ identityPriv, swiftStreamService, bucket, contractAddress,
|
|
|
60
60
|
_bucket = bucket;
|
|
61
61
|
_contractAddress = contractAddress;
|
|
62
62
|
_provider = provider;
|
|
63
|
+
_esrLedger = [];
|
|
63
64
|
}
|
|
64
65
|
|
|
65
66
|
function keccak256(buf) {
|
|
@@ -157,11 +158,20 @@ function keyHash(key) {
|
|
|
157
158
|
|
|
158
159
|
const ESR_ABI = [
|
|
159
160
|
'function commit(bytes32 key, string newCID, uint256 expectedVersion)',
|
|
161
|
+
'function commitFor(address enclave, bytes32 key, string newCID, uint256 expectedVersion, uint256 relayNonce, bytes signature)',
|
|
162
|
+
'function commitDigest(address enclave, bytes32 key, string newCID, uint256 expectedVersion, uint256 relayNonce) view returns (bytes32)',
|
|
163
|
+
'function relayNonce(address enclave) view returns (uint256)',
|
|
160
164
|
'function getState(address enclave, bytes32 key) view returns (string cid, uint256 version, uint64 updatedAt)',
|
|
161
165
|
'function getVersion(address enclave, bytes32 key) view returns (uint256)',
|
|
162
166
|
'function exists(address enclave, bytes32 key) view returns (bool)'
|
|
163
167
|
];
|
|
164
168
|
|
|
169
|
+
// Order-wide ledger of signed authorizations. ESR commits do NOT pay their own
|
|
170
|
+
// gas (see contracts/esr/RELAY-DESIGN.md): the enclave only SIGNS each commit
|
|
171
|
+
// (commitFor); the NODE relays it and pays, and does all gas accounting. The
|
|
172
|
+
// securelock does no gas math -- nothing it could claim about cost is trusted.
|
|
173
|
+
let _esrLedger = [];
|
|
174
|
+
|
|
165
175
|
class StateRegistry {
|
|
166
176
|
constructor() {
|
|
167
177
|
if (!_contractAddress) {
|
|
@@ -290,9 +300,39 @@ class StateRegistry {
|
|
|
290
300
|
}
|
|
291
301
|
|
|
292
302
|
async _sendCommit(keyHashHex, cid, expectedVersion) {
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
303
|
+
// The enclave never pays gas and does NO gas math: it SIGNS the commit
|
|
304
|
+
// (commitFor) and stages the signed authorization for the node, which
|
|
305
|
+
// relays it and pays. The trustedzone independently re-prices the whole
|
|
306
|
+
// ledger and adjudicates. Nothing the securelock could claim about cost is
|
|
307
|
+
// trusted, so it claims nothing.
|
|
308
|
+
const signer = this._signer();
|
|
309
|
+
const enclave = await signer.getAddress();
|
|
310
|
+
const contract = this._contract();
|
|
311
|
+
|
|
312
|
+
const relayNonce = await contract.relayNonce(enclave);
|
|
313
|
+
const digest = await contract.commitDigest(
|
|
314
|
+
enclave, keyHashHex, cid, expectedVersion, relayNonce);
|
|
315
|
+
// Sign the raw 32-byte digest as an eth_sign message (matches the
|
|
316
|
+
// contract's "\x19Ethereum Signed Message:\n32" recovery).
|
|
317
|
+
const signature = await signer.signMessage(ethers.utils.arrayify(digest));
|
|
318
|
+
|
|
319
|
+
const auth = {
|
|
320
|
+
enclave,
|
|
321
|
+
keyHash: keyHashHex,
|
|
322
|
+
cid,
|
|
323
|
+
expectedVersion: Number(expectedVersion),
|
|
324
|
+
relayNonce: Number(relayNonce),
|
|
325
|
+
signature
|
|
326
|
+
};
|
|
327
|
+
|
|
328
|
+
_esrLedger.push(auth);
|
|
329
|
+
await _swift.putFileContent(
|
|
330
|
+
_bucket, 'esr.authorizations.json', '',
|
|
331
|
+
Buffer.from(JSON.stringify(_esrLedger), 'utf8'));
|
|
332
|
+
await _swift.putFileContent(
|
|
333
|
+
_bucket, `esr.commit.${Number(relayNonce)}.json`, '',
|
|
334
|
+
Buffer.from(JSON.stringify(auth), 'utf8'));
|
|
335
|
+
return { relayed: true, relayNonce: Number(relayNonce) };
|
|
296
336
|
}
|
|
297
337
|
}
|
|
298
338
|
|
|
@@ -88,24 +88,29 @@ function exec(payload, input, globals = null) {
|
|
|
88
88
|
|
|
89
89
|
// return [TaskStatus.SUCCESS, 'TASK EXECUTED SUCCESSFULLY'];
|
|
90
90
|
} catch (error) {
|
|
91
|
+
// A task returns its result by RETURNING (via ___etny_result___), not by
|
|
92
|
+
// throwing, so anything caught here is a genuine failure. In every branch
|
|
93
|
+
// deliver the FULL stack trace to the data owner AS THE RESULT (visible in
|
|
94
|
+
// their runner output) and never crash the enclave -- always return a
|
|
95
|
+
// normal [code, data] tuple so the trustedzone stops waiting. Honor the
|
|
96
|
+
// embedded-result SUCCESS (code 0) case first.
|
|
97
|
+
try {
|
|
98
|
+
if (error && error.args && error.args[0] && error.args[0][0] === 0) {
|
|
99
|
+
return [TaskStatus.SUCCESS, error.args[0][1]];
|
|
100
|
+
}
|
|
101
|
+
} catch (e) { /* fall through to failure reporting */ }
|
|
102
|
+
|
|
103
|
+
const detail = (error && (error.stack || error.message)) || String(error);
|
|
104
|
+
console.error('Error in payload execution -- full stack follows:\n' + detail);
|
|
105
|
+
|
|
91
106
|
if (error instanceof ReferenceError) {
|
|
92
|
-
return [TaskStatus.SYSTEM_ERROR,
|
|
107
|
+
return [TaskStatus.SYSTEM_ERROR, 'SYSTEM_ERROR (ReferenceError): ' + detail];
|
|
93
108
|
} else if (error instanceof EvalError) {
|
|
94
|
-
return [TaskStatus.KEY_ERROR,
|
|
109
|
+
return [TaskStatus.KEY_ERROR, 'KEY_ERROR (EvalError): ' + detail];
|
|
95
110
|
} else if (error instanceof SyntaxError) {
|
|
96
|
-
return [TaskStatus.SYNTAX_WARNING,
|
|
97
|
-
} else if (error instanceof Error) {
|
|
98
|
-
try {
|
|
99
|
-
if (error.args[0][0] === 0) {
|
|
100
|
-
return [TaskStatus.SUCCESS, error.args[0][1]];
|
|
101
|
-
} else {
|
|
102
|
-
return [TaskStatus.BASE_EXCEPTION, error.args[0]];
|
|
103
|
-
}
|
|
104
|
-
} catch (e) {
|
|
105
|
-
return [TaskStatus.BASE_EXCEPTION, error.message];
|
|
106
|
-
}
|
|
111
|
+
return [TaskStatus.SYNTAX_WARNING, 'SYNTAX_WARNING (SyntaxError): ' + detail];
|
|
107
112
|
} else {
|
|
108
|
-
return [TaskStatus.BASE_EXCEPTION,
|
|
113
|
+
return [TaskStatus.BASE_EXCEPTION, 'BASE_EXCEPTION: ' + detail];
|
|
109
114
|
}
|
|
110
115
|
}
|
|
111
116
|
}
|
|
@@ -15,6 +15,8 @@ class TaskStatus {
|
|
|
15
15
|
// address that was never baked into the sealed image). Reported eagerly
|
|
16
16
|
// with the variable named, instead of a confusing downstream crash.
|
|
17
17
|
static CONFIG_ERROR = 32;
|
|
18
|
+
static EXECUTION_TIMEOUT = 33; // Started but produced no result within the order duration.
|
|
19
|
+
static ESR_GAS_LIMIT_EXCEEDED = 34; // ESR commits would exceed the per-order relayed-gas budget.
|
|
18
20
|
}
|
|
19
21
|
|
|
20
22
|
module.exports = {
|
|
@@ -27,24 +27,29 @@ function exec(payload, input, globals = null) {
|
|
|
27
27
|
|
|
28
28
|
// return [TaskStatus.SUCCESS, 'TASK EXECUTED SUCCESSFULLY'];
|
|
29
29
|
} catch (error) {
|
|
30
|
+
// A task returns its result by RETURNING (via ___etny_result___), not by
|
|
31
|
+
// throwing, so anything caught here is a genuine failure. In every branch
|
|
32
|
+
// deliver the FULL stack trace to the data owner AS THE RESULT (visible in
|
|
33
|
+
// their runner output) and never crash the enclave -- always return a
|
|
34
|
+
// normal [code, data] tuple so the trustedzone stops waiting. Honor the
|
|
35
|
+
// embedded-result SUCCESS (code 0) case first.
|
|
36
|
+
try {
|
|
37
|
+
if (error && error.args && error.args[0] && error.args[0][0] === 0) {
|
|
38
|
+
return [TaskStatus.SUCCESS, error.args[0][1]];
|
|
39
|
+
}
|
|
40
|
+
} catch (e) { /* fall through to failure reporting */ }
|
|
41
|
+
|
|
42
|
+
const detail = (error && (error.stack || error.message)) || String(error);
|
|
43
|
+
console.error('Error in payload execution -- full stack follows:\n' + detail);
|
|
44
|
+
|
|
30
45
|
if (error instanceof ReferenceError) {
|
|
31
|
-
return [TaskStatus.SYSTEM_ERROR,
|
|
46
|
+
return [TaskStatus.SYSTEM_ERROR, 'SYSTEM_ERROR (ReferenceError): ' + detail];
|
|
32
47
|
} else if (error instanceof EvalError) {
|
|
33
|
-
return [TaskStatus.KEY_ERROR,
|
|
48
|
+
return [TaskStatus.KEY_ERROR, 'KEY_ERROR (EvalError): ' + detail];
|
|
34
49
|
} else if (error instanceof SyntaxError) {
|
|
35
|
-
return [TaskStatus.SYNTAX_WARNING,
|
|
36
|
-
} else if (error instanceof Error) {
|
|
37
|
-
try {
|
|
38
|
-
if (error.args[0][0] === 0) {
|
|
39
|
-
return [TaskStatus.SUCCESS, error.args[0][1]];
|
|
40
|
-
} else {
|
|
41
|
-
return [TaskStatus.BASE_EXCEPTION, error.args[0]];
|
|
42
|
-
}
|
|
43
|
-
} catch (e) {
|
|
44
|
-
return [TaskStatus.BASE_EXCEPTION, error.message];
|
|
45
|
-
}
|
|
50
|
+
return [TaskStatus.SYNTAX_WARNING, 'SYNTAX_WARNING (SyntaxError): ' + detail];
|
|
46
51
|
} else {
|
|
47
|
-
return [TaskStatus.BASE_EXCEPTION,
|
|
52
|
+
return [TaskStatus.BASE_EXCEPTION, 'BASE_EXCEPTION: ' + detail];
|
|
48
53
|
}
|
|
49
54
|
}
|
|
50
55
|
}
|
|
@@ -25,24 +25,29 @@ function exec(payload, input, globals = null) {
|
|
|
25
25
|
|
|
26
26
|
// return [TaskStatus.SUCCESS, 'TASK EXECUTED SUCCESSFULLY'];
|
|
27
27
|
} catch (error) {
|
|
28
|
+
// A task returns its result by RETURNING (via ___etny_result___), not by
|
|
29
|
+
// throwing, so anything caught here is a genuine failure. In every branch
|
|
30
|
+
// deliver the FULL stack trace to the data owner AS THE RESULT (visible in
|
|
31
|
+
// their runner output) and never crash the enclave -- always return a
|
|
32
|
+
// normal [code, data] tuple so the trustedzone stops waiting. Honor the
|
|
33
|
+
// embedded-result SUCCESS (code 0) case first.
|
|
34
|
+
try {
|
|
35
|
+
if (error && error.args && error.args[0] && error.args[0][0] === 0) {
|
|
36
|
+
return [TaskStatus.SUCCESS, error.args[0][1]];
|
|
37
|
+
}
|
|
38
|
+
} catch (e) { /* fall through to failure reporting */ }
|
|
39
|
+
|
|
40
|
+
const detail = (error && (error.stack || error.message)) || String(error);
|
|
41
|
+
console.error('Error in payload execution -- full stack follows:\n' + detail);
|
|
42
|
+
|
|
28
43
|
if (error instanceof ReferenceError) {
|
|
29
|
-
return [TaskStatus.SYSTEM_ERROR,
|
|
44
|
+
return [TaskStatus.SYSTEM_ERROR, 'SYSTEM_ERROR (ReferenceError): ' + detail];
|
|
30
45
|
} else if (error instanceof EvalError) {
|
|
31
|
-
return [TaskStatus.KEY_ERROR,
|
|
46
|
+
return [TaskStatus.KEY_ERROR, 'KEY_ERROR (EvalError): ' + detail];
|
|
32
47
|
} else if (error instanceof SyntaxError) {
|
|
33
|
-
return [TaskStatus.SYNTAX_WARNING,
|
|
34
|
-
} else if (error instanceof Error) {
|
|
35
|
-
try {
|
|
36
|
-
if (error.args[0][0] === 0) {
|
|
37
|
-
return [TaskStatus.SUCCESS, error.args[0][1]];
|
|
38
|
-
} else {
|
|
39
|
-
return [TaskStatus.BASE_EXCEPTION, error.args[0]];
|
|
40
|
-
}
|
|
41
|
-
} catch (e) {
|
|
42
|
-
return [TaskStatus.BASE_EXCEPTION, error.message];
|
|
43
|
-
}
|
|
48
|
+
return [TaskStatus.SYNTAX_WARNING, 'SYNTAX_WARNING (SyntaxError): ' + detail];
|
|
44
49
|
} else {
|
|
45
|
-
return [TaskStatus.BASE_EXCEPTION,
|
|
50
|
+
return [TaskStatus.BASE_EXCEPTION, 'BASE_EXCEPTION: ' + detail];
|
|
46
51
|
}
|
|
47
52
|
}
|
|
48
53
|
}
|