@ethernity-cloud/sdk-js 1.6.2 → 1.7.0
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 +41 -3
- package/cas/config.js +59 -1
- package/info.js +14 -5
- package/init.js +20 -4
- package/nodenithy/build/securelock/Dockerfile.tmpl +34 -32
- package/nodenithy/build/securelock/scripts/binary-fs-build.sh +7 -6
- package/nodenithy/build.mjs +80 -68
- package/nodenithy/run/docker-compose-final.yml.tmpl +36 -31
- package/nodenithy/run/docker-compose.yml.tmpl +34 -45
- package/nodenithy/run/image_registry.js +17 -4
- package/nodenithy/run.js +42 -28
- package/package.json +5 -3
- package/publish.js +4 -2
- package/pynithy/build/securelock/Dockerfile.base.tpl +13 -0
- package/pynithy/build/securelock/Dockerfile.tpl +131 -0
- package/pynithy/build/securelock/scripts/binary-fs-build.sh +25 -34
- package/pynithy/build/securelock/scripts/pyfreeze.sh +32 -0
- package/pynithy/build/securelock/src/{pox.abi → abi/etnyImplementationV2.abi} +1489 -1489
- package/pynithy/build/securelock/src/abi/image_registry.abi +1 -0
- package/pynithy/build/securelock/src/ecld_state.py +906 -0
- package/pynithy/build/securelock/src/esr.abi +1 -0
- package/pynithy/build/securelock/src/esr_local.py +267 -0
- package/pynithy/build/securelock/src/esr_wallet.py +150 -0
- package/pynithy/build/securelock/src/etny_crypto.py +208 -167
- package/pynithy/build/securelock/src/etny_exec.py +385 -79
- package/pynithy/build/securelock/src/etny_exec_flask.py +535 -0
- package/pynithy/build/securelock/src/etny_exec_serv.py +353 -0
- package/pynithy/build/securelock/src/etny_session_exec.py +245 -0
- package/pynithy/build/securelock/src/get_sgx_report.so +0 -0
- package/pynithy/build/securelock/src/image_registry.abi +1 -1
- package/pynithy/build/securelock/src/key_generation.py +17 -17
- package/pynithy/build/securelock/src/local_api.py +189 -0
- package/pynithy/build/securelock/src/models.py +200 -176
- package/pynithy/build/securelock/src/securelock.py.tmpl +1037 -731
- package/pynithy/build/securelock/src/swift_stream_service.py +206 -186
- package/pynithy/build.mjs +139 -89
- package/pynithy/run/docker-compose-final.yml.tmpl +58 -51
- package/pynithy/run/docker-compose.yml.tmpl +62 -48
- package/pynithy/run/etny-securelock-test.yaml.tpl +4 -1
- package/pynithy/run/image_registry.js +17 -4
- package/pynithy/run.js +44 -28
- package/pynithy/src/serverless/Dockerfile.serverless +8 -0
- package/pynithy/src/serverless/requirements.txt +6 -0
- package/run.js +69 -28
- package/nodenithy/build/las/Dockerfile +0 -5
- package/pynithy/build/docker-compose.yml +0 -70
- package/pynithy/build/las/Dockerfile +0 -11
- package/pynithy/build/las/src/etny_entrypoint.sh +0 -6
- package/pynithy/build/las/src/las_entrypoint.sh +0 -26
- package/pynithy/build/scripts/binary-fs-build.sh +0 -28
- package/pynithy/build/securelock/Dockerfile.tmpl +0 -95
package/pynithy/run.js
CHANGED
|
@@ -60,13 +60,19 @@ const writeEnv = (key, value) => {
|
|
|
60
60
|
|
|
61
61
|
let templateName = process.env.TRUSTED_ZONE_IMAGE || 'etny-pynithy-testnet';
|
|
62
62
|
|
|
63
|
-
const isMainnet =
|
|
64
|
-
//
|
|
65
|
-
//
|
|
66
|
-
//
|
|
67
|
-
// the
|
|
68
|
-
|
|
63
|
+
const isMainnet = casConfig.isMainnetNetwork(process.env.BLOCKCHAIN_NETWORK);
|
|
64
|
+
// Mainnet enclaves are provisioned by the Scontain CAS. A testnet template
|
|
65
|
+
// with a SessionRegistry is CAS-attested by the ethernity-cas validator set:
|
|
66
|
+
// the session is registered on-chain, the enclave is provisioned from a
|
|
67
|
+
// validator, and the certificate comes out of the CAS session. Every other
|
|
68
|
+
// testnet's enclaves self-sign from MR_ENCLAVE and register no session.
|
|
69
|
+
const cas = casConfig.casProvisioned(templateName, isMainnet);
|
|
70
|
+
const casTestnet = !isMainnet && cas;
|
|
69
71
|
const casChain = casConfig.CHAIN[templateName] || {};
|
|
72
|
+
// An -unsafe network is a self-signing testnet whose compose carries no LAS;
|
|
73
|
+
// its securelock is registered as <project>-unsafe.
|
|
74
|
+
const unsafe = casConfig.isUnsafeNetwork(process.env.BLOCKCHAIN_NETWORK);
|
|
75
|
+
const securelock = casConfig.nameOnNetwork(process.env.PROJECT_NAME, process.env.BLOCKCHAIN_NETWORK);
|
|
70
76
|
|
|
71
77
|
const currentDir = process.cwd();
|
|
72
78
|
console.log(`currentDir: ${currentDir}`);
|
|
@@ -107,14 +113,21 @@ const extractSignedMrenclave = (service) => {
|
|
|
107
113
|
|
|
108
114
|
const main = async () => {
|
|
109
115
|
process.env.NODE_NO_WARNINGS = 1
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
116
|
+
// The securelock heap ecld-build signed it with (part of MRENCLAVE).
|
|
117
|
+
const memory = (process.env.MEMORY_TO_ALLOCATE || '').trim();
|
|
118
|
+
if (!memory) {
|
|
119
|
+
console.error("Error: MEMORY_TO_ALLOCATE is not set in .env; run ecld-build first.");
|
|
120
|
+
process.exit(1);
|
|
121
|
+
}
|
|
122
|
+
['docker-compose.yml', 'docker-compose-final.yml'].forEach(file => {
|
|
123
|
+
const template = `${file}.tmpl`;
|
|
124
|
+
if (!fs.existsSync(template)) {
|
|
125
|
+
console.error(`Error: ${template} not found!`);
|
|
114
126
|
return;
|
|
115
127
|
}
|
|
116
|
-
const
|
|
117
|
-
|
|
128
|
+
const content = casConfig.renderCompose(fs.readFileSync(template, 'utf8'), cas, unsafe)
|
|
129
|
+
.replace(/__MEMORY_TO_ALLOCATE__/g, memory);
|
|
130
|
+
fs.writeFileSync(file, content, 'utf8');
|
|
118
131
|
});
|
|
119
132
|
|
|
120
133
|
|
|
@@ -130,7 +143,7 @@ const main = async () => {
|
|
|
130
143
|
// MRENCLAVE signed --production at build time (/signed_mrenclave.txt). A
|
|
131
144
|
// mismatch means SCONE recomputed the measurement at load (params drift) and
|
|
132
145
|
// re-signed as DEBUG, which CAS rejects on mainnet. Refuse to publish.
|
|
133
|
-
if (
|
|
146
|
+
if (cas) {
|
|
134
147
|
const signedMrenclave = extractSignedMrenclave('etny-securelock');
|
|
135
148
|
if (!signedMrenclave || signedMrenclave !== process.env.MRENCLAVE_SECURELOCK) {
|
|
136
149
|
console.error(`Error: securelock runtime MRENCLAVE (${process.env.MRENCLAVE_SECURELOCK}) != signed MRENCLAVE (${signedMrenclave}).`);
|
|
@@ -218,15 +231,20 @@ const main = async () => {
|
|
|
218
231
|
MRENCLAVE: process.env.MRENCLAVE_SECURELOCK,
|
|
219
232
|
ENCLAVE_NAME: ENCLAVE_NAME_SECURELOCK
|
|
220
233
|
};
|
|
221
|
-
|
|
234
|
+
if (cas) {
|
|
235
|
+
processYamlTemplate('etny-securelock-test.yaml.tpl', 'etny-securelock-test.yaml', replacementsSecurelock);
|
|
236
|
+
}
|
|
222
237
|
|
|
223
238
|
// Where the session goes depends on who provisions the securelock. On a
|
|
224
239
|
// CAS-attested testnet it is registered ON-CHAIN in the ethernity-cas
|
|
225
240
|
// SessionRegistry, which the validator set reads and which accepts no
|
|
226
241
|
// POST; the publish then waits until the validators serve it, because the
|
|
227
|
-
// public-key harvest below provisions the enclave from them.
|
|
228
|
-
//
|
|
229
|
-
|
|
242
|
+
// public-key harvest below provisions the enclave from them. On mainnet it
|
|
243
|
+
// is registered with the Scontain CAS. A self-signing testnet has none: a
|
|
244
|
+
// CAS-issued certificate would not match the key the enclave derives.
|
|
245
|
+
if (!cas) {
|
|
246
|
+
console.log(`\t✔ ${process.env.BLOCKCHAIN_NETWORK}: no CAS session; the securelock self-signs from MR_ENCLAVE`);
|
|
247
|
+
} else if (casTestnet) {
|
|
230
248
|
const registered = await sessionRegistry.register(
|
|
231
249
|
casChain.rpcUrl, casChain.chainId, casConfig.SESSION_REGISTRY[templateName],
|
|
232
250
|
process.env.PRIVATE_KEY, fs.readFileSync('etny-securelock-test.yaml'),
|
|
@@ -429,13 +447,9 @@ const main = async () => {
|
|
|
429
447
|
console.log(`No __ENCLAVE_NAME_TRUSTEDZONE__ found in ${file}`);
|
|
430
448
|
}
|
|
431
449
|
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
}
|
|
436
|
-
if (casTestnet) {
|
|
437
|
-
ENCLAVE_NAME_TRUSTEDZONE = trustedZoneSession;
|
|
438
|
-
}
|
|
450
|
+
// Named only in a CAS-provisioned compose; a self-signing one has no
|
|
451
|
+
// __CAS_ONLY__ lines left.
|
|
452
|
+
const ENCLAVE_NAME_TRUSTEDZONE = casTestnet ? trustedZoneSession : 'ecld-pynithy-trustedzone-v3-3.0.0';
|
|
439
453
|
let updatedContent = fileContentBefore
|
|
440
454
|
.replace(/__ENCLAVE_NAME_SECURELOCK__/g, ENCLAVE_NAME_SECURELOCK)
|
|
441
455
|
.replace(/__ENCLAVE_NAME_TRUSTEDZONE__/g, ENCLAVE_NAME_TRUSTEDZONE);
|
|
@@ -544,7 +558,7 @@ const main = async () => {
|
|
|
544
558
|
console.log()
|
|
545
559
|
|
|
546
560
|
console.log(`ENCLAVE_NAME_SECURELOCK: ${ENCLAVE_NAME_SECURELOCK}`);
|
|
547
|
-
execSync(`node ./public_key_service.js --enclave_name "${
|
|
561
|
+
execSync(`node ./public_key_service.js --enclave_name "${securelock}" --protocol_version "v3" --network "${process.env.BLOCKCHAIN_NETWORK}" --template_version "${process.env.VERSION}"`, { stdio: 'inherit' });
|
|
548
562
|
PUBLIC_KEY_SECURELOCK_RES = fs.readFileSync('PUBLIC_KEY.txt', 'utf8').trim();
|
|
549
563
|
console.log(`PUBLIC_KEY_SECURELOCK_RES: ${PUBLIC_KEY_SECURELOCK_RES}`);
|
|
550
564
|
if (!PUBLIC_KEY_SECURELOCK_RES || PUBLIC_KEY_SECURELOCK_RES === '-1') {
|
|
@@ -611,10 +625,12 @@ const main = async () => {
|
|
|
611
625
|
console.log("IPFS_HASH: ", process.env.IPFS_HASH);
|
|
612
626
|
writeEnv('IPFS_HASH', process.env.IPFS_HASH);
|
|
613
627
|
process.chdir(currentDir);
|
|
614
|
-
console.log(
|
|
628
|
+
console.log(`Adding certificates for SECURELOCK ${securelock} into IMAGE REGISTRY smart contract...`);
|
|
629
|
+
// image_registry.js registers the image under PROJECT_NAME.
|
|
630
|
+
const registryEnv = { ...process.env, PROJECT_NAME: securelock };
|
|
615
631
|
let existing = false;
|
|
616
632
|
try {
|
|
617
|
-
const existingImages = execSync(`node ${runDir}/image_registry.js "${process.env.BLOCKCHAIN_NETWORK}" "${
|
|
633
|
+
const existingImages = execSync(`node ${runDir}/image_registry.js "${process.env.BLOCKCHAIN_NETWORK}" "${securelock}" "${process.env.VERSION}" "${process.env.PRIVATE_KEY}" "registerSecureLockImage"`, { stdio: "inherit", env: registryEnv });
|
|
618
634
|
if (existingImages.toString().trim().replace('Image hash: ', '') === process.env.IPFS_HASH) {
|
|
619
635
|
console.log("Certificates for SECURELOCK already added to IMAGE REGISTRY smart contract");
|
|
620
636
|
}
|
|
@@ -626,7 +642,7 @@ const main = async () => {
|
|
|
626
642
|
}
|
|
627
643
|
|
|
628
644
|
if (!existing) {
|
|
629
|
-
const res = execSync(`node ${runDir}/image_registry.js "${process.env.BLOCKCHAIN_NETWORK}" "" "" "" "registerSecureLockImage"`, { stdio: "inherit" });
|
|
645
|
+
const res = execSync(`node ${runDir}/image_registry.js "${process.env.BLOCKCHAIN_NETWORK}" "" "" "" "registerSecureLockImage"`, { stdio: "inherit", env: registryEnv });
|
|
630
646
|
}
|
|
631
647
|
// The on-chain session points at the image it admits, so a validator can
|
|
632
648
|
// pin the image beside the body it serves.
|
package/run.js
CHANGED
|
@@ -15,8 +15,10 @@
|
|
|
15
15
|
* ecld-publish), matching how ethernity_task drives a run:
|
|
16
16
|
*
|
|
17
17
|
* BLOCKCHAIN_NETWORK e.g. "Bloxberg_Testnet" -> the network token address
|
|
18
|
-
* PROJECT_NAME the securelock enclave to run
|
|
19
|
-
*
|
|
18
|
+
* PROJECT_NAME the securelock enclave to run (<PROJECT_NAME>-unsafe
|
|
19
|
+
* on an -unsafe network)
|
|
20
|
+
* TRUSTED_ZONE_IMAGE the trustedzone enclave (its -unsafe variant on an
|
|
21
|
+
* -unsafe network)
|
|
20
22
|
* PRIVATE_KEY a funded 0x key — it pays for the order
|
|
21
23
|
*
|
|
22
24
|
* Usage, from the project root:
|
|
@@ -25,6 +27,7 @@
|
|
|
25
27
|
* npx ecld-run --file payload.js
|
|
26
28
|
* npx ecld-run --input data.json 'processData(___etny_data_set___)'
|
|
27
29
|
* npx ecld-run --network BLOXBERG_TESTNET --task-price 3 'esrIncrement()'
|
|
30
|
+
* npx ecld-run --unsafe 'hello("World")' # the network's -unsafe variant
|
|
28
31
|
* npx ecld-run --json 'hello("World")' # machine-readable result
|
|
29
32
|
*
|
|
30
33
|
* The runner is ESM; this CJS entry loads it with dynamic import().
|
|
@@ -36,27 +39,47 @@
|
|
|
36
39
|
|
|
37
40
|
const fs = require('fs');
|
|
38
41
|
try { require('dotenv').config(); } catch (e) { /* dotenv optional */ }
|
|
42
|
+
const casConfig = require('./cas/config.js');
|
|
39
43
|
|
|
40
44
|
const DEFAULT_IPFS = 'https://ipfs.ethernity.cloud/api/v0';
|
|
41
45
|
|
|
42
46
|
/* Map a BLOCKCHAIN_NETWORK token (as ecld-init writes it, spaces -> underscores)
|
|
43
|
-
* to the runner's network token ADDRESS
|
|
44
|
-
*
|
|
45
|
-
|
|
47
|
+
* to the runner's network: its token ADDRESS, the chain id of a testnet whose
|
|
48
|
+
* token address other testnets share, and for an -unsafe network the
|
|
49
|
+
* (network, type) the runner is set to, which runs only -unsafe trustedzones.
|
|
50
|
+
* Built from the runner's own enums so it can't drift. Accepts a few spellings
|
|
51
|
+
* per network. */
|
|
52
|
+
function networkFor({ ECAddress, ECNetworkByChainId }, raw) {
|
|
46
53
|
const key = String(raw || '').trim().toUpperCase().replace(/\s+/g, '_');
|
|
54
|
+
const bloxbergTestnet = { address: ECAddress.BLOXBERG.TESTNET_ADDRESS };
|
|
55
|
+
const amoy = { address: ECAddress.POLYGON.TESTNET_ADDRESS };
|
|
56
|
+
const sepolia = { address: ECAddress.SEPOLIA.TESTNET_ADDRESS, chainId: ECNetworkByChainId.SEPOLIA.TESTNET };
|
|
57
|
+
const litvm = { address: ECAddress.LITVM.TESTNET_ADDRESS, chainId: ECNetworkByChainId.LITVM.TESTNET };
|
|
47
58
|
const table = {
|
|
48
|
-
BLOXBERG_TESTNET:
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
59
|
+
BLOXBERG_TESTNET: bloxbergTestnet,
|
|
60
|
+
BLOXBERG_TESTNET_UNSAFE: { ...bloxbergTestnet, unsafe: ['BLOXBERG', 'TESTNET_UNSAFE'] },
|
|
61
|
+
BLOXBERG_MAINNET: { address: ECAddress.BLOXBERG.MAINNET_ADDRESS },
|
|
62
|
+
POLYGON_MAINNET: { address: ECAddress.POLYGON.MAINNET_ADDRESS },
|
|
63
|
+
POLYGON_AMOY: amoy,
|
|
64
|
+
POLYGON_AMOY_TESTNET: amoy,
|
|
65
|
+
IOTEX_TESTNET: { address: ECAddress.IOTEX.TESTNET_ADDRESS, chainId: ECNetworkByChainId.IOTEX.TESTNET },
|
|
66
|
+
ETHEREUM_SEPOLIA: sepolia,
|
|
67
|
+
SEPOLIA: sepolia,
|
|
68
|
+
LITVM_LITEFORGE: litvm,
|
|
69
|
+
LITVM: litvm,
|
|
70
|
+
LITVM_LITEFORGE_UNSAFE: { ...litvm, unsafe: ['LITVM', 'TESTNET_UNSAFE'] },
|
|
58
71
|
};
|
|
59
|
-
return { key,
|
|
72
|
+
return { key, network: table[key] || null, known: Object.keys(table) };
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/* The -unsafe network a network token names, or whose sibling it names; null
|
|
76
|
+
* when the network has no -unsafe variant. */
|
|
77
|
+
function unsafeVariant(raw) {
|
|
78
|
+
const key = String(raw || '').trim().replace(/\s+/g, '_');
|
|
79
|
+
if (casConfig.isUnsafeNetwork(key)) return key;
|
|
80
|
+
const variant = Object.keys(casConfig.UNSAFE_NETWORKS)
|
|
81
|
+
.find((name) => casConfig.UNSAFE_NETWORKS[name].toUpperCase() === key.toUpperCase());
|
|
82
|
+
return variant || null;
|
|
60
83
|
}
|
|
61
84
|
|
|
62
85
|
function parseArgs(argv) {
|
|
@@ -68,6 +91,7 @@ function parseArgs(argv) {
|
|
|
68
91
|
else if (a === '--input' || a === '-i') opts.inputFile = argv[++i];
|
|
69
92
|
else if (a === '--input-text') opts.inputText = argv[++i];
|
|
70
93
|
else if (a === '--network') opts.network = argv[++i];
|
|
94
|
+
else if (a === '--unsafe') opts.unsafe = true;
|
|
71
95
|
else if (a === '--securelock') opts.securelock = argv[++i];
|
|
72
96
|
else if (a === '--trustedzone') opts.trustedzone = argv[++i];
|
|
73
97
|
else if (a === '--node') opts.node = argv[++i];
|
|
@@ -94,7 +118,10 @@ usage: ecld-run 'hello("World")' | ecld-run --file payload.js | ecld-run --input
|
|
|
94
118
|
|
|
95
119
|
payload: a code string, or --file <path>; input via --input <file> / --input-text <str>
|
|
96
120
|
network: --network BLOXBERG_TESTNET (default: BLOCKCHAIN_NETWORK from .env)
|
|
97
|
-
|
|
121
|
+
--unsafe: the network's -unsafe variant, which runs without a CAS
|
|
122
|
+
(BLOXBERG_TESTNET_UNSAFE, LITVM_LITEFORGE_UNSAFE)
|
|
123
|
+
enclaves: --securelock <name> (default PROJECT_NAME), --trustedzone <name> (default TRUSTED_ZONE_IMAGE);
|
|
124
|
+
on an -unsafe network the default is each one's -unsafe variant
|
|
98
125
|
key: PRIVATE_KEY (a funded 0x key) from .env / env, or ECLD_PRIVATE_KEY
|
|
99
126
|
resources: --task-price 3 --cpu 1 --memory 1 --storage 10 --bandwidth 1 --duration 1 --validators 1
|
|
100
127
|
other: --node <addr> --ipfs <url> --timeout <sec> --json`;
|
|
@@ -121,27 +148,37 @@ async function main() {
|
|
|
121
148
|
// ecld-run mirrors ecld-test: input is delivered via the payload call itself.
|
|
122
149
|
|
|
123
150
|
// ---- runner (ESM) ----
|
|
124
|
-
let EthernityCloudRunner, ECStatus, ECEvent,
|
|
151
|
+
let EthernityCloudRunner, ECStatus, ECEvent, ECOrderTaskStatus, enums;
|
|
125
152
|
try {
|
|
126
153
|
const runnerMod = await import('@ethernity-cloud/runner');
|
|
127
154
|
EthernityCloudRunner = runnerMod.default || runnerMod.EthernityCloudRunner;
|
|
128
|
-
|
|
129
|
-
({ ECStatus, ECEvent,
|
|
155
|
+
enums = await import('@ethernity-cloud/runner/enums.js');
|
|
156
|
+
({ ECStatus, ECEvent, ECOrderTaskStatus } = enums);
|
|
130
157
|
} catch (e) {
|
|
131
158
|
console.error('ecld-run: the runner package is not installed or is too old '
|
|
132
|
-
+ '(need @ethernity-cloud/runner >= 0.
|
|
159
|
+
+ '(need @ethernity-cloud/runner >= 0.6.0): ' + e.message);
|
|
133
160
|
process.exit(1);
|
|
134
161
|
}
|
|
135
162
|
|
|
136
163
|
// ---- network / enclaves / key ----
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
164
|
+
let rawNetwork = opts.network || process.env.BLOCKCHAIN_NETWORK || 'BLOXBERG_TESTNET';
|
|
165
|
+
if (opts.unsafe) {
|
|
166
|
+
const variant = unsafeVariant(rawNetwork);
|
|
167
|
+
if (!variant) {
|
|
168
|
+
console.error(`ecld-run: ${rawNetwork} has no -unsafe variant. -unsafe networks: `
|
|
169
|
+
+ Object.keys(casConfig.UNSAFE_NETWORKS).join(', '));
|
|
170
|
+
process.exit(1);
|
|
171
|
+
}
|
|
172
|
+
rawNetwork = variant;
|
|
173
|
+
}
|
|
174
|
+
const { key: netKey, network, known } = networkFor(enums, rawNetwork);
|
|
175
|
+
if (!network) {
|
|
140
176
|
console.error(`ecld-run: unknown network '${rawNetwork}'. Known: ${known.join(', ')}`);
|
|
141
177
|
process.exit(1);
|
|
142
178
|
}
|
|
143
|
-
const securelock = opts.securelock || process.env.PROJECT_NAME;
|
|
144
|
-
|
|
179
|
+
const securelock = opts.securelock || casConfig.nameOnNetwork(process.env.PROJECT_NAME, rawNetwork);
|
|
180
|
+
// May be undefined -> run() default.
|
|
181
|
+
const trustedzone = opts.trustedzone || casConfig.nameOnNetwork(process.env.TRUSTED_ZONE_IMAGE, rawNetwork);
|
|
145
182
|
if (!securelock) {
|
|
146
183
|
console.error('ecld-run: no securelock enclave: set PROJECT_NAME in .env '
|
|
147
184
|
+ '(run ecld-init/ecld-publish) or pass --securelock.');
|
|
@@ -156,7 +193,10 @@ async function main() {
|
|
|
156
193
|
}
|
|
157
194
|
if (!privateKey.startsWith('0x')) privateKey = '0x' + privateKey;
|
|
158
195
|
|
|
159
|
-
console.log(`network : ${netKey} (${address})`);
|
|
196
|
+
console.log(`network : ${netKey} (${network.address})`);
|
|
197
|
+
if (network.unsafe) {
|
|
198
|
+
console.log(' UNSAFE: no CAS; the enclaves are debug-signed and sign their own certificates');
|
|
199
|
+
}
|
|
160
200
|
console.log(`securelock : ${securelock}`);
|
|
161
201
|
console.log(`trustedzone: ${trustedzone || '(runner default)'}`);
|
|
162
202
|
console.log(`payload : ${JSON.stringify(code)}`);
|
|
@@ -165,7 +205,8 @@ async function main() {
|
|
|
165
205
|
// ---- drive the runner ----
|
|
166
206
|
let runner;
|
|
167
207
|
try {
|
|
168
|
-
runner = new EthernityCloudRunner(address, { privateKey });
|
|
208
|
+
runner = new EthernityCloudRunner(network.address, { privateKey }, network.chainId);
|
|
209
|
+
if (network.unsafe) await runner.setNetwork(...network.unsafe);
|
|
169
210
|
} catch (e) {
|
|
170
211
|
console.error('ecld-run: could not initialise the runner: ' + e.message);
|
|
171
212
|
process.exit(1);
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
version: '3.2'
|
|
2
|
-
services:
|
|
3
|
-
las:
|
|
4
|
-
container_name: las
|
|
5
|
-
privileged: true
|
|
6
|
-
image: etny-las
|
|
7
|
-
entrypoint: "/las_entrypoint.sh"
|
|
8
|
-
# -a 0.0.0.0: without it the LAS binds dual-stack (:::18766) and cannot
|
|
9
|
-
# allocate the socket on a host booted with ipv6.disable=1.
|
|
10
|
-
command: "/usr/local/bin/las -a 0.0.0.0"
|
|
11
|
-
devices:
|
|
12
|
-
- "/dev/sgx_enclave:/dev/sgx_enclave"
|
|
13
|
-
restart: on-failure
|
|
14
|
-
networks:
|
|
15
|
-
- ethernity
|
|
16
|
-
ports:
|
|
17
|
-
- target: 18766
|
|
18
|
-
published: 18766
|
|
19
|
-
protocol: tcp
|
|
20
|
-
mode: host
|
|
21
|
-
|
|
22
|
-
etny-securelock:
|
|
23
|
-
container_name: etny-securelock
|
|
24
|
-
privileged: true
|
|
25
|
-
image: etny-securelock
|
|
26
|
-
entrypoint: ""
|
|
27
|
-
command: [ "/usr/local/bin/python", "/etny-securelock/securelock.py" ]
|
|
28
|
-
environment:
|
|
29
|
-
- SCONE_CAS_ADDR=scone-cas.cf
|
|
30
|
-
- SCONE_LAS_ADDR=las
|
|
31
|
-
- SCONE_CONFIG_ID=etny-pynity-test-0.0.18/application
|
|
32
|
-
- SCONE_HEAP=128M
|
|
33
|
-
- SCONE_LOG=DEBUG
|
|
34
|
-
- SCONE_MODE=SIM
|
|
35
|
-
- SCONE_ALLOW_DLOPEN=2
|
|
36
|
-
- SCONE_EXTENSIONS_PATH=/lib/libbinary-fs.so
|
|
37
|
-
restart: on-failure
|
|
38
|
-
networks:
|
|
39
|
-
- ethernity
|
|
40
|
-
devices:
|
|
41
|
-
- "/dev/sgx_enclave:/dev/sgx_enclave"
|
|
42
|
-
depends_on:
|
|
43
|
-
- las
|
|
44
|
-
|
|
45
|
-
etny-trustedzone:
|
|
46
|
-
container_name: etny-trustedzone
|
|
47
|
-
privileged: true
|
|
48
|
-
image: etny-trustedzone
|
|
49
|
-
entrypoint: ""
|
|
50
|
-
command: [ "/usr/local/bin/python", "/etny-trustedzone/trustedzone.py" ]
|
|
51
|
-
environment:
|
|
52
|
-
- SCONE_CAS_ADDR=scone-cas.cf
|
|
53
|
-
- SCONE_LAS_ADDR=las
|
|
54
|
-
- SCONE_CONFIG_ID=etny-pynity-trustedzone-0.0.18/application
|
|
55
|
-
- SCONE_HEAP=128M
|
|
56
|
-
- SCONE_LOG=DEBUG
|
|
57
|
-
- SCONE_MODE=SIM
|
|
58
|
-
- SCONE_ALLOW_DLOPEN=2
|
|
59
|
-
- SCONE_EXTENSIONS_PATH=/lib/libbinary-fs.so
|
|
60
|
-
restart: on-failure
|
|
61
|
-
networks:
|
|
62
|
-
- ethernity
|
|
63
|
-
devices:
|
|
64
|
-
- "/dev/sgx_enclave:/dev/sgx_enclave"
|
|
65
|
-
depends_on:
|
|
66
|
-
- las
|
|
67
|
-
|
|
68
|
-
networks:
|
|
69
|
-
ethernity:
|
|
70
|
-
external: true
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
|
|
3
|
-
set -e
|
|
4
|
-
|
|
5
|
-
SOCKET="/var/run/aesmd/aesm.socket"
|
|
6
|
-
|
|
7
|
-
# Try to connect to the socket
|
|
8
|
-
# Previously we merely checked that the socket file exists. However, the
|
|
9
|
-
# file is not removed when the container stops and, thus, when we restart
|
|
10
|
-
# the file still exists and we assume that we are supposed to use an
|
|
11
|
-
# outside AESM.
|
|
12
|
-
if socat -u OPEN:/dev/null UNIX-CONNECT:${SOCKET}; then
|
|
13
|
-
# An AESM socket was already mounted into the container, don't start a local AESM service, start LAS directly
|
|
14
|
-
echo "${SOCKET} exists - Will use mounted AESM socket; the local in-container AESM service will not be started!"
|
|
15
|
-
exec "$@"
|
|
16
|
-
else
|
|
17
|
-
# No AESM socket present, delegate execution to the local AESM service
|
|
18
|
-
echo "${SOCKET} not found or unable to connect - Starting local in-container AESM service"
|
|
19
|
-
if [ -e ${SOCKET} ]; then
|
|
20
|
-
# Ensure the socket file does not exist - AESM won't start if it does...
|
|
21
|
-
rm ${SOCKET}
|
|
22
|
-
fi
|
|
23
|
-
exec /entrypoint.sh "$@"
|
|
24
|
-
fi
|
|
25
|
-
|
|
26
|
-
/etny_entrypoint.sh &
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
#!/bin/bash -v
|
|
2
|
-
|
|
3
|
-
pip3 install pyinstaller
|
|
4
|
-
apk add binutils
|
|
5
|
-
|
|
6
|
-
cd /etny-securelock
|
|
7
|
-
pyinstaller etny_result.py
|
|
8
|
-
|
|
9
|
-
EXEC=(scone binaryfs / /binary-fs-dir -v \
|
|
10
|
-
--include '/usr/local/lib/python3.10/*' \
|
|
11
|
-
--include '/etny-securelock/*' \
|
|
12
|
-
--host-path=/etc/resolv.conf \
|
|
13
|
-
--host-path=/etc/hosts)
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
for FILE in `cat ./build/etny_result/COLLECT-00.toc | grep '.so' | grep BINARY | awk -F "'" '{print $4}'`
|
|
17
|
-
do
|
|
18
|
-
EXEC+=(--include "${FILE}"'*')
|
|
19
|
-
done
|
|
20
|
-
|
|
21
|
-
rm -rf build dist etny_result.spec
|
|
22
|
-
|
|
23
|
-
echo "${EXEC[@]}"
|
|
24
|
-
|
|
25
|
-
SCONE_MODE=auto
|
|
26
|
-
exec "${EXEC[@]}"
|
|
27
|
-
|
|
28
|
-
exit
|
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
# FROM registry.scontain.com:5050/sconecuratedimages/apps:python3.10.5-alpine3.15-scone5.8-pre-release as release
|
|
2
|
-
FROM registry.ethernity.cloud:443/debuggingdelight/ethernity-cloud-sdk-registry/sconecuratedimages/apps:python3.10.5-alpine3.15-scone5.8-pre-release as release
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
RUN apk update
|
|
7
|
-
|
|
8
|
-
RUN cd /
|
|
9
|
-
RUN apk add bash openrc bind-tools sudo npm binutils curl
|
|
10
|
-
RUN pip3 install --upgrade pip
|
|
11
|
-
RUN pip3 install --upgrade setuptools
|
|
12
|
-
RUN pip3 install python-dotenv
|
|
13
|
-
RUN pip3 install web3==5.31.0
|
|
14
|
-
RUN pip3 install cryptography==42.0.7
|
|
15
|
-
RUN pip3 install ecdsa
|
|
16
|
-
RUN pip3 install pyasn1
|
|
17
|
-
RUN pip3 install tinyec
|
|
18
|
-
RUN pip3 install pyinstaller
|
|
19
|
-
RUN pip3 install minio
|
|
20
|
-
RUN pip3 install pynacl
|
|
21
|
-
RUN pip3 install pytest
|
|
22
|
-
RUN pip3 install numpy
|
|
23
|
-
RUN pip3 install scipy
|
|
24
|
-
RUN pip3 install hypothesis
|
|
25
|
-
RUN pip3 install pooch
|
|
26
|
-
RUN pip3 install ipywidgets
|
|
27
|
-
|
|
28
|
-
#RUN pip3 install requests
|
|
29
|
-
#RUN pip3 install beautifulsoup4
|
|
30
|
-
#RUN pip3 install tokenizers
|
|
31
|
-
#RUN pip3 install transformers
|
|
32
|
-
#RUN pip3 install tensorflow
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
ENV ENCLAVE_NAME_SECURELOCK=__ENCLAVE_NAME_SECURELOCK__
|
|
36
|
-
ENV BUCKET_NAME=__BUCKET_NAME__
|
|
37
|
-
ENV SMART_CONTRACT_ADDRESS=__SMART_CONTRACT_ADDRESS__
|
|
38
|
-
ENV IMAGE_REGISTRY_ADDRESS=__IMAGE_REGISTRY_ADDRESS__
|
|
39
|
-
ENV RPC_URL=__RPC_URL__
|
|
40
|
-
ENV CHAIN_ID=__CHAIN_ID__
|
|
41
|
-
ENV TRUSTED_ZONE_IMAGE=__TRUSTED_ZONE_IMAGE__
|
|
42
|
-
ENV VALIDATOR_REGISTRY_ADDRESS=__VALIDATOR_REGISTRY_ADDRESS__
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
RUN mkdir binary-fs-dir
|
|
46
|
-
|
|
47
|
-
COPY ./src /etny-securelock/
|
|
48
|
-
COPY ./scripts/* /etny-securelock/
|
|
49
|
-
|
|
50
|
-
RUN etny-securelock/binary-fs-build.sh
|
|
51
|
-
|
|
52
|
-
FROM registry.ethernity.cloud:443/debuggingdelight/ethernity-cloud-sdk-registry/sconecuratedimages/crosscompilers as build
|
|
53
|
-
|
|
54
|
-
COPY --from=release /binary-fs-dir /.
|
|
55
|
-
|
|
56
|
-
RUN scone gcc ./binary_fs_blob.s ./libbinary_fs_template.a -shared -o /libbinary-fs.so
|
|
57
|
-
|
|
58
|
-
FROM registry.ethernity.cloud:443/debuggingdelight/ethernity-cloud-sdk-registry/sconecuratedimages/apps:python3.10.5-alpine3.15-scone5.8-pre-release
|
|
59
|
-
|
|
60
|
-
COPY --from=build /usr/local/bin/scone /usr/local/bin/scone
|
|
61
|
-
|
|
62
|
-
#RUN scone cas attest scone-cas.cf 3061b9feb7fa67f3815336a085f629a13f04b0a1667c93b14ff35581dc8271e4 -GCS --only_for_testing-debug --only_for_testing-ignore-signer
|
|
63
|
-
|
|
64
|
-
COPY --from=build /libbinary-fs.so /lib/libbinary-fs.so
|
|
65
|
-
|
|
66
|
-
RUN openssl genrsa -3 -out /enclave-key.pem 3072
|
|
67
|
-
|
|
68
|
-
# SCONE runtime env. Must match the enclave-creation params passed to
|
|
69
|
-
# scone-signer below (any drift makes SCONE recompute + debug re-sign at load,
|
|
70
|
-
# which CAS rejects on mainnet). Values mirror the run/docker-compose securelock
|
|
71
|
-
# service (SCONE_HEAP=1024M, SCONE_STACK=4M, dlopen=1, extensions=libbinary-fs).
|
|
72
|
-
ENV SCONE_LOG=INFO
|
|
73
|
-
ENV SCONE_HEAP=1024M
|
|
74
|
-
ENV SCONE_STACK=4M
|
|
75
|
-
ENV SCONE_ALLOW_DLOPEN=1
|
|
76
|
-
ENV SCONE_EXTENSIONS_PATH=/lib/libbinary-fs.so
|
|
77
|
-
|
|
78
|
-
# Rendered by build.mjs. Signs the EXECUTED binary (/usr/local/bin/python -- the
|
|
79
|
-
# ENTRYPOINT and the run/publish compose command both run /usr/local/bin/python;
|
|
80
|
-
# python3 is a SEPARATE symlink, signing it leaves the executed binary
|
|
81
|
-
# debug-signed). Mainnet adds --production (CAS/DCAP); testnet omits it (non-CAS
|
|
82
|
-
# self-sign). On testnet builds this line is a no-op comment.
|
|
83
|
-
__SCONE_SIGN__
|
|
84
|
-
|
|
85
|
-
# Record the SIGNED MRENCLAVE so publish (run.js) can assert the runtime enclave
|
|
86
|
-
# measurement matches what was signed before registering the CAS session. Only
|
|
87
|
-
# produced for --production (mainnet); on testnet the file is absent and the
|
|
88
|
-
# check is skipped. Capture to a file first (piping scone-signer into head/grep
|
|
89
|
-
# kills it with SIGPIPE / exit 141 under buildkit's pipefail shell).
|
|
90
|
-
__SIGNED_MRENCLAVE__
|
|
91
|
-
|
|
92
|
-
RUN rm -rf /enclave-key.pem
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
ENTRYPOINT ["/usr/local/bin/python", "/etny-securelock/securelock.py"]
|