diff --git a/supernode/index.html b/supernode/index.html
index b3d1e7d..592354e 100644
--- a/supernode/index.html
+++ b/supernode/index.html
@@ -9636,26266 +9636,7 @@
}
-
-
+
@@ -36349,10 +10090,10 @@
`tradableAsset1=BTC,FLO,BTC_TEST,FLO_TEST#!#tradableAsset2=INR,USD,BTC,FLO,BTC_TEST,FLO_TEST,
#!#supernodes=127.0.0.1,212.88.88.2#!#MASTER_NODE=023B9F60692A17FAC805D012C5C8ADA3DD19A980A3C5F0D8A5B3500CC54D6E8B75
#!#MASTER_RECEIVING_ADDRESS=oVRq2nka1GtALQT8pbuLHAGjqAQ7PAo6uy#!#validTradingAmount=10000,50000,100000,#!#btcTradeMargin=5000
- #!#supernodesPubKeys=02598B9BDBC74C4364EB9EB2D0B2E70B27FF9B28B59F708F8C3B41B351C1DE2F8A,03998939E5E2F93A0648B16F481BE4A9299BCBF0CFAA7F25C716D9A5C80B20DFFC,
+ #!#supernodesPubKeys=03692E641440795B6279F548C7156775EB624CC8A27FDA94C5E3B8945EC94DE1F1,02F22822D5E887ABBDA3D5E3A51574C547FEAAC00BF01185AA56858D4C9B00334F,
#!#externalFiles={"d3js":"58f54395efa8346e8e94d12609770f66b916897e7f4e05f6c98780cffa5c70a3"},
- #!#ShamirsMaxShares=8#!#supernodeSeeds={"ranchimall1":{"ip":"ranchimall1.duckdns.org","port":"9002","kbucketId":"oJeYebjgWV4Hszj5oP7sfXcj1U98P5M6q4"},
- "ranchimall2":{"ip":"ranchimall1.duckdns.org","port":"9003","kbucketId":"ofo48uKuhoepiv6k7QbDgsPxrFUMipqmUh"}}`;
+ #!#ShamirsMaxShares=8#!#supernodeSeeds={"ranchimall1":{"ip":"ranchimall1.duckdns.org","port":"9002","kbucketId":"oURVEZQ6sPT8mwDVTGiBVPqJYqjctXYfF3"},
+ "ranchimall2":{"ip":"ranchimall1.duckdns.org","port":"9003","kbucketId":"oapBngvTbcNCSfQfzJ9RS1QYfb4ppSQ9KQ"}}`;
let floAssetsArray = RMAssets.split('#!#');
@@ -36544,40 +10285,40 @@
let pubKeyBytes = Crypto.util.hexToBytes(pubKey);
return Crypto.util.bytesToBase64(pubKeyBytes);
},
- getSupernodeSeed: function (flo_addr, flo_pub_key) {
+ updateClosestSupernodeSeeds: function(flo_addr) {
+ return new Promise(async (resolve, reject) => {
+ let nearestSupernodeAddresslist = await localbitcoinplusplus.kademlia.determineClosestSupernode(flo_addr);
+ await removeAllinDB('myClosestSupernodes');
+ nearestSupernodeAddresslist.map((nearestSupernodeAddress, index)=>{
+ updateinDB('myClosestSupernodes', {
+ id: index+1,
+ ip: nearestSupernodeAddress.ip,
+ port: nearestSupernodeAddress.port,
+ trader_flo_address: nearestSupernodeAddress.kbucketId
+ }).then(res=>showMessage(`INFO: Updated closest supernodes list successfully.`));
+ });
+ });
+ },
+ getSupernodeSeed: function (flo_addr) {
return new Promise(async (resolve, reject) => {
- let nearestSupernodeAddress = await localbitcoinplusplus.kademlia.determineMySupernode(flo_addr);
-
- const contactId = localbitcoinplusplus.kademlia.newBase64DiscoverId(flo_pub_key);
-
- const seedContactArray = {
- id: contactId, // Base64 encoding
- data: {
- publicKey: flo_pub_key,
- floId: flo_addr,
- msg: `Hello from ${flo_addr}!`
- },
- };
-
- seedContactArray.transport = {
- host: nearestSupernodeAddress[0].ip,
- port: nearestSupernodeAddress[0].port,
- id: nearestSupernodeAddress[0].kbucketId
+ let nearestSupernodeAddresslist = await readAllDB('myClosestSupernodes');
+ if (nearestSupernodeAddresslist.length<1) {
+ nearestSupernodeAddresslist = await this.updateClosestSupernodeSeeds(flo_addr);
}
+ //let supernodeAddressUrls = [];
- const nodeDiscoveryOptions = {
- seeds: seedContactArray
- }
-
- const kdiscover = new tristanDiscover(nodeDiscoveryOptions);
+ // nearestSupernodeAddresslist.map(nearestSupernodeAddress=>{
+ // try {
+ // supernodeAddressUrls.push(`ws://${nearestSupernodeAddress.ip}:${nearestSupernodeAddress.port}`);
+ // return supernodeAddressUrls;
+ // } catch (error) {
+ // reject(error);
+ // }
+ // });
- try {
- let supernodeAddressUrl = `ws://${kdiscover.seeds.transport.host}:${kdiscover.seeds.transport.port}`;
- resolve(supernodeAddressUrl);
- } catch (error) {
- reject(error);
- }
+ //resolve(supernodeAddressUrls);
+ resolve(nearestSupernodeAddresslist);
});
},
isNodePresentInMyKbucket: function(flo_id) {
@@ -36591,7 +10332,7 @@
}
});
},
- determineMySupernode: function(flo_addr) {
+ determineClosestSupernode: function(flo_addr) {
return new Promise((resolve, reject)=>{
const supernodeSeeds = localbitcoinplusplus.master_configurations.supernodeSeeds;
if (typeof supernodeSeeds !== "object") reject(
@@ -36606,20 +10347,16 @@
let currentNodeBucketId = localbitcoinplusplus.kademlia
.floIdToKbucketId("FLO_TEST", flo_addr);
- let nearestSupernode = KBucket.closest(currentNodeBucketId);
-
- let supernodeSeedsArray = Object.values(supernodeSeedsObj).map(seed=>seed.kbucketId);
-
- nearestSupernodeAddressId = nearestSupernode
- .filter(suSeed=>supernodeSeedsArray.includes(suSeed.data.id))
- .filter(suSeed=>suSeed.data.id !== flo_addr)
- .map(suSeed=>suSeed.data);
-
- let nearestSupernodeAddress = Object.values(supernodeSeedsObj)
- .filter(seed=>seed.kbucketId==nearestSupernodeAddressId[0].id)
+ let nearestSupernode = KBucket.closest(currentNodeBucketId, 4);
+ let nearestSupernodeIds = nearestSupernode.map(f=>f.data.id);
+ let supernodeSeedsArray = Object.values(supernodeSeedsObj)
+ .filter(seed=>nearestSupernodeIds.includes(seed.kbucketId))
+ .sort(function(a, b){
+ return nearestSupernodeIds.indexOf(a.kbucketId) - nearestSupernodeIds.indexOf(b.kbucketId);
+ });
- if (nearestSupernodeAddress.length>0) {
- resolve(nearestSupernodeAddress);
+ if (supernodeSeedsArray.length>0) {
+ resolve(supernodeSeedsArray);
} else {
reject(false);
}
@@ -36768,14 +10505,14 @@
// This function is only useful when sender and receiver are both online.
// If receiver is not online he might never get the message
- messageBroadcasting: function (message, flo_id) {
+ messageBroadcasting: function (message, flo_id, rpc_subject="messageBroadcasting") {
readDB('userPublicData', flo_id).then((res) => {
pubKey = res.trader_flo_pubKey;
let foo = localbitcoinplusplus.encrypt.encryptMessage(message, pubKey);
const RM_RPC = new localbitcoinplusplus.rpc;
let bar = RM_RPC
.send_rpc
- .call(this, "messageBroadcasting", foo);
+ .call(this, rpc_subject, foo);
doSend(bar);
});
},
@@ -39676,9 +13413,12 @@
function kickInit() {
output = document.getElementById("output_div");
const RM_WALLET = new localbitcoinplusplus.wallets;
+ const BACKUP_DB = {};
+ const backUpSupernodesWS = localbitcoinplusplus.backupWS = [];
return new Promise(resolve => {
readDB("localbitcoinUser", "00-01").then(async function (idbData) {
+
if (typeof idbData.myLocalFLOPublicKey == "undefined" || idbData.myLocalFLOPublicKey
.trim() == '') {
let user_pvt_key = prompt(
@@ -39696,10 +13436,9 @@
updateinDB("localbitcoinUser", localbitcoinplusplusObj, "00-01");
wsUri = await localbitcoinplusplus.kademlia.getSupernodeSeed(
- localbitcoinplusplusObj.myLocalFLOAddress,
- localbitcoinplusplusObj.myLocalFLOPublicKey);
+ localbitcoinplusplusObj.myLocalFLOAddress);
- await startWebSocket(wsUri);
+ await startWebSocket(`ws://${wsUri[0].ip}:${wsUri[0].port}`);
// Add new user node in Kademlia
addDB('kBucketStore', {
@@ -39723,6 +13462,22 @@
RM_WALLET.distributeShamirsSecretShares(newKeys.privateKeyWIF)
.then(() => privateKeyBuilder());
+ // Connect with backup supernodes
+ wsUri.filter((uri, index)=>{
+ if(index>0 && localbitcoinplusplus.master_configurations.supernodesPubKeys
+ .includes(localbitcoinplusplusObj.myLocalFLOPublicKey)) {
+ return uri;
+ }
+ }).map((uri, index)=>{
+ console.log(uri);
+ backUpSupernodesWS[index] = new backupSupernodesWebSocketObject(`ws://${uri.ip}:${uri.port}`);
+ backUpSupernodesWS[index].connectWS();
+
+ let dbname = `su_backup_${uri.trader_flo_address}`;
+ BACKUP_DB[uri.trader_flo_address] = new newBackupDB(dbname);
+ BACKUP_DB[uri.trader_flo_address].createNewDB();
+ });
+
resolve(true);
return;
@@ -39733,15 +13488,61 @@
}
}
- wsUri = await localbitcoinplusplus.kademlia.getSupernodeSeed(idbData.myLocalFLOAddress,
- idbData.myLocalFLOPublicKey);
+ wsUri = await localbitcoinplusplus.kademlia.getSupernodeSeed(idbData.myLocalFLOAddress);
+
+ // Connect with primary supernodes
+ startWebSocket(`ws://${wsUri[0].ip}:${wsUri[0].port}`);
- resolve(startWebSocket(wsUri));
+ // Connect with backup supernodes
+ wsUri.filter((uri, index)=>{
+ if(index>0 && localbitcoinplusplus.master_configurations.supernodesPubKeys
+ .includes(idbData.myLocalFLOPublicKey)) {
+ return uri;
+ }
+ }).map((uri, index)=>{
+ console.log(uri);
+ backUpSupernodesWS[index] = new backupSupernodesWebSocketObject(`ws://${uri.ip}:${uri.port}`);
+ backUpSupernodesWS[index].connectWS();
+
+ let dbname = `su_backup_${uri.trader_flo_address}`;
+ BACKUP_DB[uri.trader_flo_address] = new newBackupDB(dbname);
+ BACKUP_DB[uri.trader_flo_address].createNewDB();
+ });
+
+ resolve(true);
});
});
}
+ const backupSupernodesWebSocketObject = localbitcoinplusplus.backupWS = function(ws_url) {
+ this.ws_url = ws_url;
+ this.ws_connection = null;
+ }
+ backupSupernodesWebSocketObject.prototype = {
+
+ handle_backup_server_messages(evt) {
+ var response = evt.data;
+ console.log('backup response: '+response);
+ },
+
+ connectWS() {
+ this.ws_connection = new WebSocket(this.ws_url);
+ this.ws_connection.onopen = function (evt) {
+ showMessage(`Connected to backup Supernode sever: ${this.ws_url}.`);
+ }.bind(this);
+ this.ws_connection.onclose = function (evt) {
+ showMessage(`Disconnected to backup Supernode sever: ${this.ws_url}.`);
+ }.bind(this);
+ this.ws_connection.onmessage = function (evt) {
+ this.handle_backup_server_messages(evt);
+ }.bind(this);
+ this.ws_connection.onerror = function (evt) {
+ console.error(evt);
+ };
+ },
+ }
+
function startWebSocket(wsUri) {
return new Promise((resolve, reject) => {
websocket = new WebSocket(wsUri);
@@ -39763,12 +13564,12 @@
function onOpen(evt) {
loadExternalFiles();
dataBaseUIOperations();
- showMessage(`Connected successfully to Supernode: ${wsUri}.`);
+ showMessage(`Connected successfully to Supernode: ws://${wsUri[0].ip}.${wsUri[0].port}`);
writeToScreen("CONNECTED");
}
function onClose(evt) {
- showMessage(`Disconnected to Supernode sever: ${wsUri}.`);
+ showMessage(`Disconnected to Supernode sever: ws://${wsUri[0].ip}.${wsUri[0].port}`);
writeToScreen("DISCONNECTED");
}
@@ -40035,7 +13836,7 @@
if (typeof res_obj.params == "object" && typeof res_obj.params[0] == "object") {
readDB("supernode_private_key_chunks", res_obj.params[0].chunk_val)
.then(function (res) {
- if (typeof res=="string") {
+ if (typeof res=="object") {
let send_pvtkey_req = RM_RPC
.send_rpc
.call(this, "retrieve_shamirs_secret_supernode_pvtkey", {
@@ -40044,11 +13845,6 @@
doSend(send_pvtkey_req);
return;
}
- // Supernode does not have this user's private key shares. Request shares from others
- let currentNodeBucketId = localbitcoinplusplus.kademlia
- .floIdToKbucketId("FLO_TEST", flo_addr);
- let nearestSupernode = KBucket.closest(currentNodeBucketId, 1);
-
});
}
break;
@@ -40471,6 +14267,92 @@
}
break;
+ case "supernode_to_supernode_backup_request":
+
+ // RM_RPC.filter_legit_requests(function (is_valid_request) {
+ // if (is_valid_request === true) {
+ let data = res_obj.params[0];
+ const tableArray = ["deposit", "withdraw_cash", "withdraw_btc",
+ "crypto_balances", "cash_balances", "userPublicData"
+ ];
+ localbitcoinplusplus.actions.get_sharable_db_data(tableArray)
+ .then(function (su_db_data) {
+ su_db_data.trader_flo_address = data.trader_flo_address;
+
+ let msg_sha256 = Crypto.SHA256(JSON.stringify(su_db_data));
+
+ localbitcoinplusplus.encrypt
+ .messageBroadcasting(msg_sha256, data.trader_flo_address,
+ "supernode_to_supernode_backup_response");
+
+ // if (typeof su_db_data == "object") {
+ // su_db_data.trader_flo_address = data.trader_flo_address;
+ // let server_sync_response = RM_RPC
+ // .send_rpc
+ // .call(this, "supernode_to_supernode_backup_response",
+ // su_db_data);
+ // doSend(server_sync_response);
+ // }
+ })
+ // }
+ // })
+ break;
+
+ case "supernode_to_supernode_backup_response":
+ console.log(res_obj.params[0]);
+
+ if (typeof res_obj.params == "object" && typeof res_obj.params[0] == "object") {
+ let su_db_data = res_obj.params[0];
+
+ let db_data = localbitcoinplusplus.encrypt.decryptMessage(su_db_data.secret, su_db_data.senderPublicKeyString);
+ console.log(db_data);
+ return;
+
+ if (typeof localbitcoinplusplus.wallets.my_local_flo_address !== "string" ||
+ su_db_data.trader_flo_address !== localbitcoinplusplus.wallets.my_local_flo_address
+ ) return false;
+
+ // const BACKUP_DB = new newBackupDB();
+ // BACKUP_DB.createNewDB();
+
+ (async function () {
+ for (let tableStoreName in su_db_data) {
+ // skip loop if the property is from prototype
+ if (tableStoreName == 'trader_flo_address' || !su_db_data.hasOwnProperty(
+ tableStoreName)) continue;
+
+ try {
+ let obj = su_db_data[tableStoreName];
+ if (["crypto_balances", "cash_balances", "userPublicData"].includes(
+ tableStoreName)) {
+ if (obj.length > 0) {
+ for (var prop in obj) {
+ if (!obj.hasOwnProperty(prop)) continue;
+ await BACKUP_DB.backup_updateinDB(tableStoreName, obj[prop], obj[
+ prop].trader_flo_address);
+ }
+ }
+ } else {
+ let resdbdata = await BACKUP_DB.backup_removeAllinDB(tableStoreName);
+ if (resdbdata !== false) {
+ if (obj.length > 0) {
+ for (var prop in obj) {
+ if (!obj.hasOwnProperty(prop)) continue;
+ await BACKUP_DB.backup_addDB(resdbdata, obj[prop]);
+ }
+ }
+ }
+ }
+
+ } catch (error) {
+ console.log(error);
+ }
+ }
+ })();
+
+ }
+ break;
+
case "messageBroadcasting":
console.log(res_obj);
try {
@@ -40799,7 +14681,17 @@
unique: false
});
}
-
+ if (!db.objectStoreNames.contains('myClosestSupernodes')) {
+ var objectStore = db.createObjectStore("myClosestSupernodes", {
+ keyPath: 'id'
+ });
+ objectStore.createIndex('trader_flo_address', 'trader_flo_address', {
+ unique: true
+ });
+ objectStore.createIndex('ip', 'ip', {
+ unique: false
+ });
+ }
}
function readDB(tablename, id) {
@@ -40933,6 +14825,319 @@
}
+
+
+