Merge branch 'release' into beta-v3-release

This commit is contained in:
chalith
2023-12-20 10:42:02 +05:30
29 changed files with 2882 additions and 788 deletions

1
.gitmodules vendored
View File

@@ -1,3 +1,4 @@
[submodule "evernode-bootstrap-contract"]
path = evernode-bootstrap-contract
url = https://github.com/HotPocketDev/evernode-bootstrap-contract.git
branch = release

View File

@@ -47,7 +47,7 @@ Run `make installer` ('installer.tar.gz' will be placed in build directory)
1. Node app which is listening to the host xrpl account.
1. `cd mb-xrpl && npm install` (You only have to do this once)
1. `node app.js new [address] [secret] [governerAddress] [domain or ip] [leaseAmount] [rippledServer]` will create new config files called `mb-xrpl.cfg` and `secret.cfg`
1. `node app.js new [address] [secretPath] [governorAddress] [domain or ip] [leaseAmount] [rippledServer] [ipv6Subnet] [ipv6Interface] [network]` will create new config files called `mb-xrpl.cfg` and `secret.cfg`
1. `node app.js betagen [governerAddress] [domain or ip] [leaseAmount]` will generate beta host account and populate the configs.
1. `node app.js register [countryCode] [cpuMicroSec] [ramKb] [swapKb] [diskKb] [totalInstanceCount] [cpuModel] [cpuCount] [cpuSpeed] [emailAddress] [description(optional)]` will register the host on Evernode.
1. `node app.js deregister` will deregister the host from Evernode.

View File

