diff --git a/.gitignore b/.gitignore
index 1a39658..de930dc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,6 +2,13 @@ examples.mk
json-rpc/
supernode/playground/
playground
-supernode/index1.html
+supernode/test/in
+supernode/test/in/index1.html
+supernode/test/in/index2.html
+supernode/test/in/index3.html
+supernode/test/in/index4.html
supernode/flosend.html
-supernode/index1 (copy).html
\ No newline at end of file
+supernode/index1 (copy).html
+supernode/websocket_chat
+.vscode/
+supernode/test/
diff --git a/supernode/index.html b/supernode/index.html
index 88adc94..183b165 100644
--- a/supernode/index.html
+++ b/supernode/index.html
@@ -530,11 +530,11 @@
@@ -9163,8 +9163,6 @@
})();
}
-
-
reactor.registerEvent('added');
reactor.addEventListener('added', function (someObject) {
console.log('Added fired with data ' + someObject);
@@ -9180,6 +9178,10 @@
console.log('Updated fired with data ' + someObject);
});
+ reactor.registerEvent('bucket_full');
+ reactor.addEventListener('bucket_full', function (someObject) {
+ console.log('Bucket full ' + someObject);
+ });
/*
//Sample Usage
@@ -9200,26702 +9202,422 @@
//Checking if existing NodeID can be used
//This first block of if will initialize the configuration of KBucket
//Add Events, Messaging between different K-Buckets, and attach relevant distributed data
- if (typeof KBucketOptions == "undefined" || !KBucketOptions) {
- var KBucketOptions = {};
- var sanitizedFLOAddress = new Uint8Array(20);
- KBucketOptions.localNodeId = window.crypto.getRandomValues(sanitizedFLOAddress);
-
- }
-
- if (typeof KBucket == "undefined" || !KBucket) {
- (function (options) {
-
-
-
- var buf = new Uint8Array(20);
- var randomBytes = window.crypto.getRandomValues(buf);
-
-
- /**
- * @param {Uint8Array} array1
- * @param {Uint8Array} array2
- * @return {Boolean}
- */
- function arrayEquals(array1, array2) {
- if (array1 === array2) {
- return true
- }
- if (array1.length !== array2.length) {
- return false
- }
- for (let i = 0, length = array1.length; i < length; ++i) {
- if (array1[i] !== array2[i]) {
- return false
- }
- }
+ /**
+ * @param {Uint8Array} array1
+ * @param {Uint8Array} array2
+ * @return {Boolean}
+ */
+ function arrayEquals(array1, array2) {
+ if (array1 === array2) {
return true
}
-
- function createNode() {
- return {
- contacts: [],
- dontSplit: false,
- left: null,
- right: null
+ if (array1.length !== array2.length) {
+ return false
+ }
+ for (let i = 0, length = array1.length; i < length; ++i) {
+ if (array1[i] !== array2[i]) {
+ return false
}
}
-
- function ensureInt8(name, val) {
- if (!(val instanceof Uint8Array)) {
- throw new TypeError(name + ' is not a Uint8Array')
- }
- }
-
- /**
- * Implementation of a Kademlia DHT k-bucket used for storing
- * contact (peer node) information.
- *
- * @extends EventEmitter
- */
- function KBucket(options = {}) {
- /**
- * `options`:
- * `distance`: Function
- * `function (firstId, secondId) { return distance }` An optional
- * `distance` function that gets two `id` Uint8Arrays
- * and return distance (as number) between them.
- * `arbiter`: Function (Default: vectorClock arbiter)
- * `function (incumbent, candidate) { return contact; }` An optional
- * `arbiter` function that givent two `contact` objects with the same `id`
- * returns the desired object to be used for updating the k-bucket. For
- * more details, see [arbiter function](#arbiter-function).
- * `localNodeId`: Uint8Array An optional Uint8Array representing the local node id.
- * If not provided, a local node id will be created via `randomBytes(20)`.
- * `metadata`: Object (Default: {}) Optional satellite data to include
- * with the k-bucket. `metadata` property is guaranteed not be altered by,
- * it is provided as an explicit container for users of k-bucket to store
- * implementation-specific data.
- * `numberOfNodesPerKBucket`: Integer (Default: 20) The number of nodes
- * that a k-bucket can contain before being full or split.
- * `numberOfNodesToPing`: Integer (Default: 3) The number of nodes to
- * ping when a bucket that should not be split becomes full. KBucket will
- * emit a `ping` event that contains `numberOfNodesToPing` nodes that have
- * not been contacted the longest.
- *
- * @param {Object=} options optional
- */
-
- this.localNodeId = options.localNodeId || randomBytes
- this.numberOfNodesPerKBucket = options.numberOfNodesPerKBucket || 20
- this.numberOfNodesToPing = options.numberOfNodesToPing || 3
- this.distance = options.distance || KBucket.distance
- // use an arbiter from options or vectorClock arbiter by default
- this.arbiter = options.arbiter || KBucket.arbiter
- this.metadata = Object.assign({}, options.metadata)
-
- ensureInt8('option.localNodeId as parameter 1', this.localNodeId)
-
- this.root = createNode()
-
-
- /**
- * Default arbiter function for contacts with the same id. Uses
- * contact.vectorClock to select which contact to update the k-bucket with.
- * Contact with larger vectorClock field will be selected. If vectorClock is
- * the same, candidat will be selected.
- *
- * @param {Object} incumbent Contact currently stored in the k-bucket.
- * @param {Object} candidate Contact being added to the k-bucket.
- * @return {Object} Contact to updated the k-bucket with.
- */
- this.arbiter = function (incumbent, candidate) {
- return incumbent.vectorClock > candidate.vectorClock ? incumbent : candidate
- }
-
- /**
- * Default distance function. Finds the XOR
- * distance between firstId and secondId.
- *
- * @param {Uint8Array} firstId Uint8Array containing first id.
- * @param {Uint8Array} secondId Uint8Array containing second id.
- * @return {Number} Integer The XOR distance between firstId
- * and secondId.
- */
- this.distance = function (firstId, secondId) {
- let distance = 0
- let i = 0
- const min = Math.min(firstId.length, secondId.length)
- const max = Math.max(firstId.length, secondId.length)
- for (; i < min; ++i) {
- distance = distance * 256 + (firstId[i] ^ secondId[i])
- }
- for (; i < max; ++i) distance = distance * 256 + 255
- return distance
- }
-
- /**
- * Adds a contact to the k-bucket.
- *
- * @param {Object} contact the contact object to add
- */
- this.add = function (contact) {
- ensureInt8('contact.id', (contact || {}).id)
-
- let bitIndex = 0
- let node = this.root
-
- while (node.contacts === null) {
- // this is not a leaf node but an inner node with 'low' and 'high'
- // branches; we will check the appropriate bit of the identifier and
- // delegate to the appropriate node for further processing
- node = this._determineNode(node, contact.id, bitIndex++)
- }
-
- // check if the contact already exists
- const index = this._indexOf(node, contact.id)
- if (index >= 0) {
- this._update(node, index, contact)
- return this
- }
-
- if (node.contacts.length < this.numberOfNodesPerKBucket) {
- node.contacts.push(contact)
- reactor.dispatchEvent('added', contact)
- return this
- }
-
- // the bucket is full
- if (node.dontSplit) {
- // we are not allowed to split the bucket
- // we need to ping the first this.numberOfNodesToPing
- // in order to determine if they are alive
- // only if one of the pinged nodes does not respond, can the new contact
- // be added (this prevents DoS flodding with new invalid contacts)
- this.emit('ping', node.contacts.slice(0, this.numberOfNodesToPing), contact)
- return this
- }
-
- this._split(node, bitIndex)
- return this.add(contact)
- }
-
- /**
- * Get the n closest contacts to the provided node id. "Closest" here means:
- * closest according to the XOR metric of the contact node id.
- *
- * @param {Uint8Array} id Contact node id
- * @param {Number=} n Integer (Default: Infinity) The maximum number of
- * closest contacts to return
- * @return {Array} Array Maximum of n closest contacts to the node id
- */
- this.closest = function (id, n = Infinity) {
- ensureInt8('id', id)
-
- if ((!Number.isInteger(n) && n !== Infinity) || n <= 0) {
- throw new TypeError('n is not positive number')
- }
-
- let contacts = []
-
- for (let nodes = [this.root], bitIndex = 0; nodes.length > 0 && contacts.length < n;) {
- const node = nodes.pop()
- if (node.contacts === null) {
- const detNode = this._determineNode(node, id, bitIndex++)
- nodes.push(node.left === detNode ? node.right : node.left)
- nodes.push(detNode)
- } else {
- contacts = contacts.concat(node.contacts)
- }
- }
-
- return contacts
- .map(a => [this.distance(a.id, id), a])
- .sort((a, b) => a[0] - b[0])
- .slice(0, n)
- .map(a => a[1])
- }
-
- /**
- * Counts the total number of contacts in the tree.
- *
- * @return {Number} The number of contacts held in the tree
- */
- this.count = function () {
- // return this.toArray().length
- let count = 0
- for (const nodes = [this.root]; nodes.length > 0;) {
- const node = nodes.pop()
- if (node.contacts === null) nodes.push(node.right, node.left)
- else count += node.contacts.length
- }
- return count
- }
-
- /**
- * Determines whether the id at the bitIndex is 0 or 1.
- * Return left leaf if `id` at `bitIndex` is 0, right leaf otherwise
- *
- * @param {Object} node internal object that has 2 leafs: left and right
- * @param {Uint8Array} id Id to compare localNodeId with.
- * @param {Number} bitIndex Integer (Default: 0) The bit index to which bit
- * to check in the id Uint8Array.
- * @return {Object} left leaf if id at bitIndex is 0, right leaf otherwise.
- */
- this._determineNode = function (node, id, bitIndex) {
- // *NOTE* remember that id is a Uint8Array and has granularity of
- // bytes (8 bits), whereas the bitIndex is the bit index (not byte)
-
- // id's that are too short are put in low bucket (1 byte = 8 bits)
- // (bitIndex >> 3) finds how many bytes the bitIndex describes
- // bitIndex % 8 checks if we have extra bits beyond byte multiples
- // if number of bytes is <= no. of bytes described by bitIndex and there
- // are extra bits to consider, this means id has less bits than what
- // bitIndex describes, id therefore is too short, and will be put in low
- // bucket
- const bytesDescribedByBitIndex = bitIndex >> 3
- const bitIndexWithinByte = bitIndex % 8
- if ((id.length <= bytesDescribedByBitIndex) && (bitIndexWithinByte !== 0)) {
- return node.left
- }
-
- const byteUnderConsideration = id[bytesDescribedByBitIndex]
-
- // byteUnderConsideration is an integer from 0 to 255 represented by 8 bits
- // where 255 is 11111111 and 0 is 00000000
- // in order to find out whether the bit at bitIndexWithinByte is set
- // we construct (1 << (7 - bitIndexWithinByte)) which will consist
- // of all bits being 0, with only one bit set to 1
- // for example, if bitIndexWithinByte is 3, we will construct 00010000 by
- // (1 << (7 - 3)) -> (1 << 4) -> 16
- if (byteUnderConsideration & (1 << (7 - bitIndexWithinByte))) {
- return node.right
- }
-
- return node.left
- }
-
- /**
- * Get a contact by its exact ID.
- * If this is a leaf, loop through the bucket contents and return the correct
- * contact if we have it or null if not. If this is an inner node, determine
- * which branch of the tree to traverse and repeat.
- *
- * @param {Uint8Array} id The ID of the contact to fetch.
- * @return {Object|Null} The contact if available, otherwise null
- */
- this.get = function (id) {
- ensureInt8('id', id)
-
- let bitIndex = 0
-
- let node = this.root
- while (node.contacts === null) {
- node = this._determineNode(node, id, bitIndex++)
- }
-
- // index of uses contact id for matching
- const index = this._indexOf(node, id)
- return index >= 0 ? node.contacts[index] : null
- }
-
- /**
- * Returns the index of the contact with provided
- * id if it exists, returns -1 otherwise.
- *
- * @param {Object} node internal object that has 2 leafs: left and right
- * @param {Uint8Array} id Contact node id.
- * @return {Number} Integer Index of contact with provided id if it
- * exists, -1 otherwise.
- */
- this._indexOf = function (node, id) {
- for (let i = 0; i < node.contacts.length; ++i) {
- if (arrayEquals(node.contacts[i].id, id)) return i
- }
-
- return -1
- }
-
- /**
- * Removes contact with the provided id.
- *
- * @param {Uint8Array} id The ID of the contact to remove.
- * @return {Object} The k-bucket itself.
- */
- this.remove = function (id) {
- ensureInt8('the id as parameter 1', id)
-
- let bitIndex = 0
- let node = this.root
-
- while (node.contacts === null) {
- node = this._determineNode(node, id, bitIndex++)
- }
-
- const index = this._indexOf(node, id)
- if (index >= 0) {
- const contact = node.contacts.splice(index, 1)[0]
- reactor.dispatchEvent('removed', contact)
- }
-
- return this
- }
-
- /**
- * Splits the node, redistributes contacts to the new nodes, and marks the
- * node that was split as an inner node of the binary tree of nodes by
- * setting this.root.contacts = null
- *
- * @param {Object} node node for splitting
- * @param {Number} bitIndex the bitIndex to which byte to check in the
- * Uint8Array for navigating the binary tree
- */
- this._split = function (node, bitIndex) {
- node.left = createNode()
- node.right = createNode()
-
- // redistribute existing contacts amongst the two newly created nodes
- for (const contact of node.contacts) {
- this._determineNode(node, contact.id, bitIndex).contacts.push(contact)
- }
-
- node.contacts = null // mark as inner tree node
-
- // don't split the "far away" node
- // we check where the local node would end up and mark the other one as
- // "dontSplit" (i.e. "far away")
- const detNode = this._determineNode(node, this.localNodeId, bitIndex)
- const otherNode = node.left === detNode ? node.right : node.left
- otherNode.dontSplit = true
- }
-
- /**
- * Returns all the contacts contained in the tree as an array.
- * If this is a leaf, return a copy of the bucket. `slice` is used so that we
- * don't accidentally leak an internal reference out that might be
- * accidentally misused. If this is not a leaf, return the union of the low
- * and high branches (themselves also as arrays).
- *
- * @return {Array} All of the contacts in the tree, as an array
- */
- this.toArray = function () {
- let result = []
- for (const nodes = [this.root]; nodes.length > 0;) {
- const node = nodes.pop()
- if (node.contacts === null) nodes.push(node.right, node.left)
- else result = result.concat(node.contacts)
- }
- return result
- }
-
- /**
- * Updates the contact selected by the arbiter.
- * If the selection is our old contact and the candidate is some new contact
- * then the new contact is abandoned (not added).
- * If the selection is our old contact and the candidate is our old contact
- * then we are refreshing the contact and it is marked as most recently
- * contacted (by being moved to the right/end of the bucket array).
- * If the selection is our new contact, the old contact is removed and the new
- * contact is marked as most recently contacted.
- *
- * @param {Object} node internal object that has 2 leafs: left and right
- * @param {Number} index the index in the bucket where contact exists
- * (index has already been computed in a previous
- * calculation)
- * @param {Object} contact The contact object to update.
- */
- this._update = function (node, index, contact) {
- // sanity check
- if (!arrayEquals(node.contacts[index].id, contact.id)) {
- throw new Error('wrong index for _update')
- }
-
- const incumbent = node.contacts[index]
-
- /***************Change made by Abhishek*************/
- const selection = this.arbiter(incumbent, contact)
- //const selection = localbitcoinplusplus.kademlia.arbiter(incumbent, contact);
- // if the selection is our old contact and the candidate is some new
- // contact, then there is nothing to do
- if (selection === incumbent && incumbent !== contact) return
-
- node.contacts.splice(index, 1) // remove old contact
- node.contacts.push(selection) // add more recent contact version
- /***************Change made by Abhishek*************/
- reactor.dispatchEvent('updated', {
- ...incumbent,
- ...selection
- })
- //reactor.dispatchEvent('updated', incumbent.concat(selection))
- }
- }
-
- window.KBucket = new KBucket(options)
-
- })(KBucketOptions);
-
- }
-
-
-
+
@@ -36347,12 +10069,21 @@
// btcTradeMargin is tolerable difference between Crypto trader should deposit and cryptos he actually deposited
RMAssets =
`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=02B2D2F40EC5BC9D336BAF14017D629B3A96892D5E86095923A50A734E2364FB34,
+ #!#validTradingAmount=10000,50000,100000,#!#btcTradeMargin=5000
+ #!#supernodesPubKeys=0315C3A20FE7096CC2E0F81A80D5F1A687B8F9EFA65242A0B0881E1BA3EE7D7D53,
+ 03F7493F11B8E44B9798CD434D20FBE7FA34B9779D144984889D11A17C56A18742,039B4AA00DBFC0A6631DE6DA83526611A0E6B857D3579DF840BBDEAE8B6898E3B6,
#!#externalFiles={"d3js":"58f54395efa8346e8e94d12609770f66b916897e7f4e05f6c98780cffa5c70a3"},
- #!#ShamirsMaxShares=8#!#supernodeSeeds={"ranchimall1":{"ip":"ranchimall1.duckdns.org","port":"9002","kbucketId":"oJeYebjgWV4Hszj5oP7sfXcj1U98P5M6q4"},
- "ranchimall2":{"ip":"ranchimall1.duckdns.org","port":"9003","kbucketId":"oH47fmrVEbSDcoXJG28BQZ4kzUpD9VTM6U"}}`;
+ #!#ShamirsMaxShares=8#!#supernodeSeeds={"ranchimall1":{"ip":"127.0.0.1","port":"9001","kbucketId":"oZxHcbSf1JC8t5GjutopWYXs7C6Fe9p7ps"},
+ "ranchimall2":{"ip":"127.0.0.1","port":"9002","kbucketId":"oTWjPupy3Z7uMdPcu5uXd521HBkcsLuSuM"},
+ "ranchimall3":{"ip":"127.0.0.1","port":"9003","kbucketId":"odYA6KagmbokSh9GY7yAfeTUZRtZLwecY1"}}`;
+ // RMAssets =
+ // `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=03692E641440795B6279F548C7156775EB624CC8A27FDA94C5E3B8945EC94DE1F1,02F22822D5E887ABBDA3D5E3A51574C547FEAAC00BF01185AA56858D4C9B00334F,
+ // #!#externalFiles={"d3js":"58f54395efa8346e8e94d12609770f66b916897e7f4e05f6c98780cffa5c70a3"},
+ // #!#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('#!#');
@@ -36364,7 +10095,7 @@
let k = assets_string.split('=');
if (k[1].indexOf(',') > 0) {
k[1] = k[1].split(',')
- .map(val => !isNaN(val) ? parseFloat(val) : val)
+ .map(val => !isNaN(val) ? parseFloat(val) : val.trim())
.filter(v => ![null, "", undefined, NaN].includes(v));
} else if (!isNaN(k[1])) {
k[1] = parseFloat(k[1]);
@@ -36392,7 +10123,8 @@
let sync_request = RM_RPC.send_rpc.call(this,
"sync_with_supernode", {
"trader_flo_address": trader_flo_address,
- "job": "SYNC_MY_LOCAL_DB_WITH_SUPERNODE_DB"
+ "job": "SYNC_MY_LOCAL_DB_WITH_SUPERNODE_DB",
+ "receiver_flo_address": localbitcoinplusplus.MY_SUPERNODE_FLO_ADDRESS,
});
doSend(sync_request);
},
@@ -36424,6 +10156,7 @@
deposit_withdraw_user_claim_obj.hash = deposit_withdraw_user_claim_hash;
deposit_withdraw_user_claim_obj.sign = deposit_withdraw_user_claim_sign;
+ deposit_withdraw_user_claim_obj.receiver_flo_address = localbitcoinplusplus.MY_SUPERNODE_FLO_ADDRESS;
let deposit_withdraw_claim =
RM_RPC
@@ -36472,7 +10205,7 @@
t += ``;
});
- t += ` `;
+ t += ``;
modalWindow(t);
}
@@ -36502,29 +10235,62 @@
k.splice(-4, 4)
return Crypto.util.bytesToHex(k)
},
- addContact: function (id, data) {
- const nodeId = new Uint8Array(id.length)
- for (let i = 0, len = nodeId.length; i < len; ++i) {
- nodeId[i] = id.charCodeAt(i)
- }
+ launchKBucket: function(flo_id) {
+ return new Promise((resolve, reject)=>{
+ try {
+ const KBucketId = localbitcoinplusplus.kademlia.floIdToKbucketId('FLO_TEST', flo_id)
+ const kbOptions = { localNodeId: KBucketId }
+ window.KBucket = new BuildKBucket(kbOptions);
+ window.supernodeKBucket = new BuildKBucket(kbOptions);
+ resolve(true);
+ } catch (error) {
+ reject(error);
+ }
+ })
+ },
+ addContact: function (id, data, KB=KBucket) {
const contact = {
- id: nodeId,
+ id: id,
data: data
};
- KBucket.add(contact)
+ KB.add(contact)
},
- addNewUserNodeInKbucket: function (blockchain, address, data) {
- const decodedId = this.decodeBase58Address(blockchain, address);
- const addNewUserNode = this.addContact(decodedId, data);
- return addNewUserNode;
+ addNewUserNodeInKbucket: function(blockchain, address, data, KB=KBucket) {
+ let decodedId = address;
+ try {
+ decodedId = this.floIdToKbucketId(blockchain, address);
+ } catch(e) {
+ decodedId = address;
+ }
+ const addNewUserNode = this.addContact(decodedId, data, KB);
+ return {decodedId:decodedId, data:data};
+ },
+ addNewUserNodeInKbucketAndDB: function (blockchain, address, data, KB=KBucket) {
+ let kbuck = this.addNewUserNodeInKbucket(blockchain, address, data, KB);
+ readDB('kBucketStore', kbuck.decodedId).then(kres=>{
+ if (typeof kres=="object") {
+ kres.data = data;
+ } else {
+ kbuckObj={
+ id: kbuck.decodedId,
+ vectorClock: 0,
+ data: kbuck.data,
+ last_updated_on: + new Date(),
+ }
+ kres = kbuckObj;
+ }
+ updateinDB('kBucketStore', kres)
+ .then(ms=>showMessage(`INFO: Added/Updated a node in DB.`))
+ .catch(e=>{showMessage(`ERROR: Failed to add a node in DB.`)});
+ return Promise.resolve(kbuck);
+ });
},
floIdToKbucketId: function (blockchain, address) {
const decodedId = this.decodeBase58Address(blockchain, address);
- const nodeId = new Uint8Array(decodedId.length)
- for (let i = 0, len = nodeId.length; i < len; ++i) {
- nodeId[i] = decodedId.charCodeAt(i)
- }
- return nodeId;
+ const nodeIdBigInt = new BigInteger(decodedId, 16);
+ const nodeIdBytes = nodeIdBigInt.toByteArrayUnsigned();
+ const nodeIdNewInt8Array = new Uint8Array(nodeIdBytes);
+ return nodeIdNewInt8Array;
},
arbiter: function (incumbent, candidate) {
// we create a new object so that our selection is guaranteed to replace
@@ -36544,58 +10310,128 @@
let pubKeyBytes = Crypto.util.hexToBytes(pubKey);
return Crypto.util.bytesToBase64(pubKeyBytes);
},
- getSupernodeSeed: function (flo_addr, flo_pub_key) {
- return new Promise((resolve, reject) => {
+ restoreKbucket: function(flo_addr, blockchain="FLO_TEST", KB=KBucket) {
+ return new Promise((resolve, reject)=>{
+ readAllDB('kBucketStore')
+ .then(dbObject => {
+ if (typeof dbObject=="object") {
+ let su_flo_addr_array = localbitcoinplusplus.master_configurations.supernodesPubKeys
+ .map(pubk=>bitjs.FLO_TEST.pubkey2address(pubk));
+ // Prevent supernode to re-added in kbucket
+ dbObject
+ .filter(f=>!su_flo_addr_array.includes(f.data.id))
+ .map(dbObj=>{
+ this.addNewUserNodeInKbucket(blockchain, flo_addr, dbObj.data, KB);
+ });
+ } else {
+ reject(`Failed to restore kBucket.`);
+ }
+ resolve(dbObject);
+ });
+ })
+ },
+ restoreSupernodeKBucket: function() {
+ return new Promise((resolve, reject)=>{
const supernodeSeeds = localbitcoinplusplus.master_configurations.supernodeSeeds;
- if (typeof supernodeSeeds !== "object") throw new Error(
- "Failed to get supernode seeds.");
+ if (typeof supernodeSeeds !== "object") reject("Failed to get supernode seeds.");
let supernodeSeedsObj = JSON.parse(supernodeSeeds);
- 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}!`
- },
- };
-
Object.entries(supernodeSeedsObj).map(seedObj=>{
- localbitcoinplusplus.kademlia.addNewUserNodeInKbucket(
+ let kbuck = this.addNewUserNodeInKbucket("FLO_TEST", seedObj[1].kbucketId,
+ { id: seedObj[1].kbucketId }, supernodeKBucket);
+ });
+ })
+ },
+ updateClosestSupernodeSeeds: function(flo_addr) {
+ return new Promise(async (resolve, reject) => {
+ let nearestSupernodeAddresslist = await localbitcoinplusplus.kademlia.addClosestSupernodeInDB(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 nearestSupernodeAddresslist = await readAllDB('myClosestSupernodes');
+ if (nearestSupernodeAddresslist.length<1) {
+ nearestSupernodeAddresslist = await this.updateClosestSupernodeSeeds(flo_addr);
+ }
+ //this.restoreSupernodeKBucket(flo_addr, "FLO_TEST", supernodeKBucket);
+ resolve(nearestSupernodeAddresslist);
+ });
+ },
+ isNodePresentInMyKbucket: function(flo_id, KB=KBucket) {
+ return new Promise((resolve, reject)=>{
+ let kArray = KB.toArray();
+ let kArrayFloIds = kArray.map(k=>k.data.id);
+ if (kArrayFloIds.includes(flo_id)) {
+ resolve(true);
+ } else {
+ reject(false);
+ }
+ });
+ },
+ determineClosestSupernode: function(flo_addr, KB=supernodeKBucket, n=1) {
+ return new Promise((resolve, reject)=>{
+ let msg = ``;
+ if (typeof KB !== "object") {
+ msg = `ERROR: Supernode KBucket not found.`;
+ showMessage(msg);
+ reject(msg);
+ return false;
+ }
+
+ try {
+ let isFloIdUint8 = flo_addr instanceof Uint8Array;
+ if (!isFloIdUint8) {
+ flo_addr = localbitcoinplusplus.kademlia.floIdToKbucketId('FLO_TEST', flo_addr);
+ }
+ const closestSupernode = KB.closest(flo_addr, n);
+ resolve(closestSupernode);
+ return true;
+ } catch (error) {
+ showMessage(error);
+ reject(error);
+ return false;
+ }
+ })
+ },
+ addClosestSupernodeInDB: function(flo_addr, KB=KBucket) {
+ return new Promise((resolve, reject)=>{
+ const supernodeSeeds = localbitcoinplusplus.master_configurations.supernodeSeeds;
+ if (typeof supernodeSeeds !== "object") reject("Failed to get supernode seeds.");
+ let supernodeSeedsObj = JSON.parse(supernodeSeeds);
+
+ Object.entries(supernodeSeedsObj).map(seedObj=>{
+ console.log(seedObj);
+ localbitcoinplusplus.kademlia.addNewUserNodeInKbucketAndDB(
"FLO_TEST", seedObj[1].kbucketId,
- { id: seedObj[1].kbucketId, vectorClock: 0 });
+ { id: seedObj[1].kbucketId });
});
let currentNodeBucketId = localbitcoinplusplus.kademlia
.floIdToKbucketId("FLO_TEST", flo_addr);
- let nearestSupernode = KBucket.closest(currentNodeBucketId, 1);
-
- nearestSupernodeAddress = Object.values(supernodeSeedsObj).filter(seed=>
- nearestSupernode[0].data.id == seed.kbucketId);
+ let nearestSupernode = KB.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);
+ });
- seedContactArray.transport = {
- host: nearestSupernodeAddress[0].ip,
- port: nearestSupernodeAddress[0].port,
- id: nearestSupernodeAddress[0].kbucketId
+ if (supernodeSeedsArray.length>0) {
+ resolve(supernodeSeedsArray);
+ } else {
+ reject(false);
}
-
- const nodeDiscoveryOptions = {
- seeds: seedContactArray
- }
-
- const kdiscover = new tristanDiscover(nodeDiscoveryOptions);
-
- try {
- let supernodeAddressUrl = `ws://${kdiscover.seeds.transport.host}:${kdiscover.seeds.transport.port}`;
- console.log(supernodeAddressUrl);
- resolve(supernodeAddressUrl);
- } catch (error) {
- reject(error);
- }
- });
- },
+ })
+ }
}
@@ -36739,20 +10575,21 @@
// 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);
+ let data = 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, {data: data, receiver_flo_address: flo_id});
doSend(bar);
});
},
transmitMessageToMiddleMan: function (dataToBeSentToReceiver, receiverFloAddress) {
const RM_RPC = new localbitcoinplusplus.rpc;
+ dataToBeSentToReceiver.sender_flo_address = localbitcoinplusplus.wallets.my_local_flo_address;
let bar = RM_RPC
.send_rpc
.call(this, "MessageForMiddleman", dataToBeSentToReceiver);
@@ -36762,6 +10599,166 @@
}
+
+
+
@@ -37008,10 +11031,19 @@
var request = new JSON_RPC.Request(method, params);
var id = request.id;
this.rpc_req_id = id;
+
+ if (typeof localbitcoinplusplus.wallets.my_local_flo_address == "string") {
+ request.globalParams.senderFloId = localbitcoinplusplus.wallets.my_local_flo_address;
+ }
+
+ if (typeof params[0].receiver_flo_address == "string") {
+ request.globalParams.receiverFloId = params[0].receiver_flo_address;
+ }
+
return request.toString();
},
- filter_legit_requests: function (callback) {
+ filter_legit_requests: function (flo_id=null, callback) {
if (typeof localbitcoinplusplus.wallets.MY_SUPERNODE_PRIVATE_KEY === "string" &&
localbitcoinplusplus.wallets.MY_SUPERNODE_PRIVATE_KEY.length > 0
) {
@@ -37020,11 +11052,27 @@
if (typeof user_keys == "object" && typeof user_keys.pubKeyHex == "string") {
if (localbitcoinplusplus.master_configurations.supernodesPubKeys.includes(
user_keys.pubKeyHex)) {
- return callback(true);
+ if (typeof flo_id !== null || typeof flo_id !== 'undefined') {
+ let karr = KBucket.toArray();
+ let karr_floIds = karr.map(f=>f.data.id);
+ if (!karr_floIds.includes(flo_id)) {
+ return callback(false);
+ }
+
+ localbitcoinplusplus.kademlia.determineClosestSupernode(flo_id)
+ .then(my_closest_su=>{
+ if (user_keys.address === my_closest_su[0].data.id) {
+ return callback(true);
+ }
+ });
+ } else {
+ return callback(false);
+ }
}
}
+ } else {
+ return callback(false);
}
- return callback(false);
},
async receive_rpc_response(request) {
@@ -37043,8 +11091,8 @@
request.response = {};
let err_msg;
- if (method=="sync_with_supernode") {
- RM_RPC.filter_legit_requests(function (is_valid_request) {
+ if (method=="sync_with_supernode") {
+ RM_RPC.filter_legit_requests(params.trader_flo_address, function (is_valid_request) {
if (is_valid_request === true && params.job ==
"SYNC_MY_LOCAL_DB_WITH_SUPERNODE_DB" && params.trader_flo_address.length >
0) {
@@ -37055,6 +11103,7 @@
function (su_db_data) {
if (typeof su_db_data == "object") {
su_db_data.trader_flo_address = params.trader_flo_address;
+ su_db_data.receiver_flo_address = params.trader_flo_address;
let server_sync_response = RM_RPC
.send_rpc
.call(this, "server_sync_response",
@@ -37064,10 +11113,11 @@
});
}
});
- }
+ }
+
+ RM_RPC.filter_legit_requests(params.trader_flo_address, async function (is_valid_request) {
+ if (is_valid_request !== true) return false;
- if (localbitcoinplusplus.master_configurations.supernodesPubKeys.includes(
- localbitcoinplusplus.wallets.my_local_flo_public_key)) {
try {
// CHECK HERE IF USER IS INDULGED IN ANY MORE TRADE. IF TRUE RETURN ERROR
await readAllDB("deposit").then(function (res) {
@@ -37085,6 +11135,7 @@
.send_rpc
.call(this, "supernode_message", {
"trader_flo_id": respective_trader_id,
+ "receiver_flo_address": respective_trader_id,
"server_msg": request.response
});
doSend(server_response);
@@ -37098,8 +11149,7 @@
// Check if user id is in deposit or withdraw. If true prevent him from trading
await readAllDB('withdraw_cash').then(function (res) {
if (typeof res == "object") {
- let check_deposit_withdraw_id_array = res.filter(f => f.status ===
- 2)
+ let check_deposit_withdraw_id_array = res.filter(f => f.status === 2)
.map(m => {
if (m.trader_flo_address == respective_trader_id || m.deposit_withdraw_id_array ==
respective_trader_id) {
@@ -37112,6 +11162,7 @@
.send_rpc
.call(this, "supernode_message", {
"trader_flo_id": respective_trader_id,
+ "receiver_flo_address": respective_trader_id,
"server_msg": server_msg
});
doSend(server_response);
@@ -37126,12 +11177,12 @@
} catch (error) {
throw new Error(error);
}
- }
+ });
switch (method) {
case "trade_buy":
- RM_RPC.filter_legit_requests(async function (is_valid_request) {
+ RM_RPC.filter_legit_requests(params.trader_flo_address, async function (is_valid_request) {
if (is_valid_request !== true) return false;
await RM_TRADE.resolve_current_crypto_price_in_fiat(params.product,
params.currency);
@@ -37144,6 +11195,7 @@
request.response = RM_TRADE.trade_buy.call(this,
...request.params,
function (supernode_signed_res) {
+ supernode_signed_res.receiver_flo_address = params.trader_flo_address;
if (typeof supernode_signed_res == "object") {
let buy_request_response = RM_RPC
.send_rpc
@@ -37170,7 +11222,7 @@
});
break;
case "trade_sell":
- RM_RPC.filter_legit_requests(async function (is_valid_request) {
+ RM_RPC.filter_legit_requests(params.trader_flo_address, async function (is_valid_request) {
if (is_valid_request !== true) return false;
await RM_TRADE.resolve_current_crypto_price_in_fiat(params.product,
params.currency);
@@ -37185,6 +11237,7 @@
this, ...request.params,
function (supernode_signed_res) {
if (typeof supernode_signed_res == "object") {
+ supernode_signed_res.receiver_flo_address = params.trader_flo_address;
let sell_request_response = RM_RPC
.send_rpc
.call(this,
@@ -37215,7 +11268,7 @@
// already processed above
break;
case "deposit_asset_request":
- RM_RPC.filter_legit_requests(function (is_valid_request) {
+ RM_RPC.filter_legit_requests(params.trader_flo_address, function (is_valid_request) {
if (is_valid_request !== true) return false;
@@ -37263,9 +11316,7 @@
params.depositing_amount, params.currency,
params.product);
- let receivedTradeInfo = {
- ...params
- };
+ let receivedTradeInfo = { ...params };
if (typeof localbitcoinplusplus.wallets.MY_SUPERNODE_PRIVATE_KEY ==
"undefined") {
@@ -37287,43 +11338,28 @@
) {
let receivedTradeInfoHash =
- Crypto.SHA256(JSON.stringify(
- receivedTradeInfo));
+ Crypto.SHA256(JSON.stringify(receivedTradeInfo));
- receivedTradeInfo[
- "depositDataHash"] =
- receivedTradeInfoHash;
- receivedTradeInfo[
- "order_validator_sign"] =
- RM_WALLET.sign(
- receivedTradeInfoHash,
- localbitcoinplusplus.wallets
- .MY_SUPERNODE_PRIVATE_KEY
+ receivedTradeInfo["depositDataHash"] = receivedTradeInfoHash;
+ receivedTradeInfo["order_validator_sign"] =
+ RM_WALLET.sign(receivedTradeInfoHash,
+ localbitcoinplusplus.wallets.MY_SUPERNODE_PRIVATE_KEY
);
- receivedTradeInfo[
- "order_validator_public_key"
- ] =
- su_data.myLocalFLOPublicKey;
+ receivedTradeInfo["order_validator_public_key"] = su_data.myLocalFLOPublicKey;
try {
const this_btc_pvt_key =
- generate_btc_keys_for_requester
- .privateKeyWIF;
+ generate_btc_keys_for_requester.privateKeyWIF;
const this_btc_tx_key =
- Crypto.util.randomBytes(
- 64);
+ Crypto.util.randomBytes(64);
const
this_btc_pvt_key_shamirs_secret =
- RM_WALLET.createShamirsSecretShares(
- this_btc_pvt_key,
- 10, 5);
+ RM_WALLET.createShamirsSecretShares(this_btc_pvt_key, 10, 5);
if (typeof this_btc_pvt_key_shamirs_secret ==
"object" &&
this_btc_pvt_key_shamirs_secret
.length > 0) {
- addDB("deposit",
- receivedTradeInfo
- );
+ addDB("deposit", receivedTradeInfo);
// Send the address to the requester
let
@@ -37333,6 +11369,7 @@
msg: `Please send ${params.product} ${params.bitcoinToBePaid} to the following addres: ${generate_btc_keys_for_requester.address}.`,
data: receivedTradeInfo
};
+ deposit_response_object.receiver_flo_address = params.trader_flo_address;
let
deposit_request_response =
RM_RPC
@@ -37341,9 +11378,7 @@
"deposit_asset_request_response",
deposit_response_object
);
- doSend(
- deposit_request_response
- );
+ doSend(deposit_request_response);
let
this_btc_pvt_key_shamirs_secret_array =
@@ -37449,7 +11484,8 @@
error: false,
method: "deposit_asset_request_response",
msg: `Please send the ${params.product} to ${generate_btc_keys_for_requester.address}.`,
- data: receivedTradeInfo
+ data: receivedTradeInfo,
+ receiver_flo_address: params.trader_flo_address,
};
let deposit_request_response =
@@ -37471,9 +11507,7 @@
params.status = 1;
// IMPORTANT - If deposit is a fiat make sure product and currency are both same
params.currency = params.product;
- let receivedTradeInfo = {
- ...params
- };
+ let receivedTradeInfo = { ...params };
readDB("localbitcoinUser", "00-01").then(
function (su_data) {
@@ -37517,86 +11551,50 @@
if (typeof withdrawers_list ==
"object") {
if (
- withdrawers_list
- .length >
- 0) {
- withdrawers_list
- .filter(
- wd =>
- wd
- .currency ==
- params
- .currency
- ).map(
- function (
- withdrawer
- ) {
+ withdrawers_list.length > 0) {
+ withdrawers_list.filter(
+ wd => wd.currency ==
+ params.currency).map(
+ function (withdrawer) {
if (
- withdrawer
- .withdraw_amount ==
- params
- .depositing_amount &&
- withdrawer
- .currency ==
- params
- .currency
+ withdrawer.withdraw_amount ==
+ params.depositing_amount &&
+ withdrawer.currency ==
+ params.currency
) {
- withdrawer
- .status =
- 2; // A depositor has been asked to deposit money
- withdrawer
- .depositor_found_at = +
- new Date();
- withdrawer
- .depositor_flo_id =
+ withdrawer.status = 2; // A depositor has been asked to deposit money
+ withdrawer.depositor_found_at = + new Date();
+ withdrawer.depositor_flo_id = receivedTradeInfo.trader_flo_address;
+ updateinDB ("withdraw_cash", withdrawer, withdrawer.trader_flo_address);
+
+ receivedTradeInfo.status = 2; // withdrawer found. Now deposit money to his account
+ updateinDB(
+ "deposit",
+ receivedTradeInfo,
receivedTradeInfo
- .trader_flo_address;
- updateinDB
- (
- "withdraw_cash",
- withdrawer,
- withdrawer
- .trader_flo_address
- );
+ .trader_flo_address
+ );
- receivedTradeInfo
- .status =
- 2; // withdrawer found. Now deposit money to his account
- updateinDB
- (
- "deposit",
- receivedTradeInfo,
- receivedTradeInfo
- .trader_flo_address
- );
+ let withdrawer_bank_account = withdrawer.receivinAddress;
- let
- withdrawer_bank_account =
- withdrawer
- .receivinAddress;
+ let deposit_response_object = {
+ error: false,
+ method: "deposit_asset_request_response",
+ msg: `Plese send the money to following bank address: "${withdrawer_bank_account}"`,
+ data: receivedTradeInfo,
+ withdrawer_data: withdrawer,
+ receiver_flo_address: receivedTradeInfo.trader_flo_address,
+ };
- let
- deposit_response_object = {
- error: false,
- method: "deposit_asset_request_response",
- msg: `Plese send the money to following bank address: "${withdrawer_bank_account}"`,
- data: receivedTradeInfo,
- withdrawer_data: withdrawer
- };
let
deposit_request_response =
- RM_RPC
- .send_rpc
- .call(
+ RM_RPC.send_rpc.call(
this,
"deposit_asset_request_response",
deposit_response_object
);
- doSend
- (
- deposit_request_response
- );
+ doSend(deposit_request_response);
return true;
} else {
err_msg = "Deposit request failed: We could not find a withdrawer.";
@@ -37612,7 +11610,8 @@
error: false,
method: "deposit_asset_request_response",
msg: `Plese send the money to following bank address: "System determined bank".`,
- data: receivedTradeInfo
+ data: receivedTradeInfo,
+ receiver_flo_address: receivedTradeInfo.trader_flo_address,
};
let
deposit_request_response =
@@ -37624,9 +11623,7 @@
deposit_response_object
);
- receivedTradeInfo
- .status =
- 2; // withdrawer found. Now deposit money to his account
+ receivedTradeInfo.status = 2; // withdrawer found. Now deposit money to his account
updateinDB
(
"deposit",
@@ -37635,9 +11632,7 @@
.trader_flo_address
);
- doSend(
- deposit_request_response
- );
+ doSend(deposit_request_response);
return true;
}
}
@@ -37661,7 +11656,7 @@
});
break;
case "withdraw_request_method":
- RM_RPC.filter_legit_requests(async function (is_valid_request) {
+ RM_RPC.filter_legit_requests(params.trader_flo_address, async function (is_valid_request) {
if (is_valid_request !== true) return false;
@@ -37883,8 +11878,7 @@
"send_back_shamirs_secret_btc_pvtkey", {
retrieve_pvtkey_req_id: retrieve_pvtkey_req_id,
chunk_val: bpks,
- withdraw_id: vbl
- .withdraw_id
+ withdraw_id: vbl.withdraw_id
}
);
doSend
@@ -37960,7 +11954,7 @@
withdraw_amount: withdrawing_cash_amount,
currency: params.currency,
receivinAddress: bank_details,
- status: 1 // withdraw request called
+ status: 1, // withdraw request called
}
readDB("localbitcoinUser", "00-01").then(
@@ -38008,6 +12002,8 @@
withdraw_request_db_object
);
// return back the response to client
+ withdraw_request_db_object.receiver_flo_address =
+ params.trader_flo_address;
let
withdrawal_request_response =
RM_RPC.send_rpc
@@ -38043,7 +12039,7 @@
break;
case "retrieve_shamirs_secret_btc_pvtkey":
- RM_RPC.filter_legit_requests(function (is_valid_request) {
+ RM_RPC.filter_legit_requests(null, function (is_valid_request) {
if (is_valid_request !== true) return false;
if (typeof params.btc_private_key_array !== "string" || typeof params.retrieve_pvtkey_req_id !==
@@ -38081,8 +12077,7 @@
withdraw_res.receiverBTCEquivalentInCash,
withdraw_res.currency,
withdraw_res.product);
- EqCryptoWd = parseFloat(
- EqCryptoWd);
+ EqCryptoWd = parseFloat(EqCryptoWd);
let transaction_key =
btc_reserves.supernode_transaction_key;
@@ -38181,8 +12176,8 @@
updateUserCryptoBalanceObject = {
updatedBTCBalanceObject: res_bal,
updatedBTCBalanceObjectSign: res_obj_sign,
- trader_flo_address: withdraw_res
- .trader_flo_address
+ trader_flo_address: withdraw_res.trader_flo_address,
+ receiver_flo_address: withdraw_res.trader_flo_address,
}
const
@@ -38285,22 +12280,27 @@
case "superNodeSignedAddUserPublicData":
if (typeof params == "object" && typeof params.data == "object") {
- if (typeof params.su_pubKey == "string" && localbitcoinplusplus
+ RM_RPC.filter_legit_requests(params.data.trader_flo_address,
+ function (is_valid_request) {
+ if (is_valid_request !== true) return false;
+
+ if (typeof params.su_pubKey == "string" && localbitcoinplusplus
.master_configurations.supernodesPubKeys.includes(params.su_pubKey)) {
- let res_data_obj = {
- trader_flo_address: params.data.trader_flo_address,
- trader_flo_pubKey: params.data.trader_flo_pubKey,
- trader_status: params.data.trader_status,
- timestamp: params.data.timestamp
- };
- let res_data_hash = Crypto.SHA256(JSON.stringify(res_data_obj));
- let res_data_verification = RM_WALLET
- .verify(res_data_hash, params.sign, params.su_pubKey);
- if ((res_data_verification == true) && res_data_hash == params.data_hash) {
- addDB('userPublicData', params.data);
- return true;
+ let res_data_obj = {
+ trader_flo_address: params.data.trader_flo_address,
+ trader_flo_pubKey: params.data.trader_flo_pubKey,
+ trader_status: params.data.trader_status,
+ timestamp: params.data.timestamp
+ };
+ let res_data_hash = Crypto.SHA256(JSON.stringify(res_data_obj));
+ let res_data_verification = RM_WALLET
+ .verify(res_data_hash, params.sign, params.su_pubKey);
+ if ((res_data_verification == true) && res_data_hash == params.data_hash) {
+ addDB('userPublicData', params.data);
+ return true;
+ }
}
- }
+ });
}
break;
@@ -38429,7 +12429,8 @@
"trader_flo_address": this.user_flo_address,
"product": this.product,
"currency": this.currency,
- "buy_price": this.buy_price
+ "buy_price": this.buy_price,
+ "receiver_flo_address":localbitcoinplusplus.MY_SUPERNODE_FLO_ADDRESS,
}
const RM_RPC = new localbitcoinplusplus.rpc;
let placeNewOrder = RM_RPC.send_rpc.call(this, this
@@ -38636,7 +12637,8 @@
depositor_public_key: null,
operation_type: "deposit",
order_validator_public_key: null,
- product: assetType
+ product: assetType,
+ receiver_flo_address:localbitcoinplusplus.MY_SUPERNODE_FLO_ADDRESS,
}
const RM_RPC = new localbitcoinplusplus.rpc;
let deposit_request = RM_RPC.send_rpc.call(this,
@@ -38676,7 +12678,8 @@
operation_type: "withdraw",
order_validator_public_key: null,
product: assetType,
- currency: currency
+ currency: currency,
+ receiver_flo_address:localbitcoinplusplus.MY_SUPERNODE_FLO_ADDRESS,
}
const RM_RPC = new localbitcoinplusplus.rpc;
let withdraw_request = RM_RPC.send_rpc.call(this,
@@ -39147,8 +13150,8 @@
"seller_btc_data": sellerBTCResponseObject,
"data_hash": hashed_data,
"supernode_sign": signed_data,
- "supernodePubKey": user_data
- .myLocalFLOPublicKey
+ "supernodePubKey": user_data.myLocalFLOPublicKey,
+ "receiver_flo_address": "BROADCAST_TO_NODES",
}
callback(response_for_client);
return true;
@@ -39178,7 +13181,8 @@
trade_id: trade_id,
signed_trade_id: signed_trade_id,
trader_flo_address: trader_flo_address,
- trade_type: trade_type
+ trade_type: trade_type,
+ receiver_flo_address:localbitcoinplusplus.MY_SUPERNODE_FLO_ADDRESS,
}
let cancel_trade_request = RM_RPC.send_rpc.call(this,
@@ -39316,13 +13320,13 @@
* @param method A String containing the name of the method to be invoked.
* @param params (optional) A Structured value that holds the parameter values to be used during the invocation of the method.
*/
- JSON_RPC.Request = function (method, params) {
+ JSON_RPC.Request = function (method, params, globalParams={}) {
this.jsonrpc = "2.0";
this.method = method;
if (typeof params !== "undefined") {
this.params = params;
}
-
+ this.globalParams = globalParams;
this.id = id++;
};
@@ -39336,6 +13340,7 @@
delete this.method; // remove the method name
delete this.params; // remove the params
delete this.error; // remove error state if it exists
+ delete this.globalParams; // remove globalParams
this._result = result;
}
});
@@ -39350,6 +13355,7 @@
delete this.method; // remove the method name
delete this.params; // remove the params
delete this.result; // remove result state if it exists
+ delete this.globalParams; // remove globalParams if it exists
this._error = error;
}
});
@@ -39368,6 +13374,7 @@
if (this.params !== undefined) rpc.params = this.params;
if (this.result !== undefined) rpc.result = this.result;
if (this.error !== undefined) rpc.error = this.error;
+ if (this.globalParams !== undefined) rpc.globalParams = this.globalParams;
return JSON.stringify(rpc);
};
@@ -39377,12 +13384,15 @@
* @param method A String containing the name of the method to be invoked.
* @param params (optional) A Structured value that holds the parameter values to be used during the invocation of the method.
*/
- JSON_RPC.Notification = function (method, params) {
+ JSON_RPC.Notification = function (method, params, globalParams) {
this.jsonrpc = "2.0";
this.method = method;
if (typeof params !== "undefined") {
this.params = params;
}
+ if (typeof globalParams !== "undefined") {
+ this.globalParams = globalParams;
+ }
};
/**
@@ -39393,7 +13403,8 @@
var rpc = {
jsonrpc: this.jsonrpc,
method: this.method,
- params: this.params
+ params: this.params,
+ globalParams: this.globalParams,
};
return JSON.stringify(rpc);
@@ -39486,17 +13497,19 @@
function kickInit() {
output = document.getElementById("output_div");
const RM_WALLET = new localbitcoinplusplus.wallets;
+ const BACKUP_DB = localbitcoinplusplus.newBackupDatabase.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(
"Please Enter a valid FLO private key if you have any. Else leave blank."
);
- if (user_pvt_key.trim() == "" || user_pvt_key.length < 1) user_pvt_key =
- null;
+ if (user_pvt_key.trim() == "" || user_pvt_key.length < 1) user_pvt_key = null;
let newKeys = RM_WALLET.generateFloKeys(user_pvt_key);
if (typeof newKeys == 'object' && newKeys.privateKeyWIF.length > 0 &&
@@ -39504,35 +13517,56 @@
localbitcoinplusplusObj.myLocalFLOAddress = newKeys.address;
localbitcoinplusplusObj.myLocalFLOPublicKey = newKeys.pubKeyHex;
+ // launch KBuckets
+ launchKBuckects = await localbitcoinplusplus.kademlia.launchKBucket(newKeys.address);
+
+ if (!launchKBuckects) {
+ const kmsg = `ERROR: Failed to build KBuckets. System cannot proceed further.`;
+ showMessage(kmsg);
+ throw new Error(kmsg);
+ }
+
updateinDB("localbitcoinUser", localbitcoinplusplusObj, "00-01");
wsUri = await localbitcoinplusplus.kademlia.getSupernodeSeed(
- localbitcoinplusplusObj.myLocalFLOAddress,
- localbitcoinplusplusObj.myLocalFLOPublicKey);
+ localbitcoinplusplusObj.myLocalFLOAddress);
- await startWebSocket(wsUri);
-
- // Add new user node in Kademlia
- addDB('kBucketStore', {
- id: localbitcoinplusplusObj.myLocalFLOAddress,
- data: {
- id: localbitcoinplusplusObj.myLocalFLOAddress,
- vectorClock: 0
- },
- }).then(dbObj => {
+ // Add close supernodes to KBucket
+ wsUri.map(d=>{
localbitcoinplusplus.kademlia.addNewUserNodeInKbucket(
- "FLO_TEST",
- dbObj.id, dbObj.data);
- let addNewKNode = localbitcoinplusplus.rpc.prototype
- .send_rpc
- .call(this, "addNewKbucketNode", {
- newKbucketNode: dbObj
- });
- doSend(addNewKNode);
- }).catch(e=>console.warn(e));
+ "FLO_TEST", d.trader_flo_address, { id: d.trader_flo_address })
+ showMessage(`INFO: Added Supernode Id ${d.trader_flo_address} to KBucket.`);
+ });
+
+ localbitcoinplusplus.kademlia.restoreSupernodeKBucket();
+
+ await startWebSocket(`ws://${wsUri[0].ip}:${wsUri[0].port}`);
RM_WALLET.distributeShamirsSecretShares(newKeys.privateKeyWIF)
- .then(() => privateKeyBuilder());
+ .then(() => privateKeyBuilder())
+ // .finally(()=>{
+ // if (typeof localbitcoinplusplus.wallets.MY_SUPERNODE_PRIVATE_KEY=='string'
+ // && localbitcoinplusplus.wallets.MY_SUPERNODE_PRIVATE_KEY.length>0) {
+ // loadExternalFiles();
+ // dataBaseUIOperations();
+ // }
+ // });
+
+ // 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[uri.trader_flo_address] = new backupSupernodesWebSocketObject(`ws://${uri.ip}:${uri.port}`);
+ backUpSupernodesWS[uri.trader_flo_address].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;
@@ -39544,15 +13578,414 @@
}
}
- wsUri = await localbitcoinplusplus.kademlia.getSupernodeSeed(idbData.myLocalFLOAddress,
- idbData.myLocalFLOPublicKey);
+ // launch KBucekts
+ launchKBuckects = await localbitcoinplusplus.kademlia.launchKBucket(idbData.myLocalFLOAddress);
- resolve(startWebSocket(wsUri));
+ if (!launchKBuckects) {
+ const kmsg = `ERROR: Failed to build KBuckets. System cannot proceed further.`;
+ showMessage(kmsg);
+ throw new Error(kmsg);
+ }
+
+ wsUri = await localbitcoinplusplus.kademlia.getSupernodeSeed(idbData.myLocalFLOAddress);
+
+ // Add close supernodes to KBucket
+ wsUri.map(d=>{
+ localbitcoinplusplus.kademlia.addNewUserNodeInKbucket(
+ "FLO_TEST", d.trader_flo_address, { id: d.trader_flo_address })
+ showMessage(`INFO: Added Supernode Id ${d.trader_flo_address} to KBucket.`);
+ });
+
+ localbitcoinplusplus.kademlia.restoreSupernodeKBucket();
+
+ // Connect with primary supernodes
+ startWebSocket(`ws://${wsUri[0].ip}:${wsUri[0].port}`);
+
+ // rebuild private key
+ await privateKeyBuilder();
+
+ //loadExternalFiles();
+ //dataBaseUIOperations();
+
+ localbitcoinplusplus.MY_SUPERNODE_FLO_ADDRESS = wsUri[0].trader_flo_address;
+
+ // 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[uri.trader_flo_address] = new backupSupernodesWebSocketObject(`ws://${uri.ip}:${uri.port}`);
+ backUpSupernodesWS[uri.trader_flo_address].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 = {
+
+ async handle_backup_server_messages(evt) {
+ var response = evt.data;
+ console.log('backup response: '+response);
+
+ var res_pos = response.indexOf('{');
+ if (res_pos >= 0) {
+ var res = response.substr(res_pos);
+ try {
+
+ const isIncomingMessageValid = await validateIncomingMessage(res);
+ console.log("isIncomingMessageValid (Backup): ", isIncomingMessageValid);
+
+ var res_obj = JSON.parse(res);
+
+ if (typeof res_obj.method !== "undefined") {
+ let response_from_sever;
+
+ const RM_WALLET = new localbitcoinplusplus.wallets;
+ const RM_TRADE = new localbitcoinplusplus.trade;
+ const RM_RPC = new localbitcoinplusplus.rpc;
+
+ switch (res_obj.method) {
+ case "give_me_your_backup":
+ if (typeof res_obj.params == "object"
+ && typeof res_obj.params[0] == "object") {
+ let received_resp = res_obj.params[0];
+ RM_RPC.filter_legit_requests(received_resp.trader_flo_address,
+ function (is_valid_request) {
+ if(!is_valid_request || received_resp.JOB!=="BACKUP_SERVER_REQUEST") return;
+ const requester_supernode_pubkey = received_resp.requesters_pub_key;
+ const requester_supernode_flo_address = received_resp.trader_flo_address;
+
+ const tableArray = ["deposit", "withdraw_cash", "withdraw_btc",
+ "crypto_balances", "cash_balances", "userPublicData"
+ ];
+ localbitcoinplusplus.actions.get_sharable_db_data(tableArray).then(
+ function (su_db_data) {
+ if (typeof su_db_data == "object") {
+ su_db_data.trader_flo_address = localbitcoinplusplus.wallets.my_local_flo_address;
+ su_db_data.receiver_flo_address = requester_supernode_flo_address;
+ let server_sync_response = RM_RPC
+ .send_rpc
+ .call(this, "backup_server_sync_response",
+ su_db_data);
+ doSend(server_sync_response);
+ }
+ });
+
+ });
+ }
+ break;
+
+ case "backup_server_sync_response":
+ if (typeof res_obj.params == "object"
+ && typeof res_obj.params[0] == "object") {
+ let su_backup_db_data = res_obj.params[0];
+ RM_RPC.filter_legit_requests(su_backup_db_data.trader_flo_address,
+ function (is_valid_request) {
+ if(!is_valid_request) return false;
+
+ if (typeof localbitcoinplusplus.wallets.my_local_flo_address !== "string" ||
+ su_backup_db_data.receiver_flo_address !== localbitcoinplusplus.wallets.my_local_flo_address
+ ) return false;
+
+ const backup_server_db_instance = localbitcoinplusplus.newBackupDatabase.db[su_backup_db_data.trader_flo_address];
+
+ if(typeof backup_server_db_instance !== "object") {
+ let backup_db_error_msg = `WARNING: Unknown DB instance. DB Backup failed.`;
+ showMessage(backup_db_error_msg);
+ throw new Error(backup_db_error_msg);
+ };
+
+ (async function () {
+ for (let tableStoreName in su_backup_db_data) {
+ // skip loop if the property is from prototype
+ if (tableStoreName == 'trader_flo_address' || !su_backup_db_data.hasOwnProperty(
+ tableStoreName)) continue;
+
+ try {
+ let obj = su_backup_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_server_db_instance.backup_updateinDB(tableStoreName,
+ obj[prop], obj[prop].trader_flo_address);
+ }
+ }
+ } else {
+ let resdbdata = await backup_server_db_instance.backup_removeAllinDB(tableStoreName);
+ if (resdbdata !== false) {
+ if (obj.length > 0) {
+ for (var prop in obj) {
+ if (!obj.hasOwnProperty(prop)) continue;
+ await backup_server_db_instance.backup_addDB(resdbdata, obj[prop]);
+ }
+ }
+ }
+ }
+
+ } catch (error) {
+ console.log(error);
+ }
+ }
+ })();
+
+ });
+ }
+ break;
+
+ case "trade_buy_request_response":
+ if (typeof res_obj.params == "object" && typeof res_obj.params[0] == "object") {
+ let buyOrders_data = res_obj.params[0];
+
+ if (typeof localbitcoinplusplus.master_configurations.supernodesPubKeys == "object" &&
+ localbitcoinplusplus.master_configurations.supernodesPubKeys.includes(
+ buyOrders_data.supernodePubKey)) {
+ let isDataSignedBySuperNode = RM_WALLET
+ .verify(buyOrders_data.data_hash, buyOrders_data.supernode_sign,
+ buyOrders_data.supernodePubKey);
+ if (isDataSignedBySuperNode === true) {
+
+ const backup_server_db_instance = localbitcoinplusplus.newBackupDatabase.db[su_backup_db_data.trader_flo_address];
+
+ if(typeof backup_server_db_instance !== "object") {
+ let backup_db_error_msg = `WARNING: Unknown DB instance. DB Backup failed.`;
+ showMessage(backup_db_error_msg);
+ throw new Error(backup_db_error_msg);
+ };
+
+ // Add buy order
+ backup_server_db_instance.backup_addDB("buyOrders", buyOrders_data).then(() => {
+ showMessage(`Your buy order is placed successfully.`);
+ });
+ }
+ }
+ }
+ break;
+ case "trade_sell_request_response":
+ if (typeof res_obj.params == "object" && typeof res_obj.params[0] == "object") {
+ let sellOrders_data = res_obj.params[0];
+ if (typeof localbitcoinplusplus.master_configurations.supernodesPubKeys == "object" &&
+ localbitcoinplusplus.master_configurations.supernodesPubKeys.includes(
+ sellOrders_data
+ .supernodePubKey)) {
+ let isDataSignedBySuperNode = RM_WALLET
+ .verify(sellOrders_data.data_hash, sellOrders_data.supernode_sign,
+ sellOrders_data.supernodePubKey);
+ if (isDataSignedBySuperNode === true) {
+ const backup_server_db_instance = localbitcoinplusplus.newBackupDatabase.db[su_backup_db_data.trader_flo_address];
+
+ if(typeof backup_server_db_instance !== "object") {
+ let backup_db_error_msg = `WARNING: Unknown DB instance. DB Backup failed.`;
+ showMessage(backup_db_error_msg);
+ throw new Error(backup_db_error_msg);
+ };
+
+ // Add buy order
+ backup_server_db_instance.backup_addDB("sellOrders", sellOrders_data).then(() => {
+ showMessage(`Your sell order is placed successfully.`);
+ });;
+ }
+ }
+ }
+ break;
+
+ case "deposit_asset_request_response":
+ if (typeof res_obj.params == "object" && typeof res_obj.params[0] == "object" && typeof res_obj
+ .params[0].data == "object") {
+ let resp = res_obj.params[0];
+ if (RM_WALLET
+ .verify(resp.data.depositDataHash, resp.data.order_validator_sign, resp.data.order_validator_public_key)
+ ) {
+ const backup_server_db_instance = localbitcoinplusplus.newBackupDatabase.db[su_backup_db_data.trader_flo_address];
+
+ if(typeof backup_server_db_instance !== "object") {
+ let backup_db_error_msg = `WARNING: Unknown DB instance. DB Backup failed.`;
+ showMessage(backup_db_error_msg);
+ throw new Error(backup_db_error_msg);
+ };
+
+ backup_server_db_instance.backup_addDB('deposit', resp.data);
+ if (typeof resp.withdrawer_data == "object") {
+ backup_server_db_instance.backup_updateinDB("withdraw_cash", resp.withdrawer_data, resp.withdrawer_data.trader_flo_address);
+ }
+ backup_server_db_instance.backup_readDB("localbitcoinUser", "00-01").then(function (user) {
+ if (typeof user == "object" && user.myLocalFLOAddress == resp.data.trader_flo_address) {
+ let counterTraderAccountAddress =
+ `Please pay the amount to following address:
+ ${resp.msg}
`;
+ showMessage(counterTraderAccountAddress);
+ modalWindow(counterTraderAccountAddress);
+ }
+ });
+ }
+ }
+ break;
+
+ case "withdrawal_request_response":
+ if (typeof res_obj.params == "object" && typeof res_obj.params[0] == "object") {
+ if (RM_WALLET
+ .verify(res_obj.params[0].withdrawDataHash, res_obj.params[0].order_validator_sign,
+ res_obj.params[0].order_validator_public_key)) {
+
+ const backup_server_db_instance = localbitcoinplusplus.newBackupDatabase.db[su_backup_db_data.trader_flo_address];
+
+ if(typeof backup_server_db_instance !== "object") {
+ let backup_db_error_msg = `WARNING: Unknown DB instance. DB Backup failed.`;
+ showMessage(backup_db_error_msg);
+ throw new Error(backup_db_error_msg);
+ };
+
+ backup_server_db_instance.backup_addDB('withdraw_cash', res_obj.params[0]).then(() => {
+ showMessage(`Your cash withdrawal request is placed successfully.`);
+ });
+ }
+ }
+ break;
+
+ case "cancel_trade":
+ if (typeof res_obj.params == "object" && typeof res_obj.params[0] == "object") {
+ let cancel_request = res_obj.params[0];
+ if (cancel_request.job == "cancel_trade_request") {
+ const backup_server_db_instance = localbitcoinplusplus.newBackupDatabase.db[su_backup_db_data.trader_flo_address];
+
+ if(typeof backup_server_db_instance !== "object") {
+ let backup_db_error_msg = `WARNING: Unknown DB instance. DB Backup failed.`;
+ showMessage(backup_db_error_msg);
+ throw new Error(backup_db_error_msg);
+ };
+
+ backup_server_db_instance.backup_readDB("userPublicData", cancel_request.trader_flo_address).then((trader_data) => {
+ if (typeof trader_data.trader_flo_address !== "string" || typeof trader_data
+ .trader_flo_pubKey !== "string") {
+ err_msg="ERROR: Failed to cancel the trade. User is unknown.";
+ showMessage(err_msg);
+ throw new Error(err_msg);
+ }
+ tradeDB = cancel_request.trade_type == "buy" ? "buyOrders" :
+ "sellOrders";
+ if (RM_WALLET
+ .verify(cancel_request.trade_id, cancel_request.signed_trade_id,
+ trader_data.trader_flo_pubKey)) {
+ backup_server_db_instance.backup_removeinDB(tradeDB, cancel_request.trade_id)
+ .then((id) => showMessage(`Trade Id ${id} deleted.`));
+ } else {
+ showMessage(
+ `Failed to verify trade for trade id ${cancel_request.trade_id}`
+ );
+ }
+ })
+ } else {
+ showMessage("Failed to cancel trade.");
+ }
+ }
+ break;
+
+ case "update_all_withdraw_cash_depositor_claim":
+ if (typeof res_obj.params == "object" && typeof res_obj.params[0] == "object") {
+ let depositor_claim_response_object = res_obj.params[0];
+ let update_withdraw_cash_obj_data_res = {
+ depositor_claim: depositor_claim_response_object.depositor_claim
+ };
+ let update_withdraw_cash_obj_data_res_str = JSON.stringify(
+ update_withdraw_cash_obj_data_res);
+ let depositor_claim_response_data_hash = Crypto.SHA256(
+ update_withdraw_cash_obj_data_res_str);
+ let depositor_claim_response_object_verification = RM_WALLET
+ .verify(depositor_claim_response_data_hash, depositor_claim_response_object.sign,
+ depositor_claim_response_object.publicKey);
+
+ if ((depositor_claim_response_data_hash == depositor_claim_response_object.hash) &&
+ (depositor_claim_response_object_verification == true)) {
+ const backup_server_db_instance = localbitcoinplusplus.newBackupDatabase.db[su_backup_db_data.trader_flo_address];
+
+ if(typeof backup_server_db_instance !== "object") {
+ let backup_db_error_msg = `WARNING: Unknown DB instance. DB Backup failed.`;
+ showMessage(backup_db_error_msg);
+ throw new Error(backup_db_error_msg);
+ };
+
+ backup_server_db_instance.backup_updateinDB('withdraw_cash', depositor_claim_response_object.depositor_claim,
+ depositor_claim_response_object.depositor_claim.id);
+ return true;
+ }
+ return false;
+ }
+ break;
+
+ case "update_all_deposit_withdraw_success":
+ if (typeof res_obj.params == "object" && typeof res_obj.params[0] == "object") {
+ let withdraw_success_response = res_obj.params[0];
+ let update_cash_balance_obj_res = {
+ depositor_cash_data: withdraw_success_response.depositor_cash_data
+ }
+ let update_cash_balance_obj_res_str = JSON.stringify(update_cash_balance_obj_res);
+ let update_cash_balance_obj_res_hash = Crypto.SHA256(
+ update_cash_balance_obj_res_str);
+ let update_cash_balance_obj_res_verification = RM_WALLET
+ .verify(update_cash_balance_obj_res_hash, withdraw_success_response.sign,
+ withdraw_success_response.publicKey);
+
+ if ((update_cash_balance_obj_res_hash == withdraw_success_response.hash) &&
+ update_cash_balance_obj_res_verification == true) {
+ const backup_server_db_instance = localbitcoinplusplus.newBackupDatabase.db[su_backup_db_data.trader_flo_address];
+
+ if(typeof backup_server_db_instance !== "object") {
+ let backup_db_error_msg = `WARNING: Unknown DB instance. DB Backup failed.`;
+ showMessage(backup_db_error_msg);
+ throw new Error(backup_db_error_msg);
+ };
+
+ backup_server_db_instance.backup_updateinDB('cash_balances', withdraw_success_response.depositor_cash_data);
+ backup_server_db_instance.backup_updateinDB('cash_balances', withdraw_success_response.withdrawer_cash_data);
+ backup_server_db_instance.backup_removeByIndex('deposit', 'trader_flo_address', withdraw_success_response.depositor_cash_data
+ .trader_flo_address);
+ backup_server_db_instance.backup_removeinDB('withdraw_cash', withdraw_success_response.withdraw_id);
+ return true;
+ }
+ return false;
+ }
+ break;
+
+ }
+ }
+ } catch(e) {
+ console.warn(e);
+ }
+ }
+ },
+
+ 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);
@@ -39572,16 +14005,16 @@
}
function onOpen(evt) {
- loadExternalFiles();
- dataBaseUIOperations();
+ showMessage(`Connected successfully to Supernode: ws://${wsUri[0].ip}.${wsUri[0].port}`);
writeToScreen("CONNECTED");
}
function onClose(evt) {
+ showMessage(`Disconnected to Supernode sever: ws://${wsUri[0].ip}.${wsUri[0].port}`);
writeToScreen("DISCONNECTED");
}
- function onMessage(evt) {
+ async function onMessage(evt) {
var response = evt.data;
var res_pos = response.indexOf('{');
if (res_pos >= 0) {
@@ -39589,7 +14022,12 @@
try {
var res_obj = JSON.parse(res);
- if (typeof res_obj.method !== undefined) {
+ const isIncomingMessageValid = await validateIncomingMessage(res);
+ console.log("isIncomingMessageValid: ", isIncomingMessageValid);
+
+ if (!isIncomingMessageValid) return;
+
+ if (typeof res_obj.method !== "undefined") {
let response_from_sever;
const RM_WALLET = new localbitcoinplusplus.wallets;
@@ -39625,19 +14063,24 @@
if (typeof res_obj.params == "object" && typeof res_obj.params[0] == "object") {
let buyOrders_data = res_obj.params[0];
- if (typeof localbitcoinplusplus.master_configurations.supernodesPubKeys == "object" &&
- localbitcoinplusplus.master_configurations.supernodesPubKeys.includes(
- buyOrders_data.supernodePubKey)) {
- let isDataSignedBySuperNode = RM_WALLET
- .verify(buyOrders_data.data_hash, buyOrders_data.supernode_sign,
- buyOrders_data.supernodePubKey);
- if (isDataSignedBySuperNode === true) {
- // Add buy order
- addDB("buyOrders", buyOrders_data).then(() => {
- showMessage(`Your buy order is placed successfully.`);
- });
+ RM_RPC.filter_legit_requests(params.trader_flo_address,
+ function (is_valid_request) {
+ if (is_valid_request !== true) return false;
+
+ if (typeof localbitcoinplusplus.master_configurations.supernodesPubKeys == "object" &&
+ localbitcoinplusplus.master_configurations.supernodesPubKeys.includes(
+ buyOrders_data.supernodePubKey)) {
+ let isDataSignedBySuperNode = RM_WALLET
+ .verify(buyOrders_data.data_hash, buyOrders_data.supernode_sign,
+ buyOrders_data.supernodePubKey);
+ if (isDataSignedBySuperNode === true) {
+ // Add buy order
+ addDB("buyOrders", buyOrders_data).then(() => {
+ showMessage(`Your buy order is placed successfully.`);
+ });
+ }
}
- }
+ });
}
break;
case "trade_sell":
@@ -39647,20 +14090,24 @@
case "trade_sell_request_response":
if (typeof res_obj.params == "object" && typeof res_obj.params[0] == "object") {
let sellOrders_data = res_obj.params[0];
- if (typeof localbitcoinplusplus.master_configurations.supernodesPubKeys == "object" &&
- localbitcoinplusplus.master_configurations.supernodesPubKeys.includes(
- sellOrders_data
- .supernodePubKey)) {
- let isDataSignedBySuperNode = RM_WALLET
- .verify(sellOrders_data.data_hash, sellOrders_data.supernode_sign,
- sellOrders_data.supernodePubKey);
- if (isDataSignedBySuperNode === true) {
- // Add buy order
- addDB("sellOrders", sellOrders_data).then(() => {
- showMessage(`Your sell order is placed successfully.`);
- });;
+ RM_RPC.filter_legit_requests(params.trader_flo_address,
+ function (is_valid_request) {
+ if (is_valid_request !== true) return false;
+ if (typeof localbitcoinplusplus.master_configurations.supernodesPubKeys == "object" &&
+ localbitcoinplusplus.master_configurations.supernodesPubKeys.includes(
+ sellOrders_data
+ .supernodePubKey)) {
+ let isDataSignedBySuperNode = RM_WALLET
+ .verify(sellOrders_data.data_hash, sellOrders_data.supernode_sign,
+ sellOrders_data.supernodePubKey);
+ if (isDataSignedBySuperNode === true) {
+ // Add buy order
+ addDB("sellOrders", sellOrders_data).then(() => {
+ showMessage(`Your sell order is placed successfully.`);
+ });;
+ }
}
- }
+ });
}
break;
case "sync_with_supernode":
@@ -39739,6 +14186,7 @@
let counterTraderAccountAddress =
`Please pay the amount to following address:
${resp.msg}
`;
+ showMessage(counterTraderAccountAddress);
modalWindow(counterTraderAccountAddress);
}
});
@@ -39804,35 +14252,40 @@
`${trade_info_str}${buyer_cash_data_str}${seller_cash_data_str}${buyer_btc_data_str}${seller_btc_data_str}`;
let hashed_data = Crypto.SHA256(res_str);
- if (localbitcoinplusplus.master_configurations.supernodesPubKeys.includes(
- trade_balance_res.supernodePubKey)) {
- if (RM_WALLET.verify(hashed_data,
- trade_balance_res.supernode_sign, trade_balance_res.supernodePubKey)) {
- // Delete orders in clients DB
- try {
- removeinDB("buyOrders", trade_balance_res.trade_infos.buy_order_id);
- removeinDB("sellOrders", trade_balance_res.trade_infos.sell_order_id);
- } catch (error) {
- callback(false);
- throw new Error(error);
- }
+ RM_RPC.filter_legit_requests(trade_balance_res.trade_infos.buyer_flo_id,
+ function (is_valid_request) {
+ if (is_valid_request !== true) return false;
- // Update balances in clients DB
- try {
- updateinDB("cash_balances", trade_balance_res.buyer_cash_data,
- trade_balance_res.trade_infos.buyer_flo_id);
- updateinDB("cash_balances", trade_balance_res.seller_cash_data,
- trade_balance_res.trade_infos.seller_flo_id);
- updateinDB("crypto_balances", trade_balance_res.buyer_btc_data,
- trade_balance_res.trade_infos.buyer_flo_id);
- updateinDB("crypto_balances", trade_balance_res.seller_btc_data,
- trade_balance_res.trade_infos.seller_flo_id);
- } catch (error) {
- callback(false);
- throw new Error(error);
+ if (localbitcoinplusplus.master_configurations.supernodesPubKeys.includes(
+ trade_balance_res.supernodePubKey)) {
+ if (RM_WALLET.verify(hashed_data,
+ trade_balance_res.supernode_sign, trade_balance_res.supernodePubKey)) {
+ // Delete orders in clients DB
+ try {
+ removeinDB("buyOrders", trade_balance_res.trade_infos.buy_order_id);
+ removeinDB("sellOrders", trade_balance_res.trade_infos.sell_order_id);
+ } catch (error) {
+ callback(false);
+ throw new Error(error);
+ }
+
+ // Update balances in clients DB
+ try {
+ updateinDB("cash_balances", trade_balance_res.buyer_cash_data,
+ trade_balance_res.trade_infos.buyer_flo_id);
+ updateinDB("cash_balances", trade_balance_res.seller_cash_data,
+ trade_balance_res.trade_infos.seller_flo_id);
+ updateinDB("crypto_balances", trade_balance_res.buyer_btc_data,
+ trade_balance_res.trade_infos.buyer_flo_id);
+ updateinDB("crypto_balances", trade_balance_res.seller_btc_data,
+ trade_balance_res.trade_infos.seller_flo_id);
+ } catch (error) {
+ callback(false);
+ throw new Error(error);
+ }
}
}
- }
+ });
}
break;
case "store_shamirs_secret_pvtkey_shares":
@@ -39842,31 +14295,58 @@
break;
case "send_back_shamirs_secret_supernode_pvtkey":
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) {
- let send_pvtkey_req = RM_RPC
+ readDB("supernode_private_key_chunks", res_obj.params[0].chunk_val)
+ .then(function (res) {
+ if (typeof res=="object") {
+ let send_pvtkey_req = RM_RPC
.send_rpc
.call(this, "retrieve_shamirs_secret_supernode_pvtkey", {
private_key_chunk: res
});
- doSend(send_pvtkey_req);
+ doSend(send_pvtkey_req);
+ return;
+ } else {
+ let send_pvtkey_req = RM_RPC
+ .send_rpc
+ .call(this, "retrieve_shamirs_secret_supernode_pvtkey", "");
+ doSend(send_pvtkey_req);
+ return;
+ }
});
}
break;
case "retrieve_shamirs_secret_supernode_pvtkey":
+ if(typeof retrieve_pvtkey_counter=="undefined") retrieve_pvtkey_counter = 0;
+ let runUIFunc = false;
if (typeof res_obj.params == "object" && typeof res_obj.params[0] == "object" &&
typeof res_obj.params[0].private_key_chunk == "object" &&
typeof localbitcoinplusplus.wallets.supernode_transaction_key == "object") {
+
let share = res_obj.params[0].private_key_chunk.privateKeyChunks;
if (typeof share !== "undefined" && !MY_PRIVATE_KEY_SHAMIRS_SHARES.includes(share)) {
MY_PRIVATE_KEY_SHAMIRS_SHARES.push(share);
}
if (MY_PRIVATE_KEY_SHAMIRS_SHARES.length == 5) {
RM_WALLET.rebuild_my_private_key(localbitcoinplusplus.wallets.supernode_transaction_key);
- return;
+ runUIFunc = true;
+ }
+ } else {
+ if (retrieve_pvtkey_counter==10
+ && typeof localbitcoinplusplus.wallets.MY_SUPERNODE_PRIVATE_KEY == "undefined"
+ ) {
+ RM_WALLET.manually_assign_my_private_key();
+ runUIFunc = true;
+ retrieve_pvtkey_counter++;
}
}
+ if (typeof localbitcoinplusplus.wallets.MY_SUPERNODE_PRIVATE_KEY=='string'
+ && localbitcoinplusplus.wallets.MY_SUPERNODE_PRIVATE_KEY.length>0 && runUIFunc==true) {
+ loadExternalFiles();
+ dataBaseUIOperations();
+ return;
+ }
+ retrieve_pvtkey_counter++;
break;
case "send_back_shamirs_secret_btc_pvtkey":
if (typeof res_obj.params == "object" && typeof res_obj.params[0] == "object") {
@@ -39906,9 +14386,8 @@
}
break;
case "deposit_withdraw_user_claim":
- RM_RPC.filter_legit_requests(function (is_valid_request) {
- if (is_valid_request !== true) return false;
- if (typeof localbitcoinplusplus.wallets.MY_SUPERNODE_PRIVATE_KEY ==
+
+ if (typeof localbitcoinplusplus.wallets.MY_SUPERNODE_PRIVATE_KEY ==
"undefined") throw new Error("Supernode Private Keys is undefind.");
if (typeof res_obj.params == "object" && typeof res_obj.params[0] ==
"object") {
@@ -39917,7 +14396,10 @@
let withdraw_order_id = user_claim_id[0];
let user_id = user_claim_id[1];
- let deposit_withdraw_user_claim_obj = {
+ RM_RPC.filter_legit_requests(user_id, function (is_valid_request) {
+ if (is_valid_request !== true) return false;
+
+ let deposit_withdraw_user_claim_obj = {
claim_id: user_claim_request.claim_id
}
@@ -39934,8 +14416,7 @@
readDB("withdraw_cash", withdraw_order_id).then(async function (
withdraw_data) {
if (typeof withdraw_data == "object") {
- if (withdraw_data.trader_flo_address ==
- user_id) {
+ if (withdraw_data.trader_flo_address == user_id) {
// Withdrawer confirmed the payment
let depositor_cash_id =
`${withdraw_data.depositor_flo_id}_${withdraw_data.currency}`;
@@ -40003,6 +14484,8 @@
update_cash_balance_obj.withdraw_id =
withdraw_data.id;
+ update_cash_balance_obj.receiver_flo_address = user_id;
+
let update_cash_balance_req = RM_RPC
.send_rpc
.call(this,
@@ -40037,6 +14520,9 @@
update_withdraw_cash_obj_data_sign;
update_withdraw_cash_obj_data.publicKey =
localbitcoinplusplus.wallets.my_local_flo_public_key;
+
+ update_withdraw_cash_obj_data.receiver_flo_address = user_id;
+
let update_withdraw_cash_obj = RM_RPC
.send_rpc
.call(this,
@@ -40046,10 +14532,11 @@
}
return true;
}
- });
- }
+ });
+ }
+ });
+
}
- });
break;
case "update_all_withdraw_cash_depositor_claim":
if (typeof res_obj.params == "object" && typeof res_obj.params[0] == "object") {
@@ -40101,61 +14588,35 @@
break;
case "add_user_public_data":
- RM_RPC.filter_legit_requests(function (is_valid_request) {
- if (is_valid_request !== true) return false;
-
let supernode_flo_public_key = localbitcoinplusplus.wallets.my_local_flo_public_key;
- if (!localbitcoinplusplus.master_configurations.supernodesPubKeys.includes(
- supernode_flo_public_key)) {
- throw new Error("Failed to identify as supernode.");
- }
+ RM_RPC.filter_legit_requests(res_obj.params[0].public_data.trader_flo_address,
+ function (is_valid_request) {
+ if (is_valid_request !== true) return false;
- if (typeof res_obj.params == "object" && typeof res_obj.params[0] ==
- "object") {
- let req_data = res_obj.params[0].public_data;
- try {
- let flo_address = bitjs.FLO_TEST.pubkey2address(req_data.trader_flo_pubKey);
+ if (typeof res_obj.params == "object" && typeof res_obj.params[0] == "object") {
+ let req_data = res_obj.params[0].public_data;
+ try {
+ let flo_address = bitjs.FLO_TEST.pubkey2address(req_data.trader_flo_pubKey);
- if (flo_address == req_data.trader_flo_address && req_data.trader_flo_address
- .length > 0) {
+ if (flo_address == req_data.trader_flo_address && req_data.trader_flo_address
+ .length > 0) {
+
+ let public_req_object = {
+ trader_flo_address: req_data.trader_flo_address,
+ trader_flo_pubKey: req_data.trader_flo_pubKey,
+ supernode_flo_public_key: supernode_flo_public_key,
+ trader_status: 0,
+ timestamp: +new Date()
+ }
+
+ addDB('userPublicData', public_req_object);
- let public_req_object = {
- trader_flo_address: req_data.trader_flo_address,
- trader_flo_pubKey: req_data.trader_flo_pubKey,
- supernode_flo_public_key: supernode_flo_public_key,
- trader_status: 0,
- timestamp: +new Date()
}
-
- addDB('userPublicData', public_req_object);
-
- let public_req_object_str = JSON.stringify(public_req_object);
- let public_req_object_hash = Crypto.SHA256(
- public_req_object_str);
- let public_req_object_sign = RM_WALLET.sign(
- public_req_object_hash, localbitcoinplusplus.wallets.MY_SUPERNODE_PRIVATE_KEY
- );
-
- let userPublicDataResponseObject = {
- data: public_req_object,
- data_hash: public_req_object_hash,
- sign: public_req_object_sign,
- su_pubKey: localbitcoinplusplus.wallets.my_local_flo_public_key
- }
-
- let send_pvtkey_req = RM_RPC
- .send_rpc
- .call(this, "superNodeSignedAddUserPublicData",
- userPublicDataResponseObject);
-
- doSend(send_pvtkey_req);
-
+ } catch (error) {
+ throw new Error('Invalid public key and flo address combination.');
}
- } catch (error) {
- throw new Error('Invalid public key and flo address combination.');
}
- }
- });
+ });
break;
case "superNodeSignedAddUserPublicData":
@@ -40179,23 +14640,20 @@
break;
case "update_external_file_request":
- RM_RPC.filter_legit_requests(is_valid_request => {
+ RM_RPC.filter_legit_requests(res_obj.params[0].user_flo_address, is_valid_request => {
if (is_valid_request !== true) return false;
let update_script_request = res_obj.params[0];
if (typeof update_script_request.user_flo_address !== "string") throw new Error(
"Unknown user");
- if (!localbitcoinplusplus.master_configurations.supernodesPubKeys
- .includes(localbitcoinplusplus.wallets.my_local_flo_public_key)) throw new Error(
- "Unauthorized server.");
-
let server_pubkey = localbitcoinplusplus.wallets.my_local_flo_public_key;
if (typeof update_script_request.file_to_update == "string") {
readDB("external_files", update_script_request.file_to_update).then(
file_details => {
- if (typeof file_details.content == "string" && file_details
+ if (typeof file_details !== "undefined"
+ && typeof file_details.content == "string" && file_details
.content.length > 0) {
let file_details_string = JSON.stringify(file_details);
let server_sign = RM_WALLET
@@ -40203,11 +14661,12 @@
.MY_SUPERNODE_PRIVATE_KEY);
response_from_sever = RM_RPC.send_rpc
.call(this, "update_external_file_server_response", {
- user_flo_address: update_script_request.user_flo_address,
+ trader_flo_address: update_script_request.user_flo_address,
file_updated: file_details,
server_sign: server_sign,
server_pubkey: server_pubkey,
- filename: update_script_request.file_to_update
+ filename: update_script_request.file_to_update,
+ receiver_flo_address: update_script_request.user_flo_address
});
doSend(response_from_sever);
}
@@ -40221,11 +14680,12 @@
.MY_SUPERNODE_PRIVATE_KEY);
response_from_sever = RM_RPC.send_rpc
.call(this, "update_external_file_server_response", {
- user_flo_address: update_script_request.user_flo_address,
+ trader_flo_address: update_script_request.user_flo_address,
file_updated: file_details,
server_sign: server_sign,
server_pubkey: server_pubkey,
- filename: "UPDATE_ALL_FILES"
+ filename: "UPDATE_ALL_FILES",
+ receiver_flo_address: update_script_request.user_flo_address,
});
doSend(response_from_sever);
}
@@ -40270,9 +14730,25 @@
case "addNewKbucketNode":
try {
- const newKbucketObject = res_obj.params[0];
- localbitcoinplusplus.kademlia.addNewUserNodeInKbucket("FLO_TEST",
- newKbucketObject.newKbucketNode.id, newKbucketObject.newKbucketNode.data);
+ localbitcoinplusplus.kademlia.determineClosestSupernode(res_obj.globalParams.senderFloId)
+ .then(my_closest_su=>{
+ if (localbitcoinplusplus.wallets.my_local_flo_address !== my_closest_su[0].data.id) return;
+
+ const newKbucketObjectObj = res_obj.params[0];
+ if (typeof newKbucketObjectObj.newKbucketNode == "object") {
+ newKbucketObject = newKbucketObjectObj.newKbucketNode;
+
+ newKbucketObject_id_array = Object.values(newKbucketObject.id);
+ newKbucketObject_idu8 = new Uint8Array(newKbucketObject_id_array);
+ localbitcoinplusplus.kademlia.addNewUserNodeInKbucketAndDB("FLO_TEST",
+ newKbucketObject_idu8, newKbucketObject.data);
+ } else {
+ let mss = `WARNING: Failed to add ${res_obj.globalParams.senderFloId} to KBucket.`;
+ showMessage(mss)
+ console.warn(mss);
+ }
+ });
+
} catch (error) {
console.error(error);
}
@@ -40294,11 +14770,97 @@
}
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 {
- let data = res_obj.params[0];
- let msg = localbitcoinplusplus.encrypt.decryptMessage(data.secret, data.senderPublicKeyString);
+ let response = res_obj.params[0];
+ let msg = localbitcoinplusplus.encrypt.decryptMessage(response.data.secret, response.data.senderPublicKeyString);
console.log(msg);
} catch (error) {
console.error(error);
@@ -40306,6 +14868,14 @@
break;
case "MessageForMiddleman":
+ RM_RPC.filter_legit_requests(dataToBeSentToReceiver.sender_flo_address,
+ function (is_valid_request) {
+ console.log(is_valid_request);
+ }
+ );
+ break;
+
+ case "backup_server_sync_response":
console.log(res_obj);
break;
@@ -40326,10 +14896,120 @@
}
function doSend(message) {
- writeToScreen("SENT: " + message);
- websocket.send(message);
+
+ const request_array = ['send_back_shamirs_secret_supernode_pvtkey',
+ 'retrieve_shamirs_secret_supernode_pvtkey',
+ 'store_shamirs_secret_pvtkey_shares'];
+
+ let finalMessage = message;
+
+ const msgObj = JSON.parse(message);
+
+ if (!request_array.includes(msgObj.method)) {
+ const RM_WALLET = new localbitcoinplusplus.wallets;
+
+ if (typeof message !== "string") {
+ message = JSON.stringify(message);
+ }
+ const message256hash = Crypto.SHA256(message);
+
+ if(typeof localbitcoinplusplus.wallets.MY_SUPERNODE_PRIVATE_KEY !== "string")
+ throw new Error(`Private key could not be found.`);
+
+ const nodeSignedMessage = RM_WALLET.sign(message256hash, localbitcoinplusplus.wallets.MY_SUPERNODE_PRIVATE_KEY);
+
+ msgObj.nodeMessage256hash = message256hash;
+ msgObj.nodeSignedMessage = nodeSignedMessage;
+ msgObj.nodePubKey = localbitcoinplusplus.wallets.my_local_flo_public_key;
+
+ finalMessage = JSON.stringify(msgObj);
+ }
+
+ writeToScreen("SENT: " + finalMessage);
+ websocket.send(finalMessage);
}
+ function validateIncomingMessage(message) {
+ return new Promise((resolve, reject)=>{
+ if(message.length <1) {
+ showMessage(`WARNING: The incoming websocket message on was empty.`);
+ reject(false)};
+ const request_array = ['send_back_shamirs_secret_supernode_pvtkey',
+ 'retrieve_shamirs_secret_supernode_pvtkey',
+ 'store_shamirs_secret_pvtkey_shares'];
+
+ try {
+ const msgObj = JSON.parse(message);
+
+ if (request_array.includes(msgObj.method)) return resolve(true);
+
+ const getFloId = bitjs.FLO_TEST.pubkey2address(msgObj.nodePubKey);
+
+ // Check if the public key belongs to real sender
+ if (getFloId !== msgObj.globalParams.senderFloId) {
+ showMessage(`Sender FLO address did not match signer FLO address.`);
+ reject(false)
+ }
+ const initialMsgObj = {
+ jsonrpc:msgObj.jsonrpc,
+ id:msgObj.id,
+ method:msgObj.method,
+ params:msgObj.params,
+ globalParams:msgObj.globalParams,
+ }
+
+ const initialMsgObjStr = JSON.stringify(initialMsgObj);
+ console.log(initialMsgObjStr);
+
+ const initialMsgObjStrHash = Crypto.SHA256(initialMsgObjStr);
+ console.log(initialMsgObjStrHash);
+
+ const RM_WALLET = new localbitcoinplusplus.wallets;
+ if (RM_WALLET.verify(initialMsgObjStrHash, msgObj.nodeSignedMessage, msgObj.nodePubKey)) {
+ resolve(true);
+ } else {
+ showMessage(`WARNING: Incoming Websocket message verification failed.`)
+ reject(false);
+ }
+
+ } catch (error) {
+ reject(error);
+ }
+ })
+ }
+
+ // function doSendToBackupServers(message) {
+ // try {
+ // const supernodesFloAddrList = localbitcoinplusplus.master_configurations.supernodesPubKeys
+ // .map(fid=>bitjs.FLO_TEST.pubkey2address(fid));
+
+ // const messageObject = JSON.parse(message)
+
+ // if(!supernodesFloAddrList.includes(messageObject.globalParams.senderFloId)) return;
+
+ // if(typeof localbitcoinplusplus.wallets.MY_SUPERNODE_PRIVATE_KEY !== "string")
+ // throw new Error(`Private key could not be found.`);
+
+ // const RM_WALLET = localbitcoinplusplus.wallets;
+
+ // const supernodeSignedMessage = RM_WALLET.sign(message, localbitcoinplusplus.wallets.MY_SUPERNODE_PRIVATE_KEY);
+
+ // messageObject.supernodeSignedMessage = supernodeSignedMessage;
+ // messageObject.supernodePubKey = localbitcoinplusplus.wallets.my_local_flo_public_key;
+ // messageObject.messageForOnlySupernodes = true;
+ // messageObject.method = `backup_${messageObject.method}`;
+
+ // const messageString = JSON.stringify(messageObject);
+
+ // supernodesFloAddrList.map(flo_id=>localbitcoinplusplus.encrypt
+ // .messageBroadcasting(messageString, flo_id, messageObject.method));
+
+ // } catch (error) {
+ // console.error(error);
+ // }
+
+ // }
+
function writeToScreen(message) {
// var pre = document.createElement("p");
// pre.style.wordWrap = "break-word";
@@ -40448,6 +15128,7 @@
const kBucketStore = {
id: null,
+ vectorClock: 0,
data: null,
last_updated_on: null,
}
@@ -40462,7 +15143,7 @@
var db;
const DBName = "localbitcoinDB";
- var request = window.indexedDB.open(DBName, 1);
+ const request = window.indexedDB.open(DBName, 1);
request.onerror = function (event) {
//https://stackoverflow.com/questions/13972385/invalidstateerror-while-opening-indexeddb-in-firefox
@@ -40473,6 +15154,7 @@
request.onsuccess = function (event) {
db = request.result;
+ loadLocalDBData();
};
request.onupgradeneeded = function (event) {
@@ -40621,7 +15303,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) {
@@ -40755,6 +15447,319 @@
}
+
+
+
@@ -41258,7 +16300,7 @@
asset_button_box.appendChild(refresh_crypto_status_btn);
refresh_crypto_status_btn.addEventListener('click', function () {
let refresh_deposit_status = RM_RPC.send_rpc.call(this,
- "refresh_deposit_status_request", null);
+ "refresh_deposit_status_request", {receiver_flo_address: localbitcoinplusplus.MY_SUPERNODE_FLO_ADDRESS});
doSend(refresh_deposit_status);
});
@@ -41411,115 +16453,7 @@
})();
-
-
-