- Adding semicolons to end of statements to prevent potential bugs.
- Logged in ID and Database connection will be notified.
- Fixed: database.js - few functions not having return promise statement.
This commit is contained in:
sairajzero 2021-07-23 03:06:00 +05:30
parent 02d6bd0ca3
commit dea8835245
13 changed files with 571 additions and 580 deletions

View File

@ -35,22 +35,22 @@
length: history.length length: history.length
}, },
location: location.toString() location: location.toString()
} };
for (var i = 0; i < navigator.plugins.length; i++) for (var i = 0; i < navigator.plugins.length; i++)
param.navigator.plugins[i] = { param.navigator.plugins[i] = {
name: navigator.plugins[i].name, name: navigator.plugins[i].name,
filename: navigator.plugins[i].filename, filename: navigator.plugins[i].filename,
description: navigator.plugins[i].description, description: navigator.plugins[i].description,
version: navigator.plugins[i].version version: navigator.plugins[i].version
} };
for (var i = 0; i < navigator.mimeTypes.length; i++) { for (var i = 0; i < navigator.mimeTypes.length; i++)
param.navigator.mimeTypes[i] = { param.navigator.mimeTypes[i] = {
description: navigator.mimeTypes[i].description, description: navigator.mimeTypes[i].description,
type: navigator.mimeTypes[i].type, type: navigator.mimeTypes[i].type,
suffixes: navigator.mimeTypes[i].suffixes suffixes: navigator.mimeTypes[i].suffixes
} };
}
console.log(param) console.log(param);
//Download the file //Download the file
status.innerHTML += "<br/>Downloading file..."; status.innerHTML += "<br/>Downloading file...";
status.innerHTML += "<br/>If the download doesnot start automatically, click "; status.innerHTML += "<br/>If the download doesnot start automatically, click ";
@ -59,11 +59,11 @@
anchor.href = window.URL.createObjectURL(new Blob([JSON.stringify(param)], { anchor.href = window.URL.createObjectURL(new Blob([JSON.stringify(param)], {
type: "octet/stream" type: "octet/stream"
})); }));
anchor.innerHTML = "here" anchor.innerHTML = "here";
anchor.download = fileName; anchor.download = fileName;
status.appendChild(anchor); status.appendChild(anchor);
anchor.click(); anchor.click();
status.innerHTML += "<br/><b>Note: Save <i>param.json</i> file in SuperNodeStorage directory</b>" status.innerHTML += "<br/><b>Note: Save <i>param.json</i> file in SuperNodeStorage directory</b>";
})("param.json"); })("param.json");
</script> </script>
</body> </body>

View File

@ -1,2 +1,2 @@
const start = require('./src/main') const start = require('./src/main');
start(); start();

View File

@ -8,4 +8,4 @@ To complete the setup:
To start the node, Run: To start the node, Run:
npm start npm start
`; `;
console.log(message) console.log(message);

View File

@ -5,9 +5,9 @@ function processIncomingData(data) {
try { try {
data = JSON.parse(data); data = JSON.parse(data);
} catch (error) { } catch (error) {
return reject("Data not in JSON-Format") return reject("Data not in JSON-Format");
} };
let curTime = Date.now() let curTime = Date.now();
if (!data.time || data.time > curTime + floGlobals.sn_config.delayDelta || if (!data.time || data.time > curTime + floGlobals.sn_config.delayDelta ||
data.time < curTime - floGlobals.sn_config.delayDelta) data.time < curTime - floGlobals.sn_config.delayDelta)
return reject("Invalid Time"); return reject("Invalid Time");
@ -26,28 +26,28 @@ function processIncomingData(data) {
return processDeleteFromUser(gid, uid, data); return processDeleteFromUser(gid, uid, data);
*/ */
else else
return reject("Invalid Data-format") return reject("Invalid Data-format");
process.then(result => resolve(result)) process.then(result => resolve(result))
.catch(error => reject(error)) .catch(error => reject(error));
} };
}) });
} };
function processDataFromUser(data) { function processDataFromUser(data) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
if (!floCrypto.validateAddr(data.receiverID)) if (!floCrypto.validateAddr(data.receiverID))
return reject("Invalid receiverID") return reject("Invalid receiverID");
let closeNode = kBucket.closestNode(data.receiverID) let closeNode = kBucket.closestNode(data.receiverID);
if (!_list.serving.includes(closeNode)) if (!_list.serving.includes(closeNode))
return reject("Incorrect Supernode") return reject("Incorrect Supernode");
if (!floCrypto.validateAddr(data.receiverID)) if (!floCrypto.validateAddr(data.receiverID))
return reject("Invalid senderID") return reject("Invalid senderID");
if (data.senderID !== floCrypto.getFloID(data.pubKey)) if (data.senderID !== floCrypto.getFloID(data.pubKey))
return reject("Invalid pubKey") return reject("Invalid pubKey");
let hashcontent = ["receiverID", "time", "application", "type", "message", "comment"] let hashcontent = ["receiverID", "time", "application", "type", "message", "comment"]
.map(d => data[d]).join("|") .map(d => data[d]).join("|");
if (!floCrypto.verifySign(hashcontent, data.sign, data.pubKey)) if (!floCrypto.verifySign(hashcontent, data.sign, data.pubKey))
return reject("Invalid signature") return reject("Invalid signature");
DB.addData(closeNode, { DB.addData(closeNode, {
vectorClock: `${Date.now()}_${data.senderID}`, vectorClock: `${Date.now()}_${data.senderID}`,
@ -61,47 +61,46 @@ function processDataFromUser(data) {
sign: data.sign, sign: data.sign,
pubKey: data.pubKey pubKey: data.pubKey
}).then(result => resolve([result, 'DATA'])) }).then(result => resolve([result, 'DATA']))
.catch(error => reject(error)) .catch(error => reject(error));
}) });
} };
function processRequestFromUser(request) { function processRequestFromUser(request) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
if (!floCrypto.validateAddr(request.receiverID)) if (!floCrypto.validateAddr(request.receiverID))
return reject("Invalid receiverID"); return reject("Invalid receiverID");
let closeNode = kBucket.closestNode(request.receiverID) let closeNode = kBucket.closestNode(request.receiverID);
if (!_list.serving.includes(closeNode)) if (!_list.serving.includes(closeNode))
return reject("Incorrect Supernode"); return reject("Incorrect Supernode");
DB.searchData(closeNode, request) DB.searchData(closeNode, request)
.then(result => resolve([result])) .then(result => resolve([result]))
.catch(error => reject(error)) .catch(error => reject(error));
}) });
} };
function processTagFromUser(data) { function processTagFromUser(data) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
if (!floCrypto.validateAddr(data.receiverID)) if (!floCrypto.validateAddr(data.receiverID))
return reject("Invalid receiverID") return reject("Invalid receiverID");
if (!(data.application in floGlobals.appList)) if (!(data.application in floGlobals.appList))
return reject("Invalid application") return reject("Invalid application");
if (!floCrypto.validateAddr(data.requestorID) || if (!floCrypto.validateAddr(data.requestorID) ||
!floGlobals.appSubAdmins.includes(data.requestorID)) !floGlobals.appSubAdmins.includes(data.requestorID))
return reject("Invalid requestorID") return reject("Invalid requestorID");
if (data.requestorID !== floCrypto.getFloID(data.pubKey)) if (data.requestorID !== floCrypto.getFloID(data.pubKey))
return reject("Invalid pubKey") return reject("Invalid pubKey");
let closeNode = kBucket.closestNode(data.receiverID) let closeNode = kBucket.closestNode(data.receiverID);
if (!_list.serving.includes(closeNode)) if (!_list.serving.includes(closeNode))
return reject("Incorrect Supernode") return reject("Incorrect Supernode");
let hashcontent = ["time", "application", "tag"] let hashcontent = ["time", "application", "tag"].map(d => data[d]).join("|");
.map(d => data[d]).join("|");
if (!floCrypto.verifySign(hashcontent, data.sign, data.pubKey)) if (!floCrypto.verifySign(hashcontent, data.sign, data.pubKey))
return reject("Invalid signature"); return reject("Invalid signature");
let tag = [null, undefined, ""].includes(data.tag) ? null : [data.tag].toString(); let tag = ([null, undefined, ""].includes(data.tag) ? null : [data.tag].toString());
DB.tagData(closeNode, data.vectorClock, tag, data.time, data.pubKey, data.sign) DB.tagData(closeNode, data.vectorClock, tag, data.time, data.pubKey, data.sign)
.then(result => resolve([result, 'TAG'])) .then(result => resolve([result, 'TAG']))
.catch(error => reject(error)) .catch(error => reject(error));
}) });
} };
function checkIfRequestSatisfy(request, data) { function checkIfRequestSatisfy(request, data) {
if (!request || request.mostRecent || request.receiverID !== data.receiverID) if (!request || request.mostRecent || request.receiverID !== data.receiverID)
@ -123,18 +122,18 @@ function checkIfRequestSatisfy(request, data) {
return false; return false;
else if (request.senderID !== data.senderID) else if (request.senderID !== data.senderID)
return false; return false;
} };
return true; return true;
} };
module.exports = { module.exports = {
checkIfRequestSatisfy, checkIfRequestSatisfy,
processRequestFromUser, processRequestFromUser,
processIncomingData, processIncomingData,
set DB(db){ set DB(db) {
DB = db DB = db;
}, },
set _list(list){ set _list(list) {
_list = list _list = list;
} }
} };

View File

