Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 81 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,87 @@ pynithy/
- **[`nodenithy/`](command:_github.copilot.openRelativePath?%5B%7B%22scheme%22%3A%22file%22%2C%22authority%22%3A%22%22%2C%22path%22%3A%22%2FUsers%2Fbullet%2Fethernity%2Fethernity-cloud-sdk-js%2Fnodenithy%2F%22%2C%22query%22%3A%22%22%2C%22fragment%22%3A%22%22%7D%5D "/Users/bullet/ethernity/ethernity-cloud-sdk-js/nodenithy/")**: Contains various scripts and modules for the project.
- **[`pynithy/`](command:_github.copilot.openRelativePath?%5B%7B%22scheme%22%3A%22file%22%2C%22authority%22%3A%22%22%2C%22path%22%3A%22%2FUsers%2Fbullet%2Fethernity%2Fethernity-cloud-sdk-js%2Fpynithy%2F%22%2C%22query%22%3A%22%22%2C%22fragment%22%3A%22%22%7D%5D "/Users/bullet/ethernity/ethernity-cloud-sdk-js/pynithy/")**: Contains Python-related scripts and configurations.

## Usage

To use the SDK:
- after installation, run `npm run ecld-init` to initialize the project
- in you workspace, you will find the `scr/serverless` directory, this contains a `backend.js` file. This file will be imported in the dApp images to provide the backend functions for calling from the frontend of your application, eg.:
```js
function hello(msg='World') {
return "Hello "+msg;
}

module.exports = { hello };
```
From your frontend application, using the ethernity cloud runner library, you will be calling the function as seen in the below example, where we pass `hello("World");` to be executed on the backend which will run in the Blockchain:
```js
const AppCss = require('./App.css');
import EthernityCloudRunner from "@ethernity-cloud/runner";
import {ECEvent, ECRunner, ECStatus} from "@ethernity-cloud/runner/enums";
import Web3 from 'web3';

const PROJECT_NAME = "";
const IPFS_ENDPOINT = "";

const code = `hello("World");`;

function App() {
const executeTask = async () => {
const runner = new EthernityCloudRunner();
// this is a server provided by Ethernity CLOUD, please bear in mind that you can use your own Decentralized Storage server
const ipfsAddress = IPFS_ENDPOINT;
runner.initializeStorage(ipfsAddress);
console.log(PROJECT_NAME)
const onTaskProgress = (e) => {
if (e.detail.status === ECStatus.ERROR) {
console.error(e.detail.message);
} else {
console.log(e.detail.message);
}
};

const onTaskCompleted = (e) => {
console.log(`Task Result: ${e.detail.message.result}`);
// display the result in page below the buttons
const result = document.createElement("p");
result.innerHTML = `Task Result: ${e.detail.message.result}`;
document.body.appendChild(result);
}

runner.addEventListener(ECEvent.TASK_PROGRESS, onTaskProgress);
runner.addEventListener(ECEvent.TASK_COMPLETED, onTaskCompleted);

await runner.run(PROJECT_NAME,
code,
'',
{ taskPrice: 10, cpu: 1, memory: 1, storage: 10, bandwidth: 1, duration: 1, validators: 1 });
};
const connectWallet = async () => {
if (window.ethereum) {
window.web3 = new Web3(window.ethereum);
try {
// Request account access
await window.ethereum.request({ method: 'eth_requestAccounts' });
console.log("Wallet connected");
} catch (error) {
console.error("User denied account access");
}
} else {
console.log('Please install MetaMask!');
}
};

return (
<div className="container">
<button className="centeredButton" onClick={executeTask}>Execute Task</button>
<button className="centeredButton" onClick={connectWallet}>Connect Wallet</button>
</div>
);
}
export default App;
```
- you are able to define the functions needed to be used in the backend, while making sure that the function that is script is compilable and that it exports the function that will be called from the frontend, in the above example, the `hello` function.

## Contributing

Contributions are welcome! Please open an issue or submit a pull request.
Expand Down
8 changes: 6 additions & 2 deletions build.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,16 @@ const serviceType = process.env.SERVICE_TYPE;