@@ -7,6 +7,7 @@ peer_port=$2
user_port=$3
instance_name=$4
prefix="sashi"
max_kill_attempts=5
# Check whether this is a valid sashimono username.
[ ${#user} -lt 24 ] || [ ${#user} -gt 32 ] || [[ ! "$user" =~ ^$prefix[0-9]+$ ]] && echo "ARGS,UNINST_ERR" && exit 1
@@ -55,18 +56,16 @@ for mnt in "${mntarr[@]}"; do
done
# Force kill user processes.
procs=$(ps -U $user 2>/dev/null | wc -l)
if [ "$procs" != "0" ]; then
# Wait for some time and check again.
i=0
while true; do
sleep 1
procs=$(ps -U $user 2>/dev/null | wc -l)
if [ "$procs" != "0" ]; then
echo "Force killing user processes."
pkill -SIGKILL -u "$user"
fi
fi
[ "$procs" == "1" ] && echo "All user processes terminated." && break
[[ $i -ge $max_kill_attempts ]] && echo "Max force user process kill attempts $max_kill_attempts reached. Abondaning." && break
((i++))
echo "Force killing user processes. Retrying $i..."
pkill -SIGKILL -u "$user"
done
echo "Removing cgroups"
# Delete config values.

View File

@@ -4,6 +4,12 @@ const evernode = require("evernode-js-client");
const process = require("process");
const fs = require("fs");
const ip6addr = require('ip6addr');
const keypairs = require('ripple-keypairs');
const http = require('http');
const crypto = require('crypto');
const { appenv } = require("../../mb-xrpl/lib/appenv");
let NETWORK = appenv.NETWORK;
function checkParams(args, count) {
for (let i = 0; i < count; i++) {
@@ -18,11 +24,16 @@ const funcs = {
'validate-server': async (args) => {
checkParams(args, 1);
const rippledUrl = args[0];
const xrplApi = new evernode.XrplApi(rippledUrl, { autoReconnect: false });
await evernode.Defaults.useNetwork(NETWORK);
evernode.Defaults.set({
rippledServer: rippledUrl
});
const xrplApi = new evernode.XrplApi(null, { autoReconnect: false });
await xrplApi.connect();
await xrplApi.disconnect();
return { success: true };
},
'validate-account': async (args) => {
checkParams(args, 3);
const rippledUrl = args[0];
@@ -30,15 +41,22 @@ const funcs = {
const accountAddress = args[2];
const validateFor = args[3] || "register";
const xrplApi = new evernode.XrplApi(rippledUrl, { autoReconnect: false });
await evernode.Defaults.useNetwork(NETWORK);
evernode.Defaults.set({
rippledServer: rippledUrl,
governorAddress: governorAddress
});
const xrplApi = new evernode.XrplApi(null, { autoReconnect: false });
await xrplApi.connect();
const hostClient = new evernode.HostClient(accountAddress, null, {
rippledServer: rippledUrl,
governorAddress: governorAddress,
evernode.Defaults.set({
xrplApi: xrplApi
});
const hostClient = new evernode.HostClient(accountAddress, null);
if (!await hostClient.xrplAcc.exists())
return { success: false, result: "Account not found." };
@@ -71,15 +89,26 @@ const funcs = {
await xrplApi.disconnect();
return { success: true };
},
'validate-keys': async (args) => {
checkParams(args, 3);
const rippledUrl = args[0];
const accountAddress = args[1];
const accountSecret = args[2];
const xrplApi = new evernode.XrplApi(rippledUrl, { autoReconnect: false });
await evernode.Defaults.useNetwork(NETWORK);
evernode.Defaults.set({
rippledServer: rippledUrl
});
const xrplApi = new evernode.XrplApi(null, { autoReconnect: false });
await xrplApi.connect();
evernode.Defaults.set({
xrplApi: xrplApi
});
const xrplAcc = new evernode.XrplAccount(accountAddress, accountSecret, {
xrplApi: xrplApi
});
@@ -91,31 +120,33 @@ const funcs = {
},
'access-evernode-cfg': async (args) => {
checkParams(args, 4);
checkParams(args, 3);
const rippledUrl = args[0];
const governorAddress = args[1];
const accountAddress = args[2];
const configName = args[3];
const configName = args[2];
const xrplApi = new evernode.XrplApi(rippledUrl, { autoReconnect: false });
await evernode.Defaults.useNetwork(NETWORK);
evernode.Defaults.set({
rippledServer: rippledUrl,
governorAddress: governorAddress
});
const xrplApi = new evernode.XrplApi(null, { autoReconnect: false });
await xrplApi.connect();
const hostClient = new evernode.HostClient(accountAddress, null, {
rippledServer: rippledUrl,
governorAddress: governorAddress,
evernode.Defaults.set({
xrplApi: xrplApi
});
if (!await hostClient.xrplAcc.exists())
return { success: false, result: "Account not found." };
const governorClient = await evernode.HookClientFactory.create(evernode.HookTypes.governor);
await governorClient.connect();
const config = await governorClient.config;
await hostClient.connect();
const config = hostClient.config;
await hostClient.disconnect();
await governorClient.disconnect();
await xrplApi.disconnect();
return { success: true, result: config[configName] };
return { success: true, result: typeof config[configName] === 'object' ? JSON.stringify(config[configName]) : `${config[configName]}` };
},
'transfer': async (args) => {
@@ -126,15 +157,22 @@ const funcs = {
const accountSecret = args[3];
const transfereeAddress = args[4];
const xrplApi = new evernode.XrplApi(rippledUrl, { autoReconnect: false });
await evernode.Defaults.useNetwork(NETWORK);
evernode.Defaults.set({
rippledServer: rippledUrl,
governorAddress: governorAddress
});
const xrplApi = new evernode.XrplApi(null, { autoReconnect: false });
await xrplApi.connect();
const hostClient = new evernode.HostClient(accountAddress, accountSecret, {
rippledServer: rippledUrl,
governorAddress: governorAddress,
evernode.Defaults.set({
xrplApi: xrplApi
});
const hostClient = new evernode.HostClient(accountAddress, accountSecret);
if (!await hostClient.xrplAcc.exists())
return { success: false, result: "Account not found." };
@@ -203,7 +241,314 @@ const funcs = {
}
return { success: false };
},
'check-acc-condition': async (args) => {
checkParams(args, 3);
const rippledUrl = args[0];
const governorAddress = args[1];
const accountAddress = args[2];
await evernode.Defaults.useNetwork(NETWORK);
evernode.Defaults.set({
rippledServer: rippledUrl,
governorAddress: governorAddress
});
const xrplApi = new evernode.XrplApi(null, { autoReconnect: false });
await xrplApi.connect();
evernode.Defaults.set({
xrplApi: xrplApi
});
const hostClient = new evernode.HostClient(accountAddress, null);
const terminateConnections = async () => {
await hostClient.disconnect();
await xrplApi.disconnect();
}
try {
// In order to handle the account not found issue via catch block.
await hostClient.connect();
const trustline = await hostClient.xrplAcc.getTrustLines(evernode.EvernodeConstants.EVR, hostClient.config.evrIssuerAddress);
if (trustline.length > 0) {
await terminateConnections();
return { success: true, result: 'RC-PREPARED' }
} else {
await terminateConnections();
return { success: true, result: 'RC-FRESH' };
}
} catch (err) {
await terminateConnections();
if ((err.data?.error === 'actNotFound'))
return { success: true, result: "RC-FRESH" };
return { success: false, result: "Error occurred in account condition check." };
}
},
'check-balance': async (args) => {
checkParams(args, 5);
const rippledUrl = args[0];
const governorAddress = args[1];
const accountAddress = args[2];
const tokenType = args[3];
const expectedBalance = args[4];
const WAIT_PERIOD = 120; // seconds
await evernode.Defaults.useNetwork(NETWORK);
evernode.Defaults.set({
rippledServer: rippledUrl,
governorAddress: governorAddress
});
try {
const xrplApi = new evernode.XrplApi(null, { autoReconnect: false });
await xrplApi.connect();
evernode.Defaults.set({
xrplApi: xrplApi
});
const hostClient = new evernode.HostClient(accountAddress, null);
const terminateConnections = async () => {
await hostClient.disconnect();
await xrplApi.disconnect();
}
let attempts = 0;
let balance = 0;
while (attempts >= 0) {
try {
// In order to handle the account not found issue via catch block.
await hostClient.connect();
await new Promise(resolve => setTimeout(resolve, 1000));
if (tokenType === 'NATIVE')
balance = Number((await hostClient.xrplAcc.getInfo()).Balance) / 1000000;
else
balance = Number(await hostClient.getEVRBalance());
if (balance < expectedBalance) {
if (++attempts <= WAIT_PERIOD)
continue;
await terminateConnections();
return { success: false, result: "Funds not received within timeout." };
}
break;
} catch (err) {
if (err.data?.error === 'actNotFound' && ++attempts <= WAIT_PERIOD) {
await new Promise(resolve => setTimeout(resolve, 1000));
continue;
}
await terminateConnections();
return { success: false, result: (err.data?.error === 'actNotFound') ? "Funds not received within timeout." : "Error occurred in account balance check." };
}
}
await terminateConnections();
return { success: true, result: `${balance}` };
} catch {
return { success: false, result: "Error occurred in websocket connection." };
}
},
'generate-account': async (args) => {
let seed = null;
if (args[0])
seed = args[0];
else
seed = keypairs.generateSeed({ algorithm: "ecdsa-secp256k1" });
const keypair = keypairs.deriveKeypair(seed);
const createdKeypair = {
address: keypairs.deriveAddress(keypair.publicKey),
secret: seed
}
return { success: true, result: typeof createdKeypair === 'object' ? JSON.stringify(createdKeypair) : `${createdKeypair}` };
},
'prepare-host': async (args) => {
checkParams(args, 4);
const rippledUrl = args[0];
const governorAddress = args[1];
const accountAddress = args[2];
const accountSecret = args[3];
// Optional
const domain = args[4] ? args[4] : "";
const WAIT_PERIOD = 120; // seconds
await evernode.Defaults.useNetwork(NETWORK);
evernode.Defaults.set({
rippledServer: rippledUrl,
governorAddress: governorAddress
});
const xrplApi = new evernode.XrplApi(null, { autoReconnect: false });
await xrplApi.connect();
evernode.Defaults.set({
xrplApi: xrplApi
});
const hostClient = new evernode.HostClient(accountAddress, accountSecret);
await hostClient.connect();
const terminateConnections = async () => {
await hostClient.disconnect();
await xrplApi.disconnect();
}
{
let attempts = 0;
while (attempts >= 0) {
try {
await hostClient.prepareAccount(domain);
break;
}
catch (err) {
if (err.data?.error === 'actNotFound' && ++attempts <= WAIT_PERIOD) {
// Wait and retry.
await new Promise(resolve => setTimeout(resolve, 1000));
continue;
}
await terminateConnections();
return { success: false, result: "Error occurred in account preparation." };
}
}
}
await terminateConnections();
return { success: true };
},
// Starts an HTTP server on port 80 and check whether that's reachable via
// the provided domain.
'validate-domain': async (args) => {
checkParams(args, 2);
const domain = args[0];
const port = parseInt(args[1]);
const urlPath = "/" + crypto.randomBytes(16).toString('hex');
const responseString = crypto.randomBytes(16).toString('hex');
const server = http.createServer((req, res) => {
if (req.url === urlPath) {
res.writeHead(200, { "Content-Type": "text/plain" });
res.end(responseString + '\n');
} else {
res.writeHead(404, { 'Content-Type': 'text/plain' });
res.end('Not Found\n');
}
});
try {
await new Promise((resolve, reject) => {
server.on('error', function (e) {
// We assume this is an error when starting to listen.
reject("listen_error");
});
server.listen(port, () => {
// Server started. Now send a request via public domain.
const reqOptions = {
hostname: domain,
port: port,
path: urlPath,
method: "GET"
};
const req = http.request(reqOptions, (res) => {
let data = "";
res.on("data", (chunk) => {
data += chunk;
});
// request completion event.
res.on("end", () => {
server.close();
if (data.startsWith(responseString)) {
resolve();
} else {
// Return string does not match our responseString. Most probably response was
// sent by some other server. Not by us.
reject("domain_error")
}
});
});
req.on("error", (e) => {
server.close();
reject("domain_error")
});
req.setTimeout(3000, () => { // 3 second request timeout
req.destroy();
server.close();
reject("domain_error");
});
req.end();
});
});
return { success: true, result: "ok" };
} catch (errorCode) {
return { success: false, result: errorCode };
}
},
'compute-xah-requirement': async (args) => {
checkParams(args, 2);
const rippledUrl = args[0];
const incReserveCount = Number(args[1]);
await evernode.Defaults.useNetwork(NETWORK);
evernode.Defaults.set({
rippledServer: rippledUrl
});
try {
const xrplApi = new evernode.XrplApi(null, { autoReconnect: false });
await xrplApi.connect();
evernode.Defaults.set({
xrplApi: xrplApi
});
const serverInfo = await xrplApi.getServerInfo();
if (serverInfo?.info?.validated_ledger) {
const reserves = serverInfo.info.validated_ledger
const estimate = (reserves?.reserve_base_native ?? reserves?.reserve_base_xrp) + (reserves?.reserve_inc_native ?? reserves?.reserve_inc_xrp) * incReserveCount;
if (estimate > 0) {
await xrplApi.disconnect();
return { success: true, result: `${estimate}` };
}
}
await xrplApi.disconnect();
return { success: false, result: "Failed to retrieve the estimation." };
} catch {
return { success: false, result: "Error occurred in websocket connection." };
}
}
}
function handleResponse(resp) {
@@ -222,10 +567,20 @@ function handleResponse(resp) {
async function app() {
try {
const networkIdx = process.argv.findIndex(a => a.startsWith('network:'));
if (networkIdx >= 0) {
const sp = process.argv[networkIdx].split(':');
if (sp.length > 1 && sp[1]) {
NETWORK = sp[1];
process.argv.splice(networkIdx, 1);
}
}
const command = process.argv[2];
if (!command)
throw "Command not specified.";
const resp = await funcs[command](process.argv.splice(3));
if (!resp)
throw "No response.";

View File

@@ -6,8 +6,9 @@
"": {
"name": "evernode-setup-helper",
"dependencies": {
"evernode-js-client": "0.6.20",
"ip6addr": "0.2.5"
"evernode-js-client": "0.6.24",
"ip6addr": "0.2.5",
"ripple-keypairs": "1.3.1"
}
},
"node_modules/@noble/hashes": {
@@ -363,9 +364,9 @@
}
},
"node_modules/evernode-js-client": {
"version": "0.6.20",
"resolved": "https://registry.npmjs.org/evernode-js-client/-/evernode-js-client-0.6.20.tgz",
"integrity": "sha512-OC6VNAhwqnNvUc0NhffxwNI9bTDH+BkD/KBTC5Xuwoiq8BhRfYhmfHBnD6M9K5AvLqv+Jxdufc3l1AlzHgILWg==",
"version": "0.6.24",
"resolved": "https://registry.npmjs.org/evernode-js-client/-/evernode-js-client-0.6.24.tgz",
"integrity": "sha512-sT7eoN796ueo0+yZl6KpQOzINuXrYW88YlZCm2PxzRqv5G4TqgqUGFgs+GSESkxuVRkw2LBX9WcUCGwbAt6K9g==",
"dependencies": {
"elliptic": "6.5.4",
"libsodium-wrappers": "0.7.10",
@@ -376,6 +377,27 @@
"xrpl-binary-codec": "1.4.2"
}
},
"node_modules/evernode-js-client/node_modules/bn.js": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz",
"integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ=="
},
"node_modules/evernode-js-client/node_modules/ripple-keypairs": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/ripple-keypairs/-/ripple-keypairs-1.1.0.tgz",
"integrity": "sha512-Zlmbtn2YUpW4uKlLm2/tpkY5RC/EXQlkJwIIKp0AoF9D23pJ43/EuipNW2F6qURdbkUezDwB0bMV7uRXip3x2w==",
"dependencies": {
"bn.js": "^5.1.1",
"brorand": "^1.0.5",
"elliptic": "^6.5.4",
"hash.js": "^1.0.3",
"ripple-address-codec": "^4.2.0"
},
"engines": {
"node": ">= 10",
"npm": ">=7.0.0"
}
},
"node_modules/ext": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz",
@@ -818,19 +840,18 @@
}
},
"node_modules/ripple-keypairs": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/ripple-keypairs/-/ripple-keypairs-1.1.0.tgz",
"integrity": "sha512-Zlmbtn2YUpW4uKlLm2/tpkY5RC/EXQlkJwIIKp0AoF9D23pJ43/EuipNW2F6qURdbkUezDwB0bMV7uRXip3x2w==",
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/ripple-keypairs/-/ripple-keypairs-1.3.1.tgz",
"integrity": "sha512-dmPlraWKJciFJxHcoubDahGnoIalG5e/BtV6HNDUs7wLXmtnLMHt6w4ed9R8MTL2zNrVPiIdI/HCtMMo0Tm7JQ==",
"dependencies": {
"bn.js": "^5.1.1",
"brorand": "^1.0.5",
"elliptic": "^6.5.4",
"hash.js": "^1.0.3",
"ripple-address-codec": "^4.2.0"
"ripple-address-codec": "^4.3.1"
},
"engines": {
"node": ">= 10",
"npm": ">=7.0.0"
"node": ">= 10"
}
},
"node_modules/ripple-keypairs/node_modules/bn.js": {
@@ -838,6 +859,18 @@
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz",
"integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ=="
},
"node_modules/ripple-keypairs/node_modules/ripple-address-codec": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/ripple-address-codec/-/ripple-address-codec-4.3.1.tgz",
"integrity": "sha512-Qa3+9wKVvpL/xYtT6+wANsn0A1QcC5CT6IMZbRJZ/1lGt7gmwIfsrCuz1X0+LCEO7zgb+3UT1I1dc0k/5dwKQQ==",
"dependencies": {
"base-x": "^3.0.9",
"create-hash": "^1.1.2"
},
"engines": {
"node": ">= 10"
}
},
"node_modules/ripple-secret-codec": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/ripple-secret-codec/-/ripple-secret-codec-1.0.3.tgz",
@@ -1119,21 +1152,6 @@
"node": ">= 10"
}
},
"node_modules/xrpl-accountlib/node_modules/ripple-keypairs": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/ripple-keypairs/-/ripple-keypairs-1.3.0.tgz",
"integrity": "sha512-LzM3Up9Pwz3dYqnczzNptimN3AxtjeGbDGeiOzREzbkslKiZcJ615b/ghBN4H23SC6W1GAL95juEzzimDi4THw==",
"dependencies": {
"bn.js": "^5.1.1",
"brorand": "^1.0.5",
"elliptic": "^6.5.4",
"hash.js": "^1.0.3",
"ripple-address-codec": "^4.3.0"
},
"engines": {
"node": ">= 10"
}
},
"node_modules/xrpl-binary-codec": {
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/xrpl-binary-codec/-/xrpl-binary-codec-1.4.2.tgz",
@@ -1190,38 +1208,6 @@
"ripple-keypairs": "^1.1.5"
}
},
"node_modules/xrpl-secret-numbers/node_modules/bn.js": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz",
"integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ=="
},
"node_modules/xrpl-secret-numbers/node_modules/ripple-address-codec": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ripple-address-codec/-/ripple-address-codec-4.3.0.tgz",
"integrity": "sha512-Tvd81i7hpDmNqHvkj6iYlj8Tv3I1Romw5gfjni9eacewJvGV2xe+p2y0FAw39z72qfciRMhQyHvpnviBcWVBNw==",
"dependencies": {
"base-x": "^3.0.9",
"create-hash": "^1.1.2"
},
"engines": {
"node": ">= 10"
}
},
"node_modules/xrpl-secret-numbers/node_modules/ripple-keypairs": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/ripple-keypairs/-/ripple-keypairs-1.3.0.tgz",
"integrity": "sha512-LzM3Up9Pwz3dYqnczzNptimN3AxtjeGbDGeiOzREzbkslKiZcJ615b/ghBN4H23SC6W1GAL95juEzzimDi4THw==",
"dependencies": {
"bn.js": "^5.1.1",
"brorand": "^1.0.5",
"elliptic": "^6.5.4",
"hash.js": "^1.0.3",
"ripple-address-codec": "^4.3.0"
},
"engines": {
"node": ">= 10"
}
},
"node_modules/xrpl-sign-keypairs": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/xrpl-sign-keypairs/-/xrpl-sign-keypairs-2.2.0.tgz",
@@ -1233,11 +1219,6 @@
"ripple-keypairs": "^1.1.4"
}
},
"node_modules/xrpl-sign-keypairs/node_modules/bn.js": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz",
"integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ=="
},
"node_modules/xrpl-sign-keypairs/node_modules/ripple-address-codec": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ripple-address-codec/-/ripple-address-codec-4.3.0.tgz",
@@ -1267,26 +1248,6 @@
"node": ">= 10"
}
},
"node_modules/xrpl-sign-keypairs/node_modules/ripple-keypairs": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/ripple-keypairs/-/ripple-keypairs-1.3.0.tgz",
"integrity": "sha512-LzM3Up9Pwz3dYqnczzNptimN3AxtjeGbDGeiOzREzbkslKiZcJ615b/ghBN4H23SC6W1GAL95juEzzimDi4THw==",
"dependencies": {
"bn.js": "^5.1.1",
"brorand": "^1.0.5",
"elliptic": "^6.5.4",
"hash.js": "^1.0.3",
"ripple-address-codec": "^4.3.0"
},
"engines": {
"node": ">= 10"
}
},
"node_modules/xrpl/node_modules/bn.js": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz",
"integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ=="
},
"node_modules/xrpl/node_modules/ripple-address-codec": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ripple-address-codec/-/ripple-address-codec-4.3.0.tgz",
@@ -1299,21 +1260,6 @@
"node": ">= 10"
}
},
"node_modules/xrpl/node_modules/ripple-keypairs": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/ripple-keypairs/-/ripple-keypairs-1.3.0.tgz",
"integrity": "sha512-LzM3Up9Pwz3dYqnczzNptimN3AxtjeGbDGeiOzREzbkslKiZcJ615b/ghBN4H23SC6W1GAL95juEzzimDi4THw==",
"dependencies": {
"bn.js": "^5.1.1",
"brorand": "^1.0.5",
"elliptic": "^6.5.4",
"hash.js": "^1.0.3",
"ripple-address-codec": "^4.3.0"
},
"engines": {
"node": ">= 10"
}
},
"node_modules/yaeti": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/yaeti/-/yaeti-0.0.6.tgz",
@@ -1597,9 +1543,9 @@
}
},
"evernode-js-client": {
"version": "0.6.20",
"resolved": "https://registry.npmjs.org/evernode-js-client/-/evernode-js-client-0.6.20.tgz",
"integrity": "sha512-OC6VNAhwqnNvUc0NhffxwNI9bTDH+BkD/KBTC5Xuwoiq8BhRfYhmfHBnD6M9K5AvLqv+Jxdufc3l1AlzHgILWg==",
"version": "0.6.24",
"resolved": "https://registry.npmjs.org/evernode-js-client/-/evernode-js-client-0.6.24.tgz",
"integrity": "sha512-sT7eoN796ueo0+yZl6KpQOzINuXrYW88YlZCm2PxzRqv5G4TqgqUGFgs+GSESkxuVRkw2LBX9WcUCGwbAt6K9g==",
"requires": {
"elliptic": "6.5.4",
"libsodium-wrappers": "0.7.10",
@@ -1608,6 +1554,25 @@
"xrpl": "2.2.1",
"xrpl-accountlib": "2.2.0",
"xrpl-binary-codec": "1.4.2"
},
"dependencies": {
"bn.js": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz",
"integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ=="
},
"ripple-keypairs": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/ripple-keypairs/-/ripple-keypairs-1.1.0.tgz",
"integrity": "sha512-Zlmbtn2YUpW4uKlLm2/tpkY5RC/EXQlkJwIIKp0AoF9D23pJ43/EuipNW2F6qURdbkUezDwB0bMV7uRXip3x2w==",
"requires": {
"bn.js": "^5.1.1",
"brorand": "^1.0.5",
"elliptic": "^6.5.4",
"hash.js": "^1.0.3",
"ripple-address-codec": "^4.2.0"
}
}
}
},
"ext": {
@@ -1943,21 +1908,30 @@
}
},
"ripple-keypairs": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/ripple-keypairs/-/ripple-keypairs-1.1.0.tgz",
"integrity": "sha512-Zlmbtn2YUpW4uKlLm2/tpkY5RC/EXQlkJwIIKp0AoF9D23pJ43/EuipNW2F6qURdbkUezDwB0bMV7uRXip3x2w==",
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/ripple-keypairs/-/ripple-keypairs-1.3.1.tgz",
"integrity": "sha512-dmPlraWKJciFJxHcoubDahGnoIalG5e/BtV6HNDUs7wLXmtnLMHt6w4ed9R8MTL2zNrVPiIdI/HCtMMo0Tm7JQ==",
"requires": {
"bn.js": "^5.1.1",
"brorand": "^1.0.5",
"elliptic": "^6.5.4",
"hash.js": "^1.0.3",
"ripple-address-codec": "^4.2.0"
"ripple-address-codec": "^4.3.1"
},
"dependencies": {
"bn.js": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz",
"integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ=="
},
"ripple-address-codec": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/ripple-address-codec/-/ripple-address-codec-4.3.1.tgz",
"integrity": "sha512-Qa3+9wKVvpL/xYtT6+wANsn0A1QcC5CT6IMZbRJZ/1lGt7gmwIfsrCuz1X0+LCEO7zgb+3UT1I1dc0k/5dwKQQ==",
"requires": {
"base-x": "^3.0.9",
"create-hash": "^1.1.2"
}
}
}
},
@@ -2134,11 +2108,6 @@
"ws": "^8.2.2"
},
"dependencies": {
"bn.js": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz",
"integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ=="
},
"ripple-address-codec": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ripple-address-codec/-/ripple-address-codec-4.3.0.tgz",
@@ -2147,18 +2116,6 @@
"base-x": "^3.0.9",
"create-hash": "^1.1.2"
}
},
"ripple-keypairs": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/ripple-keypairs/-/ripple-keypairs-1.3.0.tgz",
"integrity": "sha512-LzM3Up9Pwz3dYqnczzNptimN3AxtjeGbDGeiOzREzbkslKiZcJ615b/ghBN4H23SC6W1GAL95juEzzimDi4THw==",
"requires": {
"bn.js": "^5.1.1",
"brorand": "^1.0.5",
"elliptic": "^6.5.4",
"hash.js": "^1.0.3",
"ripple-address-codec": "^4.3.0"
}
}
}
},
@@ -2209,18 +2166,6 @@
"decimal.js": "^10.2.0",
"ripple-address-codec": "^4.3.0"
}
},
"ripple-keypairs": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/ripple-keypairs/-/ripple-keypairs-1.3.0.tgz",
"integrity": "sha512-LzM3Up9Pwz3dYqnczzNptimN3AxtjeGbDGeiOzREzbkslKiZcJ615b/ghBN4H23SC6W1GAL95juEzzimDi4THw==",
"requires": {
"bn.js": "^5.1.1",
"brorand": "^1.0.5",
"elliptic": "^6.5.4",
"hash.js": "^1.0.3",
"ripple-address-codec": "^4.3.0"
}
}
}
},
@@ -2274,34 +2219,6 @@
"@types/brorand": "^1.0.30",
"brorand": "^1.1.0",
"ripple-keypairs": "^1.1.5"
},
"dependencies": {
"bn.js": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz",
"integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ=="
},
"ripple-address-codec": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ripple-address-codec/-/ripple-address-codec-4.3.0.tgz",
"integrity": "sha512-Tvd81i7hpDmNqHvkj6iYlj8Tv3I1Romw5gfjni9eacewJvGV2xe+p2y0FAw39z72qfciRMhQyHvpnviBcWVBNw==",
"requires": {
"base-x": "^3.0.9",
"create-hash": "^1.1.2"
}
},
"ripple-keypairs": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/ripple-keypairs/-/ripple-keypairs-1.3.0.tgz",
"integrity": "sha512-LzM3Up9Pwz3dYqnczzNptimN3AxtjeGbDGeiOzREzbkslKiZcJ615b/ghBN4H23SC6W1GAL95juEzzimDi4THw==",
"requires": {
"bn.js": "^5.1.1",
"brorand": "^1.0.5",
"elliptic": "^6.5.4",
"hash.js": "^1.0.3",
"ripple-address-codec": "^4.3.0"
}
}
}
},
"xrpl-sign-keypairs": {
@@ -2315,11 +2232,6 @@
"ripple-keypairs": "^1.1.4"
},
"dependencies": {
"bn.js": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz",
"integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ=="
},
"ripple-address-codec": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ripple-address-codec/-/ripple-address-codec-4.3.0.tgz",
@@ -2341,18 +2253,6 @@
"decimal.js": "^10.2.0",
"ripple-address-codec": "^4.3.0"
}
},
"ripple-keypairs": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/ripple-keypairs/-/ripple-keypairs-1.3.0.tgz",
"integrity": "sha512-LzM3Up9Pwz3dYqnczzNptimN3AxtjeGbDGeiOzREzbkslKiZcJ615b/ghBN4H23SC6W1GAL95juEzzimDi4THw==",
"requires": {
"bn.js": "^5.1.1",
"brorand": "^1.0.5",
"elliptic": "^6.5.4",
"hash.js": "^1.0.3",
"ripple-address-codec": "^4.3.0"
}
}
}
},

