Adding start-node process

This commit is contained in:
sairajzero 2021-07-18 20:44:48 +05:30
parent 433c395f8b
commit 854e88dde3
6 changed files with 229 additions and 18 deletions

9
config.json Normal file
View File

@ -0,0 +1,9 @@
{
"privateKey": "Replace_with_private_key",
"port": "8080",
"sql_user": "user",
"sql_pwd": "password",
"sql_db": "supernode",
"sql_host": "localhost"
}

View File

@ -5,8 +5,8 @@ const floGlobals = {
//Required for blockchain API operators
apiURL: {
FLO: ['https://explorer.mediciland.com/', 'https://livenet.flocha.in/', 'https://flosight.duckdns.org/', 'http://livenet-explorer.floexperiments.com'],
FLO_TEST: ['https://testnet-flosight.duckdns.org', 'https://testnet.flocha.in/']
FLO: ['https://explorer.mediciland.com/', 'https://livenet.flocha.in/', 'https://flosight.duckdns.org/', 'http://livenet-explorer.floexperiments.com'],
FLO_TEST: ['https://testnet-flosight.duckdns.org', 'https://testnet.flocha.in/']
},
SNStorageID: "FNaN9McoBAEFUjkRmNQRYLmBF8SpS7Tgfk",
//sendAmt: 0.001,
@ -14,13 +14,9 @@ const floGlobals = {
//Required for Supernode operations
supernodes: {}, //each supnernode must be stored as floID : {uri:<uri>,pubKey:<publicKey>}
defaultDisk : "General",
appList:{},
appSubAdmins:{},
serveList : [],
storedList : [],
backupNodes : [],
supernodeConfig : {}
appList: {},
appSubAdmins: {},
sn_config: {}
/* List of supernode configurations (all blockchain controlled by SNStorageID)
backupDepth - (Interger) Number of backup nodes
refreshDelay - (Interger) Count of requests for triggering read-blockchain and autodelete
@ -28,6 +24,5 @@ const floGlobals = {
errorFeedback - (Boolean) Send error (if any) feedback to the requestor
delayDelta - (Interger) Maximum allowed delay from the data-time
*/
}
if('object' === typeof module) module.export = floGlobals;
}
('object' === typeof module) ? module.export = floGlobals : null;

View File