if (serviceType === "Nodenithy") {
console.log("Adding prerequisites for Nodenithy...");
const scriptPath = path.resolve(__dirname, 'nodenithy/build.js');
const scriptPath = path.resolve(__dirname, 'nodenithy/build.mjs');
console.log(`Running script: ${scriptPath}`);
execSync(`node ${scriptPath}`, { stdio: 'inherit' });
console.log(`Build script finished. You can now proceed to publish: npm run ecld-publish.`);
} else if (serviceType === "Pynithy") {
console.log("Adding prerequisites for Pynithy...");
// Add any additional commands for Pynithy here if needed
const scriptPath = path.resolve(__dirname, 'pynithy/build.mjs');
console.log(`Running script: ${scriptPath}`);
execSync(`node ${scriptPath}`, { stdio: 'inherit' });
console.log(`Build script finished. You can now proceed to publish: npm run ecld-publish.`);
} else {
console.error("Something went wrong");
process.exit(1);
Expand Down
62 changes: 45 additions & 17 deletions init.js
Original file line number Diff line number Diff line change
Expand Up @@ -216,19 +216,35 @@ const main = async () => {

if (useAppTemplate === "yes") {
console.log("Bringing Frontend/Backend templates...");
console.log(" src/serverless/backend.js (Hello World function)");
console.log(
" src/ec_helloworld_example.js (Hello World function call - Frontend)",
);
// Simulate copying files
fs.cpSync("node_modules/ethernity-cloud-sdk-js/nodenithy/src/", "src/", {
recursive: true,
});
fs.cpSync(
"node_modules/ethernity-cloud-sdk-js/nodenithy/public/",
"public/",
{ recursive: true },
);
if (serviceType === "Nodenithy") {
console.log(" src/serverless/backend.js (Hello World function)");
console.log(
" src/ec_helloworld_example.js (Hello World function call - Frontend)",
);
// Simulate copying files
fs.cpSync("node_modules/ethernity-cloud-sdk-js/nodenithy/src/", "src/", {
recursive: true,
});
fs.cpSync(
"node_modules/ethernity-cloud-sdk-js/nodenithy/public/",
"public/",
{ recursive: true },
);
} else if (serviceType === "Pynithy") {
console.log(" src/serverless/backend.py (Hello World function)");
console.log(
" src/ec_helloworld_example.js (Hello World function call - Frontend)",
);
// Simulate copying files
fs.cpSync("node_modules/ethernity-cloud-sdk-js/pynithy/src/", "src/", {
recursive: true,
});
fs.cpSync(
"node_modules/ethernity-cloud-sdk-js/pynithy/public/",
"public/",
{ recursive: true },
);
}
console.log("Installing required packages...");
// Simulate npm install
execSync(
Expand All @@ -237,7 +253,7 @@ const main = async () => {
);
} else {
console.log(
"Define backend functions in src/ectasks to be available for Frontend interaction.",
"Define backend functions in src/serverless to be available for Frontend interaction.",
);
}

Expand All @@ -250,22 +266,34 @@ const main = async () => {
writeEnv("DOCKER_PASSWORD", dockerPassword);
} else if (serviceType === "Nodenithy") {
writeEnv("BASE_IMAGE_TAG", "");
writeEnv("DOCKER_REPO_URL", "registry.scontain.com:5050");
writeEnv("DOCKER_REPO_URL", "");
writeEnv("DOCKER_LOGIN", "");
writeEnv("DOCKER_PASSWORD", "");
} else if (serviceType === "Pynithy") {
writeEnv("BASE_IMAGE_TAG", "");
writeEnv("DOCKER_REPO_URL", "registry.scontain.com:5050");
writeEnv("DOCKER_REPO_URL", "");
writeEnv("DOCKER_LOGIN", "");
writeEnv("DOCKER_PASSWORD", "");
}
// write TRUSTED_ZONE_IMAGE {token}_{name}{networktype} with the following rules:
// - token should be ecld if network is polygon, etny if network is bloxberg
// - name should be serviceType.toLowerCase()
// - networktype should be "" if network contains 'mainnet' else '_testnet'
writeEnv(
"TRUSTED_ZONE_IMAGE",
`${blockchainNetwork.includes("Polygon") ? "ecld" : "etny"
}-${serviceType.toLowerCase()}${blockchainNetwork.includes("Mainnet") ? "" : "-testnet"
}`,
);


writeEnv("BLOCKCHAIN_NETWORK", blockchainNetwork.replace(/ /g, "_"));
writeEnv("IPFS_ENDPOINT", customUrl);
writeEnv("IPFS_TOKEN", ipfsToken || "");
writeEnv("VERSION", "v1");
console.log();
console.log(
"To start the application, run the appropriate start command based on your setup.",
"You can proceed to run ecld-build, once you set up the serverless functions or directly if you want to test with the provided template.",
);
rl.close();
};
Expand Down
83 changes: 50 additions & 33 deletions nodenithy/build.js → nodenithy/build.mjs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
const AdmZip = require('adm-zip');
const shell = require('shelljs');
const fs = require('fs');
const path = require('path');
require('dotenv').config();
import shell from 'shelljs';
import fs from 'fs';
import path from 'path';
import dotenv from 'dotenv';
dotenv.config();

const VERSION = process.env.VERSION;
console.log(`Building ${VERSION}`);
Expand All @@ -25,7 +25,16 @@ const writeEnv = (key, value) => {

fs.writeFileSync(envFile, envContent, 'utf8');
};

// runner name: [smart contract address, image registry address, rpc url, chainid]
export const ECRunner = {
'etny-pynithy-testnet': ['0x02882F03097fE8cD31afbdFbB5D72a498B41112c', '0x15D73a742529C3fb11f3FA32EF7f0CC3870ACA31', 'https://core.bloxberg.org', 8995],
'etny-nodenithy-testnet': ['0x02882F03097fE8cD31afbdFbB5D72a498B41112c', '0x15D73a742529C3fb11f3FA32EF7f0CC3870ACA31', 'https://core.bloxberg.org', 8995],
'etny-pynithy': ['0x549A6E06BB2084100148D50F51CF77a3436C3Ae7', '0x15D73a742529C3fb11f3FA32EF7f0CC3870ACA31', 'https://core.bloxberg.org', 8995],
'etny-nodenithy': ['0x549A6E06BB2084100148D50F51CF77a3436C3Ae7', '0x15D73a742529C3fb11f3FA32EF7f0CC3870ACA31', 'https://core.bloxberg.org', 8995],
'ecld-nodenithy-testnet': ['0x4274b1188ABCfa0d864aFdeD86bF9545B020dCDf', '0xF7F4eEb3d9a64387F4AcEb6d521b948E6E2fB049', 'https://rpc-mumbai.matic.today', 80001],
'ecld-pynithy': ['0x439945BE73fD86fcC172179021991E96Beff3Cc4', '0x689f3806874d3c8A973f419a4eB24e6fBA7E830F', 'https://polygon-rpc.com', 137],
'ecld-nodenithy': ['0x439945BE73fD86fcC172179021991E96Beff3Cc4', '0x689f3806874d3c8A973f419a4eB24e6fBA7E830F', 'https://polygon-rpc.com', 137]
};

const runCommand = (command, canPass = false) => {
if (shell.exec(command).code !== 0 && !canPass) {
Expand Down Expand Up @@ -77,24 +86,15 @@ fs.readdirSync(srcDir).forEach(file => {

process.chdir(buildDir);

let templateName = "";
if (process.env.BLOCKCHAIN_NETWORK === 'Bloxberg_Testnet') {
templateName = 'etny-nodenithy-testnet';
} else if (process.env.BLOCKCHAIN_NETWORK === 'Bloxberg_Mainnet') {
templateName = 'etny-nodenithy';
} else if (process.env.BLOCKCHAIN_NETWORK === 'Polygon_Mainnet') {
templateName = 'ecld-nodenithy';
} else if (process.env.BLOCKCHAIN_NETWORK === 'Polygon_Amoy_Testnet') {
templateName = 'ecld-nodenithy-testnet';
} else {
templateName = 'etny-nodenithy-testnet';
}
let templateName = process.env.TRUSTED_ZONE_IMAGE || 'etny-nodenithy-testnet';

const isMainnet = !templateName.includes('testnet');

const ENCLAVE_NAME_TRUSTEDZONE = templateName;

runCommand('docker pull registry:2');
runCommand('docker run -d --restart=always -p 5000:5000 --name registry registry:2');
runCommand(`docker login ${process.env.DOCKER_REPO_URL} -u ${process.env.DOCKER_LOGIN} -p ${process.env.DOCKER_PASSWORD}`);
// runCommand(`docker login ${process.env.DOCKER_REPO_URL} -u ${process.env.DOCKER_LOGIN} -p ${process.env.DOCKER_PASSWORD}`);

// const CI_COMMIT_BRANCH = process.env.PROJECT_NAME;
// aleXPRoj-securelock-v3-testnet-0.1.0...
Expand All @@ -106,9 +106,19 @@ console.log('Building etny-securelock');
process.chdir('securelock');
// runCommand(`cat Dockerfile.tmpl | sed s/"__ENCLAVE_NAME_SECURELOCK__"/"${ENCLAVE_NAME_SECURELOCK}"/g > Dockerfile`);
const dockerfileSecureTemplate = fs.readFileSync('Dockerfile.tmpl', 'utf8');
const dockerfileSecureContent = dockerfileSecureTemplate.replace(/__ENCLAVE_NAME_SECURELOCK__/g, ENCLAVE_NAME_SECURELOCK).replace(/__BUCKET_NAME__/g, templateName+"-v3");
const dockerfileSecureContent = dockerfileSecureTemplate.replace(/__ENCLAVE_NAME_SECURELOCK__/g, ENCLAVE_NAME_SECURELOCK).replace(/__BUCKET_NAME__/g, templateName + "-v3").replace(/__SMART_CONTRACT_ADDRESS__/g, ECRunner[templateName][0]).replace(/__IMAGE_REGISTRY_ADDRESS__/g, ECRunner[templateName][1]).replace(/__RPC_URL__/g, ECRunner[templateName][2]).replace(/__CHAIN_ID__/g, ECRunner[templateName][3]).replace(/__TRUSTED_ZONE_IMAGE__/g, templateName);

fs.writeFileSync('Dockerfile', dockerfileSecureContent);

let imagesTag = process.env.BLOCKCHAIN_NETWORK.toLowerCase();

if (isMainnet) {
fs.writeFileSync('Dockerfile', dockerfileSecureContent.replace('# RUN scone-signer sign', 'RUN scone-signer sign'));
imagesTag = process.env.BLOCKCHAIN_NETWORK.split("_")[0].toLowerCase()
}




runCommand(`docker build --build-arg ENCLAVE_NAME_SECURELOCK=${ENCLAVE_NAME_SECURELOCK} -t etny-securelock:latest .`);
runCommand('docker tag etny-securelock localhost:5000/etny-securelock');
Expand All @@ -133,26 +143,33 @@ process.chdir('trustedzone');
// runCommand('docker tag etny-trustedzone localhost:5000/etny-trustedzone');
// runCommand('docker push localhost:5000/etny-trustedzone');
// runCommand('docker save etny-trustedzone:latest -o etny-trustedzone.tar');
const zip = new AdmZip('etny-trustedzone.tar.zip');
zip.extractAllTo('.', true);
// const zip = new AdmZip('etny-trustedzone.tar.zip');
// zip.extractAllTo('.', true);

runCommand('docker load -i etny-trustedzone.tar');
runCommand('docker tag etny-trustedzone:latest localhost:5000/etny-trustedzone');
runCommand(`docker pull registry.ethernity.cloud:443/debuggingdelight/ethernity-cloud-sdk-registry/ethernity/etny-trustedzone:${imagesTag}`);
runCommand(`docker tag registry.ethernity.cloud:443/debuggingdelight/ethernity-cloud-sdk-registry/ethernity/etny-trustedzone:${imagesTag} localhost:5000/etny-trustedzone`);
runCommand('docker push localhost:5000/etny-trustedzone');

console.log('Building validator');
process.chdir('../validator');
runCommand('docker build -t etny-validator:latest .');
runCommand('docker tag etny-validator localhost:5000/etny-validator');
runCommand('docker push localhost:5000/etny-validator');
// runCommand('docker save etny-validator:latest -o etny-validator.tar');
if (isMainnet) {
console.log('Building validator');
process.chdir('../validator');
// runCommand('docker build -t etny-validator:latest .');
// runCommand('docker tag etny-validator localhost:5000/etny-validator');
// runCommand('docker push localhost:5000/etny-validator');
runCommand(`docker pull registry.ethernity.cloud:443/debuggingdelight/ethernity-cloud-sdk-registry/ethernity/etny-validator:${imagesTag}`);
runCommand(`docker tag registry.ethernity.cloud:443/debuggingdelight/ethernity-cloud-sdk-registry/ethernity/etny-validator:${imagesTag} localhost:5000/etny-validator`);
runCommand('docker push localhost:5000/etny-validator');
}


console.log('Building etny-las');
process.chdir('../las');
runCommand('docker build -t etny-las .');
runCommand('docker tag etny-las localhost:5000/etny-las');
// runCommand('docker build -t etny-las .');
// runCommand('docker tag etny-las localhost:5000/etny-las');
// runCommand('docker push localhost:5000/etny-las');
runCommand(`docker pull registry.ethernity.cloud:443/debuggingdelight/ethernity-cloud-sdk-registry/ethernity/etny-las:${imagesTag}`);
runCommand(`docker tag registry.ethernity.cloud:443/debuggingdelight/ethernity-cloud-sdk-registry/ethernity/etny-las:${imagesTag} localhost:5000/etny-las`);
runCommand('docker push localhost:5000/etny-las');
// runCommand('docker save etny-las:latest -o etny-las.tar');


process.chdir(currentDir);
Expand Down
2 changes: 1 addition & 1 deletion nodenithy/build/las/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM registry.scontain.com:5050/sconecuratedimages/services:las as initial
FROM registry.ethernity.cloud:443/debuggingdelight/ethernity-cloud-sdk-registry/sconecuratedimages/services:las as initial

FROM scratch

Expand Down
15 changes: 11 additions & 4 deletions nodenithy/build/securelock/Dockerfile.tmpl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM registry.scontain.com:5050/ethernity/node:16.13.1-alpine3.15-scone5.8-production as release
FROM registry.ethernity.cloud:443/debuggingdelight/ethernity-cloud-sdk-registry/ethernity/node:16.13.1-alpine3.15-scone5.8-production as release

RUN apk update

Expand All @@ -11,6 +11,12 @@ ENV SCONE_HEAP=256M
ENV SCONE_LOG=DEBUG
ENV ENCLAVE_NAME_SECURELOCK=__ENCLAVE_NAME_SECURELOCK__
ENV BUCKET_NAME=__BUCKET_NAME__
ENV SMART_CONTRACT_ADDRESS=__SMART_CONTRACT_ADDRESS__
ENV IMAGE_REGISTRY_ADDRESS=__IMAGE_REGISTRY_ADDRESS__
ENV RPC_URL=__RPC_URL__
ENV CHAIN_ID=__CHAIN_ID__
ENV TRUSTED_ZONE_IMAGE=__TRUSTED_ZONE_IMAGE__

RUN mkdir binary-fs-dir

COPY ./src /etny-securelock/
Expand All @@ -26,14 +32,14 @@ WORKDIR /
RUN ["chmod", "+x", "etny-securelock/binary-fs-build.sh"]
RUN etny-securelock/binary-fs-build.sh

FROM registry.scontain.com:5050/sconecuratedimages/crosscompilers as build
FROM registry.ethernity.cloud:443/debuggingdelight/ethernity-cloud-sdk-registry/sconecuratedimages/crosscompilers as build

COPY --from=release /binary-fs-dir /.

RUN scone gcc ./binary_fs_blob.s ./libbinary_fs_template.a -shared -o /libbinary-fs.so

#
FROM registry.scontain.com:5050/ethernity/node:16.13.1-alpine3.15-scone5.8-production
FROM registry.ethernity.cloud:443/debuggingdelight/ethernity-cloud-sdk-registry/ethernity/node:16.13.1-alpine3.15-scone5.8-production

COPY --from=build /libbinary-fs.so /lib/libbinary-fs.so
#
Expand All @@ -50,7 +56,8 @@ ENV SCONE_HEAP=1024M
ENV SCONE_ALLOW_DLOPEN=1
ENV SCONE_EXTENSIONS_PATH=/lib/libbinary-fs.so

# RUN scone-signer sign --key=/enclave-key.pem --env --production /usr/bin/node -- only for production
# Enable production mode for mainnet
# RUN scone-signer sign --key=/enclave-key.pem --env --production /usr/bin/node
RUN rm -rf /enclave-key.pem

#RUN scone cas attest scone-cas.cf 3061b9feb7fa67f3815336a085f629a13f04b0a1667c93b14ff35581dc8271e4 -GCS --only_for_testing-debug --only_for_testing-ignore-signer
Expand Down
8 changes: 7 additions & 1 deletion nodenithy/build/securelock/scripts/binary-fs-build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,13 @@ cat .env
echo "####################"

cat securelock.js.tmpl | sed s/"__ENCLAVE_NAME_SECURELOCK__"/"${ENCLAVE_NAME_SECURELOCK}"/g > securelock.js.tmp
cat securelock.js.tmp | sed s/"__BUCKET_NAME__"/"${BUCKET_NAME}"/g > securelock.js
sed -i "s/__BUCKET_NAME__/${BUCKET_NAME}/g" securelock.js.tmp
sed -i "s/__SMART_CONTRACT_ADDRESS__/${SMART_CONTRACT_ADDRESS}/g" securelock.js.tmp
sed -i "s/__IMAGE_REGISTRY_ADDRESS__/${IMAGE_REGISTRY_ADDRESS}/g" securelock.js.tmp
sed -i "s/__RPC_URL__/${RPC_URL}/g" securelock.js.tmp
sed -i "s/__CHAIN_ID__/${CHAIN_ID}/g" securelock.js.tmp
sed -i "s/__TRUSTED_ZONE_IMAGE__/${TRUSTED_ZONE_IMAGE}/g" securelock.js.tmp
mv securelock.js.tmp securelock.js

echo "starting building binary-fs..."
EXEC=(scone binaryfs / /binary-fs-dir -v \
Expand Down
Loading