View File

@@ -4,7 +4,8 @@
"build": "ncc build index.js --minify -o dist"
},
"dependencies": {
"evernode-js-client": "0.6.20",
"ip6addr": "0.2.5"
"evernode-js-client": "0.6.24",
"ip6addr": "0.2.5",
"ripple-keypairs": "1.3.1"
}
}

View File

@@ -28,6 +28,7 @@ stage "Installing dependencies"
# To fix - Repository 'https://apprepo.vultr.com/ubuntu universal InRelease' changed its 'Codename' value from 'buster' to 'universal'
apt-get update --allow-releaseinfo-change
apt-get install -y uidmap fuse3 cgroup-tools quota curl openssl jq
# uidmap # Required for rootless docker.
# slirp4netns # Required for high performance rootless networking.
# fuse3 # Required for hpfs.
@@ -40,8 +41,13 @@ apt-get install -y uidmap fuse3 cgroup-tools quota curl openssl jq
# Install nodejs if not exists.
if ! command -v node &>/dev/null; then
stage "Installing nodejs"
apt-get -y install ca-certificates # In case nodejs package certitficates are renewed.
curl -sL https://deb.nodesource.com/setup_16.x | bash -
apt-get install -y ca-certificates curl gnupg
mkdir -p /etc/apt/keyrings
curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg
NODE_MAJOR=16
echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" | tee /etc/apt/sources.list.d/nodesource.list
apt-get update
apt-get -y install nodejs
else
version=$(node -v | cut -d '.' -f1)