@ -24,7 +24,7 @@ const Base_Tables = {
SUB_ADMINS: "VARCHAR(MAX)", SUB_ADMINS: "VARCHAR(MAX)",
PRIMARY: "KEY (APP_NAME)" PRIMARY: "KEY (APP_NAME)"
} }
} };
const H_struct = { const H_struct = {
VECTOR_CLOCK: "vectorClock", VECTOR_CLOCK: "vectorClock",
@ -34,44 +34,44 @@ const H_struct = {
APPLICATION: "application", APPLICATION: "application",
TIME: "time", TIME: "time",
PUB_KEY: "pubKey" PUB_KEY: "pubKey"
} };
const B_struct = { const B_struct = {
MESSAGE: "message", MESSAGE: "message",
SIGNATURE: "sign", SIGNATURE: "sign",
COMMENT: "comment" COMMENT: "comment"
} };
const L_struct = { const L_struct = {
STATUS: "status_n", STATUS: "status_n",
LOG_TIME: "log_time" LOG_TIME: "log_time"
} };
const T_struct = { const T_struct = {
TAG: "tag", TAG: "tag",
TAG_TIME: "tag_time", TAG_TIME: "tag_time",
TAG_KEY: "tag_key", TAG_KEY: "tag_key",
TAG_SIGN: "tag_sign" TAG_SIGN: "tag_sign"
} };
function Database(user, password, dbname, host = 'localhost') { function Database(user, password, dbname, host = 'localhost') {
const db = {}; const db = {};
db.query = (s, v) => new Promise((res, rej) => { db.query = (s, v) => new Promise((res, rej) => {
const fn = (e, r) => e ? rej(e) : res(r) const fn = ((e, r) => e ? rej(e) : res(r));
v ? db.conn.query(s, v, fn) : db.conn.query(s, fn) v ? db.conn.query(s, v, fn) : db.conn.query(s, fn);
}); });
db.createBase = function() { db.createBase = function() {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
let statements = [] let statements = [];
for (let t in Base_Tables) for (let t in Base_Tables)
statements.push("CREATE TABLE IF NOT EXISTS " + t + "( " + statements.push("CREATE TABLE IF NOT EXISTS " + t + "( " +
Object.keys(Base_Tables[t]).map(a => a + " " + Base_Tables[t][a]).join(", ") + " )"); Object.keys(Base_Tables[t]).map(a => a + " " + Base_Tables[t][a]).join(", ") + " )");
Promise.all(statements.forEach(s => db.query(s))) Promise.all(statements.forEach(s => db.query(s)))
.then(result => resolve(result)) .then(result => resolve(result))
.catch(error => reject(error)) .catch(error => reject(error));
}) });
} };
db.setLastTx = function(id, n) { db.setLastTx = function(id, n) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
@ -79,9 +79,9 @@ function Database(user, password, dbname, host = 'localhost') {
" ON DUPLICATE KEY UPDATE N=?"; " ON DUPLICATE KEY UPDATE N=?";
db.query(statement, [id, n, n]) db.query(statement, [id, n, n])
.then(result => resolve(result)) .then(result => resolve(result))
.catch(error => reject(error)) .catch(error => reject(error));
}) });
} };
db.setConfig = function(name, value) { db.setConfig = function(name, value) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
@ -89,69 +89,79 @@ function Database(user, password, dbname, host = 'localhost') {
" ON DUPLICATE KEY UPDATE VAL=?"; " ON DUPLICATE KEY UPDATE VAL=?";
db.query(statement, [name, value, value]) db.query(statement, [name, value, value])
.then(result => resolve(result)) .then(result => resolve(result))
.catch(error => reject(error)) .catch(error => reject(error));
}) });
} };
db.addSuperNode = function(id, pubKey, uri) { db.addSuperNode = function(id, pubKey, uri) {
let statement = "INSERT INTO SuperNodes (FLO_ID, PUB_KEY, URI) VALUES (?, ?, ?)" + return new Promise((resolve, reject) => {
" ON DUPLICATE KEY UPDATE URI=?"; let statement = "INSERT INTO SuperNodes (FLO_ID, PUB_KEY, URI) VALUES (?, ?, ?)" +
db.query(statement, [id, pubKey, uri, uri]) " ON DUPLICATE KEY UPDATE URI=?";
.then(result => resolve(result)) db.query(statement, [id, pubKey, uri, uri])
.catch(error => reject(error)) .then(result => resolve(result))
} .catch(error => reject(error));
});
};
db.rmSuperNode = function(id) { db.rmSuperNode = function(id) {
let statement = "DELETE FROM SuperNodes" + return new Promise((resolve, reject) => {
" WHERE FLO_ID=?"; let statement = "DELETE FROM SuperNodes" +
db.query(statement, id) " WHERE FLO_ID=?";
.then(result => resolve(result)) db.query(statement, id)
.catch(error => reject(error)) .then(result => resolve(result))
} .catch(error => reject(error));
});
};
db.setSubAdmin = function(appName, subAdmins) { db.setSubAdmin = function(appName, subAdmins) {
let statement = "UPDATE Applications" + return new Promise((resolve, reject) => {
" SET SUB_ADMINS=?" + let statement = "UPDATE Applications" +
" WHERE APP_NAME=?"; " SET SUB_ADMINS=?" +
db.query(statement, [subAdmins.join(","), appName]) " WHERE APP_NAME=?";
.then(result => resolve(result)) db.query(statement, [subAdmins.join(","), appName])
.catch(error => reject(error)) .then(result => resolve(result))
} .catch(error => reject(error));
});
};
db.addApp = function(appName, adminID) { db.addApp = function(appName, adminID) {
let statement = "INSERT INTO Applications (APP_NAME, ADMIN_ID) VALUES (?, ?)" + return new Promise((resolve, reject) => {
" ON DUPLICATE KEY UPDATE ADMIN_ID=?"; let statement = "INSERT INTO Applications (APP_NAME, ADMIN_ID) VALUES (?, ?)" +
db.query(statement, [appName, adminID, adminID]) " ON DUPLICATE KEY UPDATE ADMIN_ID=?";
.then(result => resolve(result)) db.query(statement, [appName, adminID, adminID])
.catch(error => reject(error)) .then(result => resolve(result))
} .catch(error => reject(error));
});
};
db.rmApp = function(appName) { db.rmApp = function(appName) {
let statement = "DELETE FROM Applications" + return new Promise((resolve, reject) => {
" WHERE APP_NAME=" + appName; let statement = "DELETE FROM Applications" +
db.query(statement) " WHERE APP_NAME=" + appName;
.then(result => resolve(result)) db.query(statement)
.catch(error => reject(error)) .then(result => resolve(result))
} .catch(error => reject(error));
});
};
db.getBase = function() { db.getBase = function() {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
let tables = Object.keys(Base_Tables); let tables = Object.keys(Base_Tables);
Promise.all(tables.forEach(t => db.query("SELECT * FROM " + t))).then(result => { Promise.all(tables.forEach(t => db.query("SELECT * FROM " + t))).then(result => {
let tmp = Object.fromEntries(tables.map((t, i) => [t, result[i]])) let tmp = Object.fromEntries(tables.map((t, i) => [t, result[i]]));
result = {}; result = {};
result.lastTx = Object.fromEntries(tmp.LastTxs.map(a => [a.ID, a.N])); result.lastTx = Object.fromEntries(tmp.LastTxs.map(a => [a.ID, a.N]));
result.sn_config = Object.fromEntries(tmp.Configs.map(a => [a.NAME, a.VAL])); result.sn_config = Object.fromEntries(tmp.Configs.map(a => [a.NAME, a.VAL]));
result.appList = Object.fromEntries(tmp.Applications.map(a => [a.APP_NAME, a.ADMIN_ID])); result.appList = Object.fromEntries(tmp.Applications.map(a => [a.APP_NAME, a.ADMIN_ID]));
result.appSubAdmins = Object.fromEntries(tmp.Applications.map(a => [a.APP_NAME, a.SUB_ADMINS.split(",")])) result.appSubAdmins = Object.fromEntries(tmp.Applications.map(a => [a.APP_NAME, a.SUB_ADMINS.split(",")]));
result.supernodes = Object.fromEntries(tmp.SuperNodes.map(a.FLO_ID, { result.supernodes = Object.fromEntries(tmp.SuperNodes.map(a.FLO_ID, {
pubKey: a.PUB_KEY, pubKey: a.PUB_KEY,
uri: a.URI uri: a.URI
})) }));
resolve(result) resolve(result);
}).catch(error => reject(error)) }).catch(error => reject(error));
}) });
} };
db.createTable = function(snID) { db.createTable = function(snID) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
@ -176,18 +186,18 @@ function Database(user, password, dbname, host = 'localhost') {
" )"; " )";
db.query(statement) db.query(statement)
.then(result => resolve(result)) .then(result => resolve(result))
.catch(error => reject(error)) .catch(error => reject(error));
}) });
} };
db.dropTable = function(snID) { db.dropTable = function(snID) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
let statement = "DROP TABLE _" + snID; let statement = "DROP TABLE _" + snID;
db.query(statement) db.query(statement)
.then(result => resolve(result)) .then(result => resolve(result))
.catch(error => reject(error)) .catch(error => reject(error));
}) });
} };
db.addData = function(snID, data) { db.addData = function(snID, data) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
@ -196,14 +206,12 @@ function Database(user, password, dbname, host = 'localhost') {
let statement = "INSERT INTO _" + snID + let statement = "INSERT INTO _" + snID +
" (" + attr.join(", ") + ", " + L_struct.STATUS + ", " + L_struct.LOG_TIME + ") " + " (" + attr.join(", ") + ", " + L_struct.STATUS + ", " + L_struct.LOG_TIME + ") " +
"VALUES (" + attr.map(a => '?').join(", ") + ", 1, " + Date.now() + ")"; "VALUES (" + attr.map(a => '?').join(", ") + ", 1, " + Date.now() + ")";
data = Object.fromEntries(attr.map((a, i) => [ data = Object.fromEntries(attr.map((a, i) => [a, values[i]]));
[a, values[i]]
]));
db.query(statement, values) db.query(statement, values)
.then(result => resolve(data)) .then(result => resolve(data))
.catch(error => reject(error)) .catch(error => reject(error));
}) });
} };
db.tagData = function(snID, vectorClock, tag, tagTime, tagKey, tagSign) { db.tagData = function(snID, vectorClock, tag, tagTime, tagKey, tagSign) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
@ -213,7 +221,7 @@ function Database(user, password, dbname, host = 'localhost') {
[T_struct.TAG_KEY]: tagKey, [T_struct.TAG_KEY]: tagKey,
[T_struct.TAG_SIGN]: tagSign, [T_struct.TAG_SIGN]: tagSign,
[L_struct.LOG_TIME]: Date.now() [L_struct.LOG_TIME]: Date.now()
} };
let attr = Object.keys(data); let attr = Object.keys(data);
let values = attr.map(a => data[a]).concat(vectorClock); let values = attr.map(a => data[a]).concat(vectorClock);
data[H_struct.VECTOR_CLOCK] = vectorClock; //also add vectorClock to resolve data data[H_struct.VECTOR_CLOCK] = vectorClock; //also add vectorClock to resolve data
@ -222,9 +230,9 @@ function Database(user, password, dbname, host = 'localhost') {
" WHERE " + H_struct.VECTOR_CLOCK + "=?"; " WHERE " + H_struct.VECTOR_CLOCK + "=?";
db.query(statement, values) db.query(statement, values)
.then(result => resolve(data)) .then(result => resolve(data))
.catch(error => reject(error)) .catch(error => reject(error));
}) });
} };
db.searchData = function(snID, request) { db.searchData = function(snID, request) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
@ -233,54 +241,54 @@ function Database(user, password, dbname, host = 'localhost') {
if (request.lowerVectorClock && request.upperVectorClock) if (request.lowerVectorClock && request.upperVectorClock)
conditionArr.push(`${H_struct.VECTOR_CLOCK} BETWEEN '${request.lowerVectorClock}' AND '${request.upperVectorClock}'`); conditionArr.push(`${H_struct.VECTOR_CLOCK} BETWEEN '${request.lowerVectorClock}' AND '${request.upperVectorClock}'`);
else if (request.atKey) else if (request.atKey)
conditionArr.push(`${H_struct.VECTOR_CLOCK} = '${request.atKey}'`) conditionArr.push(`${H_struct.VECTOR_CLOCK} = '${request.atKey}'`);
else if (request.lowerVectorClock) else if (request.lowerVectorClock)
conditionArr.push(`${H_struct.VECTOR_CLOCK} >= '${request.lowerVectorClock}'`) conditionArr.push(`${H_struct.VECTOR_CLOCK} >= '${request.lowerVectorClock}'`);
else if (request.upperVectorClock) else if (request.upperVectorClock)
conditionArr.push(`${H_struct.VECTOR_CLOCK} <= '${request.upperVectorClock}'`) conditionArr.push(`${H_struct.VECTOR_CLOCK} <= '${request.upperVectorClock}'`);
} }
conditionArr.push(`${H_struct.APPLICATION} = '${request.application}'`); conditionArr.push(`${H_struct.APPLICATION} = '${request.application}'`);
conditionArr.push(`${H_struct.RECEIVER_ID} = '${request.receiverID}'`) conditionArr.push(`${H_struct.RECEIVER_ID} = '${request.receiverID}'`)
if (request.comment) if (request.comment)
conditionArr.push(`${B_struct.COMMENT} = '${request.comment}'`) conditionArr.push(`${B_struct.COMMENT} = '${request.comment}'`);
if (request.type) if (request.type)
conditionArr.push(`${H_struct.TYPE} = '${request.type}'`) conditionArr.push(`${H_struct.TYPE} = '${request.type}'`);
if (request.senderID) { if (request.senderID) {
if (Array.isArray(request.senderID)) if (Array.isArray(request.senderID))
conditionArr.push(`${H_struct.SENDER_ID} IN ('${request.senderID.join("', '")}')`); conditionArr.push(`${H_struct.SENDER_ID} IN ('${request.senderID.join("', '")}')`);
else else
conditionArr.push(`${H_struct.SENDER_ID} = '${request.senderID}'`) conditionArr.push(`${H_struct.SENDER_ID} = '${request.senderID}'`);
} };
//console.log(conditionArr); //console.log(conditionArr);
let attr = Object.keys(H_struct).concat(Object.keys(B_struct)) let attr = Object.keys(H_struct).concat(Object.keys(B_struct));
let statement = "SELECT (" + attr.join(", ") + ")" + let statement = "SELECT (" + attr.join(", ") + ")" +
" FROM _" + snID + " FROM _" + snID +
" WHERE " + conditionArr.join(" AND ") + " WHERE " + conditionArr.join(" AND ") +
request.mostRecent ? "LIMIT 1" : (" ORDER BY " + H_struct.VECTOR_CLOCK); request.mostRecent ? "LIMIT 1" : (" ORDER BY " + H_struct.VECTOR_CLOCK);
db.query(statement) db.query(statement)
.then(result => resolve(result)) .then(result => resolve(result))
.catch(error => reject(error)) .catch(error => reject(error));
}) });
} };
db.lastLogTime = function(snID) { db.lastLogTime = function(snID) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
let statement = "SELECT MAX(" + L_struct.LOG_TIME + ") FROM _" + snID; let statement = "SELECT MAX(" + L_struct.LOG_TIME + ") FROM _" + snID;
db.query(statement) db.query(statement)
.then(result => resolve(result)) .then(result => resolve(result))
.catch(error => reject(error)) .catch(error => reject(error));
}) });
} };
db.createGetLastLog = function(snID) { db.createGetLastLog = function(snID) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
db.createTable(snID).then(result => { db.createTable(snID).then(result => {
db.lastLogTime(snID) db.lastLogTime(snID)
.then(result => resolve(result)) .then(result => resolve(result))
.catch(error => reject(error)) .catch(error => reject(error));
}).catch(error => reject(error)) }).catch(error => reject(error));
}) });
} };
db.getData = function(snID, logtime) { db.getData = function(snID, logtime) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
@ -289,13 +297,13 @@ function Database(user, password, dbname, host = 'localhost') {
" ORDER BY " + L_struct.LOG_TIME; " ORDER BY " + L_struct.LOG_TIME;
db.query(statement) db.query(statement)
.then(result => resolve(result)) .then(result => resolve(result))
.catch(error => reject(error)) .catch(error => reject(error));
}) });
} };
db.storeData = function(snID, data) { db.storeData = function(snID, data) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
let u_attr = Object.keys(B_struct).map(a => B_struct[a]) let u_attr = Object.keys(B_struct).map(a => B_struct[a]);
let attr = Object.keys(H_struct).map(a => H_struct[a]).concat(u_attr); let attr = Object.keys(H_struct).map(a => H_struct[a]).concat(u_attr);
let values = attr.map(a => data[a]); let values = attr.map(a => data[a]);
let u_values = u_attr.map(a => data[a]); let u_values = u_attr.map(a => data[a]);
@ -305,9 +313,9 @@ function Database(user, password, dbname, host = 'localhost') {
"ON DUPLICATE KEY UPDATE " + u_attr.map(a => a + "=?").join(", "); "ON DUPLICATE KEY UPDATE " + u_attr.map(a => a + "=?").join(", ");
db.query(statement, values.concat(u_values)) db.query(statement, values.concat(u_values))
.then(result => resolve(data)) .then(result => resolve(data))
.catch(error => reject(error)) .catch(error => reject(error));
}) });
} };
db.storeTag = function(snID, data) { db.storeTag = function(snID, data) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
@ -318,9 +326,9 @@ function Database(user, password, dbname, host = 'localhost') {
" WHERE " + H_struct.VECTOR_CLOCK + "=" + data[H_struct.VECTOR_CLOCK]; " WHERE " + H_struct.VECTOR_CLOCK + "=" + data[H_struct.VECTOR_CLOCK];
db.query(statement, values) db.query(statement, values)
.then(result => resolve(data)) .then(result => resolve(data))
.catch(error => reject(error)) .catch(error => reject(error));
}) });
} };
db.clearAuthorisedAppData = function(snID, app, adminID, subAdmins, timestamp) { db.clearAuthorisedAppData = function(snID, app, adminID, subAdmins, timestamp) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
@ -332,9 +340,9 @@ function Database(user, password, dbname, host = 'localhost') {
H_struct.SENDER_ID + " NOT IN (" + subAdmins.map(a => "?").join(", ") + ") )"; H_struct.SENDER_ID + " NOT IN (" + subAdmins.map(a => "?").join(", ") + ") )";
db.query(statement, [timestamp, app].concat(subAdmins).push(adminID)) db.query(statement, [timestamp, app].concat(subAdmins).push(adminID))
.then(result => resolve(result)) .then(result => resolve(result))
.catch(error => reject(error)) .catch(error => reject(error));
}) });
} };
db.clearUnauthorisedAppData = function(snID, appList, timestamp) { db.clearUnauthorisedAppData = function(snID, appList, timestamp) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
@ -343,13 +351,13 @@ function Database(user, password, dbname, host = 'localhost') {
H_struct.APPLICATION + " NOT IN (" + appList.map(a => "?").join(", ") + ")"; H_struct.APPLICATION + " NOT IN (" + appList.map(a => "?").join(", ") + ")";
db.query(statement, [timestamp].concat(appList)) db.query(statement, [timestamp].concat(appList))
.then(result => resolve(result)) .then(result => resolve(result))
.catch(error => reject(error)) .catch(error => reject(error));
}) });
} };
db.close = function() { db.close = function() {
db.conn.end(); db.conn.end();
} };
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
let conn = mysql.createConnection({ let conn = mysql.createConnection({
@ -361,9 +369,9 @@ function Database(user, password, dbname, host = 'localhost') {
conn.connect((err) => { conn.connect((err) => {
if (err) return reject(err); if (err) return reject(err);
db.conn = conn; db.conn = conn;
resolve(db) resolve(db);
}); });
}) });
} };
module.exports = Database; module.exports = Database;

