@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.
Files changed (51) hide show
  1. package/README.md +41 -3
  2. package/cas/config.js +59 -1
  3. package/info.js +14 -5
  4. package/init.js +20 -4
  5. package/nodenithy/build/securelock/Dockerfile.tmpl +34 -32
  6. package/nodenithy/build/securelock/scripts/binary-fs-build.sh +7 -6
  7. package/nodenithy/build.mjs +80 -68
  8. package/nodenithy/run/docker-compose-final.yml.tmpl +36 -31
  9. package/nodenithy/run/docker-compose.yml.tmpl +34 -45
  10. package/nodenithy/run/image_registry.js +17 -4
  11. package/nodenithy/run.js +42 -28
  12. package/package.json +5 -3
  13. package/publish.js +4 -2
  14. package/pynithy/build/securelock/Dockerfile.base.tpl +13 -0
  15. package/pynithy/build/securelock/Dockerfile.tpl +131 -0
  16. package/pynithy/build/securelock/scripts/binary-fs-build.sh +25 -34
  17. package/pynithy/build/securelock/scripts/pyfreeze.sh +32 -0
  18. package/pynithy/build/securelock/src/{pox.abi → abi/etnyImplementationV2.abi} +1489 -1489
  19. package/pynithy/build/securelock/src/abi/image_registry.abi +1 -0
  20. package/pynithy/build/securelock/src/ecld_state.py +906 -0
  21. package/pynithy/build/securelock/src/esr.abi +1 -0
  22. package/pynithy/build/securelock/src/esr_local.py +267 -0
  23. package/pynithy/build/securelock/src/esr_wallet.py +150 -0
  24. package/pynithy/build/securelock/src/etny_crypto.py +208 -167
  25. package/pynithy/build/securelock/src/etny_exec.py +385 -79
  26. package/pynithy/build/securelock/src/etny_exec_flask.py +535 -0
  27. package/pynithy/build/securelock/src/etny_exec_serv.py +353 -0
  28. package/pynithy/build/securelock/src/etny_session_exec.py +245 -0
  29. package/pynithy/build/securelock/src/get_sgx_report.so +0 -0
  30. package/pynithy/build/securelock/src/image_registry.abi +1 -1
  31. package/pynithy/build/securelock/src/key_generation.py +17 -17
  32. package/pynithy/build/securelock/src/local_api.py +189 -0
  33. package/pynithy/build/securelock/src/models.py +200 -176
  34. package/pynithy/build/securelock/src/securelock.py.tmpl +1037 -731
  35. package/pynithy/build/securelock/src/swift_stream_service.py +206 -186
  36. package/pynithy/build.mjs +139 -89
  37. package/pynithy/run/docker-compose-final.yml.tmpl +58 -51
  38. package/pynithy/run/docker-compose.yml.tmpl +62 -48
  39. package/pynithy/run/etny-securelock-test.yaml.tpl +4 -1
  40. package/pynithy/run/image_registry.js +17 -4
  41. package/pynithy/run.js +44 -28
  42. package/pynithy/src/serverless/Dockerfile.serverless +8 -0
  43. package/pynithy/src/serverless/requirements.txt +6 -0
  44. package/run.js +69 -28
  45. package/nodenithy/build/las/Dockerfile +0 -5
  46. package/pynithy/build/docker-compose.yml +0 -70
  47. package/pynithy/build/las/Dockerfile +0 -11
  48. package/pynithy/build/las/src/etny_entrypoint.sh +0 -6
  49. package/pynithy/build/las/src/las_entrypoint.sh +0 -26
  50. package/pynithy/build/scripts/binary-fs-build.sh +0 -28
  51. 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 = !templateName.includes('testnet');