View File

@@ -16,7 +16,7 @@ diskKB=${9}
lease_amount=${10}
rippled_server=${11}
xrpl_account_address=${12}
xrpl_account_secret=${13}
xrpl_account_secret_path=${13}
email_address=${14}
tls_key_file=${15}
tls_cert_file=${16}
@@ -27,6 +27,7 @@ ipv6_net_interface=${20}
script_dir=$(dirname "$(realpath "$0")")
desired_slirp4netns_version="1.2.1"
setup_helper_dir="/tmp/evernode-setup-helpers"
function stage() {
echo "STAGE $1" # This is picked up by the setup console output filter.
@@ -55,48 +56,6 @@ function set_cpu_info() {
[ -z $cpu_mhz ] && cpu_mhz=$(lscpu | grep -i "^CPU MHz:" | sed 's/CPU MHz://g' | sed 's/\.[0-9]*//g' | xargs)
}
function enable_evernode_auto_updater() {
# Create the service.
echo "[Unit]
Description=Service for the Evernode auto-update.
After=network.target
[Service]
User=root
Group=root
Type=oneshot
ExecStart=/usr/bin/evernode update -q
[Install]
WantedBy=multi-user.target" >/etc/systemd/system/$EVERNODE_AUTO_UPDATE_SERVICE.service
# Create a timer for the service (every two hours).
echo "[Unit]
Description=Timer for the Evernode auto-update.
# Allow manual starts
RefuseManualStart=no
# Allow manual stops
RefuseManualStop=no
[Timer]
Unit=$EVERNODE_AUTO_UPDATE_SERVICE.service
OnCalendar=0/12:00:00
# Execute job if it missed a run due to machine being off
Persistent=true
# To prevent rush time, adding 2 hours delay
RandomizedDelaySec=7200
[Install]
WantedBy=timers.target" >/etc/systemd/system/$EVERNODE_AUTO_UPDATE_SERVICE.timer
# Reload the systemd daemon.
systemctl daemon-reload
echo "Enabling Evernode auto update service..."
systemctl enable $EVERNODE_AUTO_UPDATE_SERVICE.service
echo "Enabling Evernode auto update timer..."
systemctl enable $EVERNODE_AUTO_UPDATE_SERVICE.timer
echo "Starting Evernode auto update timer..."
systemctl start $EVERNODE_AUTO_UPDATE_SERVICE.timer
}
function setup_certbot() {
stage "Setting up letsencrypt certbot"
@@ -230,13 +189,16 @@ rm -r "$tmp"
openssl req -newkey rsa:2048 -new -nodes -x509 -days 365 -keyout $SASHIMONO_DATA/contract_template/cfg/tlskey.pem \
-out $SASHIMONO_DATA/contract_template/cfg/tlscert.pem -subj "/C=HP/CN=$(jq -r '.hp.host_address' $SASHIMONO_DATA/sa.cfg)"
# Setup tls certs used for contract instance websockets.
[ "$UPGRADE" == "0" ] && setup_tls_certs
# Install Sashimono agent binaries into sashimono bin dir.
cp "$script_dir"/{sagent,hpfs,user-cgcreate.sh,user-install.sh,user-uninstall.sh,docker-registry-uninstall.sh} $SASHIMONO_BIN
chmod -R +x $SASHIMONO_BIN
# Setup tls certs used for contract instance websockets.
[ "$UPGRADE" == "0" ] && setup_tls_certs
# Copy the temporary setup-helper directory content to SASHIMONO_BIN directory.
cp -Rdp $setup_helper_dir $SASHIMONO_BIN/evernode-setup-helpers
# Copy Blake3 and update linker library cache.
[ ! -f /usr/local/lib/libblake3.so ] && cp "$script_dir"/libblake3.so /usr/local/lib/ && ldconfig
@@ -275,9 +237,13 @@ if [ "$NO_MB" == "" ]; then
cp -r "$script_dir"/mb-xrpl $SASHIMONO_BIN
# Creating message board user (if not exists).
# Create MB_XRPL_USER if does not exists.
if ! grep -q "^$MB_XRPL_USER:" /etc/passwd; then
useradd --shell /usr/sbin/nologin -m $MB_XRPL_USER
fi
# Assign message board user priviledges.
if ! id -nG "$MB_XRPL_USER" | grep -qw "$SASHIADMIN_GROUP"; then
usermod --lock $MB_XRPL_USER
usermod -a -G $SASHIADMIN_GROUP $MB_XRPL_USER
loginctl enable-linger $MB_XRPL_USER # Enable lingering to support service installation.
@@ -289,18 +255,14 @@ if [ "$NO_MB" == "" ]; then
# Change ownership to message board user.
chown -R "$MB_XRPL_USER":"$MB_XRPL_USER" $MB_XRPL_DATA
# Betage and register if not upgrade mode.
# Register if not upgrade mode.
if [ "$UPGRADE" == "0" ]; then
# Setup and register the account.
if ! sudo -u $MB_XRPL_USER MB_DATA_DIR=$MB_XRPL_DATA node $MB_XRPL_BIN reginfo basic >/dev/null 2>&1; then
stage "Configuring host xrpl account"
echo "Using registry: $EVERNODE_REGISTRY_ADDRESS"
# Commented for now, because 'betagen' will no longer be used.
# ! sudo -u $MB_XRPL_USER MB_DATA_DIR=$MB_XRPL_DATA node $MB_XRPL_BIN betagen $EVERNODE_GOVERNOR_ADDRESS $inetaddr $lease_amount $rippled_server $xrpl_account_secret && echo "XRPLACC_FAILURE" && rollback
# doreg=1
! sudo -u $MB_XRPL_USER MB_DATA_DIR=$MB_XRPL_DATA node $MB_XRPL_BIN new $xrpl_account_address $xrpl_account_secret $EVERNODE_GOVERNOR_ADDRESS $inetaddr $lease_amount $rippled_server $ipv6_subnet $ipv6_net_interface && echo "XRPLACC_FAILURE" && rollback
! sudo -u $MB_XRPL_USER MB_DATA_DIR=$MB_XRPL_DATA node $MB_XRPL_BIN new $xrpl_account_address $xrpl_account_secret_path $EVERNODE_GOVERNOR_ADDRESS $inetaddr $lease_amount $rippled_server $ipv6_subnet $ipv6_net_interface $NETWORK && echo "XRPLACC_FAILURE" && rollback
doreg=1
fi
@@ -364,7 +326,7 @@ else
fi
if [[ "$NO_MB" == "" && -f $MB_XRPL_DATA/mb-xrpl.cfg ]]; then
! sudo -u "$MB_XRPL_USER" MB_DATA_DIR="$MB_XRPL_DATA" node "$MB_XRPL_BIN" upgrade $EVERNODE_GOVERNOR_ADDRESS && rollback
! sudo -u "$MB_XRPL_USER" MB_DATA_DIR="$MB_XRPL_DATA" node "$MB_XRPL_BIN" upgrade && rollback
fi
# Install Sashimono Agent systemd service.
@@ -448,11 +410,6 @@ if [ ! -f /run/reboot-required.pkgs ] || [ ! -n "$(grep sashimono /run/reboot-re
fi
fi
stage "Configuring auto updater service"
# Enable the Evernode Auto Updater Service.
enable_evernode_auto_updater
echo "Sashimono installed successfully."
exit 0

View File

@@ -2,6 +2,8 @@
# Sashimono agent uninstall script.
# This must be executed with root privileges.
export TRANSFER=${TRANSFER:-0}
[ "$UPGRADE" == "0" ] && echo "---Sashimono uninstaller---" || echo "---Sashimono uninstaller (for upgrade)---"
force=$1
@@ -30,24 +32,6 @@ function cgrulesengd_servicename() {
fi
}
function remove_evernode_auto_updater() {
echo "Removing Evernode auto update timer..."
systemctl stop $EVERNODE_AUTO_UPDATE_SERVICE.timer
systemctl disable $EVERNODE_AUTO_UPDATE_SERVICE.timer
service_path="/etc/systemd/system/$EVERNODE_AUTO_UPDATE_SERVICE.timer"
rm $service_path
echo "Removing Evernode auto update service..."
systemctl stop $EVERNODE_AUTO_UPDATE_SERVICE.service
systemctl disable $EVERNODE_AUTO_UPDATE_SERVICE.service
service_path="/etc/systemd/system/$EVERNODE_AUTO_UPDATE_SERVICE.service"
rm $service_path
# Reload the systemd daemon.
systemctl daemon-reload
}
function cleanup_certbot_ssl() {
# revoke/delete certs if certbot is used.
if command -v certbot &>/dev/null && [ -f "$SASHIMONO_DATA/sa.cfg" ]; then
@@ -195,7 +179,6 @@ if grep -q "^$MB_XRPL_USER:" /etc/passwd; then
pkill -u $MB_XRPL_USER # Kill any running processes.
sleep 0.5
userdel -f "$MB_XRPL_USER"
rm -r /home/"${MB_XRPL_USER:?}"
fi
@@ -215,7 +198,4 @@ groupdel $SASHIADMIN_GROUP
[ "$UPGRADE" == "0" ] && echo "Sashimono uninstalled successfully." || echo "Sashimono uninstalled successfully. Your data has been preserved."
# Remove the Evernode Auto Updater Service.
[ "$UPGRADE" == "0" ] && remove_evernode_auto_updater
exit 0

1447
installer/setup-old.sh Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -15,25 +15,20 @@ async function main() {
if (process.argv.length >= 3) {
if (process.argv.length >= 9 && process.argv[2] === 'new') {
const accountAddress = process.argv[3];
const accountSecret = process.argv[4];
const accountSecretPath = process.argv[4];
const governorAddress = process.argv[5];
const domain = process.argv[6];
const leaseAmount = process.argv[7];
const rippledServer = process.argv[8];
const ipv6Subnet = (process.argv[9] === '-') ? null : process.argv[9];
const ipv6NetInterface = (process.argv[10] === '-') ? null : process.argv[10];
const network = process.argv.length > 11 ? process.argv[11] : appenv.NETWORK;
const setup = new Setup();
const acc = await setup.setupHostAccount(accountAddress, accountSecret, rippledServer, governorAddress, domain);
setup.newConfig(acc.address, acc.secret, governorAddress, parseFloat(leaseAmount), rippledServer, ipv6Subnet, ipv6NetInterface);
}
else if (process.argv.length === 7 && process.argv[2] === 'betagen') {
const governorAddress = process.argv[3];
const domain = process.argv[4];
const leaseAmount = process.argv[5];
const rippledServer = process.argv[6];
const setup = new Setup();
const acc = await setup.generateBetaHostAccount(rippledServer, governorAddress, domain);
setup.newConfig(acc.address, acc.secret, governorAddress, parseFloat(leaseAmount), rippledServer);
setup.newConfig(accountAddress, accountSecretPath, governorAddress, parseFloat(leaseAmount), rippledServer, ipv6Subnet, ipv6NetInterface, network);
if (appenv.IS_DEV_MODE) {
await setup.prepareHostAccount(domain);
}
}
else if (process.argv.length >= 13 && process.argv[2] === 'register') {
await new Setup().register(process.argv[3], parseInt(process.argv[4]), parseInt(process.argv[5]),
@@ -51,8 +46,8 @@ async function main() {
else if (process.argv.length === 4 && process.argv[2] === 'reginfo' && process.argv[3] === 'basic') {
await new Setup().regInfo(true);
}
else if (process.argv.length === 4 && process.argv[2] === 'upgrade') {
await new Setup().upgrade(process.argv[3]);
else if (process.argv.length >= 3 && process.argv[2] === 'upgrade') {
await new Setup().upgrade();
}
else if ((process.argv.length === 8) && process.argv[2] === 'reconfig') {
if (process.argv[5] == '-') process.argv[5] = null;
@@ -73,13 +68,15 @@ async function main() {
else if (process.argv.length >= 4 && process.argv[2] === 'governance') {
await GovernanceManager.handleCommand(process.argv[3], ...process.argv.slice(4));
}
else if (process.argv.length >= 3 && process.argv[2] === 'regkey') {
await new Setup().setRegularKey(process.argv[3]);
}
else if (process.argv[2] === 'help') {
console.log(`Usage:
node index.js - Run message board.
node index.js version - Print version.
node index.js new [address] [secret] [governorAddress] [leaseAmount] [rippledServer] [ipv6Subnet] [ipv6Interface] - Create new config files.
node index.js betagen [governorAddress] [domain or ip] [leaseAmount] [rippledServer] - Generate beta host account and populate the configs.
node index.js register [countryCode] [cpuMicroSec] [ramKb] [swapKb] [diskKb] [totalInstanceCount] [description] - Register the host on Evernode.
node index.js new [address] [secretPath] [governorAddress] [domain or ip] [leaseAmount] [rippledServer] [ipv6Subnet] [ipv6Interface] [network] - Create new config files.
node index.js register [countryCode] [cpuMicroSec] [ramKb] [swapKb] [diskKb] [totalInstanceCount] [description] [network] - Register the host on Evernode.
node index.js transfer [transfereeAddress] - Initiate a transfer.
node index.js deregister - Deregister the host from Evernode.
node index.js reginfo - Display Evernode registration info.
@@ -87,6 +84,7 @@ async function main() {
node index.js reconfig [leaseAmount] [totalInstanceCount] [rippledServer] - Update message board configuration.
node index.js delete [containerName] - Delete an instance and recreate the lease offer
node index.js governance [command] [args] - Governance handling.
node index.js regkey [regularKey] - Regular key management.
node index.js help - Print help.`);
}
else {

View File

@@ -1,19 +1,16 @@
const process = require('process');
const path = require('path');
const fs = require('fs');
let appenv = {
IS_DEV_MODE: process.env.MB_DEV === "1",
FILE_LOG_ENABLED: process.env.MB_FILE_LOG === "1",
DATA_DIR: process.env.MB_DATA_DIR || __dirname,
FAUCET_URL: process.env.MB_FAUCET_URL || "https://hooks-testnet-v3.xrpl-labs.com/newcreds",
DEFAULT_RIPPLED_SERVER: 'wss://hooks-testnet-v3.xrpl-labs.com',
DEFAULT_FULL_HISTORY_NODE: 'wss://hooks-testnet-v3.xrpl-labs.com' // If we migrate to Main NET, this should be configured with the relevant full history Node WebSocket.
DATA_DIR: process.env.MB_DATA_DIR || __dirname
}
appenv = {
...appenv,
CONFIG_PATH: appenv.DATA_DIR + '/mb-xrpl.cfg',
SECRET_CONFIG_PATH: appenv.DATA_DIR + '/secret.cfg',
GOVERNANCE_CONFIG_PATH: appenv.DATA_DIR + '/governance.cfg',
LOG_PATH: appenv.DATA_DIR + '/log/mb-xrpl.log',
DB_PATH: appenv.DATA_DIR + '/mb-xrpl.sqlite',
@@ -28,9 +25,17 @@ appenv = {
ORPHAN_PRUNE_SCHEDULER_INTERVAL_HOURS: 4,
SASHIMONO_SCHEDULER_INTERVAL_SECONDS: 2,
SASHI_CLI_PATH: appenv.IS_DEV_MODE ? "../build/sashi" : "/usr/bin/sashi",
MB_VERSION: '0.7.2',
TOS_HASH: '757A0237B44D8B2BBB04AE2BAD5813858E0AECD2F0B217075E27E0630BA74314' // This is the sha256 hash of TOS text.
MB_VERSION: '0.8.0',
TOS_HASH: '0801677EBCB2F76EF97D531549D8B27DB2C7A4A8EE7F60032AE40184247F0810', // This is the sha256 hash of EVERNODE-HOSTING-PRINCIPLES.pdf.
NETWORK: 'mainnet'
}
const getSecretPath = () => {
return fs.existsSync(appenv.CONFIG_PATH) ? JSON.parse(fs.readFileSync(appenv.CONFIG_PATH).toString()).xrpl.secretPath : "";
}
appenv = { ...appenv, SECRET_CONFIG_PATH: getSecretPath() }
Object.freeze(appenv);
module.exports = {

View File

@@ -28,15 +28,10 @@ class ConfigHelper {
return config;
}
static writeConfig(config, configPath, secretConfigPath) {
static writeConfig(config, configPath) {
let publicCfg = JSON.parse(JSON.stringify(config)); // Make a copy. So, referenced object won't get changed.
const secretCfg = {
xrpl: {
secret: publicCfg.xrpl.secret
}
}
delete publicCfg.xrpl.secret;
fs.writeFileSync(secretConfigPath, JSON.stringify(secretCfg, null, 2), { mode: 0o600 }); // Set file permission so only current user can read/write.
if ('secret' in publicCfg.xrpl)
delete publicCfg.xrpl.secret;
fs.writeFileSync(configPath, JSON.stringify(publicCfg, null, 2), { mode: 0o644 }); // Set file permission so only current user can read/write and others can read.
}

View File

@@ -4,12 +4,18 @@ const fs = require('fs');
const { appenv } = require('./appenv');
const { ConfigHelper } = require('./config-helper');
function setEvernodeDefaults(governorAddress, rippledServer, xrplApi) {
evernode.Defaults.set({
governorAddress: governorAddress,
rippledServer: rippledServer,
xrplApi: xrplApi
});
async function setEvernodeDefaults(network, governorAddress, rippledServer) {
await evernode.Defaults.useNetwork(network || appenv.NETWORK);
if (governorAddress)
evernode.Defaults.set({
governorAddress: governorAddress
});
if (rippledServer)
evernode.Defaults.set({
rippledServer: rippledServer
});
}
class GovernanceManager {
@@ -181,7 +187,7 @@ class GovernanceManager {
// Secret is needed for propose, withdraw, and report in order to send the transaction
const sashiMBConfig = ConfigHelper.readConfig(appenv.CONFIG_PATH,
(command == 'propose' || command === 'withdraw' || command === 'report') ? appenv.SECRET_CONFIG_PATH : null);
setEvernodeDefaults(sashiMBConfig.xrpl.governorAddress, sashiMBConfig.xrpl.rippledServer);
await setEvernodeDefaults(sashiMBConfig.xrpl.network, sashiMBConfig.xrpl.governorAddress, sashiMBConfig.xrpl.rippledServer);
hostClient = new evernode.HostClient(sashiMBConfig.xrpl.address, sashiMBConfig.xrpl.secret);
}
const mgr = new GovernanceManager(appenv.GOVERNANCE_CONFIG_PATH);

View File

@@ -52,9 +52,20 @@ class MessageBoard {
if (!this.cfg.version || !this.cfg.xrpl.address || !this.cfg.xrpl.secret || !this.cfg.xrpl.governorAddress)
throw "Required cfg fields cannot be empty.";
this.xrplApi = new evernode.XrplApi(this.cfg.xrpl.rippledServer);
await evernode.Defaults.useNetwork(this.cfg.xrpl.network || appenv.NETWORK);
if (this.cfg.xrpl.governorAddress)
evernode.Defaults.set({
governorAddress: this.cfg.xrpl.governorAddress
});
if (this.cfg.xrpl.rippledServer)
evernode.Defaults.set({
rippledServer: this.cfg.xrpl.rippledServer
});
this.xrplApi = new evernode.XrplApi();
evernode.Defaults.set({
governorAddress: this.cfg.xrpl.governorAddress,
xrplApi: this.xrplApi
})
await this.xrplApi.connect();
@@ -448,9 +459,6 @@ class MessageBoard {
}
async #startHeartBeatScheduler() {
// Sending a heartbeat at startup
await this.#sendHeartbeat();
const momentSize = this.hostClient.config.momentSize;
const halfMomentSize = momentSize / 2; // Getting half of moment size
const timeout = momentSize * 1000; // Converting seconds to milliseconds.
@@ -462,10 +470,24 @@ class MessageBoard {
await this.#sendHeartbeat();
};
const currentTimestamp = evernode.UtilHelpers.getCurrentUnixTime();
const currentMomentStartIdx = await this.hostClient.getMomentStartIndex();
const currentMoment = await this.hostClient.getMoment();
const currentMomentDuration = currentTimestamp - currentMomentStartIdx;
const hostInfo = await this.hostClient.getRegistration();
// If the start index is in the begining of the moment, delay the heartbeat scheduler 1 minute to make sure the hook timestamp is not in previous moment when accepting the heartbeat.
const startTimeout = (evernode.UtilHelpers.getCurrentUnixTime() - currentMomentStartIdx) < halfMomentSize ? ((momentSize + 60) * 1000) : ((momentSize) * 1000);
// Schedule the next heartbeat based on last heartbeat occurrence.
// NOTE : Initially checks whether host has sent a heartbeat in the current moment or not.
// If schedule the next heartbeat based on its last heartbeat.
// If it is not further checks whether it is about to send the heartbeat at the second half of a moment or not.
// If the current timestamp lies in the second half of the moment, schedule the next heartbeat withing the next moment (in the its first half).
// If it is not schedule it right now.
const schedule = (this.lastHeartbeatMoment === currentMoment)
? momentSize - (currentTimestamp - hostInfo.lastHeartbeatIndex)
: (currentMomentDuration > halfMomentSize && currentMomentDuration < momentSize) ? halfMomentSize : 0;
// If the start index is in the beginning of the moment, delay the heartbeat scheduler 1 minute to make sure the hook timestamp is not in previous moment when accepting the heartbeat.
const startTimeout = (currentMomentDuration) < halfMomentSize ? ((schedule + 60) * 1000) : ((schedule) * 1000);
setTimeout(async () => {
await scheduler();
@@ -602,7 +624,7 @@ class MessageBoard {
}
async #catchupMissedLeases() {
const fullHistoryXrplApi = new evernode.XrplApi(appenv.DEFAULT_FULL_HISTORY_NODE);
const fullHistoryXrplApi = new evernode.XrplApi();
await fullHistoryXrplApi.connect();
this.db.open();
@@ -1065,7 +1087,7 @@ class MessageBoard {
}
persistConfig() {
ConfigHelper.writeConfig(this.cfg, this.configPath, this.secretConfigPath);
ConfigHelper.writeConfig(this.cfg, this.configPath);
}
}

View File

@@ -49,7 +49,13 @@ class SashiCLI {
execSashiCli(msg) {
this.#waiting = true;
return new Promise((resolve, reject) => {
exec(`${this.cliPath} json -m '${JSON.stringify(msg)}'`, { stdio: 'pipe' }, (err, stdout, stderr) => {
let command = `${this.cliPath} json -m '${JSON.stringify(msg)}'`;
if (msg.type === "create") {
command = `DEV_MODE=1 ${command}`;
}
exec(command, { stdio: 'pipe' }, (err, stdout, stderr) => {
this.#waiting = false;
if (err || stderr) {

View File

@@ -8,12 +8,18 @@ const { ConfigHelper } = require('./config-helper');
const { SashiCLI } = require('./sashi-cli');
const { UtilHelper } = require('./util-helper');
function setEvernodeDefaults(governorAddress, rippledServer, xrplApi = null) {
evernode.Defaults.set({
governorAddress: governorAddress,
rippledServer: rippledServer || appenv.DEFAULT_RIPPLED_SERVER,
xrplApi: xrplApi
});
async function setEvernodeDefaults(network, governorAddress, rippledServer) {
await evernode.Defaults.useNetwork(network || appenv.NETWORK);
if (governorAddress)
evernode.Defaults.set({
governorAddress: governorAddress
});
if (rippledServer)
evernode.Defaults.set({
rippledServer: rippledServer
});
}
class Setup {
@@ -37,32 +43,21 @@ class Setup {
})
}
async #generateFaucetAccount() {
console.log("Generating faucet account...");
const resp = await this.#httpPost(appenv.FAUCET_URL);
const json = JSON.parse(resp);
// If Hooks TEST NET is used.
return {
address: json.address,
secret: json.secret
};
}
#getConfig(readSecret = true) {
return ConfigHelper.readConfig(appenv.CONFIG_PATH, readSecret ? appenv.SECRET_CONFIG_PATH : null);
}
#saveConfig(cfg) {
ConfigHelper.writeConfig(cfg, appenv.CONFIG_PATH, appenv.SECRET_CONFIG_PATH);
ConfigHelper.writeConfig(cfg, appenv.CONFIG_PATH);
}
newConfig(address = "", secret = "", governorAddress = "", leaseAmount = 0, rippledServer = null, ipv6Subnet = null, ipv6NetInterface = null) {
newConfig(address = "", secretPath = "", governorAddress = "", leaseAmount = 0, rippledServer = null, ipv6Subnet = null, ipv6NetInterface = null, network = "") {
const baseConfig = {
version: appenv.MB_VERSION,
xrpl: {
network: network,
address: address,
secret: secret,
secretPath: secretPath,
governorAddress: governorAddress,
rippledServer: rippledServer || appenv.DEFAULT_RIPPLED_SERVER,
leaseAmount: leaseAmount
@@ -72,18 +67,22 @@ class Setup {
this.#saveConfig(ipv6NetInterface ? { ...baseConfig, networking: { ipv6: { subnet: ipv6Subnet, interface: ipv6NetInterface } } } : baseConfig);
}
async setupHostAccount(address, secret, rippledServer, governorAddress, domain) {
async prepareHostAccount(domain) {
setEvernodeDefaults(governorAddress, rippledServer);
const xrplApi = new evernode.XrplApi(rippledServer);
const acc = new evernode.XrplAccount(address, secret, { xrplApi: xrplApi });
const config = this.#getConfig();
const acc = config.xrpl;
await setEvernodeDefaults(acc.network, acc.governorAddress, acc.rippledServer);
// Prepare host account.
{
const hostClient = new evernode.HostClient(acc.address, acc.secret);
await hostClient.connect();
// Update the Defaults with "xrplApi" of the client.
evernode.Defaults.set({
xrplApi: hostClient.xrplApi
});
console.log(`Preparing host account:${acc.address} (domain:${domain} registry:${hostClient.config.registryAddress})`);
// Sometimes we may get 'account not found' error from rippled when some servers in the cluster
@@ -110,70 +109,6 @@ class Setup {
await hostClient.disconnect();
}
return acc;
}
async generateBetaHostAccount(rippledServer, governorAddress, domain) {
setEvernodeDefaults(governorAddress, rippledServer);
const acc = await this.#generateFaucetAccount();
// Prepare host account.
{
const hostClient = new evernode.HostClient(acc.address, acc.secret);
await hostClient.connect();
console.log(`Preparing host account:${acc.address} (domain:${domain} registry:${hostClient.config.registryAddress})`);
// Sometimes we may get 'account not found' error from rippled when some servers in the testnet cluster
// haven't still updated the ledger. In such cases, we retry several times before giving up.
{
let attempts = 0;
while (attempts >= 0) {
try {
await hostClient.prepareAccount(domain);
break;
}
catch (err) {
if (err.data?.error === 'actNotFound' && ++attempts <= 5) {
console.log("actNotFound - retrying...")
// Wait and retry.
await new Promise(resolve => setTimeout(resolve, 3000));
continue;
}
throw err;
}
}
}
// Get beta EVRs from foundation to host account.
{
console.log("Requesting beta EVRs...");
await hostClient.xrplAcc.makePayment(hostClient.config.foundationAddress,
evernode.XrplConstants.MIN_XRP_AMOUNT,
evernode.XrplConstants.XRP,
null,
[{ type: 'giftBetaEvr', format: '', data: '' }]);
// Keep watching our EVR balance.
let attempts = 0;
while (attempts >= 0) {
await new Promise(resolve => setTimeout(resolve, 1000));
const balance = await hostClient.getEVRBalance();
if (balance === '0') {
if (++attempts <= 20)
continue;
throw "EVR funds not received within timeout.";
}
break;
}
}
await hostClient.disconnect();
}
return acc;
}
async register(countryCode, cpuMicroSec, ramKb, swapKb, diskKb, totalInstanceCount, cpuModel, cpuCount, cpuSpeed, emailAddress, description) {
@@ -181,13 +116,15 @@ class Setup {
let cpuModelFormatted = cpuModel.replaceAll('_', ' ');
const config = this.#getConfig();
const acc = config.xrpl;
setEvernodeDefaults(acc.governorAddress, acc.rippledServer);
await setEvernodeDefaults(acc.network, acc.governorAddress, acc.rippledServer);
const hostClient = new evernode.HostClient(acc.address, acc.secret);
await hostClient.connect();
// Update the Defaults with "xrplApi" of the client.
setEvernodeDefaults(acc.governorAddress, acc.rippledServer, hostClient.xrplApi);
evernode.Defaults.set({
xrplApi: hostClient.xrplApi
});
const isAReReg = await hostClient.isTransferee();
const evrBalance = await hostClient.getEVRBalance();
@@ -230,13 +167,15 @@ class Setup {
async deregister() {
console.log("Deregistering host...");
const acc = this.#getConfig().xrpl;
setEvernodeDefaults(acc.governorAddress, acc.rippledServer);
await setEvernodeDefaults(acc.network, acc.governorAddress, acc.rippledServer);
const hostClient = new evernode.HostClient(acc.address, acc.secret);
await hostClient.connect();
// Update the Defaults with "xrplApi" of the client.
setEvernodeDefaults(acc.governorAddress, acc.rippledServer, hostClient.xrplApi);
evernode.Defaults.set({
xrplApi: hostClient.xrplApi
});
await this.burnMintedURITokens(hostClient.xrplAcc);
await hostClient.deregister();
@@ -249,7 +188,7 @@ class Setup {
console.log(`Governor address: ${acc?.governorAddress}`);
if (!isBasic) {
setEvernodeDefaults(acc.governorAddress, acc.rippledServer);
await setEvernodeDefaults(acc.network, acc.governorAddress, acc.rippledServer);
try {
const hostClient = new evernode.HostClient(acc.address);
@@ -257,7 +196,9 @@ class Setup {
console.log(`Registry address: ${hostClient.config.registryAddress}`);
console.log(`Heartbeat address: ${hostClient.config.heartbeatAddress}`);
setEvernodeDefaults(acc.governorAddress, acc.rippledServer, hostClient.xrplApi);
evernode.Defaults.set({
xrplApi: hostClient.xrplApi
});
const [evrBalance, hostInfo] = await Promise.all([hostClient.getEVRBalance(), hostClient.getRegistration()]);
if (hostInfo) {
@@ -279,7 +220,7 @@ class Setup {
}
// Upgrades existing message board data to the new version.
async upgrade(governorAddress) {
async upgrade() {
// Do a simple version change in the config.
const cfg = this.#getConfig();
@@ -289,19 +230,6 @@ class Setup {
if (!cfg.xrpl.rippledServer)
cfg.xrpl.rippledServer = appenv.DEFAULT_RIPPLED_SERVER
if (!cfg.xrpl.governorAddress) {
setEvernodeDefaults(governorAddress, cfg.xrpl.rippledServer);
const hostClient = new evernode.HostClient(cfg.xrpl.address, cfg.xrpl.secret);
await hostClient.connect();
setEvernodeDefaults(governorAddress, cfg.xrpl.rippledServer, hostClient.xrplApi);
cfg.xrpl.governorAddress = governorAddress;
await hostClient.disconnect();
}
this.#saveConfig(cfg);
await Promise.resolve(); // async placeholder.
@@ -311,13 +239,15 @@ class Setup {
async hostInfo() {
const acc = this.#getConfig(false).xrpl;
setEvernodeDefaults(acc.governorAddress, acc.rippledServer);
await setEvernodeDefaults(acc.network, acc.governorAddress, acc.rippledServer);
const hostClient = new evernode.HostClient(acc.address);
await hostClient.connect();
// Update the Defaults with "xrplApi" of the client.
setEvernodeDefaults(acc.governorAddress, acc.rippledServer, hostClient.xrplApi);
evernode.Defaults.set({
xrplApi: hostClient.xrplApi
});
const hostInfo = await hostClient.getHostInfo();
@@ -331,13 +261,15 @@ class Setup {
console.log("Updating host...");
const acc = this.#getConfig().xrpl;
setEvernodeDefaults(acc.governorAddress, acc.rippledServer);
await setEvernodeDefaults(acc.network, acc.governorAddress, acc.rippledServer);
const hostClient = new evernode.HostClient(acc.address, acc.secret);
await hostClient.connect();
// Update the Defaults with "xrplApi" of the client.
setEvernodeDefaults(acc.governorAddress, acc.rippledServer, hostClient.xrplApi);
evernode.Defaults.set({
xrplApi: hostClient.xrplApi
});
const hostInfo = await hostClient.getHostInfo();
await hostClient.updateRegInfo(hostInfo.activeInstances, null, null, null, null, null, null, null, null, emailAddress);
@@ -385,12 +317,14 @@ class Setup {
async transfer(transfereeAddress) {
console.log("Transferring host...");
const acc = this.#getConfig().xrpl;
setEvernodeDefaults(acc.governorAddress, acc.rippledServer);
await setEvernodeDefaults(acc.network, acc.governorAddress, acc.rippledServer);
const hostClient = new evernode.HostClient(acc.address, acc.secret);
await hostClient.connect();
setEvernodeDefaults(acc.governorAddress, acc.rippledServer, hostClient.xrplApi);
evernode.Defaults.set({
xrplApi: hostClient.xrplApi
});
await hostClient.transfer(transfereeAddress);
await this.burnMintedURITokens(hostClient.xrplAcc);
@@ -410,7 +344,7 @@ class Setup {
else if (totalInstanceCount && isNaN(totalInstanceCount))
throw 'Maximum instance count should be a number';
const leaseAmountParsed = leaseAmount ? parseInt(leaseAmount) : 0;
const leaseAmountParsed = leaseAmount ? parseFloat(leaseAmount) : 0;
const totalInstanceCountParsed = totalInstanceCount ? parseInt(totalInstanceCount) : 0;
// Return if not changed.
@@ -448,13 +382,14 @@ class Setup {
let hostClient;
async function initClients(rippledServer) {
setEvernodeDefaults(acc.governorAddress, rippledServer);
await setEvernodeDefaults(acc.network, acc.governorAddress, rippledServer);
xrplApi = new evernode.XrplApi();
hostClient = new evernode.HostClient(acc.address, acc.secret, { xrplApi: xrplApi });
await xrplApi.connect();
await hostClient.connect();
setEvernodeDefaults(acc.governorAddress, acc.rippledServer, xrplApi);
evernode.Defaults.set({
xrplApi: xrplApi
});
}
async function deinitClients() {
@@ -594,12 +529,14 @@ class Setup {
lease = lease[0];
const acc = this.#getConfig().xrpl;
setEvernodeDefaults(acc.governorAddress, acc.rippledServer);
await setEvernodeDefaults(acc.network, acc.governorAddress, acc.rippledServer);
xrplApi = new evernode.XrplApi(acc.rippledServer);
await xrplApi.connect();
setEvernodeDefaults(acc.governorAddress, acc.rippledServer, xrplApi);
evernode.Defaults.set({
xrplApi: xrplApi
});
// Get the existing uriToken of the lease.
const uriToken = (await (new evernode.XrplAccount(lease.tenant_xrp_address, null, { xrplApi: xrplApi }).getURITokens()))?.find(n => n.index == lease.container_name);
@@ -643,7 +580,43 @@ class Setup {
if (xrplApi)
await xrplApi.disconnect();
}
}
async setRegularKey(regularKey) {
{
const acc = this.#getConfig().xrpl;
await setEvernodeDefaults(acc.network, acc.governorAddress, acc.rippledServer);
if (regularKey) {
console.log(`Setting Regular Key...`);
}
else {
console.log(`Deleting Regular Key...`);
}
try {
await setEvernodeDefaults(acc.network, acc.governorAddress, acc.rippledServer);
const xrplApi = new evernode.XrplApi(acc.rippledServer, { autoReconnect: false });
await xrplApi.connect();
const xrplAcc = new evernode.XrplAccount(acc.address, acc.secret, { xrplApi: xrplApi });
await xrplAcc.setRegularKey(regularKey);
if (regularKey) {
console.log(`Regular key ${regularKey} was assigned to account ${acc.address} successfully.`);
}
else {
console.log(`Regular key was deleted from account ${acc.address} successfully.`);
}
await xrplApi.disconnect();
}
catch (e) {
throw e;
}
}
}
}

View File

@@ -6,7 +6,7 @@
"": {
"name": "mb-xrpl",
"dependencies": {
"evernode-js-client": "0.6.20",
"evernode-js-client": "0.6.24",
"ip6addr": "0.2.5",
"sqlite3": "5.0.2"
},
@@ -980,9 +980,9 @@
}
},
"node_modules/evernode-js-client": {
"version": "0.6.20",
"resolved": "https://registry.npmjs.org/evernode-js-client/-/evernode-js-client-0.6.20.tgz",
"integrity": "sha512-OC6VNAhwqnNvUc0NhffxwNI9bTDH+BkD/KBTC5Xuwoiq8BhRfYhmfHBnD6M9K5AvLqv+Jxdufc3l1AlzHgILWg==",
"version": "0.6.24",
"resolved": "https://registry.npmjs.org/evernode-js-client/-/evernode-js-client-0.6.24.tgz",
"integrity": "sha512-sT7eoN796ueo0+yZl6KpQOzINuXrYW88YlZCm2PxzRqv5G4TqgqUGFgs+GSESkxuVRkw2LBX9WcUCGwbAt6K9g==",
"dependencies": {
"elliptic": "6.5.4",
"libsodium-wrappers": "0.7.10",
@@ -4010,9 +4010,9 @@
"dev": true
},
"evernode-js-client": {
"version": "0.6.20",
"resolved": "https://registry.npmjs.org/evernode-js-client/-/evernode-js-client-0.6.20.tgz",
"integrity": "sha512-OC6VNAhwqnNvUc0NhffxwNI9bTDH+BkD/KBTC5Xuwoiq8BhRfYhmfHBnD6M9K5AvLqv+Jxdufc3l1AlzHgILWg==",
"version": "0.6.24",
"resolved": "https://registry.npmjs.org/evernode-js-client/-/evernode-js-client-0.6.24.tgz",
"integrity": "sha512-sT7eoN796ueo0+yZl6KpQOzINuXrYW88YlZCm2PxzRqv5G4TqgqUGFgs+GSESkxuVRkw2LBX9WcUCGwbAt6K9g==",
"requires": {
"elliptic": "6.5.4",
"libsodium-wrappers": "0.7.10",

View File

@@ -5,7 +5,7 @@
"build": "npm run lint && ncc build app.js --minify -o dist"
},
"dependencies": {
"evernode-js-client": "0.6.20",
"evernode-js-client": "0.6.24",
"sqlite3": "5.0.2",
"ip6addr": "0.2.5"
},

View File

@@ -5,6 +5,8 @@
#include "cli-manager.hpp"
#include "version.hpp"
#define DEV_MODE "DEV_MODE"
std::string exec_dir;
/**
@@ -90,6 +92,7 @@ int parse_cmd(int argc, char **argv)
std::string json_message;
json->add_option("-m,--message", json_message, "JSON message");
create->group(""); //Hides 'create' command from help-all
std::string owner, contract_id, image, outbound_ipv6, outbound_net_interface;
create->add_option("-o,--owner", owner, "Hex (ed-prefixed) public key of the instance owner");
create->add_option("-c,--contract-id", contract_id, "Contract Id (GUID) of the instance");
@@ -126,6 +129,25 @@ int parse_cmd(int argc, char **argv)
}
// Verifying subcommands.
bool is_dev_mode = (getenv(DEV_MODE) != nullptr);
if (!is_dev_mode)
{
if(create->parsed()){
std::cout << "Command not supported: Run with --help or --help-all for more information." << std::endl;
return -1;
}
if(json->parsed() && !json_message.empty()){
jsoncons::json json_data = jsoncons::json::parse(json_message);
if (json_data.contains("type") && json_data["type"].as_string() == "create")
{
std::cout << "Command not supported: Run with --help or --help-all for more information." << std::endl;
return -1;
}
}
}
if (version->parsed())
{
std::cout << "Sashimono CLI version " << version::CLI_VERSION << std::endl;

View File

@@ -69,7 +69,7 @@ namespace conf
cfg.system.max_cpu_us = !cpu_us ? 900000 : cpu_us; // Total CPU allocation out of 1000000 microsec (1 sec).
cfg.system.max_storage_kbytes = !disk_kbytes ? 5242880 : disk_kbytes;
cfg.docker.image_prefix = "evernodedev/sashimono:";
cfg.docker.image_prefix = "evernode/sashimono:";
cfg.docker.registry_port = docker_registry_port;
cfg.log.max_file_count = 50;

View File

@@ -6,7 +6,7 @@
namespace version
{
// Sashimono agent version. Written to new configs.
constexpr const char *AGENT_VERSION = "0.7.2";
constexpr const char *AGENT_VERSION = "0.8.0";
// Minimum compatible config version (this will be used to validate configs).
constexpr const char *MIN_CONFIG_VERSION = "0.5.0";

View File

@@ -1,4 +1,4 @@
FROM evernodedev/hotpocket:0.6.3-ubt.20.04
FROM evernode/hotpocket:0.6.4-ubt.20.04
RUN apt-get update \
&& apt-get install --no-install-recommends -y unzip jq \

View File

@@ -1,4 +1,4 @@
FROM evernodedev/hotpocket:0.6.3-ubt.20.04-njs.20
FROM evernode/hotpocket:0.6.4-ubt.20.04-njs.20
RUN apt-get update \
&& apt-get install --no-install-recommends -y unzip jq \

View File

@@ -1,6 +1,6 @@
#!/bin/bash
img=evernodedev/sashimono
img=evernode/sashimono
docker build -t $img:hp.latest-ubt.20.04 -t $img:hp.0.6.3-ubt.20.04 -f ./Dockerfile.ubt.20.04 .
docker build -t $img:hp.latest-ubt.20.04-njs.20 -t $img:hp.0.6.3-ubt.20.04-njs.20 -f ./Dockerfile.ubt.20.04-njs .
docker build -t $img:hp.latest-ubt.20.04 -t $img:hp.0.6.4-ubt.20.04 -f ./Dockerfile.ubt.20.04 .
docker build -t $img:hp.latest-ubt.20.04-njs.20 -t $img:hp.0.6.4-ubt.20.04-njs.20 -f ./Dockerfile.ubt.20.04-njs .

View File

@@ -1,5 +1,5 @@
#!/bin/bash
img=evernodedev/sashimono
img=evernode/sashimono
docker image push --all-tags $img

View File

@@ -473,7 +473,7 @@ if [ $mode == "create" ] || [ $mode == "createall" ]; then
config=$(echo "$config" | jq -c ".mesh.known_peers = [$peers]" | jq -c ".contract.unl = [\"$pubkey\"]")
fi
command="sashi json -m '{\"type\":\"create\",\"owner_pubkey\":\"$ownerpubkey\",\"contract_id\":\"$contractid\",\"image\":\"$image\",\"config\":$config}'"
command="DEV_MODE=1 sashi json -m '{\"type\":\"create\",\"owner_pubkey\":\"$ownerpubkey\",\"contract_id\":\"$contractid\",\"image\":\"$image\",\"config\":$config}'"
output=$(sshskp $sshuser@$hostaddr $command | tr '\0' '\n')
# If an output received consider updating the json file.
if [ ! "$output" = "" ]; then