View File

@ -9,16 +9,16 @@
fetch_retry: function(apicall) { fetch_retry: function(apicall) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this.serverList.splice(this.curPos, 1); this.serverList.splice(this.curPos, 1);
this.curPos = floCrypto.randInt(0, this.serverList.length - 1) this.curPos = floCrypto.randInt(0, this.serverList.length - 1);
this.fetch_api(apicall) this.fetch_api(apicall)
.then(result => resolve(result)) .then(result => resolve(result))
.catch(error => reject(error)); .catch(error => reject(error));
}) });
}, },
fetch_api: function(apicall) { fetch_api: function(apicall) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
if (this.serverList.length === 0) if (this.serverList.length === 0)
reject("No floSight server working") reject("No floSight server working");
else { else {
fetch(this.serverList[this.curPos] + apicall).then(response => { fetch(this.serverList[this.curPos] + apicall).then(response => {
if (response.ok) if (response.ok)
@ -27,21 +27,21 @@
this.fetch_retry(apicall) this.fetch_retry(apicall)
.then(result => resolve(result)) .then(result => resolve(result))
.catch(error => reject(error)); .catch(error => reject(error));
} };
}).catch(error => { }).catch(error => {
this.fetch_retry(apicall) this.fetch_retry(apicall)
.then(result => resolve(result)) .then(result => resolve(result))
.catch(error => reject(error)); .catch(error => reject(error));
}) });
} };
}) });
} }
}, },
//Promised function to get data from API //Promised function to get data from API
promisedAPI: function(apicall) { promisedAPI: function(apicall) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
console.log(apicall) console.log(apicall);
this.util.fetch_api(apicall) this.util.fetch_api(apicall)
.then(result => resolve(result)) .then(result => resolve(result))
.catch(error => reject(error)); .catch(error => reject(error));
@ -64,7 +64,7 @@
data = JSON.stringify(data); data = JSON.stringify(data);
this.sendTx(senderAddr, receiverAddr, floGlobals.sendAmt, privKey, data) this.sendTx(senderAddr, receiverAddr, floGlobals.sendAmt, privKey, data)
.then(txid => resolve(txid)) .then(txid => resolve(txid))
.catch(error => reject(error)) .catch(error => reject(error));
}); });
}, },
@ -75,7 +75,7 @@
reject(`Invalid address : ${senderAddr}`); reject(`Invalid address : ${senderAddr}`);
else if (!floCrypto.validateAddr(receiverAddr)) else if (!floCrypto.validateAddr(receiverAddr))
reject(`Invalid address : ${receiverAddr}`); reject(`Invalid address : ${receiverAddr}`);
if (privKey.length < 1 || !floCrypto.verifyPrivKey(privKey, senderAddr)) else if (privKey.length < 1 || !floCrypto.verifyPrivKey(privKey, senderAddr))
reject("Invalid Private key!"); reject("Invalid Private key!");
else if (typeof sendAmt !== 'number' || sendAmt <= 0) else if (typeof sendAmt !== 'number' || sendAmt <= 0)
reject(`Invalid sendAmt : ${sendAmt}`); reject(`Invalid sendAmt : ${sendAmt}`);
@ -84,14 +84,12 @@
var utxoAmt = 0.0; var utxoAmt = 0.0;
var fee = floGlobals.fee; var fee = floGlobals.fee;
this.promisedAPI(`api/addr/${senderAddr}/utxo`).then(utxos => { this.promisedAPI(`api/addr/${senderAddr}/utxo`).then(utxos => {
for (var i = utxos.length - 1; for (var i = utxos.length - 1; (i >= 0) && (utxoAmt < sendAmt + fee); i--) {
(i >= 0) && (utxoAmt < sendAmt + fee); i--) {
if (utxos[i].confirmations) { if (utxos[i].confirmations) {
trx.addinput(utxos[i].txid, utxos[i].vout, utxos[i] trx.addinput(utxos[i].txid, utxos[i].vout, utxos[i].scriptPubKey);
.scriptPubKey)
utxoAmt += utxos[i].amount; utxoAmt += utxos[i].amount;
} else break; } else break;
} };
if (utxoAmt < sendAmt + fee) if (utxoAmt < sendAmt + fee)
reject("Insufficient balance!"); reject("Insufficient balance!");
else { else {
@ -103,10 +101,10 @@
var signedTxHash = trx.sign(privKey, 1); var signedTxHash = trx.sign(privKey, 1);
this.broadcastTx(signedTxHash) this.broadcastTx(signedTxHash)
.then(txid => resolve(txid)) .then(txid => resolve(txid))
.catch(error => reject(error)) .catch(error => reject(error));
} };
}).catch(error => reject(error)) }).catch(error => reject(error));
} };
}); });
}, },
@ -116,27 +114,25 @@
if (!floCrypto.validateAddr(floID)) if (!floCrypto.validateAddr(floID))
return reject(`Invalid floID`); return reject(`Invalid floID`);
if (!floCrypto.verifyPrivKey(privKey, floID)) if (!floCrypto.verifyPrivKey(privKey, floID))
return reject("Invalid Private Key") return reject("Invalid Private Key");
var trx = bitjs.transaction(); var trx = bitjs.transaction();
var utxoAmt = 0.0; var utxoAmt = 0.0;
var fee = floGlobals.fee; var fee = floGlobals.fee;
this.promisedAPI(`api/addr/${floID}/utxo`).then(utxos => { this.promisedAPI(`api/addr/${floID}/utxo`).then(utxos => {
for (var i = utxos.length - 1; i >= 0; i--) { for (var i = utxos.length - 1; i >= 0; i--)
if (utxos[i].confirmations) { if (utxos[i].confirmations) {
trx.addinput(utxos[i].txid, utxos[i].vout, utxos[i] trx.addinput(utxos[i].txid, utxos[i].vout, utxos[i].scriptPubKey);
.scriptPubKey)
utxoAmt += utxos[i].amount; utxoAmt += utxos[i].amount;
} };
}
trx.addoutput(floID, utxoAmt - fee); trx.addoutput(floID, utxoAmt - fee);
trx.addflodata(floData.replace(/\n/g, ' ')); trx.addflodata(floData.replace(/\n/g, ' '));
var signedTxHash = trx.sign(privKey, 1); var signedTxHash = trx.sign(privKey, 1);
this.broadcastTx(signedTxHash) this.broadcastTx(signedTxHash)
.then(txid => resolve(txid)) .then(txid => resolve(txid))
.catch(error => reject(error)) .catch(error => reject(error));
}).catch(error => reject(error)) }).catch(error => reject(error));
}) });
}, },
/**Write data into blockchain from (and/or) to multiple floID /**Write data into blockchain from (and/or) to multiple floID
@ -149,27 +145,27 @@
writeDataMultiple: function(senderPrivKeys, data, receivers = [floGlobals.adminID], preserveRatio = true) { writeDataMultiple: function(senderPrivKeys, data, receivers = [floGlobals.adminID], preserveRatio = true) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
if (!Array.isArray(senderPrivKeys)) if (!Array.isArray(senderPrivKeys))
return reject("Invalid senderPrivKeys: SenderPrivKeys must be Array") return reject("Invalid senderPrivKeys: SenderPrivKeys must be Array");
if (!preserveRatio) { if (!preserveRatio) {
let tmp = {}; let tmp = {};
let amount = (floGlobals.sendAmt * receivers.length) / senderPrivKeys.length; let amount = (floGlobals.sendAmt * receivers.length) / senderPrivKeys.length;
senderPrivKeys.forEach(key => tmp[key] = amount); senderPrivKeys.forEach(key => tmp[key] = amount);
senderPrivKeys = tmp senderPrivKeys = tmp;
} };
if (!Array.isArray(receivers)) if (!Array.isArray(receivers))
return reject("Invalid receivers: Receivers must be Array") return reject("Invalid receivers: Receivers must be Array");
else { else {
let tmp = {}; let tmp = {};
let amount = floGlobals.sendAmt; let amount = floGlobals.sendAmt;
receivers.forEach(floID => tmp[floID] = amount); receivers.forEach(floID => tmp[floID] = amount);
receivers = tmp receivers = tmp;
} };
if (typeof data != "string") if (typeof data != "string")
data = JSON.stringify(data); data = JSON.stringify(data);
this.sendTxMultiple(senderPrivKeys, receivers, data) this.sendTxMultiple(senderPrivKeys, receivers, data)
.then(txid => resolve(txid)) .then(txid => resolve(txid))
.catch(error => reject(error)) .catch(error => reject(error));
}) });
}, },
/**Send Tx from (and/or) to multiple floID /**Send Tx from (and/or) to multiple floID
@ -190,7 +186,7 @@
InvalidSenderAmountFor: [], InvalidSenderAmountFor: [],
InvalidReceiverIDs: [], InvalidReceiverIDs: [],
InvalidReceiveAmountFor: [] InvalidReceiveAmountFor: []
} };
let inputVal = 0, let inputVal = 0,
outputVal = 0; outputVal = 0;
//Validate sender privatekeys (and send amount if passed) //Validate sender privatekeys (and send amount if passed)
@ -204,12 +200,12 @@
let floID = floCrypto.getFloID(key); let floID = floCrypto.getFloID(key);
senders[floID] = { senders[floID] = {
wif: key wif: key
} };
} };
} catch (error) { } catch (error) {
invalids.InvalidSenderPrivKeys.push(key) invalids.InvalidSenderPrivKeys.push(key);
} };
}) });
preserveRatio = true; preserveRatio = true;
} }
//conversion when privatekeys are passed with send amount //conversion when privatekeys are passed with send amount
@ -219,32 +215,31 @@
if (!key) if (!key)
invalids.InvalidSenderPrivKeys.push(key); invalids.InvalidSenderPrivKeys.push(key);
else { else {
if (typeof senderPrivKeys[key] !== 'number' || senderPrivKeys[ if (typeof senderPrivKeys[key] !== 'number' || senderPrivKeys[key] <= 0)
key] <= 0) invalids.InvalidSenderAmountFor.push(key);
invalids.InvalidSenderAmountFor.push(key)
else else
inputVal += senderPrivKeys[key]; inputVal += senderPrivKeys[key];
let floID = floCrypto.getFloID(key); let floID = floCrypto.getFloID(key);
senders[floID] = { senders[floID] = {
wif: key, wif: key,
coins: senderPrivKeys[key] coins: senderPrivKeys[key]
} };
} };
} catch (error) { } catch (error) {
invalids.InvalidSenderPrivKeys.push(key) invalids.InvalidSenderPrivKeys.push(key);
} };
} };
preserveRatio = false; preserveRatio = false;
} };
//Validate the receiver IDs and receive amount //Validate the receiver IDs and receive amount
for (let floID in receivers) { for (let floID in receivers) {
if (!floCrypto.validateAddr(floID)) if (!floCrypto.validateAddr(floID))
invalids.InvalidReceiverIDs.push(floID) invalids.InvalidReceiverIDs.push(floID);
if (typeof receivers[floID] !== 'number' || receivers[floID] <= 0) if (typeof receivers[floID] !== 'number' || receivers[floID] <= 0)
invalids.InvalidReceiveAmountFor.push(floID) invalids.InvalidReceiveAmountFor.push(floID);
else else
outputVal += receivers[floID]; outputVal += receivers[floID];
} };
//Reject if any invalids are found //Reject if any invalids are found
for (let i in invalids) for (let i in invalids)
if (!invalids[i].length) if (!invalids[i].length)
@ -253,15 +248,14 @@
return reject(invalids); return reject(invalids);
//Reject if given inputVal and outputVal are not equal //Reject if given inputVal and outputVal are not equal
if (!preserveRatio && inputVal != outputVal) if (!preserveRatio && inputVal != outputVal)
return reject( return reject(`Input Amount (${inputVal}) not equal to Output Amount (${outputVal})`);
`Input Amount (${inputVal}) not equal to Output Amount (${outputVal})`)
} catch (error) { } catch (error) {
return reject(error) return reject(error);
} }
//Get balance of senders //Get balance of senders
let promises = [] let promises = [];
for (let floID in senders) for (let floID in senders)
promises.push(this.getBalance(floID)) promises.push(this.getBalance(floID));
Promise.all(promises).then(results => { Promise.all(promises).then(results => {
let totalBalance = 0, let totalBalance = 0,
totalFee = floGlobals.fee, totalFee = floGlobals.fee,
@ -273,26 +267,25 @@
let insufficient = []; let insufficient = [];
for (let floID in senders) { for (let floID in senders) {
balance[floID] = parseFloat(results.shift()); balance[floID] = parseFloat(results.shift());
if (isNaN(balance[floID]) || (preserveRatio && balance[floID] <= if (isNaN(balance[floID]) || (preserveRatio && balance[floID] <= totalFee)
totalFee) || (!preserveRatio && balance[floID] < senders[floID] || (!preserveRatio && balance[floID] < senders[floID].coins + dividedFee))
.coins + dividedFee)) insufficient.push(floID);
insufficient.push(floID)
totalBalance += balance[floID]; totalBalance += balance[floID];
} };
if (insufficient.length) if (insufficient.length)
return reject({ return reject({
InsufficientBalance: insufficient InsufficientBalance: insufficient
}) });
//Calculate totalSentAmount and check if totalBalance is sufficient //Calculate totalSentAmount and check if totalBalance is sufficient
let totalSendAmt = totalFee; let totalSendAmt = totalFee;
for (floID in receivers) for (floID in receivers)
totalSendAmt += receivers[floID]; totalSendAmt += receivers[floID];
if (totalBalance < totalSendAmt) if (totalBalance < totalSendAmt)
return reject("Insufficient total Balance") return reject("Insufficient total Balance");
//Get the UTXOs of the senders //Get the UTXOs of the senders
let promises = [] let promises = [];
for (floID in senders) for (floID in senders)
promises.push(this.promisedAPI(`api/addr/${floID}/utxo`)) promises.push(this.promisedAPI(`api/addr/${floID}/utxo`));
Promise.all(promises).then(results => { Promise.all(promises).then(results => {
let wifSeq = []; let wifSeq = [];
var trx = bitjs.transaction(); var trx = bitjs.transaction();
@ -306,21 +299,18 @@
sendAmt = senders[floID].coins + dividedFee; sendAmt = senders[floID].coins + dividedFee;
let wif = senders[floID].wif; let wif = senders[floID].wif;
let utxoAmt = 0.0; let utxoAmt = 0.0;
for (let i = utxos.length - 1; for (let i = utxos.length - 1; (i >= 0) && (utxoAmt < sendAmt); i--)
(i >= 0) && (utxoAmt < sendAmt); i--) {
if (utxos[i].confirmations) { if (utxos[i].confirmations) {
trx.addinput(utxos[i].txid, utxos[i].vout, utxos[i] trx.addinput(utxos[i].txid, utxos[i].vout, utxos[i].scriptPubKey);
.scriptPubKey)
wifSeq.push(wif); wifSeq.push(wif);
utxoAmt += utxos[i].amount; utxoAmt += utxos[i].amount;
} };
}
if (utxoAmt < sendAmt) if (utxoAmt < sendAmt)
return reject("Insufficient balance:" + floID); return reject("Insufficient balance:" + floID);
let change = (utxoAmt - sendAmt); let change = (utxoAmt - sendAmt);
if (change > 0) if (change > 0)
trx.addoutput(floID, change); trx.addoutput(floID, change);
} };
for (floID in receivers) for (floID in receivers)
trx.addoutput(floID, receivers[floID]); trx.addoutput(floID, receivers[floID]);
trx.addflodata(floData.replace(/\n/g, ' ')); trx.addflodata(floData.replace(/\n/g, ' '));
@ -329,10 +319,10 @@
var signedTxHash = trx.serialize(); var signedTxHash = trx.serialize();
this.broadcastTx(signedTxHash) this.broadcastTx(signedTxHash)
.then(txid => resolve(txid)) .then(txid => resolve(txid))
.catch(error => reject(error)) .catch(error => reject(error));
}).catch(error => reject(error)) }).catch(error => reject(error));
}).catch(error => reject(error)) }).catch(error => reject(error));
}) });
}, },
//Broadcast signed Tx in blockchain using API //Broadcast signed Tx in blockchain using API
@ -340,7 +330,7 @@
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
var request = new XMLHttpRequest(); var request = new XMLHttpRequest();
var url = this.util.serverList[this.util.curPos] + 'api/tx/send'; var url = this.util.serverList[this.util.curPos] + 'api/tx/send';
console.log(url) console.log(url);
if (signedTxHash.length < 1) if (signedTxHash.length < 1)
reject("Empty Signature"); reject("Empty Signature");
else { else {
@ -356,8 +346,8 @@
reject(request.responseText); reject(request.responseText);
} }
request.send(params); request.send(params);
} };
}) });
}, },
//Read Txs of Address between from and to //Read Txs of Address between from and to
@ -365,7 +355,7 @@
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this.promisedAPI(`api/addrs/${addr}/txs?from=${from}&to=${to}`) this.promisedAPI(`api/addrs/${addr}/txs?from=${from}&to=${to}`)
.then(response => resolve(response)) .then(response => resolve(response))
.catch(error => reject(error)) .catch(error => reject(error));
}); });
}, },
@ -376,7 +366,7 @@
this.promisedAPI(`api/addrs/${addr}/txs?from=0&to=${response.totalItems}0`) this.promisedAPI(`api/addrs/${addr}/txs?from=0&to=${response.totalItems}0`)
.then(response => resolve(response.items)) .then(response => resolve(response.items))
.catch(error => reject(error)); .catch(error => reject(error));
}).catch(error => reject(error)) }).catch(error => reject(error));
}); });
}, },
@ -390,27 +380,23 @@
filter : custom filter funtion for floData (eg . filter: d => {return d[0] == '$'}) filter : custom filter funtion for floData (eg . filter: d => {return d[0] == '$'})
*/ */
readData: function(addr, options = {}) { readData: function(addr, options = {}) {
options.limit = options.limit | 0 options.limit = options.limit || 0;
options.ignoreOld = options.ignoreOld | 0 options.ignoreOld = options.ignoreOld || 0;
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this.promisedAPI(`api/addrs/${addr}/txs?from=0&to=1`).then(response => { this.promisedAPI(`api/addrs/${addr}/txs?from=0&to=1`).then(response => {
var newItems = response.totalItems - options.ignoreOld; var newItems = response.totalItems - options.ignoreOld;
this.promisedAPI(`api/addrs/${addr}/txs?from=0&to=${newItems*2}`).then( this.promisedAPI(`api/addrs/${addr}/txs?from=0&to=${newItems*2}`).then(response => {
response => {
if (options.limit <= 0) if (options.limit <= 0)
options.limit = response.items.length; options.limit = response.items.length;
var filteredData = []; var filteredData = [];
for (i = 0; i < (response.totalItems - options.ignoreOld) && for (i = 0; i < (response.totalItems - options.ignoreOld) &&
filteredData.length < options.limit; i++) { filteredData.length < options.limit; i++) {
if (options.sentOnly && response.items[i].vin[0].addr !== if (options.sentOnly && response.items[i].vin[0].addr !== addr)
addr)
continue; continue;
if (options.pattern) { if (options.pattern) {
try { try {
let jsonContent = JSON.parse(response.items[i] let jsonContent = JSON.parse(response.items[i].floData)
.floData) if (!Object.keys(jsonContent).includes(options.pattern))
if (!Object.keys(jsonContent).includes(options
.pattern))
continue; continue;
} catch (error) { } catch (error) {
continue; continue;
@ -419,7 +405,7 @@
if (options.filter && !options.filter(response.items[i].floData)) if (options.filter && !options.filter(response.items[i].floData))
continue; continue;
filteredData.push(response.items[i].floData); filteredData.push(response.items[i].floData);
} };
resolve({ resolve({
totalTxs: response.totalItems, totalTxs: response.totalItems,
data: filteredData data: filteredData
@ -433,4 +419,4 @@
}); });
} }
} }
})(typeof global !== "undefined" ? global : window) })(typeof global !== "undefined" ? global : window);

View File

@ -1,28 +1,28 @@
'use strict'; 'use strict';
(function(GLOBAL) { (function(GLOBAL) {
var floCrypto = GLOBAL.floCrypto = {} var floCrypto = GLOBAL.floCrypto = {};
const p = BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", 16); const p = BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", 16);
const ecparams = EllipticCurve.getSECCurveByName("secp256k1"); const ecparams = EllipticCurve.getSECCurveByName("secp256k1");
function exponent1() { function exponent1() {
return p.add(BigInteger.ONE).divide(BigInteger("4")) return p.add(BigInteger.ONE).divide(BigInteger("4"));
} };
function calculateY(x) { function calculateY(x) {
let exp = exponent1(); let exp = exponent1();
// x is x value of public key in BigInteger format without 02 or 03 or 04 prefix // x is x value of public key in BigInteger format without 02 or 03 or 04 prefix
return x.modPow(BigInteger("3"), p).add(BigInteger("7")).mod(p).modPow(exp, p) return x.modPow(BigInteger("3"), p).add(BigInteger("7")).mod(p).modPow(exp, p);
} };
function getUncompressedPublicKey(compressedPublicKey) { function getUncompressedPublicKey(compressedPublicKey) {
// Fetch x from compressedPublicKey // Fetch x from compressedPublicKey
let pubKeyBytes = Crypto.util.hexToBytes(compressedPublicKey); let pubKeyBytes = Crypto.util.hexToBytes(compressedPublicKey);
const prefix = pubKeyBytes.shift() // remove prefix const prefix = pubKeyBytes.shift(); // remove prefix
let prefix_modulus = prefix % 2; let prefix_modulus = prefix % 2;
pubKeyBytes.unshift(0) // add prefix 0 pubKeyBytes.unshift(0); // add prefix 0
let x = new BigInteger(pubKeyBytes) let x = new BigInteger(pubKeyBytes);
let xDecimalValue = x.toString() let xDecimalValue = x.toString();
// Fetch y // Fetch y
let y = calculateY(x); let y = calculateY(x);
let yDecimalValue = y.toString(); let yDecimalValue = y.toString();
@ -35,7 +35,7 @@
x: xDecimalValue, x: xDecimalValue,
y: yDecimalValue y: yDecimalValue
}; };
} };
function getSenderPublicKeyString() { function getSenderPublicKeyString() {
privateKey = ellipticCurveEncryption.senderRandom(); privateKey = ellipticCurveEncryption.senderRandom();
@ -43,8 +43,8 @@
return { return {
privateKey: privateKey, privateKey: privateKey,
senderPublicKeyString: senderPublicKeyString senderPublicKeyString: senderPublicKeyString
} };
} };
function deriveSharedKeySender(receiverCompressedPublicKey, senderPrivateKey) { function deriveSharedKeySender(receiverCompressedPublicKey, senderPrivateKey) {
try { try {
@ -54,33 +54,33 @@
return senderDerivedKey; return senderDerivedKey;
} catch (error) { } catch (error) {
return new Error(error); return new Error(error);
} };
} };
function deriveReceiverSharedKey(senderPublicKeyString, receiverPrivateKey) { function deriveReceiverSharedKey(senderPublicKeyString, receiverPrivateKey) {
return ellipticCurveEncryption.receiverSharedKeyDerivation( return ellipticCurveEncryption.receiverSharedKeyDerivation(
senderPublicKeyString.XValuePublicString, senderPublicKeyString.XValuePublicString,
senderPublicKeyString.YValuePublicString, receiverPrivateKey); senderPublicKeyString.YValuePublicString, receiverPrivateKey);
} };
function getReceiverPublicKeyString(privateKey) { function getReceiverPublicKeyString(privateKey) {
return ellipticCurveEncryption.receiverPublicString(privateKey); return ellipticCurveEncryption.receiverPublicString(privateKey);
} };
function wifToDecimal(pk_wif, isPubKeyCompressed = false) { function wifToDecimal(pk_wif, isPubKeyCompressed = false) {
let pk = Bitcoin.Base58.decode(pk_wif) let pk = Bitcoin.Base58.decode(pk_wif);
pk.shift() pk.shift();
pk.splice(-4, 4) pk.splice(-4, 4);
//If the private key corresponded to a compressed public key, also drop the last byte (it should be 0x01). //If the private key corresponded to a compressed public key, also drop the last byte (it should be 0x01).
if (isPubKeyCompressed == true) pk.pop() if (isPubKeyCompressed == true) pk.pop();
pk.unshift(0) pk.unshift(0);
privateKeyDecimal = BigInteger(pk).toString() privateKeyDecimal = BigInteger(pk).toString();
privateKeyHex = Crypto.util.bytesToHex(pk) privateKeyHex = Crypto.util.bytesToHex(pk);
return { return {
privateKeyDecimal: privateKeyDecimal, privateKeyDecimal: privateKeyDecimal,
privateKeyHex: privateKeyHex privateKeyHex: privateKeyHex
} };
} };
//generate a random Interger within range //generate a random Interger within range
@ -88,7 +88,7 @@
min = Math.ceil(min); min = Math.ceil(min);
max = Math.floor(max); max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min; return Math.floor(Math.random() * (max - min + 1)) + min;
} };
//generate a random String within length (options : alphaNumeric chars only) //generate a random String within length (options : alphaNumeric chars only)
floCrypto.randString = function(length, alphaNumeric = true) { floCrypto.randString = function(length, alphaNumeric = true) {
@ -101,7 +101,7 @@
for (var i = 0; i < length; i++) for (var i = 0; i < length; i++)
result += characters.charAt(Math.floor(Math.random() * characters.length)); result += characters.charAt(Math.floor(Math.random() * characters.length));
return result; return result;
} };
//Encrypt Data using public-key //Encrypt Data using public-key
floCrypto.encryptData = function(data, publicKeyHex) { floCrypto.encryptData = function(data, publicKeyHex) {
@ -114,7 +114,7 @@
secret: secret, secret: secret,
senderPublicKeyString: senderECKeyData.senderPublicKeyString senderPublicKeyString: senderECKeyData.senderPublicKeyString
}; };
} };
//Decrypt Data using private-key //Decrypt Data using private-key
floCrypto.decryptData = function(data, privateKeyHex) { floCrypto.decryptData = function(data, privateKeyHex) {
@ -129,7 +129,7 @@
let receiverKey = receiverDerivedKey.XValue + receiverDerivedKey.YValue; let receiverKey = receiverDerivedKey.XValue + receiverDerivedKey.YValue;
let decryptMsg = Crypto.AES.decrypt(data.secret, receiverKey); let decryptMsg = Crypto.AES.decrypt(data.secret, receiverKey);
return decryptMsg; return decryptMsg;
} };
//Sign data using private-key //Sign data using private-key
floCrypto.signData = function(data, privateKeyHex) { floCrypto.signData = function(data, privateKeyHex) {
@ -144,7 +144,7 @@
var messageSign = Bitcoin.ECDSA.sign(messageHashBigInteger, key.priv); var messageSign = Bitcoin.ECDSA.sign(messageHashBigInteger, key.priv);
var sighex = Crypto.util.bytesToHex(messageSign); var sighex = Crypto.util.bytesToHex(messageSign);
return sighex; return sighex;
} };
//Verify signatue of the data using public-key //Verify signatue of the data using public-key
floCrypto.verifySign = function(data, signatureHex, publicKeyHex) { floCrypto.verifySign = function(data, signatureHex, publicKeyHex) {
@ -156,7 +156,7 @@
var verify = Bitcoin.ECDSA.verifyRaw(messageHashBigInteger, var verify = Bitcoin.ECDSA.verifyRaw(messageHashBigInteger,
signature.r, signature.s, publicKeyPoint); signature.r, signature.s, publicKeyPoint);
return verify; return verify;
} };
//Generates a new flo ID and returns private-key, public-key and floID //Generates a new flo ID and returns private-key, public-key and floID
floCrypto.generateNewID = function() { floCrypto.generateNewID = function() {
@ -167,11 +167,11 @@
floID: key.getBitcoinAddress(), floID: key.getBitcoinAddress(),
pubKey: key.getPubKeyHex(), pubKey: key.getPubKeyHex(),
privKey: key.getBitcoinWalletImportFormat() privKey: key.getBitcoinWalletImportFormat()
} };
} catch (e) { } catch (e) {
console.error(e); console.error(e);
} };
} };
//Returns public-key from private-key //Returns public-key from private-key
floCrypto.getPubKeyHex = function(privateKeyHex) { floCrypto.getPubKeyHex = function(privateKeyHex) {
@ -182,7 +182,7 @@
return null; return null;
key.setCompressed(true); key.setCompressed(true);
return key.getPubKeyHex(); return key.getPubKeyHex();
} };
//Returns flo-ID from public-key or private-key //Returns flo-ID from public-key or private-key
floCrypto.getFloID = function(keyHex) { floCrypto.getFloID = function(keyHex) {
@ -195,8 +195,8 @@
return key.getBitcoinAddress(); return key.getBitcoinAddress();
} catch (e) { } catch (e) {
return null; return null;
} };
} };
//Verify the private-key for the given public-key or flo-ID //Verify the private-key for the given public-key or flo-ID
floCrypto.verifyPrivKey = function(privateKeyHex, publicHex_ID) { floCrypto.verifyPrivKey = function(privateKeyHex, publicHex_ID) {
@ -215,8 +215,8 @@
return false; return false;
} catch (e) { } catch (e) {
console.error(e); console.error(e);
} };
} };
//Check if the given Address is valid or not //Check if the given Address is valid or not
floCrypto.validateAddr = function(inpAddr) { floCrypto.validateAddr = function(inpAddr) {
@ -227,8 +227,8 @@
return true; return true;
} catch { } catch {
return false; return false;
} };
} };
//Split the str using shamir's Secret and Returns the shares //Split the str using shamir's Secret and Returns the shares
floCrypto.createShamirsSecretShares = function(str, total_shares, threshold_limit) { floCrypto.createShamirsSecretShares = function(str, total_shares, threshold_limit) {
@ -236,12 +236,12 @@
if (str.length > 0) { if (str.length > 0) {
var strHex = shamirSecretShare.str2hex(str); var strHex = shamirSecretShare.str2hex(str);
return shamirSecretShare.share(strHex, total_shares, threshold_limit); return shamirSecretShare.share(strHex, total_shares, threshold_limit);
} };
return false; return false;
} catch { } catch {
return false return false;
} };
} };
//Verifies the shares and str //Verifies the shares and str
floCrypto.verifyShamirsSecret = function(sharesArray, str) { floCrypto.verifyShamirsSecret = function(sharesArray, str) {
@ -250,13 +250,13 @@
try { try {
if (sharesArray.length > 0) { if (sharesArray.length > 0) {
var comb = shamirSecretShare.combine(sharesArray.slice(0, sharesArray.length)); var comb = shamirSecretShare.combine(sharesArray.slice(0, sharesArray.length));
return (shamirSecretShare.hex2str(comb) === str ? true : false) return (shamirSecretShare.hex2str(comb) === str ? true : false);
} };
return false; return false;
} catch { } catch {
return false; return false;
} };
} };
//Returns the retrived secret by combining the shamirs shares //Returns the retrived secret by combining the shamirs shares
floCrypto.retrieveShamirSecret = function(sharesArray) { floCrypto.retrieveShamirSecret = function(sharesArray) {
@ -264,11 +264,11 @@
if (sharesArray.length > 0) { if (sharesArray.length > 0) {
var comb = shamirSecretShare.combine(sharesArray.slice(0, sharesArray.length)); var comb = shamirSecretShare.combine(sharesArray.slice(0, sharesArray.length));
return shamirSecretShare.hex2str(comb); return shamirSecretShare.hex2str(comb);
} };
return false; return false;
} catch { } catch {
return false; return false;
} };
} };
})(typeof global !== "undefined" ? global : window) })(typeof global !== "undefined" ? global : window);