@ -412,7 +412,7 @@ function sendStoredData(lastlogs, node) {
id: n,
status: false
}))
}).catch(error => reject(error))
}).catch(error => console.error(error))
}
}
}
@ -457,11 +457,17 @@ function forwardToNextNode(mode, data) {
}));
}
function dataMigration(node_change){
console.log("data migration")
//TODO
}
//-----EXPORTS-----
module.exports = {
processTaskFromSupernode,
setBlockchainParameters,
forwardToNextNode,
dataMigration,
SUPERNODE_INDICATOR,
_list,
set DB(db){

View File

@ -31,16 +31,16 @@ require('./lib/BuildKBucket')
return KB;
}
kBucket.launch = function(masterID, superNodeList) {
kBucket.launch = function() {
return new Promise((resolve, reject) => {
try {
//let superNodeList = Object.keys(floGlobals.supernodes);
//let masterID = floGlobals.SNStorageID;
let superNodeList = Object.keys(floGlobals.supernodes);
let masterID = floGlobals.SNStorageID;
SNKB = constructKB(superNodeList, masterID);
SNCO = superNodeList.map(sn => [distanceOf(sn), sn])
.sort((a, b) => a[0] - b[0])
.map(a => a[1])
resolve('Supernode KBucket formed');
resolve('SuperNode KBucket formed');
} catch (error) {
reject(error);
}

View File

@ -3,12 +3,14 @@ const WebSocket = require('ws')
module.exports = function Server(port, client, intra) {
var refresher; //container for refresher
const server = http.createServer((req, res) => {
if (req.method === "GET") {
//GET request (requesting data)
req.on('end', () => {
let i = req.url.indexOf("?");
if (i) {
if (i !== -1) {
var request = JSON.parse(req.url.substring(i));
client.processRequestFromUser(request)
.then(result => res.end(JSON.parse(result[0])))
@ -25,6 +27,7 @@ module.exports = function Server(port, client, intra) {
client.processIncomingData(data).then(result => {
res.end(result[0]);
if (result[1]) {
refresher.countdown;
if (result[1] === 'DATA')
sendToLiveRequests(result[0])
intra.forwardToNextNode(result[1], result[0])
@ -66,4 +69,7 @@ module.exports = function Server(port, client, intra) {
Object.defineProperty(this, "webSocket", {
get: () => wsServer
});
Object.defineProperty(this, "refresher", {
set: (r) => refresher = r
})
}

195
src/start.js Normal file
View File

@ -0,0 +1,195 @@
const config = require("../config.json")
global.floGlobals = require("./floGlobals")
require('./lib')
require('./lib/BuildKBucket')
require('./floCrypto')
require('./floBlockchainAPI')
const Database = require("./database")
const intra = require('./intra')
const client = require('./client')
const Server = require('./server')
var DB; //Container for Database object
function startNode() {
//Set myPrivKey, myPubKey, myFloID
global.myPrivKey = config["privateKey"]
global.myPubKey = floCrypto.getPubKeyHex(config["privateKey"])
global.myFloID = floCrypto.getFloID(config["privateKey"])
//DB connect
Database(config["sql_user"], config["sql_pwd"], config["sql_db"], config["sql_host"]).then(db => {
DB = db;
//Set DB to client and intra scripts
intra.DB = DB;
client.DB = DB;
client._list = intra._list;
loadBase().then(base => {
//Set base data from DB to floGlobals
floGlobals.supernodes = base.supernodes;
floGlobals.sn_config = base.sn_config;
floGlobals.appList = base.appList;
floGlobals.appSubAdmins = base.appSubAdmins;
refreshData.base = base;
refreshData.invoke();
//Start Server
const server = new Server(config["port"], client, intra);
server.refresher = refreshData;
}).catch(error => reject(error))
}).catch(error => reject(error))
}
function loadBase(DB) {
return new Promise((resolve, reject) => {
DB.createBase().then(result => {
DB.getBase(DB)
.then(result => resolve(result))
.catch(error => reject(error))
}).catch(error => reject(error))
})
}
const refreshData = {
count: null,
base: null,
invoke() {
this.count = floGlobals.sn_config.refreshDelay;
refreshBlockchainData(this.base).then(result => {
console.log(result)
diskCleanUp()
.then(result => console.info(result))
.catch(error => console.error(error))
}).catch(error => console.error(error))
},
get countdown() {
this.count--;
if (this.count <= 0)
this.invoke();
}
}
function refreshBlockchainData(base) {
return new Promise((resolve, reject) => {
readSupernodeConfigFromAPI(base).then(result => {
console.log(result)
kBucket.launch().then(result => {
console.log(result)
readAppSubAdminListFromAPI(base)
.then(result => console.log(result))
.catch(error => console.warn(error))
.finally(_ => resolve("Refreshed Data from blockchain"))
}).catch(error => reject(error))
}).catch(error => reject(error))
})
}
function readSupernodeConfigFromAPI(base) {
return new Promise((resolve, reject) => {
floBlockchainAPI.readData(floGlobals.SNStorageID, {
ignoreOld: base.lastTx[floGlobals.SNStorageID],
sentOnly: true,
pattern: "SuperNodeStorage"
}).then(result => {
let promises = [],
node_change = {}
result.data.reverse().forEach(data => {
var content = JSON.parse(data).SuperNodeStorage;
if (content.removeNodes)
for (let sn of content.removeNodes) {
promises.push(DB.rmSuperNode(sn));
delete base.supernodes[sn];
if (node_change[sn] === true)
delete node_change[sn];
else
node_change[sn] = false;
}
if (content.newNodes)
for (let sn in content.newNodes) {
promises.push(DB.addSuperNode(sn, content.newNodes[sn].pubKey, content.newNodes[sn].uri));
base.supernodes[sn] = {
pubKey: content.newNodes[sn].pubKey,
uri: content.newNodes[sn].uri
};
if (node_change[sn] === false)
delete node_change[sn];
else
node_change[sn] = true;
}
if (content.config)
for (let c in content.config) {
promises.push(DB.setConfig(c, content.config[c]));
base.sn_config[c] = content.config[c];
}
if (content.removeApps)
for (let app of content.removeApps) {
promises.push(DB.rmApp(app));
delete base.appList;
}
if (content.addApps)
for (let app in content.addApps) {
promises.push(DB.addApp(app, content.addApps[app]));
base.appList[app] = content.addApps[app];
}
});
promises.push(DB.setLastTx(floGlobals.SNStorageID, result.totalTxs));
//Check if all save process were successful
Promise.allSettled(promises).then(results => {
if (results.reduce((a, r) => r.status === "rejected" ? ++a : a, 0))
console.warn("Some data might not have been saved in database correctly");
else
console.log("All data are saved in database");
});
//Process data migration if nodes are changed
if (Object.keys(node_change))
intra.dataMigration(node_change)
resolve('Updated Supernode Configuration');
}).catch(error => reject(error))
})
}
function readAppSubAdminListFromAPI(base) {
var promises = [];
//Load for each apps
for (let app in base.appList) {
promises.push(new Promise((resolve, reject) => {
floBlockchainAPI.readData(base.appList[app], {
ignoreOld: base.lastTx[`${app}_${base.appList[app]}`],
sentOnly: true,
pattern: app
}).then(result => {
let subAdmins = new Set(base.appSubAdmins[app]);
result.data.reverse().forEach(data => {
let content = JSON.parse(result.data[i])[app];
if (Array.isArray(content.removeSubAdmin))
content.removeSubAdmin.forEach(sa => subAdmins.delete(sa));
if (Array.isArray(content.addSubAdmin))
content.addSubAdmin.forEach(sa => subAdmins.add(sa));
});
base.appSubAdmins[app] = Array.from(subAdmins);
Promise.allSettled([
DB.setLastTx(`${app}_${base.appList[app]}`, result.totalTxs),
DB.setSubAdmin(app, base.appSubAdmins[app])
]).then(results => {
if (results.reduce((a, r) => r.status === "rejected" ? ++a : a, 0))
console.warn(`SubAdmin list for app(${app}) might not have been saved in database`);
});
resolve("Loaded subAdmin List for APP:" + app);
}).catch(error => reject([app, error]))
}));
}
return new Promise((resolve, reject) => {
Promise.allSettled(results => {
if (results.reduce((a, r) => r.status === "rejected" ? ++a : a, 0)) {
let error = Object.fromEntries(results.filter(r => r.status === "rejected").map(r => r.reason));
console.error(JSON.stringify(error));
reject(`subAdmin List for APPS(${Object.keys(error)} might not have loaded correctly`);
} else
resolve("Loaded subAdmin List for all APPs successfully");
});
})
}
function diskCleanUp(){
//TODO: Clear all unauthorised data from before deleteDelay
}
module.exports = startNode;