64
- // A testnet template with a SessionRegistry is CAS-attested by the
65
- // ethernity-cas validator set: the session is registered on-chain, the
66
- // enclave is provisioned from a validator, and the certificate comes out of
67
- // the CAS session. Other testnets self-sign and register nothing.
68
- const casTestnet = !isMainnet && casConfig.casProvisioned(templateName, isMainnet);
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
- const backupFiles = ['docker-compose.yml.tmpl', 'docker-compose-final.yml.tmpl'];
111
- backupFiles.forEach(file => {
112
- if (!fs.existsSync(file)) {
113
- console.error(`Error: ${file} not found!`);
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 backupContent = fs.readFileSync(file, 'utf8');
117
- fs.writeFileSync(file.replace('.tmpl', ''), backupContent, 'utf8');
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 (isMainnet || casTestnet) {
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
- processYamlTemplate('etny-securelock-test.yaml.tpl', 'etny-securelock-test.yaml', replacementsSecurelock);
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. Every other
228
- // network keeps the Scontain CAS registration that follows.
229
- if (casTestnet) {
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
- let ENCLAVE_NAME_TRUSTEDZONE = 'etny-pynithy-trustedzone-v3-testnet-0.1.12'
433
- if (isMainnet) {
434
- ENCLAVE_NAME_TRUSTEDZONE = 'ecld-pynithy-trustedzone-v3-3.0.0'
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 "${process.env.PROJECT_NAME}" --protocol_version "v3" --network "${process.env.BLOCKCHAIN_NETWORK}" --template_version "${process.env.VERSION}"`, { stdio: 'inherit' });
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("Adding certificates for SECURELOCK into IMAGE REGISTRY smart contract...");
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}" "${process.env.PROJECT_NAME}" "${process.env.VERSION}" "${process.env.PRIVATE_KEY}" "registerSecureLockImage"`, { stdio: "inherit" });
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.
@@ -0,0 +1,8 @@
1
+ FROM etny-securelock-base
2
+
3
+ # System packages your backend needs, added to the securelock base image by
4
+ # ecld-build.
5
+ #
6
+ # Example:
7
+ # RUN apk update
8
+ # RUN apk add gcc g++ git openblas-dev
@@ -0,0 +1,6 @@
1
+ # Python packages your backend imports, one per line; ecld-build installs them
2
+ # into the securelock enclave.
3
+ # Example:
4
+ #
5
+ # scipy
6
+ # numpy
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
- * TRUSTED_ZONE_IMAGE the trustedzone enclave
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. Built from the runner's own ECAddress
44
- * so it can't drift. Accepts a few spellings per network. */
45
- function networkAddress(ECAddress, raw) {
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: ECAddress.BLOXBERG.TESTNET_ADDRESS,
49
- BLOXBERG_MAINNET: ECAddress.BLOXBERG.MAINNET_ADDRESS,
50
- POLYGON_MAINNET: ECAddress.POLYGON.MAINNET_ADDRESS,
51
- POLYGON_AMOY: ECAddress.POLYGON.TESTNET_ADDRESS,
52
- POLYGON_AMOY_TESTNET: ECAddress.POLYGON.TESTNET_ADDRESS,
53
- IOTEX_TESTNET: ECAddress.IOTEX && ECAddress.IOTEX.TESTNET_ADDRESS,
54
- ETHEREUM_SEPOLIA: ECAddress.SEPOLIA && ECAddress.SEPOLIA.TESTNET_ADDRESS,
55
- SEPOLIA: ECAddress.SEPOLIA && ECAddress.SEPOLIA.TESTNET_ADDRESS,
56
- LITVM_LITEFORGE: ECAddress.LITVM && ECAddress.LITVM.TESTNET_ADDRESS,
57
- LITVM: ECAddress.LITVM && ECAddress.LITVM.TESTNET_ADDRESS,
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, address: table[key] || null, known: Object.keys(table) };
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
- enclaves: --securelock <name> (default PROJECT_NAME), --trustedzone <name> (default TRUSTED_ZONE_IMAGE)
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, ECAddress, ECOrderTaskStatus;
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
- const enums = await import('@ethernity-cloud/runner/enums.js');
129
- ({ ECStatus, ECEvent, ECAddress, ECOrderTaskStatus } = enums);
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.4.4): ' + e.message);
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
- const rawNetwork = opts.network || process.env.BLOCKCHAIN_NETWORK || 'BLOXBERG_TESTNET';
138
- const { key: netKey, address, known } = networkAddress(ECAddress, rawNetwork);
139
- if (!address) {
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
- const trustedzone = opts.trustedzone || process.env.TRUSTED_ZONE_IMAGE; // may be undefined -> run() default
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,5 +0,0 @@
1
- FROM registry.ethernity.cloud:443/debuggingdelight/ethernity-cloud-sdk-registry/sconecuratedimages/services:las as initial
2
-
3
- FROM scratch
4
-
5
- COPY --from=initial / /
@@ -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,11 +0,0 @@
1
- FROM registry.scontain.com:5050/sconecuratedimages/services:las as initial
2
-
3
- FROM scratch
4
-
5
- COPY --from=initial / /
6
-
7
- RUN apt-get update
8
- RUN apt-get install psmisc
9
-
10
- COPY src/* /
11
-
@@ -1,6 +0,0 @@
1
-
2
- #!/bin/bash
3
-
4
- ( tail -f -n0 /var/log/las.log & ) | grep -q "Sign request failed with Enclave lost after power transition or used in child process created by"
5
-
6
- killall -9 las
@@ -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"]