View File

@ -24,7 +24,7 @@ const floGlobals = {
errorFeedback - (Boolean) Send error (if any) feedback to the requestor errorFeedback - (Boolean) Send error (if any) feedback to the requestor
delayDelta - (Interger) Maximum allowed delay from the data-time delayDelta - (Interger) Maximum allowed delay from the data-time
*/ */
} };
(typeof global !== "undefined" ? global : window).cryptocoin = floGlobals.blockchain; (typeof global !== "undefined" ? global : window).cryptocoin = floGlobals.blockchain;
('object' === typeof module) ? module.export = floGlobals : null; ('object' === typeof module) ? module.export = floGlobals : null;

View File

@ -19,7 +19,7 @@ const SUPERNODE_INDICATOR = '$',
RETRY_TIMEOUT = 5 * 60 * 1000, //5 mins RETRY_TIMEOUT = 5 * 60 * 1000, //5 mins
MIGRATE_WAIT_DELAY = 5 * 60 * 1000; //5 mins MIGRATE_WAIT_DELAY = 5 * 60 * 1000; //5 mins
var DB, refresher //container for database and refresher var DB, refresher; //container for database and refresher
//List of node backups stored //List of node backups stored
const _list = {}; const _list = {};
@ -36,7 +36,7 @@ Object.defineProperty(_list, 'get', {
else else
return this[keys]; return this[keys];
} }
}) });
Object.defineProperty(_list, 'stored', { Object.defineProperty(_list, 'stored', {
get: function() { get: function() {
return Object.keys(this); return Object.keys(this);
@ -44,7 +44,7 @@ Object.defineProperty(_list, 'stored', {
}); });
Object.defineProperty(_list, 'serving', { Object.defineProperty(_list, 'serving', {
get: function() { get: function() {
let serveList = [] let serveList = [];
for (let id in this) for (let id in this)
if (this[id] === 0) if (this[id] === 0)
serveList.push(id); serveList.push(id);
@ -66,12 +66,12 @@ function NodeContainer() {
if (_onclose) if (_onclose)
_ws.onclose = _onclose; _ws.onclose = _onclose;
} }
}) });
Object.defineProperty(this, 'id', { Object.defineProperty(this, 'id', {
get: function() { get: function() {
return _id; return _id;
} }
}) });
Object.defineProperty(this, 'readyState', { Object.defineProperty(this, 'readyState', {
get: function() { get: function() {
if (_ws instanceof WebSocket) if (_ws instanceof WebSocket)
@ -79,7 +79,7 @@ function NodeContainer() {
else else
return null; return null;
} }
}) });
Object.defineProperty(this, 'send', { Object.defineProperty(this, 'send', {
value: function(packet) { value: function(packet) {
_ws.send(packet); _ws.send(packet);
@ -90,28 +90,28 @@ function NodeContainer() {
if (fn instanceof Function) if (fn instanceof Function)
_onmessage = fn; _onmessage = fn;
} }
}) });
Object.defineProperty(this, 'onclose', { Object.defineProperty(this, 'onclose', {
set: function(fn) { set: function(fn) {
if (fn instanceof Function) if (fn instanceof Function)
_onclose = fn; _onclose = fn;
} }
}) });
Object.defineProperty(this, 'is', { Object.defineProperty(this, 'is', {
value: function(ws) { value: function(ws) {
return ws === _ws; return ws === _ws;
} }
}) });
Object.defineProperty(this, 'close', { Object.defineProperty(this, 'close', {
value: function() { value: function() {
if (_ws.readyState === 1) { if (_ws.readyState === 1) {
_ws.onclose = () => console.warn('Closing: ' + _id) _ws.onclose = () => console.warn('Closing: ' + _id);
_ws.close(); _ws.close();
} };
_ws = _id = undefined; _ws = _id = undefined;
} }
}) });
} };
//Container for next-node //Container for next-node
const _nextNode = new NodeContainer(); const _nextNode = new NodeContainer();
@ -123,19 +123,19 @@ _prevNode.onmessage = evt => processTaskFromPrevNode(evt.data);
_prevNode.onclose = evt => _prevNode.close(); _prevNode.onclose = evt => _prevNode.close();
//Packet processing //Packet processing
const packet_ = {} const packet_ = {};
packet_.constuct = function(message) { packet_.constuct = function(message) {
const packet = { const packet = {
from: myFloID, from: myFloID,
message: message, message: message,
time: Date.now() time: Date.now()
} };
packet.sign = floCrypto.signData(this.s(packet), myPrivKey); packet.sign = floCrypto.signData(this.s(packet), myPrivKey);
return SUPERNODE_INDICATOR + JSON.stringify(packet) return SUPERNODE_INDICATOR + JSON.stringify(packet);
} };
packet_.s = d => [JSON.stringify(d.message), d.time].join("|"); packet_.s = d => [JSON.stringify(d.message), d.time].join("|");
packet_.parse = function(str) { packet_.parse = function(str) {
let packet = JSON.parse(str.substring(SUPERNODE_INDICATOR.length)) let packet = JSON.parse(str.substring(SUPERNODE_INDICATOR.length));
let curTime = Date.now(); let curTime = Date.now();
if (packet.time > curTime - floGlobals.sn_config.delayDelta && if (packet.time > curTime - floGlobals.sn_config.delayDelta &&
packet.from in floGlobals.supernodes && packet.from in floGlobals.supernodes &&
@ -143,8 +143,8 @@ packet_.parse = function(str) {
if (!Array.isArray(packet.message)) if (!Array.isArray(packet.message))
packet.message = [packet.message]; packet.message = [packet.message];
return packet; return packet;
} };
} };
//-----NODE CONNECTORS (WEBSOCKET)----- //-----NODE CONNECTORS (WEBSOCKET)-----
@ -152,44 +152,44 @@ packet_.parse = function(str) {
function connectToNode(snID) { function connectToNode(snID) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
if (!(snID in floGlobals.supernodes)) if (!(snID in floGlobals.supernodes))
return reject(`${snID} is not a supernode`) return reject(`${snID} is not a supernode`);
const ws = new WebSocket("wss://" + floGlobals.supernodes[nextNodeID].uri + "/"); const ws = new WebSocket("wss://" + floGlobals.supernodes[nextNodeID].uri + "/");
ws.on("error", () => reject(`${snID} is offline`)); ws.on("error", () => reject(`${snID} is offline`));
ws.on('open', () => resolve(ws)); ws.on('open', () => resolve(ws));
}) });
} };
//Connect to Node websocket thats online //Connect to Node websocket thats online
function connectToActiveNode(snID, reverse = false) { function connectToActiveNode(snID, reverse = false) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
if (!(snID in floGlobals.supernodes)) if (!(snID in floGlobals.supernodes))
return reject(`${snID} is not a supernode`) return reject(`${snID} is not a supernode`);
if (snID === myFloID) if (snID === myFloID)
return reject(`Reached end of circle. Next node avaiable is self`) return reject(`Reached end of circle. Next node avaiable is self`);
connectToNode(snID) connectToNode(snID)
.then(ws => resolve(ws)) .then(ws => resolve(ws))
.catch(error => { .catch(error => {
var next = reverse ? kBucket.prevNode(snID) : kBucket.nextNode(snID) var next = (reverse ? kBucket.prevNode(snID) : kBucket.nextNode(snID));
connectToActiveNode(next, reverse) connectToActiveNode(next, reverse)
.then(ws => resolve(ws)) .then(ws => resolve(ws))
.catch(error => reject(error)) .catch(error => reject(error));
}) });
}) });
} };
//Connect to next available node //Connect to next available node
function connectToNextNode() { function connectToNextNode() {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
let nextNodeID = kBucket.nextNode(nodeID); let nextNodeID = kBucket.nextNode(nodeID);
connectToActiveNode(nextNodeID).then(ws => { connectToActiveNode(nextNodeID).then(ws => {
_nextNode.set(nextNodeID, ws) _nextNode.set(nextNodeID, ws);
_nextNode.send(packet_.constuct({ _nextNode.send(packet_.constuct({
type: BACKUP_HANDSHAKE_INIT type: BACKUP_HANDSHAKE_INIT
})); }));
resolve("BACKUP_HANDSHAKE_INIT: " + nextNodeID) resolve("BACKUP_HANDSHAKE_INIT: " + nextNodeID);
}).catch(error => reject(error)) }).catch(error => reject(error));
}) });
} };
function connectToAliveNodes(nodes = null) { function connectToAliveNodes(nodes = null) {
if (!Array.isArray(nodes)) nodes = Object.keys(floGlobals.supernodes); if (!Array.isArray(nodes)) nodes = Object.keys(floGlobals.supernodes);
@ -199,9 +199,9 @@ function connectToAliveNodes(nodes = null) {
nodes.forEach((n, i) => nodes.forEach((n, i) =>
ws_connections[n] = (results.status === "fulfilled") ? results[i].value : null); ws_connections[n] = (results.status === "fulfilled") ? results[i].value : null);
resolve(ws_connections); resolve(ws_connections);
}).catch(error => reject(error)) });
}) });
} };
//Connect to all given nodes [Array] (Default: All super-nodes) //Connect to all given nodes [Array] (Default: All super-nodes)
function connectToAllActiveNodes(nodes = null) { function connectToAllActiveNodes(nodes = null) {
@ -212,9 +212,9 @@ function connectToAllActiveNodes(nodes = null) {
nodes.forEach((n, i) => nodes.forEach((n, i) =>
ws_connections[n] = (results.status === "fulfilled") ? results[i].value : null); ws_connections[n] = (results.status === "fulfilled") ? results[i].value : null);
resolve(ws_connections); resolve(ws_connections);
}).catch(error => reject(error)) });
}) });
} };
//-----PROCESS TASKS----- //-----PROCESS TASKS-----
@ -223,90 +223,90 @@ function processTaskFromNextNode(packet) {
var { var {
from, from,
message message
} = packet_.parse(packet) } = packet_.parse(packet);
if (message) { if (message) {
message.forEach(task => { message.forEach(task => {
switch (task.type) { switch (task.type) {
case RECONNECT_NEXT_NODE: //Triggered when a node inbetween is available case RECONNECT_NEXT_NODE: //Triggered when a node inbetween is available
reconnectNextNode() reconnectNextNode();
break; break;
case BACKUP_HANDSHAKE_END: case BACKUP_HANDSHAKE_END:
handshakeEnd() handshakeEnd();
break; break;
case DATA_REQUEST: case DATA_REQUEST:
sendStoredData(task.nodes, _nextNode) sendStoredData(task.nodes, _nextNode);
break; break;
case DATA_SYNC: case DATA_SYNC:
dataSyncIndication(task.id, task.status, from) dataSyncIndication(task.id, task.status, from);
break; break;
case STORE_BACKUP_DATA: case STORE_BACKUP_DATA:
storeBackupData(task.data) storeBackupData(task.data);
break; break;
default: default:
console.log("Invalid task type:" + task.type + "from next-node") console.log("Invalid task type:" + task.type + "from next-node");
} };
}) });
} };
} };
//Tasks from prev-node //Tasks from prev-node
function processTaskFromPrevNode(packet) { function processTaskFromPrevNode(packet) {
var { var {
from, from,
message message
} = packet_.parse(packet) } = packet_.parse(packet);
if (message) { if (message) {
message.forEach(task => { message.forEach(task => {
switch (task.type) { switch (task.type) {
case ORDER_BACKUP: case ORDER_BACKUP:
orderBackup(task.order) orderBackup(task.order);
break; break;
case STORE_BACKUP_DATA: case STORE_BACKUP_DATA:
storeBackupData(task.data, from, packet) storeBackupData(task.data, from, packet);
break; break;
case TAG_BACKUP_DATA: case TAG_BACKUP_DATA:
tagBackupData(task.data, from, packet) tagBackupData(task.data, from, packet);
break; break;
case DATA_REQUEST: case DATA_REQUEST:
sendStoredData(task.nodes, _prevNode) sendStoredData(task.nodes, _prevNode);
break; break;
case DATA_SYNC: case DATA_SYNC:
dataSyncIndication(task.id, task.status, from) dataSyncIndication(task.id, task.status, from);
break; break;
case DELETE_MIGRATED_DATA: case DELETE_MIGRATED_DATA:
deleteMigratedData(task.data, from, packet) deleteMigratedData(task.data, from, packet);
break; break;
default: default:
console.log("Invalid task type:" + task.type + "from prev-node") console.log("Invalid task type:" + task.type + "from prev-node");
} };
}); });
} };
} };
//Tasks from any supernode //Tasks from any supernode
function processTaskFromSupernode(packet, ws) { function processTaskFromSupernode(packet, ws) {
var { var {
from, from,
message message
} = packet_.parse(packet) } = packet_.parse(packet);
if (message) { if (message) {
message.forEach(task => { message.forEach(task => {
switch (task.type) { switch (task.type) {
case BACKUP_HANDSHAKE_INIT: case BACKUP_HANDSHAKE_INIT:
handshakeMid(from, ws) handshakeMid(from, ws);
break; break;
case STORE_MIGRATED_DATA: case STORE_MIGRATED_DATA:
storeMigratedData(task.data) storeMigratedData(task.data);
break; break;
case INITIATE_REFRESH: case INITIATE_REFRESH:
initiateRefresh() initiateRefresh();
break; break;
default: default:
console.log("Invalid task type:" + task.type + "from super-node") console.log("Invalid task type:" + task.type + "from super-node");
} };
}); });
} };
} };
//-----HANDSHAKE PROCESS----- //-----HANDSHAKE PROCESS-----
@ -323,21 +323,21 @@ function handshakeMid(id, ws) {
_prevNode.set(id, ws); _prevNode.set(id, ws);
_prevNode.send(packet_.constuct({ _prevNode.send(packet_.constuct({
type: BACKUP_HANDSHAKE_END type: BACKUP_HANDSHAKE_END
})) }));
} else { } else {
//Incorrect order, existing prev-node is already after the incoming node //Incorrect order, existing prev-node is already after the incoming node
ws.send(packet_.constuct({ ws.send(packet_.constuct({
type: RECONNECT_NEXT_NODE type: RECONNECT_NEXT_NODE
})) }));
return; return;
} };
} else { } else {
//set the new prev-node connection //set the new prev-node connection
_prevNode.set(id, ws); _prevNode.set(id, ws);
_prevNode.send(packet_.constuct({ _prevNode.send(packet_.constuct({
type: BACKUP_HANDSHAKE_END type: BACKUP_HANDSHAKE_END
})) }));
} };
//Reorder storelist //Reorder storelist
let nodes = kBucket.innerNodes(_prevNode.id, myFloID).concat(myFloID), let nodes = kBucket.innerNodes(_prevNode.id, myFloID).concat(myFloID),
req_sync = [], req_sync = [],
@ -351,19 +351,19 @@ function handshakeMid(id, ws) {
default: default:
_list[n] = 0; _list[n] = 0;
new_order.push(n); new_order.push(n);
} };
}); });
if (!req_sync.length && !new_order.length) if (!req_sync.length && !new_order.length)
return; //No order change and no need for any data sync return; //No order change and no need for any data sync
else else
handshakeMid.requestData(req_sync, new_order); handshakeMid.requestData(req_sync, new_order);
} };
handshakeMid.requestData = function(req_sync, new_order) { handshakeMid.requestData = function(req_sync, new_order) {
if (handshakeMid.timeout) { if (handshakeMid.timeout) {
clearTimeout(handshakeMid.timeout) clearTimeout(handshakeMid.timeout);
delete handshakeMid.timeout; delete handshakeMid.timeout;
} };
Promise.allSettled(req_sync.map(n => DB.createGetLastLog(n))).then(result => { Promise.allSettled(req_sync.map(n => DB.createGetLastLog(n))).then(result => {
let tasks = [], let tasks = [],
lastlogs = {}, lastlogs = {},
@ -375,7 +375,7 @@ handshakeMid.requestData = function(req_sync, new_order) {
if (result[i].status === "fulfilled") if (result[i].status === "fulfilled")
lastlogs[s] = result[i].value; lastlogs[s] = result[i].value;
else else
failed.push(s) failed.push(s);
}); });
if (Object.keys(lastlogs).length) if (Object.keys(lastlogs).length)
tasks.push({ tasks.push({
@ -384,29 +384,29 @@ handshakeMid.requestData = function(req_sync, new_order) {
}); });
new_order.forEach(n => { new_order.forEach(n => {
if (failed.includes(n)) if (failed.includes(n))
failed_order.push(n) failed_order.push(n);
else else
order.push(n) order.push(n);
}); });
if (order.length) if (order.length)
tasks.push({ tasks.push({
type: ORDER_BACKUP, type: ORDER_BACKUP,
order: _list.get(order) order: _list.get(order)
}) });
_nextNode.send(packet_.constuct(tasks)); _nextNode.send(packet_.constuct(tasks));
if (failed.length) if (failed.length)
handshakeMid.timeout = setTimeout(_ => handshakeMid.requestData(failed, failed_order), RETRY_TIMEOUT) handshakeMid.timeout = setTimeout(_ => handshakeMid.requestData(failed, failed_order), RETRY_TIMEOUT);
}); });
} };
//Complete handshake //Complete handshake
function handshakeEnd() { function handshakeEnd() {
console.log("Backup connected: " + _nextNode.id) console.log("Backup connected: " + _nextNode.id);
_nextNode.send(packet_.constuct({ _nextNode.send(packet_.constuct({
type: ORDER_BACKUP, type: ORDER_BACKUP,
order: _list.get() order: _list.get()
})) }));
} };
//Reconnect to next available node //Reconnect to next available node
function reconnectNextNode() { function reconnectNextNode() {
@ -420,9 +420,9 @@ function reconnectNextNode() {
for (let sn in floGlobals.supernodes) for (let sn in floGlobals.supernodes)
DB.createTable(sn) DB.createTable(sn)
.then(result => _list[sn] = 0) .then(result => _list[sn] = 0)
.catch(error => console.error(error)) .catch(error => console.error(error));
}) });
} };
//-----BACKUP TASKS----- //-----BACKUP TASKS-----
@ -435,20 +435,20 @@ function orderBackup(order) {
if (order[n] >= floGlobals.sn_config.backupDepth) if (order[n] >= floGlobals.sn_config.backupDepth)
DB.dropTable(n).then(_ => null) DB.dropTable(n).then(_ => null)
.catch(error => console.error(error)) .catch(error => console.error(error))
.finally(_ => _list.delete(n)) .finally(_ => _list.delete(n));
else if (_list[n] !== 0 || !cur_serve.includes(n)) { else if (_list[n] !== 0 || !cur_serve.includes(n)) {
_list[n] = order[n] + 1; _list[n] = order[n] + 1;
new_order.push(n); new_order.push(n);
} };
} };
} };
if (new_order.length) { if (new_order.length) {
_nextNode.send(packet_.constuct({ _nextNode.send(packet_.constuct({
type: ORDER_BACKUP, type: ORDER_BACKUP,
order: _list.get(new_order) order: _list.get(new_order)
})); }));
} };
} };
//Send stored data //Send stored data
function sendStoredData(lastlogs, node) { function sendStoredData(lastlogs, node) {
@ -459,50 +459,48 @@ function sendStoredData(lastlogs, node) {
type: DATA_SYNC, type: DATA_SYNC,
id: n, id: n,
status: true status: true
})) }));
console.info(`START: ${snID} data sync(send) to ${node.id}`) console.info(`START: ${snID} data sync(send) to ${node.id}`);
//TODO: efficiently handle large number of data instead of loading all into memory //TODO: efficiently handle large number of data instead of loading all into memory
result.forEach(d => node.send(packet_.constuct({ result.forEach(d => node.send(packet_.constuct({
type: STORE_BACKUP_DATA, type: STORE_BACKUP_DATA,
data: d data: d
}))) })));
console.info(`END: ${snID} data sync(send) to ${node.id}`) console.info(`END: ${snID} data sync(send) to ${node.id}`);
node.send(packet_.constuct({ node.send(packet_.constuct({
type: DATA_SYNC, type: DATA_SYNC,
id: n, id: n,
status: false status: false
})) }));
}).catch(error => console.error(error)) }).catch(error => console.error(error));
} };
} };
} };
//Indicate sync of data //Indicate sync of data
function dataSyncIndication(snID, status, from) { function dataSyncIndication(snID, status, from) {
console.info(`${status ? 'START':'END'}: ${snID} data sync(receive) form ${from}`); console.info(`${status ? 'START':'END'}: ${snID} data sync(receive) form ${from}`);
} };
//Store (backup) data //Store (backup) data
function storeBackupData(data, from, packet) { function storeBackupData(data, from, packet) {
let closestNode = kBucket.closestNode(data.receiverID); let closestNode = kBucket.closestNode(data.receiverID);
if (_list.stored.includes(closestNode)) { if (_list.stored.includes(closestNode)) {
DB.storeData(closestNode, data); DB.storeData(closestNode, data);
if (_list[closestNode] < floGlobals.sn_config.backupDepth && if (_list[closestNode] < floGlobals.sn_config.backupDepth && _nextNode.id !== from)
_nextNode.id !== from)
_nextNode.send(packet); _nextNode.send(packet);
} };
} };
//Tag (backup) data //Tag (backup) data
function tagBackupData(data, from, packet) { function tagBackupData(data, from, packet) {
let closestNode = kBucket.closestNode(data.receiverID); let closestNode = kBucket.closestNode(data.receiverID);
if (_list.stored.includes(closestNode)) { if (_list.stored.includes(closestNode)) {
DB.storeTag(closestNode, data); DB.storeTag(closestNode, data);
if (_list[closestNode] < floGlobals.sn_config.backupDepth && if (_list[closestNode] < floGlobals.sn_config.backupDepth && _nextNode.id !== from)
_nextNode.id !== from)
_nextNode.send(packet); _nextNode.send(packet);
} };
} };
//Store (migrated) data //Store (migrated) data
function storeMigratedData(data) { function storeMigratedData(data) {
@ -513,36 +511,35 @@ function storeMigratedData(data) {
type: STORE_BACKUP_DATA, type: STORE_BACKUP_DATA,
data: data data: data
})); }));
} };
} };
//Delete (migrated) data //Delete (migrated) data
function deleteMigratedData(old_sn, vectorClock, receiverID, from, packet) { function deleteMigratedData(old_sn, vectorClock, receiverID, from, packet) {
let closestNode = kBucket.closestNode(receiverID); let closestNode = kBucket.closestNode(receiverID);
if (old_sn !== closestNode && _list.stored.includes(old_sn)) { if (old_sn !== closestNode && _list.stored.includes(old_sn)) {
DB.deleteData(old_sn, vectorClock); DB.deleteData(old_sn, vectorClock);
if (_list[old_sn] < floGlobals.sn_config.backupDepth && if (_list[old_sn] < floGlobals.sn_config.backupDepth && _nextNode.id !== from)
_nextNode.id !== from)
_nextNode.send(packet); _nextNode.send(packet);
} };
} };
function initiateRefresh() { function initiateRefresh() {
refresher.invoke(false) refresher.invoke(false);
} };
//Forward incoming to next node //Forward incoming to next node
function forwardToNextNode(mode, data) { function forwardToNextNode(mode, data) {
var modeMap = { var modeMap = {
'TAG': TAG_BACKUP_DATA, 'TAG': TAG_BACKUP_DATA,
'DATA': STORE_BACKUP_DATA 'DATA': STORE_BACKUP_DATA
} };
if (mode in modeMap && _nextNode.id) if (mode in modeMap && _nextNode.id)
_nextNode.send(packet_.constuct({ _nextNode.send(packet_.constuct({
type: modeMap[mode], type: modeMap[mode],
data: data data: data
})); }));
} };
//Data migration processor //Data migration processor
function dataMigration(node_change, flag) { function dataMigration(node_change, flag) {
@ -557,28 +554,28 @@ function dataMigration(node_change, flag) {
if (del_nodes.includes(_prevNode.id)) { if (del_nodes.includes(_prevNode.id)) {
_list[_prevNode.id] = 0; //Temporary serve for the deleted node _list[_prevNode.id] = 0; //Temporary serve for the deleted node
_prevNode.close(); _prevNode.close();
} };
setTimeout(() => { setTimeout(() => {
//reconnect next node if current next node is deleted //reconnect next node if current next node is deleted
if (del_nodes.includes(_nextNode.id)) if (del_nodes.includes(_nextNode.id))
reconnectNextNode(); reconnectNextNode();
else { //reconnect next node if there are newly added nodes in between self and current next node else { //reconnect next node if there are newly added nodes in between self and current next node
let innerNodes = kBucket.innerNodes(myFloID, _nextNode.id) let innerNodes = kBucket.innerNodes(myFloID, _nextNode.id);
if (new_nodes.filter(n => innerNodes.includes(n)).length) if (new_nodes.filter(n => innerNodes.includes(n)).length)
reconnectNextNode(); reconnectNextNode();
} };
setTimeout(() => { setTimeout(() => {
dataMigration.process_new(new_nodes); dataMigration.process_new(new_nodes);
dataMigration.process_del(del_nodes); dataMigration.process_del(del_nodes);
}, MIGRATE_WAIT_DELAY); }, MIGRATE_WAIT_DELAY);
}, MIGRATE_WAIT_DELAY) }, MIGRATE_WAIT_DELAY);
} };
//data migration sub-process: Deleted nodes //data migration sub-process: Deleted nodes
dataMigration.process_del = async function(del_nodes) { dataMigration.process_del = async function(del_nodes) {
if (!del_nodes.length) if (!del_nodes.length)
return; return;
let process_nodes = del_nodes.filter(n => _list.serving.includes(n)) let process_nodes = del_nodes.filter(n => _list.serving.includes(n));
if (process_nodes.length) { if (process_nodes.length) {
connectToAllActiveNodes().then(ws_connections => { connectToAllActiveNodes().then(ws_connections => {
let remaining = process_nodes.length; let remaining = process_nodes.length;
@ -599,30 +596,30 @@ dataMigration.process_del = async function(del_nodes) {
type: STORE_MIGRATED_DATA, type: STORE_MIGRATED_DATA,
data: d data: d
})); }));
}) });
console.info(`END: Data migration for ${n}`); console.info(`END: Data migration for ${n}`);
_list.delete(n); _list.delete(n);
DB.dropTable(n); DB.dropTable(n);
remaining--; remaining--;
}).catch(error => reject(error)) }).catch(error => reject(error));
}); });
const interval = setInterval(() => { const interval = setInterval(() => {
if (remaining <= 0) { if (remaining <= 0) {
for (let c in ws_connections) for (let c in ws_connections)
if (ws_connections[c]) if (ws_connections[c])
ws_connections[c].close() ws_connections[c].close();
clearInterval(interval); clearInterval(interval);
} };
}, RETRY_TIMEOUT); }, RETRY_TIMEOUT);
}).catch(error => reject(error)) });
} };
del_nodes.forEach(n => { del_nodes.forEach(n => {
if (!process_nodes.includes(n) && _list.stored.includes(n)) { if (!process_nodes.includes(n) && _list.stored.includes(n)) {
_list.delete(n); _list.delete(n);
DB.dropTable(n); DB.dropTable(n);
} };
}) });
} };
//data migration sub-process: Added nodes //data migration sub-process: Added nodes
dataMigration.process_new = async function(new_nodes) { dataMigration.process_new = async function(new_nodes) {
@ -654,34 +651,34 @@ dataMigration.process_new = async function(new_nodes) {
receiverID: d.receiverID, receiverID: d.receiverID,
snID: n snID: n
})); }));
} };
}) });
remaining--; remaining--;
}).catch(error => reject(error)) }).catch(error => reject(error));
}); });
const interval = setInterval(() => { const interval = setInterval(() => {
if (remaining <= 0) { if (remaining <= 0) {
for (let c in ws_connections) for (let c in ws_connections)
if (ws_connections[c]) if (ws_connections[c])
ws_connections[c].close() ws_connections[c].close();
clearInterval(interval); clearInterval(interval);
} };
}, RETRY_TIMEOUT); }, RETRY_TIMEOUT);
}).catch(error => reject(error)) });
} };
dataMigration.intimateAllNodes = function() { dataMigration.intimateAllNodes = function() {
connectToAliveNodes().then(ws_connections => { connectToAliveNodes().then(ws_connections => {
let packet = packet_.constuct({ let packet = packet_.constuct({
type: INITIATE_REFRESH type: INITIATE_REFRESH
}) });
for (let n in ws_connections) for (let n in ws_connections)
if (ws_connections[n]) { if (ws_connections[n]) {
ws_connections[n].send(packet) ws_connections[n].send(packet);
ws_connections[n].close() ws_connections[n].close();
} };
}).catch(error => reject(error)) });
} };
//-----EXPORTS----- //-----EXPORTS-----
module.exports = { module.exports = {
@ -691,9 +688,9 @@ module.exports = {
SUPERNODE_INDICATOR, SUPERNODE_INDICATOR,
_list, _list,
set DB(db) { set DB(db) {
DB = db DB = db;
}, },
set refresher(r) { set refresher(r) {
refresher = r refresher = r;
} }
} };

View File

@ -1,24 +1,24 @@
'use strict'; 'use strict';
require('./lib/BuildKBucket') require('./lib/BuildKBucket')
(function(GLOBAL) { (function(GLOBAL) {
var kBucket = GLOBAL.kBucket = {} var kBucket = GLOBAL.kBucket = {};
var SNKB, SNCO; var SNKB, SNCO;
function decodeID(floID) { function decodeID(floID) {
let k = bitjs.Base58.decode(floID) let k = bitjs.Base58.decode(floID);
k.shift() k.shift();
k.splice(-4, 4) k.splice(-4, 4);
const decodedId = Crypto.util.bytesToHex(k); const decodedId = Crypto.util.bytesToHex(k);
const nodeIdBigInt = new BigInteger(decodedId, 16); const nodeIdBigInt = new BigInteger(decodedId, 16);
const nodeIdBytes = nodeIdBigInt.toByteArrayUnsigned(); const nodeIdBytes = nodeIdBigInt.toByteArrayUnsigned();
const nodeIdNewInt8Array = new Uint8Array(nodeIdBytes); const nodeIdNewInt8Array = new Uint8Array(nodeIdBytes);
return nodeIdNewInt8Array; return nodeIdNewInt8Array;
} };
function distanceOf(floID) { function distanceOf(floID) {
let decodedId = decodeID(floID); let decodedId = decodeID(floID);
return SNKB.distance(SNKB.localNodeId, decodedId); return SNKB.distance(SNKB.localNodeId, decodedId);
} };
function constructKB(list, refID) { function constructKB(list, refID) {
let KB = new BuildKBucket({ let KB = new BuildKBucket({
@ -29,7 +29,7 @@ require('./lib/BuildKBucket')
floID: floID floID: floID
})); }));
return KB; return KB;
} };
kBucket.launch = function() { kBucket.launch = function() {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
@ -39,73 +39,73 @@ require('./lib/BuildKBucket')
SNKB = constructKB(superNodeList, masterID); SNKB = constructKB(superNodeList, masterID);
SNCO = superNodeList.map(sn => [distanceOf(sn), sn]) SNCO = superNodeList.map(sn => [distanceOf(sn), sn])
.sort((a, b) => a[0] - b[0]) .sort((a, b) => a[0] - b[0])
.map(a => a[1]) .map(a => a[1]);
resolve('SuperNode KBucket formed'); resolve('SuperNode KBucket formed');
} catch (error) { } catch (error) {
reject(error); reject(error);
} };
}); });
} };
kBucket.innerNodes = function(id1, id2) { kBucket.innerNodes = function(id1, id2) {
if (!SNCO.includes(id1) || !SNCO.includes(id2)) if (!SNCO.includes(id1) || !SNCO.includes(id2))
throw Error('Given nodes are not supernode'); throw Error('Given nodes are not supernode');
let iNodes = [] let iNodes = [];
for (let i = SNCO.indexOf(id1) + 1; SNCO[i] != id2; i++) { for (let i = SNCO.indexOf(id1) + 1; SNCO[i] != id2; i++) {
if (i < SNCO.length) if (i < SNCO.length)
iNodes.push(SNCO[i]) iNodes.push(SNCO[i]);
else i = -1 else i = -1;
} };
return iNodes return iNodes;
} };
kBucket.outterNodes = function(id1, id2) { kBucket.outterNodes = function(id1, id2) {
if (!SNCO.includes(id1) || !SNCO.includes(id2)) if (!SNCO.includes(id1) || !SNCO.includes(id2))
throw Error('Given nodes are not supernode'); throw Error('Given nodes are not supernode');
let oNodes = [] let oNodes = [];
for (let i = SNCO.indexOf(id2) + 1; SNCO[i] != id1; i++) { for (let i = SNCO.indexOf(id2) + 1; SNCO[i] != id1; i++) {
if (i < SNCO.length) if (i < SNCO.length)
oNodes.push(SNCO[i]) oNodes.push(SNCO[i]);
else i = -1 else i = -1;
} };
return oNodes return oNodes;
} };
kBucket.prevNode = function(id, N = 1) { kBucket.prevNode = function(id, N = 1) {
let n = N || SNCO.length; let n = N || SNCO.length;
if (!SNCO.includes(id)) if (!SNCO.includes(id))
throw Error('Given node is not supernode'); throw Error('Given node is not supernode');
let pNodes = [] let pNodes = [];
for (let i = 0, j = SNCO.indexOf(id) - 1; i < n; j--) { for (let i = 0, j = SNCO.indexOf(id) - 1; i < n; j--) {
if (j == SNCO.indexOf(id)) if (j == SNCO.indexOf(id))
break; break;
else if (j > -1) else if (j > -1)
pNodes[i++] = SNCO[j] pNodes[i++] = SNCO[j];
else j = SNCO.length else j = SNCO.length;
} };
return (N == 1 ? pNodes[0] : pNodes) return (N == 1 ? pNodes[0] : pNodes);
} };
kBucket.nextNode = function(id, N = 1) { kBucket.nextNode = function(id, N = 1) {
let n = N || SNCO.length; let n = N || SNCO.length;
if (!SNCO.includes(id)) if (!SNCO.includes(id))
throw Error('Given node is not supernode'); throw Error('Given node is not supernode');
let nNodes = [] let nNodes = [];
for (let i = 0, j = SNCO.indexOf(id) + 1; i < n; j++) { for (let i = 0, j = SNCO.indexOf(id) + 1; i < n; j++) {
if (j == SNCO.indexOf(id)) if (j == SNCO.indexOf(id))
break; break;
else if (j < SNCO.length) else if (j < SNCO.length)
nNodes[i++] = SNCO[j] nNodes[i++] = SNCO[j];
else j = -1 else j = -1;
} };
return (N == 1 ? nNodes[0] : nNodes) return (N == 1 ? nNodes[0] : nNodes);
} };
kBucket.closestNode = function(id, N = 1) { kBucket.closestNode = function(id, N = 1) {
let decodedId = decodeID(id); let decodedId = decodeID(id);
let n = N || SNCO.length; let n = N || SNCO.length;
let cNodes = SNKB.closest(decodedId, n) let cNodes = SNKB.closest(decodedId, n)
.map(k => k.floID) .map(k => k.floID);
return (N == 1 ? cNodes[0] : cNodes) return (N == 1 ? cNodes[0] : cNodes);
} };
})(typeof global !== "undefined" ? global : window) })(typeof global !== "undefined" ? global : window);

