From 601780cd27901dd53b2c4076681b66002988078b Mon Sep 17 00:00:00 2001 From: sairajzero Date: Wed, 4 Sep 2019 14:12:04 +0530 Subject: [PATCH] Adding Group Feature --- app/app.js | 601 +++++++++++++++++++++++++++------ app/index.html | 19 +- app/{registerID.js => init.js} | 141 +------- 3 files changed, 519 insertions(+), 242 deletions(-) rename app/{registerID.js => init.js} (95%) diff --git a/app/app.js b/app/app.js index d57d5c5..5a4d2c2 100644 --- a/app/app.js +++ b/app/app.js @@ -7,17 +7,17 @@ if (!window.indexedDB) { window.alert("Your browser doesn't support a stable version of IndexedDB.") } -var contacts = []; -var receiverID,selfID,recStat; +var contacts = [], groups = []; +var receiverID,selfID,recStat,modSuperNode, msgType; var selfwebsocket,receiverWebSocket,receiverSuperNodeWS; var privKey; -var encrypt = { +var floOpt = { p: BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", 16), exponent1: function () { - return encrypt.p.add(BigInteger.ONE).divide(BigInteger("4")) + return floOpt.p.add(BigInteger.ONE).divide(BigInteger("4")) }, calculateY: function (x) { @@ -105,7 +105,7 @@ var encrypt = { } }, - encryptMessage: function (data, receiverCompressedPublicKey) { + encryptData: function (data, receiverCompressedPublicKey) { var senderECKeyData = this.getSenderPublicKeyString(); var senderDerivedKey = { XValue: "", @@ -123,13 +123,12 @@ var encrypt = { }; }, - decryptMessage: function (secret, senderPublicKeyString) { + decryptData: function (secret, senderPublicKeyString,myPrivateKey) { var receiverDerivedKey = { XValue: "", YValue: "" }; var receiverECKeyData = {}; - var myPrivateKey = privKey; if (typeof myPrivateKey !== "string") throw new Error("No private key found."); let privateKey = this.wifToDecimal(myPrivateKey, true); @@ -162,7 +161,7 @@ var encrypt = { var floID = key.getBitcoinAddress(); return floID; }, - sign: function (msg, privateKeyHex) { + signData: function (msg, privateKeyHex) { var key = new Bitcoin.ECKey(privateKeyHex); key.setCompressed(true); @@ -176,7 +175,7 @@ var encrypt = { var sighex = Crypto.util.bytesToHex(messageSign); return sighex; }, - verify: function (msg, signatureHex, publicKeyHex) { + verifyData: function (msg, signatureHex, publicKeyHex) { var msgHash = Crypto.SHA256(msg); var messageHashBigInteger = new BigInteger(msgHash); @@ -202,8 +201,108 @@ var encrypt = { privateKeyDecimal: privateKeyDecimal, privateKeyHex: privateKeyHex } - } + }, + genNewIDpair: function(){ + try { + var key = new Bitcoin.ECKey(false); + key.setCompressed(true); + return {floID:key.getBitcoinAddress(),pubKey:key.getPubKeyHex(),privKey:key.getBitcoinWalletImportFormat()} + } + catch (e) { + console.log(e); + } } + } +//Script for AJAX, and register functions +function ajax(method, uri){ + var request = new XMLHttpRequest(); + var url = `${server}/${uri}` + console.log(url) + var result; + request.open(method,url , false); + request.onload = function () { + if (request.readyState == 4 && request.status == 200) + result = this.response; + else { + console.log('error'); + result = false; + } + }; + request.send(); + console.log(result); + return result; +} + + +function registerID(sender,onionAddr,wif,pubkey,username) { + + var receiver = adminID; + + var trx = bitjs.transaction(); + var utxoAmt = 0.0; + var x = sendAmt+fee; + var response = ajax("GET",`api/addr/${sender}/utxo`); + var utxos = JSON.parse(response); + for(var x = utxos.length-1; x >= 0; x--){ + if(utxoAmt < sendAmt+fee){ + trx.addinput(utxos[x].txid, utxos[x].vout, utxos[x].scriptPubKey); + utxoAmt += utxos[x].amount; + }else + break; + } + console.log(utxoAmt+":"+(sendAmt+fee)); + if(utxoAmt < sendAmt+fee){ + alert("Insufficient balance!"); + return; + } + + trx.addoutput(receiver, sendAmt); + console.log(receiver+":"+ sendAmt); + + var change = utxoAmt-sendAmt-fee; + if(change>0) + trx.addoutput(sender, change); + console.log(sender+":"+ change); + var key = new Bitcoin.ECKey(wif); + var sendFloData = JSON.stringify({FLO_chat:{onionAddr:onionAddr, name: username, pubKey: pubkey}});; + trx.addflodata(sendFloData); + console.log(sendFloData); + + var signedTxHash = trx.sign(wif, 1); + console.log(signedTxHash); + return broadcastTx(signedTxHash); +} + function broadcastTx(signedTxHash) { + var http = new XMLHttpRequest(); + var url = `${server}/api/tx/send`; + if (signedTxHash.length < 1) { + alert("Empty Signature"); + return false; + } + + var params = `{"rawtx":"${signedTxHash}"}`; + var result; + http.open('POST', url, false); + + //Send the proper header information along with the request + http.setRequestHeader('Content-type', 'application/json'); + + http.onreadystatechange = function () { //Call a function when the state changes. + if (http.readyState == 4 && http.status == 200) { + console.log(http.response); + var txid = JSON.parse(http.response).txid.result; + alert("Transaction successful! txid : " + txid); + result = true; + + } else { + console.log(http.responseText); + result = false; + } + } + http.send(params); + return result; + } + function convertStringToInt(string){ return parseInt(string,10); @@ -222,35 +321,45 @@ function userDataStartUp(){ getDatafromAPI().then(function (result) { console.log(result); getContactsfromIDB().then(function(result){ - contacts = arrayToObject(result); - console.log(contacts); - getSuperNodeListfromIDB().then(function(result){ - console.log(result) - superNodeList = result; - kBucketObj.launchKBucket().then(function(result){ + contacts = result; + getGroupsfromIDB().then(function(result){ + groups = result; + console.log(groups); + getSuperNodeListfromIDB().then(function(result){ console.log(result) - getuserID().then(function(result){ - console.log(result); - selfID = result; - if(superNodeList.includes(selfID)) - modSuperNode = true; - alert(`${selfID}\nWelcome ${contacts[selfID].name}`) - readMsgfromIDB().then(function(result){ + superNodeList = result; + kBucketObj.launchKBucket().then(function(result){ + console.log(result) + getuserID().then(function(result){ console.log(result); - initselfWebSocket(); - pingSuperNodeForMessages(); - displayContacts(); - const createClock = setInterval(checkStatusInterval, 30000); - }).catch(function(error){ - console.log(error); + selfID = result; + if(superNodeList.includes(selfID)) + modSuperNode = true; + alert(`${selfID}\nWelcome ${contacts[selfID].name}`) + readMsgfromIDB().then(function(result){ + console.log(result); + readGroupMsgfromIDB().then(function(result){ + console.log(result); + initselfWebSocket(); + pingSuperNodeForMessages(); + displayContacts(); + const createClock = setInterval(checkStatusInterval, 30000); + }).catch(function(error){ + console.log(error); + }); + }).catch(function(error){ + console.log(error); + }); + //startChats(); + }).catch(function (error) { + console.log(error.message); }); - //startChats(); - }).catch(function (error) { + }).catch(function(error){ + console.log(error.message); + }); + }).catch(function (error) { console.log(error.message); - }); - }).catch(function(error){ - console.log(error.message); - }); + }); }).catch(function (error) { console.log(error.message); }); @@ -262,13 +371,6 @@ function userDataStartUp(){ }); } - function arrayToObject(array){ - obj = {}; - array.forEach(element => { - obj[element.floID] = {onionAddr : element.onionAddr, name : element.name, pubKey : element.pubKey}; - }); - return obj; - } function storeContact(data){ return new Promise( @@ -326,22 +428,28 @@ function userDataStartUp(){ console.log("Error in opening IndexedDB!"); }; idb.onupgradeneeded = function(event) { - var objectStore0 = event.target.result.createObjectStore("superNodes"); - var objectStore1 = event.target.result.createObjectStore("contacts",{ keyPath: 'floID' }); + var db = event.target.result; + var objectStore0 = db.createObjectStore("superNodes"); + var objectStore1 = db.createObjectStore("contacts",{ keyPath: 'floID' }); objectStore1.createIndex('onionAddr', 'onionAddr', { unique: false }); objectStore1.createIndex('name', 'name', { unique: false }); objectStore1.createIndex('pubKey', 'pubKey', { unique: false }); - var objectStore2 = event.target.result.createObjectStore("lastTx"); - var objectStore3 = event.target.result.createObjectStore("messages",{ keyPath: 'time' }); + var objectStore2 = db.createObjectStore("lastTx"); + var objectStore3 = db.createObjectStore("messages",{ keyPath: 'time' }); objectStore3.createIndex('text', 'text', { unique: false }); objectStore3.createIndex('floID', 'floID', { unique: false }); objectStore3.createIndex('type', 'type', { unique: false }); + var objectStore4 = db.createObjectStore("groups",{ keyPath: 'groupID' }); + objectStore4.createIndex('groupInfo', 'groupInfo', { unique: false }); + var objectStore5 = db.createObjectStore("groupMsg",{ keyPath: 'time' }); + objectStore5.createIndex('text', 'text', { unique: false }); + objectStore5.createIndex('groupID', 'groupID', { unique: false }); + objectStore5.createIndex('type', 'type', { unique: false }); + objectStore5.createIndex('sender', 'sender', { unique: false }); }; idb.onsuccess = function(event) { var db = event.target.result; - //window["wait"] = addrList.length; var lastTx = db.transaction('lastTx', "readwrite").objectStore('lastTx'); - //addrList.forEach(function(addr){ console.log(addr); new Promise(function(res,rej){ var lastTxReq = lastTx.get(addr); @@ -376,7 +484,7 @@ function userDataStartUp(){ }else{ var data = JSON.parse(tx.floData).FLO_chat; if(data !== undefined){ - if(encrypt.getFLOIDfromPubkeyHex(data.pubKey)!=tx.vin[0].addr) + if(floOpt.getFLOIDfromPubkeyHex(data.pubKey)!=tx.vin[0].addr) throw("PublicKey doesnot match with floID") data = {floID : tx.vin[0].addr, onionAddr : data.onionAddr, name : data.name, pubKey:data.pubKey}; storeContact(data).then(function (response) { @@ -394,7 +502,6 @@ function userDataStartUp(){ obs.put(response.totalItems,addr); break; } - window["wait"]--; db.close(); resolve('retrived data from API'); }); @@ -446,7 +553,38 @@ function getContactsfromIDB(){ var obs = db.transaction("contacts", "readwrite").objectStore("contacts"); var getReq = obs.getAll(); getReq.onsuccess = function(event){ - resolve(event.target.result); + var result = {} + event.target.result.forEach(c => { + result[c.floID] = c; + }); + resolve(result); + } + getReq.onerror = function(event){ + reject('Unable to read contacts!') + } + db.close(); + }; + } + ); +} + +function getGroupsfromIDB(){ + return new Promise( + function(resolve,reject){ + var idb = indexedDB.open("FLO_Chat"); + idb.onerror = function(event) { + reject("Error in opening IndexedDB!"); + }; + idb.onsuccess = function(event) { + var db = event.target.result; + var obs = db.transaction("groups", "readwrite").objectStore("groups"); + var getReq = obs.getAll(); + getReq.onsuccess = function(event){ + var result = {} + event.target.result.forEach(g => { + result[g.groupID] = JSON.parse(g.groupInfo); + }); + resolve(result); } getReq.onerror = function(event){ reject('Unable to read contacts!') @@ -533,7 +671,6 @@ function readMsgfromIDB(){ cursor.continue(); } else { - console.log('Entries all displayed.'); resolve("Read Msg from IDB"); } }; @@ -543,6 +680,71 @@ function readMsgfromIDB(){ ); } +function readGroupMsgfromIDB(){ + return new Promise( + function(resolve,reject){ + var disp = document.getElementById("conversation"); + for(floID in groups){ + var createLi = document.createElement('div'); + createLi.setAttribute("id", floID); + createLi.setAttribute("class", "message-inner"); + createLi.style.display = 'none'; + disp.appendChild(createLi); + } + var idb = indexedDB.open("FLO_Chat"); + idb.onerror = function(event) { + reject("Error in opening IndexedDB!"); + }; + idb.onsuccess = function(event) { + var db = event.target.result; + var obs = db.transaction("groupMsg", "readwrite").objectStore("groupMsg"); + obs.openCursor().onsuccess = function(event) { + var cursor = event.target.result; + if(cursor) { + var chat = document.getElementById(cursor.value.groupID); + if(cursor.value.type == "R"){ + var msgdiv = document.createElement('div'); + msgdiv.setAttribute("class", "row message-body"); + msgdiv.innerHTML = `
+
+ + ${cursor.value.sender} +
${cursor.value.text} +
+ + ${getTime(cursor.value.time)} + +
+
`; + chat.appendChild(msgdiv); + }else if(cursor.value.type == "S"){ + var msgdiv = document.createElement('div'); + msgdiv.setAttribute("class", "row message-body"); + msgdiv.innerHTML = `
+
+ + ${cursor.value.sender} +
${cursor.value.text} +
+ + ${getTime(cursor.value.time)} + +
+
`; + chat.appendChild(msgdiv); + } + + cursor.continue(); + } else { + resolve("Read Group Msgs from IDB"); + } + }; + db.close(); + }; + } + ); +} + function storeMsg(data){ var idb = indexedDB.open("FLO_Chat"); idb.onerror = function(event) { @@ -556,6 +758,19 @@ function storeMsg(data){ }; } +function storeGroupMsg(data){ + var idb = indexedDB.open("FLO_Chat"); + idb.onerror = function(event) { + console.log("Error in opening IndexedDB!"); + }; + idb.onsuccess = function(event) { + var db = event.target.result; + var obs = db.transaction("groupMsg", "readwrite").objectStore("groupMsg"); + obs.add(data); + db.close(); + }; +} + function storeSuperNodeMsg(data){ var idb = indexedDB.open("FLO_Chat",2); idb.onerror = function(event) { @@ -587,13 +802,24 @@ function displayContacts(){ createLi.setAttribute("class", "row sideBar-body"); createLi.innerHTML = `