Supernode Update
Changes: - Changes for wss update Added: - Added time to data - errorFeedback: (if on)Feedback if any error in processing data from users. - live-request: When a new data is stored, sends it to all respective requestors of that floID. - deleteRequest: Users will now be able to delete the data received by them from cloud. (Note: user must be the receiverID of the data; sign verification ll be done). Improvements: - Improved data processing from wss. - Improved data-signature format (new format: "receiverID|time|application|type|message|comment"). - Time in data must be within the allowed delayDelta. - Feedback vectorclock of stored data to the sender. - Dedicated disk will now be applied to authorised apps instead of diskList (removed floGlobals.diskList) . Authorising apps will automatically create a new disk for the app and imports all data of the app from defaultDisk. . Unauthorising apps will automatically exports all data from app disk to defaultDisk and deletes the app disk. (Caution: Unauthorising an app will cause diskCleanUp to delete all data stored before deleteDelay). - Improved autoDeleteStoredData to diskCleanUp. For defaultDisk: deletes all data before deleteDelay, For authorised apps deletes data before deleteDelay sent 'from non-subAdmins' and/or 'to non-admin'. Bug fixes: - Minor bug fixes
This commit is contained in:
parent
4a8e8bd241
commit
fd592da8ed
603
app/index.html
603
app/index.html
@ -31,14 +31,19 @@
|
|||||||
|
|
||||||
//Required for Supernode operations
|
//Required for Supernode operations
|
||||||
supernodes: {}, //each supnernode must be stored as floID : {uri:<uri>,pubKey:<publicKey>}
|
supernodes: {}, //each supnernode must be stored as floID : {uri:<uri>,pubKey:<publicKey>}
|
||||||
diskList : ["General"],
|
|
||||||
defaultDisk : "General",
|
defaultDisk : "General",
|
||||||
applicationList:{},
|
appList:{},
|
||||||
appSubAdmins:{},
|
appSubAdmins:{},
|
||||||
serveList : [],
|
serveList : [],
|
||||||
storedList : [],
|
storedList : [],
|
||||||
supernodeConfig : {},
|
backupNodes : [],
|
||||||
backupNodes : []
|
supernodeConfig : {}
|
||||||
|
/* List of supernode configurations (all blockchain controlled by SNStorageID)
|
||||||
|
backupDepth - (Interger) Number of backup nodes
|
||||||
|
refreshDelay - (Interger) Count of requests for triggering read-blockchain and autodelete
|
||||||
|
deleteDelay - (Interger) Maximum number of duration (milliseconds) an unauthorised data is stored
|
||||||
|
errorFeedback - (Boolean) Send error (if any) feedback to the requestor
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -7532,7 +7537,7 @@ Bitcoin.Util = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
//generate a random String within length (options : alphaNumeric chars only)
|
//generate a random String within length (options : alphaNumeric chars only)
|
||||||
randString: function (length, alphaNumeric = false) {
|
randString: function (length, alphaNumeric = true) {
|
||||||
var result = '';
|
var result = '';
|
||||||
if (alphaNumeric)
|
if (alphaNumeric)
|
||||||
var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
||||||
@ -7630,20 +7635,18 @@ Bitcoin.Util = {
|
|||||||
if (key.priv == null)
|
if (key.priv == null)
|
||||||
return null;
|
return null;
|
||||||
key.setCompressed(true);
|
key.setCompressed(true);
|
||||||
var pubkeyHex = key.getPubKeyHex();
|
return key.getPubKeyHex();
|
||||||
return pubkeyHex;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
//Returns flo-ID from public-key or private-key
|
//Returns flo-ID from public-key or private-key
|
||||||
getFloID: function (keyHex) {
|
getFloID: function (keyHex) {
|
||||||
if(!pubkeyHex)
|
if(!keyHex)
|
||||||
return null;
|
return null;
|
||||||
try {
|
try {
|
||||||
var key = new Bitcoin.ECKey(privateKeyHex);
|
var key = new Bitcoin.ECKey(keyHex);
|
||||||
if (key.priv == null)
|
if (key.priv == null)
|
||||||
key.setPub(pubkeyHex);
|
key.setPub(keyHex);
|
||||||
var floID = key.getBitcoinAddress();
|
return key.getBitcoinAddress();
|
||||||
return floID;
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -8196,7 +8199,7 @@ Bitcoin.Util = {
|
|||||||
return KB.distance(KB.localNodeId, decodedId);
|
return KB.distance(KB.localNodeId, decodedId);
|
||||||
},
|
},
|
||||||
|
|
||||||
closest: function (floID, n, KB) {
|
closestOf: function (floID, n, KB) {
|
||||||
let decodedId = this.decodeID(floID);
|
let decodedId = this.decodeID(floID);
|
||||||
return KB.closest(flo_addr, n)
|
return KB.closest(flo_addr, n)
|
||||||
},
|
},
|
||||||
@ -8218,7 +8221,7 @@ Bitcoin.Util = {
|
|||||||
let superNodeList = Object.keys(floGlobals.supernodes);
|
let superNodeList = Object.keys(floGlobals.supernodes);
|
||||||
let masterID = floGlobals.SNStorageID;
|
let masterID = floGlobals.SNStorageID;
|
||||||
this.SNKB = this.util.constructKB(superNodeList, masterID);
|
this.SNKB = this.util.constructKB(superNodeList, masterID);
|
||||||
this.SNCO = superNodeList.map(sn => [this.util.distance(sn, this.SNKB), sn])
|
this.SNCO = superNodeList.map(sn => [this.util.distanceOf(sn, this.SNKB), sn])
|
||||||
.sort((a, b) => a[0] - b[0])
|
.sort((a, b) => a[0] - b[0])
|
||||||
.map(a => a[1])
|
.map(a => a[1])
|
||||||
console.log(this.SNCO)
|
console.log(this.SNCO)
|
||||||
@ -8285,7 +8288,7 @@ Bitcoin.Util = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
closestNode: function (id, n = 1) {
|
closestNode: function (id, n = 1) {
|
||||||
let cNodes = this.util.closest(id, n).map(k => k.floID)
|
let cNodes = this.util.closestOf(id, n).map(k => k.floID)
|
||||||
return (n == 1 ? cNodes[0] : cNodes)
|
return (n == 1 ? cNodes[0] : cNodes)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -8297,10 +8300,7 @@ Bitcoin.Util = {
|
|||||||
var wsConn = new WebSocket("wss://" + floGlobals.supernodes[snID].uri + "/ws");
|
var wsConn = new WebSocket("wss://" + floGlobals.supernodes[snID].uri + "/ws");
|
||||||
wsConn.onmessage = (evt) => {
|
wsConn.onmessage = (evt) => {
|
||||||
if (evt.data == '$+')
|
if (evt.data == '$+')
|
||||||
resolve({
|
resolve(wsConn)
|
||||||
snID,
|
|
||||||
wsConn
|
|
||||||
})
|
|
||||||
else if (evt.data == '$-') {
|
else if (evt.data == '$-') {
|
||||||
wsConn.close();
|
wsConn.close();
|
||||||
reject(`${snID} is not active`)
|
reject(`${snID} is not active`)
|
||||||
@ -8328,33 +8328,6 @@ Bitcoin.Util = {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
//Sends data to the supernode
|
|
||||||
sendData: function (data, floID) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
this.connectActive(floID).then(node => {
|
|
||||||
node.wsConn.send(data);
|
|
||||||
node.wsConn.close();
|
|
||||||
resolve(`Data sent to supernode : ${node.snID}`)
|
|
||||||
}).catch(error => reject(error));
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
//Request data from supernode
|
|
||||||
requestData: function (request, floID) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
this.connectActive(floID).then(node => {
|
|
||||||
node.wsConn.onmessage = (evt) => {
|
|
||||||
if (evt.data[0] != '$')
|
|
||||||
resolve(evt.data);
|
|
||||||
else
|
|
||||||
reject(evt.data)
|
|
||||||
node.wsConn.close();
|
|
||||||
}
|
|
||||||
node.wsConn.send(`?${request}`)
|
|
||||||
}).catch(error => reject(error));
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
//Supernode initate (call this function only when client is authorized as supernode)
|
//Supernode initate (call this function only when client is authorized as supernode)
|
||||||
initSupernode: function (pwd, floID) {
|
initSupernode: function (pwd, floID) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
@ -8375,13 +8348,13 @@ Bitcoin.Util = {
|
|||||||
if (evt.data[0] == '$') {
|
if (evt.data[0] == '$') {
|
||||||
console.log('Admin Message :', evt.data);
|
console.log('Admin Message :', evt.data);
|
||||||
if (evt.data == '$Access Granted!')
|
if (evt.data == '$Access Granted!')
|
||||||
resolve("Access Granted! Initiated Supernode client");
|
resolve("Access Granted: Initiated Supernode");
|
||||||
else if (evt.data == '$Access Denied!')
|
else if (evt.data == '$Access Denied!')
|
||||||
reject("Access Denied! Failed to initiate Supernode client");
|
reject("Access Denied: Failed to initiate Supernode");
|
||||||
} else if (evt.data[0] == '?')
|
else if (evt.data == '$Access Locked')
|
||||||
processIncomingRequest(evt.data.substr(1));
|
reject("Access Locked: Another instance of Supernode is active")
|
||||||
else
|
} else
|
||||||
processIncomingData(evt.data)
|
processIncomingData(evt.data);
|
||||||
};
|
};
|
||||||
this.supernodeClientWS.onerror = (evt) => {
|
this.supernodeClientWS.onerror = (evt) => {
|
||||||
console.error('Error! Unable to connect supernode websocket!');
|
console.error('Error! Unable to connect supernode websocket!');
|
||||||
@ -8395,84 +8368,126 @@ Bitcoin.Util = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Process incoming request from clients
|
//Process incoming request from clients
|
||||||
function processIncomingRequest(request) {
|
function processIncomingData(data) {
|
||||||
console.log('Request :', request);
|
console.log(data);
|
||||||
try {
|
try {
|
||||||
request = request.split(" ");
|
let gid = evt.data.substring(0, 34);
|
||||||
requestor = request.shift();
|
let uid = evt.data.substring(35, 40);
|
||||||
request = JSON.parse(request.join(" "));
|
let data = JSON.parse(evt.data.substring(41));
|
||||||
let closeNode = floSupernode.kBucket.closestNode(request.receiverID)
|
if (data.from in floGlobals.supernodes && data.sn_msg)
|
||||||
if (floGlobals.serveList.includes(closeNode)) {
|
processTaskFromSupernode(gid, uid, data);
|
||||||
var filterOptions = {
|
else {
|
||||||
lowerKey: request.lowerVectorClock,
|
let curTime = Date.now()
|
||||||
upperKey: request.upperVectorClock,
|
if(data.time > curTime + floGlobals.supernodeConfig.delayDelta ||
|
||||||
lastOnly: request.mostRecent,
|
data.time < curTime + floGlobals.supernodeConfig.delayDelta)
|
||||||
atKey: request.atVectorClock,
|
throw Error("Time deviation longer than allowed delay");
|
||||||
patternEval: (k, v) => {
|
else if (data.request)
|
||||||
return (v.application == request.application && v.receiverID == request.receiverID && (!
|
processRequestFromUser(gid, uid, data);
|
||||||
request.comment || v.comment == request.comment) && (!request.type || v
|
else if (data.message)
|
||||||
.type == request.type) && (!request.senderIDs || request.senderIDs.includes(
|
processDataFromUser(gid, uid, data);
|
||||||
v.senderID)))
|
else if (data.delete)
|
||||||
}
|
processDeleteFromUser(gid, uid, data);
|
||||||
}
|
|
||||||
compactIDB.searchData(floGlobals.diskList.includes(request.application) ? request.application :
|
|
||||||
floGlobals.defaultDisk, filterOptions, `SN_${closeNode}`)
|
|
||||||
.then(result => floSupernode.supernodeClientWS.send(`${requestor} ${JSON.stringify(result)}`))
|
|
||||||
.catch(error => console.error(error))
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error.message)
|
console.error(error)
|
||||||
|
if(floGlobals.supernodeConfig.errorFeedback)
|
||||||
|
floSupernode.supernodeClientWS.send(`@${uid}#${gid}:${error}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Process Incoming data
|
//Process request from users
|
||||||
function processIncomingData(data) {
|
function processRequestFromUser(gid, uid, data) {
|
||||||
console.log('Data :', data);
|
let request = data.request;
|
||||||
try {
|
if (!floCrypto.validateAddr(request.receiverID))
|
||||||
data = JSON.parse(data)
|
throw Error("Invalid receiverID")
|
||||||
if (data.from in floGlobals.supernodes && data.sn_msg)
|
let closeNode = floSupernode.kBucket.closestNode(request.receiverID)
|
||||||
processDataFromSupernode(data);
|
if (!floGlobals.serveList.includes(closeNode))
|
||||||
else { //Serving Users
|
throw Error("Incorrect Supernode")
|
||||||
|
var filterOptions = {
|
||||||
//Delete request from receiver
|
lowerKey: request.lowerVectorClock,
|
||||||
if (data.delete) {
|
upperKey: request.upperVectorClock,
|
||||||
let closeNode = floSupernode.kBucket.closestNode(data.from);
|
lastOnly: request.mostRecent,
|
||||||
if (floGlobals.serveList.includes(closeNode) &&
|
atKey: request.atVectorClock
|
||||||
data.senderID == floCrypto.getFloIDfromPubkeyHex(data.pubKey) &&
|
|
||||||
floCrypto.verifySign(JSON.stringify(data.delete), data.sign, data.pubKey)) {
|
|
||||||
//start the deletion process
|
|
||||||
|
|
||||||
//indicate backup nodes to delete data
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
let closeNode = floSupernode.kBucket.closestNode(data.receiverID)
|
|
||||||
if (floGlobals.serveList.includes(closeNode) &&
|
|
||||||
data.senderID == floCrypto.getFloIDfromPubkeyHex(data.pubKey) &&
|
|
||||||
floCrypto.verifySign(JSON.stringify(data.message), data.sign, data.pubKey)) {
|
|
||||||
var key = `${Date.now()}_${data.senderID}`
|
|
||||||
var value = {
|
|
||||||
senderID: data.senderID,
|
|
||||||
receiverID: data.receiverID,
|
|
||||||
pubKey: data.pubKey,
|
|
||||||
message: data.message,
|
|
||||||
sign: data.sign,
|
|
||||||
application: data.application,
|
|
||||||
type: data.type,
|
|
||||||
comment: data.comment
|
|
||||||
}
|
|
||||||
compactIDB.addData(floGlobals.diskList.includes(value.application) ? value.application :
|
|
||||||
floGlobals
|
|
||||||
.defaultDisk, value, key, `SN_${closeNode}`)
|
|
||||||
sendBackupData(key, value, closeNode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((refreshData.countdown--) <= 0)
|
|
||||||
refreshData();
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error.message);
|
|
||||||
}
|
}
|
||||||
|
filterOptions.patternEval = (
|
||||||
|
v.application == request.application &&
|
||||||
|
v.receiverID == request.receiverID &&
|
||||||
|
(!request.comment || v.comment == request.comment) &&
|
||||||
|
(!request.type || v.type == request.type) &&
|
||||||
|
(!request.senderIDs || request.senderIDs.includes(v.senderID))
|
||||||
|
)
|
||||||
|
compactIDB.searchData(request.application in floGlobals.appList ? request.application :
|
||||||
|
floGlobals.defaultDisk, filterOptions, `SN_${closeNode}`)
|
||||||
|
.then(result => floSupernode.supernodeClientWS.send(`@${uid}#${gid}:${JSON.stringify(result)}`))
|
||||||
|
.catch(error => {
|
||||||
|
throw Error("Invalid request")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
//Process data from users
|
||||||
|
function processDataFromUser(gid, uid, data) {
|
||||||
|
if (!floCrypto.validateAddr(data.receiverID))
|
||||||
|
throw Error("Invalid receiverID")
|
||||||
|
let closeNode = floSupernode.kBucket.closestNode(data.receiverID)
|
||||||
|
if (!floGlobals.serveList.includes(closeNode))
|
||||||
|
throw Error("Incorrect Supernode")
|
||||||
|
if (data.senderID !== floCrypto.getFloID(data.pubKey))
|
||||||
|
throw Error("Invalid senderID/pubKey")
|
||||||
|
let hashcontent = ["receiverID", "time", "application", "type", "message", "comment"]
|
||||||
|
.map(d => data[d]).join("|")
|
||||||
|
if (!floCrypto.verifySign(hashcontent, data.sign, data.pubKey))
|
||||||
|
throw Error("Invalid signature")
|
||||||
|
var key = `${Date.now()}_${data.senderID}`
|
||||||
|
var value = {
|
||||||
|
senderID: data.senderID,
|
||||||
|
receiverID: data.receiverID,
|
||||||
|
pubKey: data.pubKey,
|
||||||
|
time: data.time,
|
||||||
|
message: data.message,
|
||||||
|
sign: data.sign,
|
||||||
|
application: data.application,
|
||||||
|
type: data.type,
|
||||||
|
comment: data.comment
|
||||||
|
}
|
||||||
|
compactIDB.addData(value.application in floGlobals.appList ? value.application :
|
||||||
|
floGlobals.defaultDisk, value, key, `SN_${closeNode}`).then(result => {
|
||||||
|
floSupernode.supernodeClientWS.send(`@${uid}#${gid}:${JSON.stringify({vectorClock: key})}`)
|
||||||
|
floSupernode.supernodeClientWS.send(`#${data.receiverID}:${JSON.stringify({[key]: value})}`)
|
||||||
|
sendBackupData(key, value, closeNode);
|
||||||
|
}).catch(error => {
|
||||||
|
throw Error("Invalid Data")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function processDeleteFromUser(gid, uid, data) {
|
||||||
|
if (!floCrypto.validateAddr(data.requestorID))
|
||||||
|
throw Error("Invalid requestorID")
|
||||||
|
let closeNode = floSupernode.kBucket.closestNode(data.requestorID)
|
||||||
|
if (!floGlobals.serveList.includes(closeNode))
|
||||||
|
throw Error("Incorrect Supernode")
|
||||||
|
if (data.requestorID !== floCrypto.getFloID(data.pubKey))
|
||||||
|
throw Error("Invalid senderID/pubKey")
|
||||||
|
let hashcontent = ["time", "application", "delete"]
|
||||||
|
.map(d => data[d]).join("|")
|
||||||
|
throw Error("Invalid signature")
|
||||||
|
let disk = data.application in floGlobals.appList ? data.application : floGlobals.defaultDisk;
|
||||||
|
const deleteData = v => new Promise((res, rej) => {
|
||||||
|
compactIDB.readData(disk, vc, `SN_${closeNode}`).then(result => {
|
||||||
|
if(result.receiverID === data.requestorID)
|
||||||
|
compactIDB.removeData(disk, vc, `SN_${closeNode}`)
|
||||||
|
.then(r => res(true)).catch(e => res(false))
|
||||||
|
else
|
||||||
|
res(false)
|
||||||
|
}).catch(e => res(false))
|
||||||
|
})
|
||||||
|
Promise.all(data.delete.map(vc => deleteData(vc))).then(result => {
|
||||||
|
floSupernode.supernodeClientWS.send(`@${uid}#${gid}:${JSON.stringify(result)}`)
|
||||||
|
let vectorClocks = []
|
||||||
|
for(let i in result)
|
||||||
|
if(result[i]) vectorClocks.push(data.delete[i])
|
||||||
|
sendBackupDelete(data.application, vectorClocks, closeNode);
|
||||||
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<script id="compactIDB">
|
<script id="compactIDB">
|
||||||
@ -8642,9 +8657,7 @@ Bitcoin.Util = {
|
|||||||
searchData: function (obsName, options = {}, dbName = this.defaultDB) {
|
searchData: function (obsName, options = {}, dbName = this.defaultDB) {
|
||||||
options.lowerKey = options.atKey || options.lowerKey || 0
|
options.lowerKey = options.atKey || options.lowerKey || 0
|
||||||
options.upperKey = options.atKey || options.upperKey || false
|
options.upperKey = options.atKey || options.upperKey || false
|
||||||
options.patternEval = options.patternEval || ((k, v) => {
|
options.patternEval = options.patternEval || ((k, v) => true)
|
||||||
return true
|
|
||||||
})
|
|
||||||
options.lastOnly = options.lastOnly || false
|
options.lastOnly = options.lastOnly || false
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
this.openDB(dbName).then(db => {
|
this.openDB(dbName).then(db => {
|
||||||
@ -8657,12 +8670,16 @@ Bitcoin.Util = {
|
|||||||
curReq.onsuccess = (evt) => {
|
curReq.onsuccess = (evt) => {
|
||||||
var cursor = evt.target.result;
|
var cursor = evt.target.result;
|
||||||
if (cursor) {
|
if (cursor) {
|
||||||
if (options.patternEval(cursor.primaryKey, cursor.value)) {
|
try{
|
||||||
filteredResult[cursor.primaryKey] = cursor.value;
|
if(options.patternEval(cursor.primaryKey, cursor.value)){
|
||||||
options.lastOnly ? resolve(filteredResult) : cursor
|
filteredResult[cursor.primaryKey] = cursor.value;
|
||||||
.continue();
|
if(options.lastOnly)
|
||||||
} else
|
return resolve(filteredResult);
|
||||||
|
}
|
||||||
|
}catch(error) {}
|
||||||
|
finally{
|
||||||
cursor.continue();
|
cursor.continue();
|
||||||
|
}
|
||||||
} else
|
} else
|
||||||
resolve(filteredResult);
|
resolve(filteredResult);
|
||||||
}
|
}
|
||||||
@ -8722,7 +8739,7 @@ Bitcoin.Util = {
|
|||||||
getPrivateKeyCredentials().then(privKey => {
|
getPrivateKeyCredentials().then(privKey => {
|
||||||
myPrivKey = privKey
|
myPrivKey = privKey
|
||||||
myPubKey = floCrypto.getPubKeyHex(myPrivKey)
|
myPubKey = floCrypto.getPubKeyHex(myPrivKey)
|
||||||
myFloID = floCrypto.getFloIDfromPubkeyHex(myPubKey)
|
myFloID = floCrypto.getFloID(myPubKey)
|
||||||
getServerPasswordCredentials().then(pass => {
|
getServerPasswordCredentials().then(pass => {
|
||||||
serverPwd = pass
|
serverPwd = pass
|
||||||
resolve('Login Credentials loaded successful')
|
resolve('Login Credentials loaded successful')
|
||||||
@ -8743,7 +8760,7 @@ Bitcoin.Util = {
|
|||||||
var privKey = prompt("Enter Private Key: ")
|
var privKey = prompt("Enter Private Key: ")
|
||||||
if (!privKey)
|
if (!privKey)
|
||||||
return reject("Empty Private Key")
|
return reject("Empty Private Key")
|
||||||
var floID = floCrypto.getFloIDfromPubkeyHex(floCrypto.getPubKeyHex(privKey))
|
var floID = floCrypto.getFloID(floCrypto.getPubKeyHex(privKey))
|
||||||
console.log(floID)
|
console.log(floID)
|
||||||
alert(`Supernode floID: ${floID}`)
|
alert(`Supernode floID: ${floID}`)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -8863,18 +8880,21 @@ Bitcoin.Util = {
|
|||||||
}
|
}
|
||||||
compactIDB.setDefaultDB("SupernodeUtil")
|
compactIDB.setDefaultDB("SupernodeUtil")
|
||||||
compactIDB.initDB("SupernodeUtil", snObj)
|
compactIDB.initDB("SupernodeUtil", snObj)
|
||||||
.then(result => resolve("Initiated supernode configuration IDB"))
|
.then(result => resolve("Initiated supernode master IDB"))
|
||||||
.catch(error => reject(error));
|
.catch(error => reject(error));
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function initIndexedDBforSupernodeDataStorage(floID) {
|
function initIndexedDBforSupernodeDataStorage(floID) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
var indexesList = ["senderID", "receiverID", "pubKey", "message", "sign", "application", "type",
|
var indexesList = [
|
||||||
"comment"
|
"senderID", "receiverID", "application",
|
||||||
|
"type", "message", "time", "comment",
|
||||||
|
"pubKey", "sign"
|
||||||
];
|
];
|
||||||
|
let obsList = Object.keys(floGlobals.appList).push(floGlobals.defaultDisk)
|
||||||
var idbObj = {}
|
var idbObj = {}
|
||||||
for (let d of floGlobals.diskList) {
|
for (let d of obsList) {
|
||||||
idbObj[d] = {
|
idbObj[d] = {
|
||||||
indexes: {}
|
indexes: {}
|
||||||
}
|
}
|
||||||
@ -8892,37 +8912,36 @@ Bitcoin.Util = {
|
|||||||
refreshData.countdown = floGlobals.supernodeConfig.refreshDelay;
|
refreshData.countdown = floGlobals.supernodeConfig.refreshDelay;
|
||||||
refreshBlockchainData().then(result => {
|
refreshBlockchainData().then(result => {
|
||||||
console.log(result)
|
console.log(result)
|
||||||
autoDeleteStoredData()
|
diskCleanUp()
|
||||||
.then(result => console.log(result))
|
.then(result => console.log(result))
|
||||||
.catch(error => console.error(error))
|
.catch(error => console.error(error))
|
||||||
}).catch(error => console.error(error))
|
}).catch(error => console.error(error))
|
||||||
}
|
}
|
||||||
|
|
||||||
function autoDeleteStoredData() {
|
function diskCleanUp() {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
var deleteEnd = Date.now() - floGlobals.supernodeConfig.deleteDelay
|
const upperKey = Date.now() - floGlobals.supernodeConfig.deleteDelay
|
||||||
var deleteStart = 0;
|
const filterDelete = (obs, db, filter) => {
|
||||||
var promises = []
|
return new Promise((res, rej) => {
|
||||||
var filterOptions = {
|
compactIDB.searchData(obs, filter, db).then(results => {
|
||||||
lowerKey: `${deleteStart}`,
|
for(let k in results)
|
||||||
upperKey: `${deleteEnd}`,
|
compactIDB.removeData(obs, k, db)
|
||||||
}
|
res(true)
|
||||||
for (let i in floGlobals.storedList) {
|
})
|
||||||
var promise = new Promise((res, rej) => {
|
|
||||||
compactIDB.searchData(floGlobals.defaultDisk, filterOptions,
|
|
||||||
`SN_${floGlobals.storedList[i]}`).then(results => {
|
|
||||||
for (key in results)
|
|
||||||
if (!(results[key].application in floGlobals.applicationList) ||
|
|
||||||
floGlobals.applicationList[results[key].application] != results[
|
|
||||||
key].receiverID || !floGlobals.appSubAdmins[results[key]
|
|
||||||
.application].includes(results[key].senderID))
|
|
||||||
compactIDB.removeData(floGlobals.defaultDisk, key,
|
|
||||||
`SN_${floGlobals.storedList[i]}`)
|
|
||||||
res(`Auto-delete successful for SN_${floGlobals.storedList[i]} from ${deleteStart} to ${deleteEnd}`)
|
|
||||||
}).catch(error => rej(error))
|
|
||||||
})
|
})
|
||||||
promises.push(promise)
|
|
||||||
}
|
}
|
||||||
|
var promises = []
|
||||||
|
//For authorised-apps data
|
||||||
|
for(let app in floGlobals.appList){
|
||||||
|
const patternEval = (k, v) => (floGlobals.appList[app] != v.receiverID ||
|
||||||
|
(!floGlobals.appSubAdmins[app].includes(v.senderID) &&
|
||||||
|
floGlobals.appList[app] != v.senderID))
|
||||||
|
for(let sn of floGlobals.storedList)
|
||||||
|
promises.push(filterDelete(app, `SN_${sn}`, {upperKey, patternEval}))
|
||||||
|
}
|
||||||
|
//For all other-apps data
|
||||||
|
for(let sn of floGlobals.storedList)
|
||||||
|
promises.push(filterDelete(floGlobals.defaultDisk, `SN_${sn}`, {upperKey}))
|
||||||
Promise.all(promises).then(results => {
|
Promise.all(promises).then(results => {
|
||||||
resolve(`Auto-delete successful from ${deleteStart} to ${deleteEnd}`)
|
resolve(`Auto-delete successful from ${deleteStart} to ${deleteEnd}`)
|
||||||
}).catch(error => reject(error))
|
}).catch(error => reject(error))
|
||||||
@ -8952,35 +8971,57 @@ Bitcoin.Util = {
|
|||||||
pattern: "SuperNodeStorage"
|
pattern: "SuperNodeStorage"
|
||||||
}).then(result => {
|
}).then(result => {
|
||||||
let promises = []
|
let promises = []
|
||||||
let newNodes = []
|
let newNodes = [], delNodes = [];
|
||||||
let delNodes = []
|
let newApps = [], delApps = [];
|
||||||
|
|
||||||
for (var i = result.data.length - 1; i >= 0; i--) {
|
for (var i = result.data.length - 1; i >= 0; i--) {
|
||||||
var content = JSON.parse(result.data[i]).SuperNodeStorage;
|
var content = JSON.parse(result.data[i]).SuperNodeStorage;
|
||||||
for (sn in content.removeNodes) {
|
for (let sn of content.removeNodes) {
|
||||||
promises.push(compactIDB.removeData("supernodes", sn))
|
promises.push(compactIDB.removeData("supernodes", sn))
|
||||||
delNodes.push(sn)
|
if(newNodes.includes(sn)){
|
||||||
|
let i = newNodes.indexOf(sn)
|
||||||
|
newNodes.splice(i, 1)
|
||||||
|
} else delNodes.push(sn)
|
||||||
}
|
}
|
||||||
for (sn in content.addNodes) {
|
for (sn in content.newNodes) {
|
||||||
promises.push(compactIDB.writeData("supernodes", content
|
promises.push(compactIDB.writeData("supernodes", content
|
||||||
.addNodes[sn], sn))
|
.newNodes[sn], sn))
|
||||||
newNodes.push(sn)
|
if(delNodes.includes(sn)){
|
||||||
|
let i = delNodes.indexOf(sn)
|
||||||
|
delNodes.splice(i, 1)
|
||||||
|
} else newNodes.push(sn)
|
||||||
}
|
}
|
||||||
for (c in content.config)
|
for (c in content.config)
|
||||||
promises.push(compactIDB.writeData("config", content
|
promises.push(compactIDB.writeData("configuration", content
|
||||||
.config[c], c))
|
.config[c], c))
|
||||||
for (app in content.application)
|
for(let app of content.removeApps){
|
||||||
|
promises.push(compactIDB.removeData("applications", app))
|
||||||
|
if(newApps.includes(sn)){
|
||||||
|
let i = newApps.indexOf(sn)
|
||||||
|
newApps.splice(i, 1)
|
||||||
|
} else delApps.push(sn)
|
||||||
|
}
|
||||||
|
for (let app in content.addApps){
|
||||||
promises.push(compactIDB.writeData("applications",
|
promises.push(compactIDB.writeData("applications",
|
||||||
content.application[app], app))
|
content.application[app], app))
|
||||||
|
if(delApps.includes(sn)){
|
||||||
|
let i = delApps.indexOf(sn)
|
||||||
|
delApps.splice(i, 1)
|
||||||
|
} else newApps.push(sn)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
compactIDB.writeData("lastTx", result.totalTxs, floGlobals.SNStorageID);
|
compactIDB.writeData("lastTx", result.totalTxs, floGlobals.SNStorageID);
|
||||||
Promise.all(promises).then(results => {
|
Promise.all(promises).then(results => {
|
||||||
readDataFromIDB().then(result => {
|
readDataFromIDB().then(result => {
|
||||||
migrateData(newNodes, delNodes, flag).then(
|
updateAppDisk(newApps, delApps).then(result => {
|
||||||
result => {
|
console.log(result)
|
||||||
console.info(result)
|
migrateData(newNodes, delNodes, flag).then(
|
||||||
resolve(
|
result => {
|
||||||
"Read Supernode Data from Blockchain")
|
console.info(result)
|
||||||
}).catch(error => reject(error))
|
resolve(`Updated Supernode Configuration`)
|
||||||
|
}).catch(error => reject(error))
|
||||||
|
}).catch(error => reject(error))
|
||||||
}).catch(error => reject(error))
|
}).catch(error => reject(error))
|
||||||
}).catch(error => reject(error))
|
}).catch(error => reject(error))
|
||||||
}).catch(error => reject(error))
|
}).catch(error => reject(error))
|
||||||
@ -8992,8 +9033,8 @@ Bitcoin.Util = {
|
|||||||
|
|
||||||
const dataList = {
|
const dataList = {
|
||||||
supernodes: "supernodes",
|
supernodes: "supernodes",
|
||||||
supernodeConfig: "config",
|
supernodeConfig: "configuration",
|
||||||
applicationList: "applications"
|
appList: "applications"
|
||||||
}
|
}
|
||||||
|
|
||||||
const readIDB = function (name, obs) {
|
const readIDB = function (name, obs) {
|
||||||
@ -9018,13 +9059,13 @@ Bitcoin.Util = {
|
|||||||
function readAppSubAdminListFromAPI() {
|
function readAppSubAdminListFromAPI() {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
var promises = []
|
var promises = []
|
||||||
for (app in floGlobals.applicationList) {
|
for (app in floGlobals.appList) {
|
||||||
var promise = new Promise((res, rej) => {
|
var promise = new Promise((res, rej) => {
|
||||||
compactIDB.readData("appSubAdmins", app).then(subAdmins => {
|
compactIDB.readData("appSubAdmins", app).then(subAdmins => {
|
||||||
if (!Array.isArray(subAdmins)) subAdmins = []
|
if (!Array.isArray(subAdmins)) subAdmins = []
|
||||||
compactIDB.readData("lastTx", floGlobals.applicationList[app]).then(
|
compactIDB.readData("lastTx", floGlobals.appList[app]).then(
|
||||||
lastTx => {
|
lastTx => {
|
||||||
floBlockchainAPI.readData(floGlobals.applicationList[app], {
|
floBlockchainAPI.readData(floGlobals.appList[app], {
|
||||||
ignoreOld: lastTx,
|
ignoreOld: lastTx,
|
||||||
sentOnly: true,
|
sentOnly: true,
|
||||||
pattern: app
|
pattern: app
|
||||||
@ -9041,7 +9082,7 @@ Bitcoin.Util = {
|
|||||||
.addSubAdmin)
|
.addSubAdmin)
|
||||||
}
|
}
|
||||||
compactIDB.writeData("lastTx", result.totalTxs,
|
compactIDB.writeData("lastTx", result.totalTxs,
|
||||||
floGlobals.applicationList[app]);
|
floGlobals.appList[app]);
|
||||||
compactIDB.writeData("appSubAdmins", subAdmins,
|
compactIDB.writeData("appSubAdmins", subAdmins,
|
||||||
app)
|
app)
|
||||||
.then(result => res(app))
|
.then(result => res(app))
|
||||||
@ -9096,11 +9137,11 @@ Bitcoin.Util = {
|
|||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
console.log("Attempting to connect to backupNode:", nodeID)
|
console.log("Attempting to connect to backupNode:", nodeID)
|
||||||
floSupernode.connect(nodeID).then(node => {
|
floSupernode.connect(nodeID).then(node => {
|
||||||
node.wsConn.onmessage = (evt) => {
|
node.onmessage = (evt) => {
|
||||||
if (evt.data === "$-")
|
if (evt.data === "$-")
|
||||||
replaceOfflineBackupNode(nodeID);
|
replaceOfflineBackupNode(nodeID);
|
||||||
}
|
}
|
||||||
node.wsConn.onclose = (evt) => {
|
node.onclose = (evt) => {
|
||||||
let i = floGlobals.backupNodes.map(d => d.floID).indexOf(nodeID);
|
let i = floGlobals.backupNodes.map(d => d.floID).indexOf(nodeID);
|
||||||
if (i !== -1)
|
if (i !== -1)
|
||||||
initateBackupWebsocket(nodeID)
|
initateBackupWebsocket(nodeID)
|
||||||
@ -9108,8 +9149,8 @@ Bitcoin.Util = {
|
|||||||
.catch(error => replaceOfflineBackupNode(nodeID))
|
.catch(error => replaceOfflineBackupNode(nodeID))
|
||||||
}
|
}
|
||||||
backupNode = {
|
backupNode = {
|
||||||
floID: node.snID,
|
floID: nodeID,
|
||||||
wsConn: node.wsConn
|
wsConn: node
|
||||||
}
|
}
|
||||||
resolve(backupNode);
|
resolve(backupNode);
|
||||||
}).catch(error => reject(error))
|
}).catch(error => reject(error))
|
||||||
@ -9164,13 +9205,16 @@ Bitcoin.Util = {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function processDataFromSupernode(data) {
|
function processTaskFromSupernode(gid, uid, data) {
|
||||||
if (floCrypto.verifySign(JSON.stringify(data.sn_msg), data.sign, floGlobals.supernodes[data.from].pubKey)) {
|
if (floCrypto.verifySign(JSON.stringify(data.sn_msg), data.sign, floGlobals.supernodes[data.from].pubKey)) {
|
||||||
//Backup event messages (most crucial part)
|
//Backup event messages (most crucial part)
|
||||||
switch (data.sn_msg.type) {
|
switch (data.sn_msg.type) {
|
||||||
case "backupData":
|
case "backupData":
|
||||||
storeBackupData(data.sn_msg)
|
storeBackupData(data.sn_msg)
|
||||||
break;
|
break;
|
||||||
|
case "backupDelete":
|
||||||
|
deleteBackupData(data.sn_msg)
|
||||||
|
break;
|
||||||
case "supernodeUp":
|
case "supernodeUp":
|
||||||
nodeBackOnline(data.from)
|
nodeBackOnline(data.from)
|
||||||
break;
|
break;
|
||||||
@ -9198,6 +9242,8 @@ Bitcoin.Util = {
|
|||||||
case "dataRequest":
|
case "dataRequest":
|
||||||
sendStoredData(data.sn_msg.snID, data.from, data.sn_msg.lowerKey)
|
sendStoredData(data.sn_msg.snID, data.from, data.sn_msg.lowerKey)
|
||||||
break;
|
break;
|
||||||
|
case "dataSync":
|
||||||
|
dataSyncIndication(data.sn_msg.snID, data.sn_msg.mode, data.from)
|
||||||
default:
|
default:
|
||||||
console.log(data.sn_msg)
|
console.log(data.sn_msg)
|
||||||
}
|
}
|
||||||
@ -9221,7 +9267,7 @@ Bitcoin.Util = {
|
|||||||
sn_msg: sn_msg,
|
sn_msg: sn_msg,
|
||||||
sign: floCrypto.signData(JSON.stringify(sn_msg), myPrivKey)
|
sign: floCrypto.signData(JSON.stringify(sn_msg), myPrivKey)
|
||||||
}
|
}
|
||||||
node.wsConn.send(JSON.stringify(data));
|
node.send(JSON.stringify(data));
|
||||||
}).catch(error => console.error(error))
|
}).catch(error => console.error(error))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -9229,53 +9275,90 @@ Bitcoin.Util = {
|
|||||||
var sn_msg = {
|
var sn_msg = {
|
||||||
type: "backupData",
|
type: "backupData",
|
||||||
snID: snID,
|
snID: snID,
|
||||||
time: Data.now(),
|
time: Date.now(),
|
||||||
key: key,
|
key: key,
|
||||||
value: value
|
value: value
|
||||||
}
|
}
|
||||||
sendDataToBackupNodes(sn_msg);
|
sendDataToBackupNodes(sn_msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function sendBackupDelete(application, vectorClocks, snID){
|
||||||
|
var sn_msg = {
|
||||||
|
type: "backupDelete",
|
||||||
|
snID: snID,
|
||||||
|
time: Date.now(),
|
||||||
|
application: application,
|
||||||
|
vectorClocks: vectorClocks
|
||||||
|
}
|
||||||
|
sendDataToBackupNodes(sn_msg);
|
||||||
|
}
|
||||||
|
|
||||||
function sendStoredData(snID, receiver, lowerKey) {
|
function sendStoredData(snID, receiver, lowerKey) {
|
||||||
if (typeof lowerKey != "object") lowerKey = {};
|
if (typeof lowerKey != "object") lowerKey = {};
|
||||||
if (floGlobals.storedList.includes(snID)) {
|
const sendObs = (obs, node) => {
|
||||||
floSupernode.connect(receiver).then(node => {
|
return new Promise((res, rej) => {
|
||||||
floGlobals.diskList.forEach(obs => {
|
compactIDB.searchData(obs, {
|
||||||
compactIDB.searchData(obs, {
|
|
||||||
lowerKey: lowerKey[obs]
|
lowerKey: lowerKey[obs]
|
||||||
}, `SN_${snID}`).then(result => {
|
}`SN_${snID}`).then(result => {
|
||||||
for (let k in result) {
|
for (let k in result) {
|
||||||
var data = {
|
var data = {
|
||||||
from: myFloID,
|
from: myFloID,
|
||||||
sn_msg: {
|
sn_msg: {
|
||||||
type: "backupData",
|
type: "backupData",
|
||||||
snID: snID,
|
snID: snID,
|
||||||
time: Data.now(),
|
time: Date.now(),
|
||||||
key: k,
|
key: k,
|
||||||
value: result[k]
|
value: result[k]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
data.sign = floCrypto.signData(JSON.stringify(data.sn_msg),
|
data.sign = floCrypto.signData(JSON.stringify(data.sn_msg), myPrivKey)
|
||||||
myPrivKey)
|
node.send(JSON.stringify(data));
|
||||||
node.wsConn.send(JSON.stringify(data));
|
|
||||||
}
|
}
|
||||||
}).catch(error => console.error(error))
|
}).catch(error => console.error(error))
|
||||||
|
.finally(res(true))
|
||||||
|
})
|
||||||
|
};
|
||||||
|
if (floGlobals.storedList.includes(snID)) {
|
||||||
|
floSupernode.connect(receiver).then(node => {
|
||||||
|
let obsList = Object.keys(floGlobals.appList).push(floGlobals.defaultDisk)
|
||||||
|
console.info(`START: ${snID} data sync(send) to ${receiver}`)
|
||||||
|
var data = {
|
||||||
|
from: myFloID,
|
||||||
|
sn_msg: {
|
||||||
|
type: "dataSync",
|
||||||
|
mode: "START",
|
||||||
|
snID: snID,
|
||||||
|
time: Date.now()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
data.sign = floCrypto.signData(JSON.stringify(data.sn_msg), myPrivKey)
|
||||||
|
node.send(JSON.stringify(data));
|
||||||
|
Promise.all(obsList.map(o => sendObs(o, node))).then(result => {
|
||||||
|
data.sn_msg.mode = "END";
|
||||||
|
data.sn_msg.time = Date.now();
|
||||||
|
data.sign = floCrypto.signData(JSON.stringify(data.sn_msg), myPrivKey)
|
||||||
|
node.send(JSON.stringify(data));
|
||||||
|
console.info(`END: ${snID} data sync(send) to ${receiver}`)
|
||||||
})
|
})
|
||||||
}).catch(error => console.error(error))
|
}).catch(error => console.error(error))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function dataSyncIndication(snID, mode, from) {
|
||||||
|
console.info(`${mode}: ${snID} data sync(receive) form ${from}`);
|
||||||
|
}
|
||||||
|
|
||||||
function requestBackupData(from, snID) {
|
function requestBackupData(from, snID) {
|
||||||
var promises = []
|
var promises = []
|
||||||
for (let i in floGlobals.diskList)
|
let obsList = Object.keys(floGlobals.appList).push(floGlobals.defaultDisk)
|
||||||
promises[i] = compactIDB.searchData(floGlobals.diskList[i], {
|
for (let i in obsList)
|
||||||
|
promises[i] = compactIDB.searchData(obsList[i], {
|
||||||
lastOnly: true
|
lastOnly: true
|
||||||
}, `SN_${snID}`)
|
}, `SN_${snID}`)
|
||||||
Promise.all(promises).then(results => {
|
Promise.all(promises).then(results => {
|
||||||
var lowerKey = {}
|
var lowerKey = {}
|
||||||
for (let i in results)
|
for (let i in results)
|
||||||
for (let key in results[i])
|
lowerKey[obsList[i]] = Object.keys(results[i]).sort().pop()
|
||||||
lowerKey[floGlobals.diskList[i]] = key
|
|
||||||
var sn_msg = {
|
var sn_msg = {
|
||||||
type: "dataRequest",
|
type: "dataRequest",
|
||||||
snID: snID,
|
snID: snID,
|
||||||
@ -9290,13 +9373,19 @@ Bitcoin.Util = {
|
|||||||
if (floGlobals.storedList.includes(data.snID) &&
|
if (floGlobals.storedList.includes(data.snID) &&
|
||||||
floSupernode.kBucket.closestNode(data.value.receiverID) === data.snID) {
|
floSupernode.kBucket.closestNode(data.value.receiverID) === data.snID) {
|
||||||
compactIDB.addData(
|
compactIDB.addData(
|
||||||
floGlobals.diskList.includes(data.value.application) ? data.value.application : floGlobals
|
data.value.application in floGlobals.appList ? data.value.application :
|
||||||
.defaultDisk,
|
floGlobals.defaultDisk, data.value, data.key, `SN_${data.snID}`
|
||||||
data.value, data.key, `SN_${data.snID}`
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function deleteBackupData(data) {
|
||||||
|
if (floGlobals.storedList.includes(data.snID)){
|
||||||
|
let disk = data.application in floGlobals.appList ? data.application : floGlobals.defaultDisk;
|
||||||
|
data.vectorClocks.forEach(vc => compactIDB.removeData(disk, vc, `SN_${data.snID}`))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function indicateSupernodeUp() {
|
function indicateSupernodeUp() {
|
||||||
console.log("Indicating supernode is up")
|
console.log("Indicating supernode is up")
|
||||||
if (floGlobals.backupNodes.length) {
|
if (floGlobals.backupNodes.length) {
|
||||||
@ -9314,9 +9403,9 @@ Bitcoin.Util = {
|
|||||||
if (sn !== myFloID) {
|
if (sn !== myFloID) {
|
||||||
floSupernode.connect(sn)
|
floSupernode.connect(sn)
|
||||||
.then(node => {
|
.then(node => {
|
||||||
node.wsConn.send(dataStr);
|
node.send(dataStr);
|
||||||
console.info('Indicated:' + sn)
|
console.info('Indicated:' + sn)
|
||||||
node.wsConn.close();
|
node.close();
|
||||||
}).catch(error => console.error(error))
|
}).catch(error => console.error(error))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -9358,10 +9447,10 @@ Bitcoin.Util = {
|
|||||||
data.sn_msg.snID = sn;
|
data.sn_msg.snID = sn;
|
||||||
data.sn_msg.type = "startBackupStore";
|
data.sn_msg.type = "startBackupStore";
|
||||||
data.sign = floCrypto.signData(JSON.stringify(data.sn_msg), myPrivKey);
|
data.sign = floCrypto.signData(JSON.stringify(data.sn_msg), myPrivKey);
|
||||||
node.wsConn.send(JSON.stringify(data))
|
node.send(JSON.stringify(data))
|
||||||
data.sn_msg.type = "startBackupServe";
|
data.sn_msg.type = "startBackupServe";
|
||||||
data.sign = floCrypto.signData(JSON.stringify(data.sn_msg), myPrivKey);
|
data.sign = floCrypto.signData(JSON.stringify(data.sn_msg), myPrivKey);
|
||||||
node.wsConn.send(JSON.stringify(data))
|
node.send(JSON.stringify(data))
|
||||||
stopBackupServe(sn);
|
stopBackupServe(sn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -9391,7 +9480,7 @@ Bitcoin.Util = {
|
|||||||
for (let sn of floGlobals.serveList) {
|
for (let sn of floGlobals.serveList) {
|
||||||
data.sn_msg.snID = sn;
|
data.sn_msg.snID = sn;
|
||||||
data.sign = floCrypto.signData(JSON.stringify(data.sn_msg), myPrivKey);
|
data.sign = floCrypto.signData(JSON.stringify(data.sn_msg), myPrivKey);
|
||||||
node.wsConn.send(JSON.stringify(data))
|
node.send(JSON.stringify(data))
|
||||||
}
|
}
|
||||||
}).catch(error => console.error(error))
|
}).catch(error => console.error(error))
|
||||||
}
|
}
|
||||||
@ -9420,7 +9509,7 @@ Bitcoin.Util = {
|
|||||||
data.sn_msg.snID = sn;
|
data.sn_msg.snID = sn;
|
||||||
data.sn_msg.type = "startBackupStore";
|
data.sn_msg.type = "startBackupStore";
|
||||||
data.sign = floCrypto.signData(JSON.stringify(data.sn_msg), myPrivKey);
|
data.sign = floCrypto.signData(JSON.stringify(data.sn_msg), myPrivKey);
|
||||||
node.wsConn.send(JSON.stringify(data)) //start for connected backup node
|
node.send(JSON.stringify(data)) //start for connected backup node
|
||||||
data.sn_msg.type = "stopBackupStore";
|
data.sn_msg.type = "stopBackupStore";
|
||||||
data.sign = floCrypto.signData(JSON.stringify(data.sn_msg), myPrivKey);
|
data.sign = floCrypto.signData(JSON.stringify(data.sn_msg), myPrivKey);
|
||||||
rmNode.wsConn.send(JSON.stringify(data)) //stop for removed backup node
|
rmNode.wsConn.send(JSON.stringify(data)) //stop for removed backup node
|
||||||
@ -9543,8 +9632,8 @@ Bitcoin.Util = {
|
|||||||
if (sn !== myFloID) {
|
if (sn !== myFloID) {
|
||||||
floSupernode.connect(sn)
|
floSupernode.connect(sn)
|
||||||
.then(node => {
|
.then(node => {
|
||||||
node.wsConn.send(dataStr);
|
node.send(dataStr);
|
||||||
node.wsConn.close();
|
node.close();
|
||||||
}).catch(error => console.error(error))
|
}).catch(error => console.error(error))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -9572,7 +9661,7 @@ Bitcoin.Util = {
|
|||||||
sn_msg: {
|
sn_msg: {
|
||||||
type: "backupData",
|
type: "backupData",
|
||||||
snID: toID,
|
snID: toID,
|
||||||
time: Data.now(),
|
time: Date.now(),
|
||||||
key: k,
|
key: k,
|
||||||
value: result[k]
|
value: result[k]
|
||||||
}
|
}
|
||||||
@ -9580,12 +9669,12 @@ Bitcoin.Util = {
|
|||||||
data.sign = floCrypto.signData(JSON.stringify(data
|
data.sign = floCrypto.signData(JSON.stringify(data
|
||||||
.sn_msg),
|
.sn_msg),
|
||||||
myPrivKey)
|
myPrivKey)
|
||||||
node.wsConn.send(JSON.stringify(data));
|
node.send(JSON.stringify(data));
|
||||||
promises.push(compactIDB.removeData(obs, k,
|
promises.push(compactIDB.removeData(obs, k,
|
||||||
`SN_${snID}`))
|
`SN_${snID}`))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Promise.all(promises).then(r => {}).catch(e => {})
|
Promise.all(promises).then(r => null).catch(e => null)
|
||||||
.finally(_ => res(true))
|
.finally(_ => res(true))
|
||||||
}).catch(error => console.error(error))
|
}).catch(error => console.error(error))
|
||||||
})
|
})
|
||||||
@ -9600,14 +9689,15 @@ Bitcoin.Util = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
data.sign = floCrypto.signData(JSON.stringify(data.sn_msg), myPrivKey)
|
data.sign = floCrypto.signData(JSON.stringify(data.sn_msg), myPrivKey)
|
||||||
node.wsConn.send(JSON.stringify(data));
|
node.send(JSON.stringify(data));
|
||||||
data.sn_msg.type = "startBackupServe";
|
data.sn_msg.type = "startBackupServe";
|
||||||
data.sign = floCrypto.signData(JSON.stringify(data.sn_msg), myPrivKey)
|
data.sign = floCrypto.signData(JSON.stringify(data.sn_msg), myPrivKey)
|
||||||
node.wsConn.send(JSON.stringify(data));
|
node.send(JSON.stringify(data));
|
||||||
await sleep(5000);
|
await sleep(5000);
|
||||||
//process all data for sending
|
//process all data for sending
|
||||||
Promise.all(floGlobals.diskList.map(obs => transferObs(obs))).then(result => {
|
let obsList = Object.keys(floGlobals.appList).push(floGlobals.defaultDisk)
|
||||||
node.wsConn.close();
|
Promise.all(obsList.map(obs => transferObs(obs))).then(result => {
|
||||||
|
node.close();
|
||||||
//initiate reconstruct phase
|
//initiate reconstruct phase
|
||||||
let sn_msg = {
|
let sn_msg = {
|
||||||
type: "reconstructBackupStore",
|
type: "reconstructBackupStore",
|
||||||
@ -9635,7 +9725,7 @@ Bitcoin.Util = {
|
|||||||
sn_msg: {
|
sn_msg: {
|
||||||
type: "backupData",
|
type: "backupData",
|
||||||
snID: prev,
|
snID: prev,
|
||||||
time: Data.now(),
|
time: Date.now(),
|
||||||
key: k,
|
key: k,
|
||||||
value: result[k]
|
value: result[k]
|
||||||
}
|
}
|
||||||
@ -9643,12 +9733,12 @@ Bitcoin.Util = {
|
|||||||
data.sign = floCrypto.signData(JSON.stringify(data
|
data.sign = floCrypto.signData(JSON.stringify(data
|
||||||
.sn_msg),
|
.sn_msg),
|
||||||
myPrivKey)
|
myPrivKey)
|
||||||
node.wsConn.send(JSON.stringify(data));
|
node.send(JSON.stringify(data));
|
||||||
} else
|
} else
|
||||||
promises.push(compactIDB.addData(obs, result[k], k,
|
promises.push(compactIDB.addData(obs, result[k], k,
|
||||||
`SN_${next}`))
|
`SN_${next}`))
|
||||||
}
|
}
|
||||||
Promise.all(promises).then(r => {}).catch(e => {})
|
Promise.all(promises).then(r => null).catch(e => null)
|
||||||
.finally(_ => res(true))
|
.finally(_ => res(true))
|
||||||
}).catch(error => console.error(error))
|
}).catch(error => console.error(error))
|
||||||
})
|
})
|
||||||
@ -9663,13 +9753,14 @@ Bitcoin.Util = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
data.sign = floCrypto.signData(JSON.stringify(data.sn_msg), myPrivKey)
|
data.sign = floCrypto.signData(JSON.stringify(data.sn_msg), myPrivKey)
|
||||||
node.wsConn.send(JSON.stringify(data));
|
node.send(JSON.stringify(data));
|
||||||
data.sn_msg.type = "startBackupServe";
|
data.sn_msg.type = "startBackupServe";
|
||||||
data.sign = floCrypto.signData(JSON.stringify(data.sn_msg), myPrivKey)
|
data.sign = floCrypto.signData(JSON.stringify(data.sn_msg), myPrivKey)
|
||||||
node.wsConn.send(JSON.stringify(data));
|
node.send(JSON.stringify(data));
|
||||||
await sleep(5000);
|
await sleep(5000);
|
||||||
//process all data for split (and send data to prev if needed)
|
//process all data for split (and send data to prev if needed)
|
||||||
Promise.all(floGlobals.diskList.map(obs => splitObs(obs))).then(result => {
|
let obsList = Object.keys(floGlobals.appList).push(floGlobals.defaultDisk)
|
||||||
|
Promise.all(obsList.map(obs => splitObs(obs))).then(result => {
|
||||||
//initiate reconstruct phase
|
//initiate reconstruct phase
|
||||||
let sn_msg = {
|
let sn_msg = {
|
||||||
type: "reconstructBackupStore",
|
type: "reconstructBackupStore",
|
||||||
@ -9687,14 +9778,15 @@ Bitcoin.Util = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
sn_data.sign = floCrypto.signData(JSON.stringify(sn_data.sn_msg), myPrivKey)
|
sn_data.sign = floCrypto.signData(JSON.stringify(sn_data.sn_msg), myPrivKey)
|
||||||
node.wsConn.send(JSON.stringify(sn_data));
|
node.send(JSON.stringify(sn_data));
|
||||||
node.wsConn.close();
|
node.close();
|
||||||
})
|
})
|
||||||
}).catch(error => console.error(error))
|
}).catch(error => console.error(error))
|
||||||
}
|
}
|
||||||
|
|
||||||
function reconstructBackupStore(snID, from) {
|
function reconstructBackupStore(snID, from) {
|
||||||
Promise.all(floGlobals.diskList.map(obs => compactIDB.clearData(obs, `SN_${snID}`)))
|
let obsList = Object.keys(floGlobals.appList).push(floGlobals.defaultDisk)
|
||||||
|
Promise.all(obsList.map(obs => compactIDB.clearData(obs, `SN_${snID}`)))
|
||||||
.then(results => {
|
.then(results => {
|
||||||
var sn_msg = {
|
var sn_msg = {
|
||||||
type: "dataRequest",
|
type: "dataRequest",
|
||||||
@ -9717,5 +9809,60 @@ Bitcoin.Util = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
<script>
|
||||||
|
function updateAppDisk(newApps, delApps) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
if(!newApps.length && !delApps.length)
|
||||||
|
return resolve('No need for app disk update')
|
||||||
|
const transfer = (from, to, filter, db) => {
|
||||||
|
return new Promise((res, rej) => {
|
||||||
|
(filter ? compactIDB.searchData(from, filter, db) :
|
||||||
|
compactIDB.readAllData(from, db)).then(results => {
|
||||||
|
let promises = [];
|
||||||
|
for (let k in result) {
|
||||||
|
promises.push(compactIDB.writeData(to, result[k], k, db))
|
||||||
|
promises.push(compactIDB.removeData(from, k, db))
|
||||||
|
}
|
||||||
|
Promise.all(promises).then(r => null).catch(e => null)
|
||||||
|
.finally(_ => res(true))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
};
|
||||||
|
const transferObs = (from, to, filter) =>
|
||||||
|
Promise.all(floGlobals.storedList.map(sn => transfer(from, to, filter, `SN_${sn}`)));
|
||||||
|
const reInitateDB = () =>
|
||||||
|
Promise.all(floGlobals.storedList.map(sn => initIndexedDBforSupernodeDataStorage(sn)));
|
||||||
|
const unauthoriseApps = (apps) =>
|
||||||
|
Promise.all(apps.map(a => transferObs(a, floGlobals.defaultDisk, null))
|
||||||
|
.push(rmSubAdminList(apps)));
|
||||||
|
const authoriseApps = (apps) =>
|
||||||
|
Promise.all(apps.map(a => transferObs(floGlobals.defaultDisk, a, {
|
||||||
|
patternEval: ((k, v) => v.application === a)
|
||||||
|
})));
|
||||||
|
const rmSubAdminList = (apps) => {
|
||||||
|
let promises = [];
|
||||||
|
apps.forEach(a => {
|
||||||
|
promises.push(compactIDB.removeData("lastTx", floGlobals.appList[a]))
|
||||||
|
promises.push(compactIDB.removeData("appSubAdmins", a))
|
||||||
|
});
|
||||||
|
return Promises.all(promises);
|
||||||
|
}
|
||||||
|
|
||||||
|
unauthoriseApps(delApps).then(result => {
|
||||||
|
console.info(`Unauthorised apps: `, delApps);
|
||||||
|
reInitateDB().then(result => {
|
||||||
|
console.log('Re-initated Database');
|
||||||
|
authoriseApps(newApps).then(result => {
|
||||||
|
console.info(`Authorised apps: `, newApps)
|
||||||
|
resolve('Update app disk completed')
|
||||||
|
})
|
||||||
|
}).catch(error => {
|
||||||
|
console.error(error)
|
||||||
|
reject('Database re-initation failed')
|
||||||
|
})
|
||||||
|
});
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user