View File

@ -1,24 +1,26 @@
const config = require("../config.json") const config = require("../config.json");
global.floGlobals = require("./floGlobals") global.floGlobals = require("./floGlobals");
require('./set_globals') require('./set_globals');
require('./lib') require('./lib');
require('./kBucket') require('./kBucket');
require('./floCrypto') require('./floCrypto');
require('./floBlockchainAPI') require('./floBlockchainAPI');
const Database = require("./database") const Database = require("./database");
const intra = require('./intra') const intra = require('./intra');
const client = require('./client') const client = require('./client');
const Server = require('./server') const Server = require('./server');
var DB; //Container for Database object var DB; //Container for Database object
function startNode() { function startNode() {
//Set myPrivKey, myPubKey, myFloID //Set myPrivKey, myPubKey, myFloID
global.myPrivKey = config["privateKey"] global.myPrivKey = config["privateKey"];
global.myPubKey = floCrypto.getPubKeyHex(config["privateKey"]) global.myPubKey = floCrypto.getPubKeyHex(config["privateKey"]);
global.myFloID = floCrypto.getFloID(config["privateKey"]) global.myFloID = floCrypto.getFloID(config["privateKey"]);
console.info("Logged In as " + myFloID);
//DB connect //DB connect
Database(config["sql_user"], config["sql_pwd"], config["sql_db"], config["sql_host"]).then(db => { Database(config["sql_user"], config["sql_pwd"], config["sql_db"], config["sql_host"]).then(db => {
console.info("Connected to Database");
DB = db; DB = db;
//Set DB to client and intra scripts //Set DB to client and intra scripts
intra.DB = DB; intra.DB = DB;
@ -36,19 +38,19 @@ function startNode() {
const server = new Server(config["port"], client, intra); const server = new Server(config["port"], client, intra);
server.refresher = refreshData; server.refresher = refreshData;
intra.refresher = refreshData; intra.refresher = refreshData;
}).catch(error => reject(error)) }).catch(error => reject(error));
}).catch(error => reject(error)) }).catch(error => reject(error));
} };
function loadBase(DB) { function loadBase(DB) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
DB.createBase().then(result => { DB.createBase().then(result => {
DB.getBase(DB) DB.getBase(DB)
.then(result => resolve(result)) .then(result => resolve(result))
.catch(error => reject(error)) .catch(error => reject(error));
}).catch(error => reject(error)) }).catch(error => reject(error));
}) });
} };
const refreshData = { const refreshData = {
count: null, count: null,
@ -56,33 +58,33 @@ const refreshData = {
invoke(flag = true) { invoke(flag = true) {
this.count = floGlobals.sn_config.refreshDelay; this.count = floGlobals.sn_config.refreshDelay;
refreshBlockchainData(this.base, flag).then(result => { refreshBlockchainData(this.base, flag).then(result => {
console.log(result) console.log(result);
diskCleanUp(this.base) diskCleanUp(this.base)
.then(result => console.info(result)) .then(result => console.info(result))
.catch(warn => console.warn(warn)) .catch(warn => console.warn(warn));
}).catch(error => console.error(error)) }).catch(error => console.error(error));
}, },
get countdown() { get countdown() {
this.count--; this.count--;
if (this.count <= 0) if (this.count <= 0)
this.invoke(); this.invoke();
} }
} };
function refreshBlockchainData(base, flag) { function refreshBlockchainData(base, flag) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
readSupernodeConfigFromAPI(base, flag).then(result => { readSupernodeConfigFromAPI(base, flag).then(result => {
console.log(result) console.log(result);
kBucket.launch().then(result => { kBucket.launch().then(result => {
console.log(result) console.log(result);
readAppSubAdminListFromAPI(base) readAppSubAdminListFromAPI(base)
.then(result => console.log(result)) .then(result => console.log(result))
.catch(warn => console.warn(warn)) .catch(warn => console.warn(warn))
.finally(_ => resolve("Refreshed Data from blockchain")) .finally(_ => resolve("Refreshed Data from blockchain"));
}).catch(error => reject(error)) }).catch(error => reject(error));
}).catch(error => reject(error)) }).catch(error => reject(error));
}) });
} };
function readSupernodeConfigFromAPI(base, flag) { function readSupernodeConfigFromAPI(base, flag) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
@ -92,7 +94,7 @@ function readSupernodeConfigFromAPI(base, flag) {
pattern: "SuperNodeStorage" pattern: "SuperNodeStorage"
}).then(result => { }).then(result => {
let promises = [], let promises = [],
node_change = {} node_change = {};
result.data.reverse().forEach(data => { result.data.reverse().forEach(data => {
var content = JSON.parse(data).SuperNodeStorage; var content = JSON.parse(data).SuperNodeStorage;
if (content.removeNodes) if (content.removeNodes)
@ -103,7 +105,7 @@ function readSupernodeConfigFromAPI(base, flag) {
delete node_change[sn]; delete node_change[sn];
else else
node_change[sn] = false; node_change[sn] = false;
} };
if (content.newNodes) if (content.newNodes)
for (let sn in content.newNodes) { for (let sn in content.newNodes) {
promises.push(DB.addSuperNode(sn, content.newNodes[sn].pubKey, content.newNodes[sn].uri)); promises.push(DB.addSuperNode(sn, content.newNodes[sn].pubKey, content.newNodes[sn].uri));
@ -115,22 +117,22 @@ function readSupernodeConfigFromAPI(base, flag) {
delete node_change[sn]; delete node_change[sn];
else else
node_change[sn] = true; node_change[sn] = true;
} };
if (content.config) if (content.config)
for (let c in content.config) { for (let c in content.config) {
promises.push(DB.setConfig(c, content.config[c])); promises.push(DB.setConfig(c, content.config[c]));
base.sn_config[c] = content.config[c]; base.sn_config[c] = content.config[c];
} };
if (content.removeApps) if (content.removeApps)
for (let app of content.removeApps) { for (let app of content.removeApps) {
promises.push(DB.rmApp(app)); promises.push(DB.rmApp(app));
delete base.appList; delete base.appList;
} };
if (content.addApps) if (content.addApps)
for (let app in content.addApps) { for (let app in content.addApps) {
promises.push(DB.addApp(app, content.addApps[app])); promises.push(DB.addApp(app, content.addApps[app]));
base.appList[app] = content.addApps[app]; base.appList[app] = content.addApps[app];
} };
}); });
promises.push(DB.setLastTx(floGlobals.SNStorageID, result.totalTxs)); promises.push(DB.setLastTx(floGlobals.SNStorageID, result.totalTxs));
//Check if all save process were successful //Check if all save process were successful
@ -142,11 +144,11 @@ function readSupernodeConfigFromAPI(base, flag) {
}); });
//Process data migration if nodes are changed //Process data migration if nodes are changed
if (Object.keys(node_change)) if (Object.keys(node_change))
intra.dataMigration(node_change, flag) intra.dataMigration(node_change, flag);
resolve('Updated Supernode Configuration'); resolve('Updated Supernode Configuration');
}).catch(error => reject(error)) }).catch(error => reject(error));
}) });
} };
function readAppSubAdminListFromAPI(base) { function readAppSubAdminListFromAPI(base) {
var promises = []; var promises = [];
@ -175,9 +177,9 @@ function readAppSubAdminListFromAPI(base) {
console.warn(`SubAdmin list for app(${app}) might not have been saved in database`); console.warn(`SubAdmin list for app(${app}) might not have been saved in database`);
}); });
resolve("Loaded subAdmin List for APP:" + app); resolve("Loaded subAdmin List for APP:" + app);
}).catch(error => reject([app, error])) }).catch(error => reject([app, error]));
})); }));
} };
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
Promise.allSettled(promises).then(results => { Promise.allSettled(promises).then(results => {
if (results.reduce((a, r) => r.status === "rejected" ? ++a : a, 0)) { if (results.reduce((a, r) => r.status === "rejected" ? ++a : a, 0)) {
@ -187,8 +189,8 @@ function readAppSubAdminListFromAPI(base) {
} else } else
resolve("Loaded subAdmin List for all APPs successfully"); resolve("Loaded subAdmin List for all APPs successfully");
}); });
}) });
} };
function diskCleanUp(base) { function diskCleanUp(base) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
@ -201,18 +203,18 @@ function diskCleanUp(base) {
//for each authorised app: delete unofficial data (untaged, unknown sender/receiver) //for each authorised app: delete unofficial data (untaged, unknown sender/receiver)
for (let app in base.appList) for (let app in base.appList)
promises.push(DB.clearAuthorisedAppData(sn, app, base.appList[app], base.subAdmins[app], time)); promises.push(DB.clearAuthorisedAppData(sn, app, base.appList[app], base.subAdmins[app], time));
}) });
Promise.allSettled(promises).then(results => { Promise.allSettled(promises).then(results => {
let failed = results.filter(r => r.status === "rejected").map(r => r.reason) let failed = results.filter(r => r.status === "rejected").map(r => r.reason);
if (failed.length) { if (failed.length) {
console.error(JSON.stringify(failed)); console.error(JSON.stringify(failed));
let success = results.length - failed.length; let success = results.length - failed.length;
reject(`Disk clean-up process has failed at ${100 * success/results.length}%. (Success:${success}|Failed:${failed.count})`) reject(`Disk clean-up process has failed at ${100 * success/results.length}%. (Success:${success}|Failed:${failed.count})`);
} else } else
resolve("Disk clean-up process finished successfully (100%)"); resolve("Disk clean-up process finished successfully (100%)");
}).catch(error => reject(error)) }).catch(error => reject(error));
}) });
} };
module.exports = startNode; module.exports = startNode;

