@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
|
@@ -1 +1 @@
|
|
|
1
|
-
[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"wallet","type":"address"}],"name":"AllowedWalletAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"wallet","type":"address"}],"name":"AllowedWalletRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"ipfsHash","type":"string"},{"indexed":false,"internalType":"string","name":"publicKey","type":"string"},{"indexed":false,"internalType":"string","name":"version","type":"string"}],"name":"ImageAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"ipfsHash","type":"string"}],"name":"ImagePublished","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"ipfsHash","type":"string"}],"name":"ImageRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"ipfsHash","type":"string"}],"name":"ImageValidated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"ipfsHash","type":"string"}],"name":"TrustedZoneImageAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"ipfsHash","type":"string"}],"name":"TrustedZoneImageRemoved","type":"event"},{"inputs":[{"internalType":"address","name":"wallet","type":"address"}],"name":"addAllowedWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"ipfsHash","type":"string"},{"internalType":"string","name":"certPublicKey","type":"string"},{"internalType":"string","name":"version","type":"string"},{"internalType":"string","name":"imageName","type":"string"},{"internalType":"string","name":"dockerComposeHash","type":"string"},{"internalType":"string","name":"session","type":"string"},{"internalType":"uint8","name":"fee","type":"uint8"}],"name":"addImage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"ipfsHash","type":"string"},{"internalType":"string","name":"certPublicKey","type":"string"},{"internalType":"string","name":"version","type":"string"},{"internalType":"string","name":"imageName","type":"string"},{"internalType":"string","name":"dockerComposeHash","type":"string"},{"internalType":"string","name":"session","type":"string"},{"internalType":"uint8","name":"fee","type":"uint8"}],"name":"addTrustedZoneImage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"ipfsHash","type":"string"},{"internalType":"address","name":"newRewardAddress","type":"address"}],"name":"changeImageRewardAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"changeOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"ipfsHash","type":"string"},{"internalType":"address","name":"newRewardAddress","type":"address"}],"name":"changeTrustedZoneImageRewardAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"ipfsHash","type":"string"}],"name":"publishImage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"wallet","type":"address"}],"name":"removeAllowedWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"ipfsHash","type":"string"}],"name":"validateImage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"allowedWallets","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"ipfsHash","type":"string"}],"name":"getImageCertPublicKey","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"ipfsHash","type":"string"}],"name":"getImageSession","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"imageName","type":"string"},{"internalType":"string","name":"version","type":"string"}],"name":"getLatestImageVersionPublicKey","outputs":[{"internalType":"string","name":"","type":"string"},{"internalType":"string","name":"","type":"string"},{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"imageName","type":"string"},{"internalType":"string","name":"version","type":"string"}],"name":"getLatestTrustedZoneImageCertPublicKey","outputs":[{"internalType":"string","name":"","type":"string"},{"internalType":"string","name":"","type":"string"},{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"ipfsHash","type":"string"}],"name":"getRewardAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"ipfsHash","type":"string"}],"name":"getTrustedZoneImageCertPublicKey","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"ipfsHash","type":"string"}],"name":"getTrustedZoneImageSession","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"ipfsHash","type":"string"}],"name":"getTrustedZoneRewardAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"","type":"string"}],"name":"imageDetails","outputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"string","name":"ipfsHash","type":"string"},{"internalType":"string","name":"version","type":"string"},{"internalType":"string","name":"session","type":"string"},{"internalType":"uint8","name":"fee","type":"uint8"},{"internalType":"address","name":"rewardAddress","type":"address"},{"internalType":"bool","name":"validated","type":"bool"},{"internalType":"bool","name":"published","type":"bool"},{"internalType":"string","name":"certPublicKey","type":"string"},{"internalType":"string","name":"dockerComposeHash","type":"string"},{"internalType":"string","name":"name","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"images","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"","type":"string"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"imageVersions","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"","type":"string"},{"internalType":"string","name":"","type":"string"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"imageVersionsHash","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"","type":"string"}],"name":"trustedZoneImageDetails","outputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"string","name":"ipfsHash","type":"string"},{"internalType":"string","name":"version","type":"string"},{"internalType":"string","name":"session","type":"string"},{"internalType":"uint8","name":"fee","type":"uint8"},{"internalType":"address","name":"rewardAddress","type":"address"},{"internalType":"bool","name":"validated","type":"bool"},{"internalType":"bool","name":"published","type":"bool"},{"internalType":"string","name":"certPublicKey","type":"string"},{"internalType":"string","name":"dockerComposeHash","type":"string"},{"internalType":"string","name":"name","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"","type":"string"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"trustedZoneImageVersions","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"","type":"string"},{"internalType":"string","name":"","type":"string"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"trustedZoneVersionsHash","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"}]
|
|
1
|
+
[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"wallet","type":"address"}],"name":"AllowedWalletAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"wallet","type":"address"}],"name":"AllowedWalletRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"ipfsHash","type":"string"},{"indexed":false,"internalType":"string","name":"publicKey","type":"string"},{"indexed":false,"internalType":"string","name":"version","type":"string"}],"name":"ImageAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"ipfsHash","type":"string"}],"name":"ImagePublished","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"ipfsHash","type":"string"}],"name":"ImageRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"ipfsHash","type":"string"}],"name":"ImageValidated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"ipfsHash","type":"string"}],"name":"TrustedZoneImageAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"ipfsHash","type":"string"}],"name":"TrustedZoneImageRemoved","type":"event"},{"inputs":[{"internalType":"address","name":"wallet","type":"address"}],"name":"addAllowedWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"ipfsHash","type":"string"},{"internalType":"string","name":"certPublicKey","type":"string"},{"internalType":"string","name":"version","type":"string"},{"internalType":"string","name":"imageName","type":"string"},{"internalType":"string","name":"dockerComposeHash","type":"string"},{"internalType":"string","name":"session","type":"string"},{"internalType":"uint8","name":"fee","type":"uint8"}],"name":"addImage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"ipfsHash","type":"string"},{"internalType":"string","name":"certPublicKey","type":"string"},{"internalType":"string","name":"version","type":"string"},{"internalType":"string","name":"imageName","type":"string"},{"internalType":"string","name":"dockerComposeHash","type":"string"},{"internalType":"string","name":"session","type":"string"},{"internalType":"uint8","name":"fee","type":"uint8"}],"name":"addTrustedZoneImage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"ipfsHash","type":"string"},{"internalType":"address","name":"newRewardAddress","type":"address"}],"name":"changeImageRewardAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"changeOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"ipfsHash","type":"string"},{"internalType":"address","name":"newRewardAddress","type":"address"}],"name":"changeTrustedZoneImageRewardAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"ipfsHash","type":"string"}],"name":"publishImage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"wallet","type":"address"}],"name":"removeAllowedWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"ipfsHash","type":"string"}],"name":"validateImage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"allowedWallets","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"ipfsHash","type":"string"}],"name":"getImageCertPublicKey","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"ipfsHash","type":"string"}],"name":"getImageSession","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"imageName","type":"string"},{"internalType":"string","name":"version","type":"string"}],"name":"getLatestImageVersionPublicKey","outputs":[{"internalType":"string","name":"","type":"string"},{"internalType":"string","name":"","type":"string"},{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"imageName","type":"string"},{"internalType":"string","name":"version","type":"string"}],"name":"getLatestTrustedZoneImageCertPublicKey","outputs":[{"internalType":"string","name":"","type":"string"},{"internalType":"string","name":"","type":"string"},{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"ipfsHash","type":"string"}],"name":"getRewardAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"ipfsHash","type":"string"}],"name":"getTrustedZoneImageCertPublicKey","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"ipfsHash","type":"string"}],"name":"getTrustedZoneImageSession","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"ipfsHash","type":"string"}],"name":"getTrustedZoneRewardAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"","type":"string"}],"name":"imageDetails","outputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"string","name":"ipfsHash","type":"string"},{"internalType":"string","name":"version","type":"string"},{"internalType":"string","name":"session","type":"string"},{"internalType":"uint8","name":"fee","type":"uint8"},{"internalType":"address","name":"rewardAddress","type":"address"},{"internalType":"bool","name":"validated","type":"bool"},{"internalType":"bool","name":"published","type":"bool"},{"internalType":"string","name":"certPublicKey","type":"string"},{"internalType":"string","name":"dockerComposeHash","type":"string"},{"internalType":"string","name":"name","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"images","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"","type":"string"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"imageVersions","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"","type":"string"},{"internalType":"string","name":"","type":"string"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"imageVersionsHash","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"","type":"string"}],"name":"trustedZoneImageDetails","outputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"string","name":"ipfsHash","type":"string"},{"internalType":"string","name":"version","type":"string"},{"internalType":"string","name":"session","type":"string"},{"internalType":"uint8","name":"fee","type":"uint8"},{"internalType":"address","name":"rewardAddress","type":"address"},{"internalType":"bool","name":"validated","type":"bool"},{"internalType":"bool","name":"published","type":"bool"},{"internalType":"string","name":"certPublicKey","type":"string"},{"internalType":"string","name":"dockerComposeHash","type":"string"},{"internalType":"string","name":"name","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"","type":"string"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"trustedZoneImageVersions","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"","type":"string"},{"internalType":"string","name":"","type":"string"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"trustedZoneVersionsHash","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"}]
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import hashlib
|
|
2
|
-
from eth_account import Account
|
|
3
|
-
|
|
4
|
-
def get_wallet_address(first_string, second_string):
|
|
5
|
-
concat = (first_string + second_string).encode()
|
|
6
|
-
_hash1 = hashlib.sha256(concat).hexdigest()
|
|
7
|
-
_hash = hashlib.sha256(_hash1.encode()).hexdigest()
|
|
8
|
-
acct = Account.from_key(_hash)
|
|
9
|
-
return acct.address, _hash
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
if __name__ == '__main__':
|
|
13
|
-
first_string = 'test'
|
|
14
|
-
second_string = 'test'
|
|
15
|
-
(addr, private) = get_wallet_address(first_string, second_string)
|
|
16
|
-
print('account address = ', addr) # 0xf63106856F7007A30025f0fFD5A534EA880878C3
|
|
17
|
-
print('private = ', private)
|
|
1
|
+
import hashlib
|
|
2
|
+
from eth_account import Account
|
|
3
|
+
|
|
4
|
+
def get_wallet_address(first_string, second_string):
|
|
5
|
+
concat = (first_string + second_string).encode()
|
|
6
|
+
_hash1 = hashlib.sha256(concat).hexdigest()
|
|
7
|
+
_hash = hashlib.sha256(_hash1.encode()).hexdigest()
|
|
8
|
+
acct = Account.from_key(_hash)
|
|
9
|
+
return acct.address, _hash
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
if __name__ == '__main__':
|
|
13
|
+
first_string = 'test'
|
|
14
|
+
second_string = 'test'
|
|
15
|
+
(addr, private) = get_wallet_address(first_string, second_string)
|
|
16
|
+
print('account address = ', addr) # 0xf63106856F7007A30025f0fFD5A534EA880878C3
|
|
17
|
+
print('private = ', private)
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
"""Local test API over the securelock executor. NOT used inside the enclave.
|
|
2
|
+
|
|
3
|
+
This file lives in the securelock source tree on purpose: it imports and reuses
|
|
4
|
+
the exact same etny_exec module that runs inside the SGX enclave, so a payload
|
|
5
|
+
tested against this API is executed by the same code, with the same globals and
|
|
6
|
+
the same TaskStatus semantics, as a real on-chain task. What it deliberately
|
|
7
|
+
skips is everything around execution: attestation, checksums, encryption,
|
|
8
|
+
IPFS, and the blockchain.
|
|
9
|
+
|
|
10
|
+
Launched by `ecld-test serve` (which puts the project's src/ on sys.path so
|
|
11
|
+
`serverless.backend` resolves to the developer's backend, exactly as inside
|
|
12
|
+
binary-fs). The runners' LOCAL mode talks to it:
|
|
13
|
+
|
|
14
|
+
GET /v1/health -> {"status": "ok", "backend": [...function names...]}
|
|
15
|
+
POST /v1/task {"payload": "...", "input": "..."|null}
|
|
16
|
+
-> {"task_code": 0, "task_code_name": "SUCCESS",
|
|
17
|
+
"result": "...", "checksum": "<sha256(result)>",
|
|
18
|
+
"enclave_challenge": "<20 chars>",
|
|
19
|
+
"result_string": "v3:<code>:<checksum>:<challenge>:"}
|
|
20
|
+
|
|
21
|
+
The enclave is stateless per task and so is this server: every POST is one
|
|
22
|
+
isolated execution.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
import hashlib
|
|
26
|
+
import json
|
|
27
|
+
import random
|
|
28
|
+
import string
|
|
29
|
+
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
|
|
30
|
+
|
|
31
|
+
import etny_exec
|
|
32
|
+
|
|
33
|
+
# Local ESR emulation. ON BY DEFAULT so `ecld-test` matches a real ESR-enabled
|
|
34
|
+
# build with no extra setup: a StateRegistry() in the backend works fully
|
|
35
|
+
# in-process against an in-memory registry + store -- no chain, node, or SGX.
|
|
36
|
+
# See esr_local.py. Disabled only if installation fails (e.g. no web3 dep).
|
|
37
|
+
_ESR = {"installed": False, "default_caller": None, "handles": None}
|
|
38
|
+
|
|
39
|
+
TASK_STATUS_NAMES = {
|
|
40
|
+
0: "SUCCESS",
|
|
41
|
+
1: "SYSTEM_ERROR",
|
|
42
|
+
2: "KEY_ERROR",
|
|
43
|
+
3: "SYNTAX_WARNING",
|
|
44
|
+
4: "BASE_EXCEPTION",
|
|
45
|
+
5: "PAYLOAD_NOT_DEFINED",
|
|
46
|
+
6: "PAYLOAD_CHECKSUM_ERROR",
|
|
47
|
+
7: "INPUT_CHECKSUM_ERROR",
|
|
48
|
+
8: "EXECVE",
|
|
49
|
+
28: "IMPORT_ERROR",
|
|
50
|
+
32: "CONFIG_ERROR",
|
|
51
|
+
33: "EXECUTION_TIMEOUT",
|
|
52
|
+
34: "ESR_GAS_LIMIT_EXCEEDED",
|
|
53
|
+
35: "SECURITY_VIOLATION",
|
|
54
|
+
36: "ESR_NONCE_VIOLATION",
|
|
55
|
+
37: "ESR_RELAY_TIMEOUT",
|
|
56
|
+
38: "ESR_COMMIT_LIMIT_EXCEEDED",
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def _challenge(length=20):
|
|
61
|
+
# Same shape as the trustedzone's enclave challenge (base36).
|
|
62
|
+
alphabet = string.ascii_lowercase + string.digits
|
|
63
|
+
return "".join(random.choice(alphabet) for _ in range(length))
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def _install_esr(default_caller=None, persist=True):
|
|
67
|
+
"""Install the local ESR emulator into ecld_state (best-effort). ON by
|
|
68
|
+
default so ecld-test matches a real ESR-enabled build."""
|
|
69
|
+
try:
|
|
70
|
+
import ecld_state
|
|
71
|
+
import esr_local
|
|
72
|
+
handles = esr_local.install(
|
|
73
|
+
ecld_state, caller=default_caller,
|
|
74
|
+
file_prefix=".ecld-esr-local" if persist else None)
|
|
75
|
+
_ESR["installed"] = True
|
|
76
|
+
_ESR["default_caller"] = default_caller
|
|
77
|
+
_ESR["handles"] = handles
|
|
78
|
+
return True
|
|
79
|
+
except Exception as e:
|
|
80
|
+
_ESR["installed"] = False
|
|
81
|
+
print(f"[local-api] ESR emulation unavailable: {e}")
|
|
82
|
+
return False
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def _set_caller(caller):
|
|
86
|
+
"""Set the task caller EXACTLY as the real securelock does after the
|
|
87
|
+
trustedzone hands it the DO owner -- available to any payload via
|
|
88
|
+
task_caller(), and used by the ESR ACL. Applies whether or not the payload
|
|
89
|
+
uses ESR."""
|
|
90
|
+
try:
|
|
91
|
+
import ecld_state
|
|
92
|
+
ecld_state._task_caller = ecld_state._norm_addr(caller) if caller else None
|
|
93
|
+
except Exception:
|
|
94
|
+
pass
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def run_task(payload, input_data=None, caller=None):
|
|
98
|
+
"""One task through the real executor; returns the API response dict.
|
|
99
|
+
|
|
100
|
+
`caller` mirrors the trustedzone-attested DO owner the real securelock
|
|
101
|
+
receives: it is set for EVERY task (not just ESR ones), so task_caller()
|
|
102
|
+
behaves locally as it does in the enclave. Falls back to the server's
|
|
103
|
+
default caller when a request does not specify one."""
|
|
104
|
+
effective_caller = caller if caller is not None else _ESR.get("default_caller")
|
|
105
|
+
_set_caller(effective_caller)
|
|
106
|
+
code, result = etny_exec.execute_task_v3(payload, input_data)
|
|
107
|
+
result_text = result if isinstance(result, str) else repr(result)
|
|
108
|
+
checksum = hashlib.sha256(result_text.encode("utf-8")).hexdigest()
|
|
109
|
+
challenge = _challenge()
|
|
110
|
+
return {
|
|
111
|
+
"task_code": code,
|
|
112
|
+
"task_code_name": TASK_STATUS_NAMES.get(code, f"UNKNOWN_{code}"),
|
|
113
|
+
"result": result_text,
|
|
114
|
+
"checksum": checksum,
|
|
115
|
+
"enclave_challenge": challenge,
|
|
116
|
+
"result_string": f"v3:{code}:{checksum}:{challenge}:",
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
class Handler(BaseHTTPRequestHandler):
|
|
121
|
+
server_version = "ecld-local-api/1.0"
|
|
122
|
+
|
|
123
|
+
def _send(self, status, obj):
|
|
124
|
+
body = json.dumps(obj).encode("utf-8")
|
|
125
|
+
self.send_response(status)
|
|
126
|
+
self.send_header("Content-Type", "application/json")
|
|
127
|
+
self.send_header("Content-Length", str(len(body)))
|
|
128
|
+
# Browser dApps (JS runner local mode) call this from another origin.
|
|
129
|
+
self.send_header("Access-Control-Allow-Origin", "*")
|
|
130
|
+
self.send_header("Access-Control-Allow-Headers", "Content-Type")
|
|
131
|
+
self.end_headers()
|
|
132
|
+
self.wfile.write(body)
|
|
133
|
+
|
|
134
|
+
def do_OPTIONS(self):
|
|
135
|
+
self._send(204, {})
|
|
136
|
+
|
|
137
|
+
def do_GET(self):
|
|
138
|
+
if self.path == "/v1/health":
|
|
139
|
+
funcs = sorted(getattr(etny_exec, "sdkFunctions", {}).keys())
|
|
140
|
+
self._send(200, {"status": "ok", "backend": funcs})
|
|
141
|
+
else:
|
|
142
|
+
self._send(404, {"error": "not found"})
|
|
143
|
+
|
|
144
|
+
def do_POST(self):
|
|
145
|
+
if self.path != "/v1/task":
|
|
146
|
+
self._send(404, {"error": "not found"})
|
|
147
|
+
return
|
|
148
|
+
try:
|
|
149
|
+
length = int(self.headers.get("Content-Length", 0))
|
|
150
|
+
req = json.loads(self.rfile.read(length) or b"{}")
|
|
151
|
+
payload = req.get("payload")
|
|
152
|
+
if not isinstance(payload, str) or not payload.strip():
|
|
153
|
+
self._send(400, {"error": "payload (string) is required"})
|
|
154
|
+
return
|
|
155
|
+
input_data = req.get("input")
|
|
156
|
+
if input_data is not None and not isinstance(input_data, str):
|
|
157
|
+
input_data = json.dumps(input_data)
|
|
158
|
+
# A request may name the task caller (the DO owner the trustedzone
|
|
159
|
+
# would attest); else the server's default caller is used.
|
|
160
|
+
caller = req.get("caller")
|
|
161
|
+
self._send(200, run_task(payload, input_data, caller=caller))
|
|
162
|
+
except json.JSONDecodeError:
|
|
163
|
+
self._send(400, {"error": "invalid JSON body"})
|
|
164
|
+
except Exception as e: # harness fault, not a task result
|
|
165
|
+
self._send(500, {"error": str(e)})
|
|
166
|
+
|
|
167
|
+
def log_message(self, fmt, *args):
|
|
168
|
+
print(f"[local-api] {self.address_string()} {fmt % args}")
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
def serve(host="127.0.0.1", port=8745, caller=None, esr=True, persist=True):
|
|
172
|
+
funcs = sorted(getattr(etny_exec, "sdkFunctions", {}).keys())
|
|
173
|
+
print(f"[local-api] backend functions: {funcs if funcs else 'none (stock-enclave mode)'}")
|
|
174
|
+
if esr:
|
|
175
|
+
if _install_esr(default_caller=caller, persist=persist):
|
|
176
|
+
wallet = None
|
|
177
|
+
try:
|
|
178
|
+
import ecld_state
|
|
179
|
+
wallet = ecld_state.StateRegistry().wallet_address
|
|
180
|
+
except Exception:
|
|
181
|
+
pass
|
|
182
|
+
print(f"[local-api] ESR emulation: ON (in-process, no chain)"
|
|
183
|
+
+ (f" enclave wallet {wallet}" if wallet else ""))
|
|
184
|
+
caller_note = caller or "(none -- pass 'caller' per request)"
|
|
185
|
+
print(f"[local-api] task caller: {caller_note}")
|
|
186
|
+
if persist:
|
|
187
|
+
print("[local-api] ESR state persists in .ecld-esr-local.*.json")
|
|
188
|
+
print(f"[local-api] listening on http://{host}:{port} (POST /v1/task, GET /v1/health)")
|
|
189
|
+
ThreadingHTTPServer((host, port), Handler).serve_forever()
|