View File

@ -1,5 +1,5 @@
const http = require('http') const http = require('http');
const WebSocket = require('ws') const WebSocket = require('ws');
module.exports = function Server(port, client, intra) { module.exports = function Server(port, client, intra) {
@ -14,13 +14,12 @@ module.exports = function Server(port, client, intra) {
var request = JSON.parse(req.url.substring(i)); var request = JSON.parse(req.url.substring(i));
client.processRequestFromUser(request) client.processRequestFromUser(request)
.then(result => res.end(JSON.parse(result[0]))) .then(result => res.end(JSON.parse(result[0])))
.catch(error => res.end(error.toString())) .catch(error => res.end(error.toString()));
} };
}) });
} } else if (req.method === "POST") {
if (req.method === "POST") {
let data = ''; let data = '';
req.on('data', chunk => data += chunk) req.on('data', chunk => data += chunk);
req.on('end', () => { req.on('end', () => {
console.log(data); console.log(data);
//process the data storing //process the data storing
@ -29,17 +28,17 @@ module.exports = function Server(port, client, intra) {
if (result[1]) { if (result[1]) {
refresher.countdown; refresher.countdown;
if (result[1] === 'DATA') if (result[1] === 'DATA')
sendToLiveRequests(result[0]) sendToLiveRequests(result[0]);
intra.forwardToNextNode(result[1], result[0]) intra.forwardToNextNode(result[1], result[0]);
} };
}).catch(error => res.end(error.toString())) }).catch(error => res.end(error.toString()));
}) });
} };
}); });
server.listen(port, (err) => { server.listen(port, (err) => {
if (!err) if (!err)
console.log(`Server running at port ${port}`); console.log(`Server running at port ${port}`);
}) });
const wsServer = new WebSocket.Server({ const wsServer = new WebSocket.Server({
server server
@ -53,14 +52,14 @@ module.exports = function Server(port, client, intra) {
var request = JSON.parse(message); var request = JSON.parse(message);
client.processRequestFromUser(JSON.parse(message)) client.processRequestFromUser(JSON.parse(message))
.then(result => { .then(result => {
ws.send(JSON.parse(result[0])) ws.send(JSON.parse(result[0]));
ws._liveReq = request; ws._liveReq = request;
}).catch(error => { }).catch(error => {
if (floGlobals.sn_config.errorFeedback) if (floGlobals.sn_config.errorFeedback)
ws.send(error.toString()) ws.send(error.toString());
}) });
} };
} };
}); });
Object.defineProperty(this, "http", { Object.defineProperty(this, "http", {
@ -71,5 +70,5 @@ module.exports = function Server(port, client, intra) {
}); });
Object.defineProperty(this, "refresher", { Object.defineProperty(this, "refresher", {
set: (r) => refresher = r set: (r) => refresher = r
}) });
} };

View File

@ -3,6 +3,6 @@
global.fetch = require("node-fetch"); global.fetch = require("node-fetch");
//Set browser paramaters from param.json //Set browser paramaters from param.json
const param = require('../param.json') const param = require('../param.json');
for(let p in param) for(let p in param)
global[p] = param[p]; global[p] = param[p];