From a3ea303aabf44132d0a3616193ea74e67de5a268 Mon Sep 17 00:00:00 2001 From: sairajzero Date: Tue, 16 Aug 2022 03:26:07 +0530 Subject: [PATCH] Update std_op --- index.html | 1 + scripts/btcOperator.js | 92 +++++++++---- scripts/floCloudAPI.js | 4 +- scripts/floCrypto.js | 158 +++++++++++++++++++-- scripts/floDapps.js | 305 ++++++++++++++++++++++++++++++----------- scripts/lib.js | 8 +- 6 files changed, 438 insertions(+), 130 deletions(-) diff --git a/index.html b/index.html index c5f2e4d..2425010 100644 --- a/index.html +++ b/index.html @@ -16,6 +16,7 @@ + diff --git a/scripts/btcOperator.js b/scripts/btcOperator.js index 170be20..591cd0a 100644 --- a/scripts/btcOperator.js +++ b/scripts/btcOperator.js @@ -1,4 +1,4 @@ -(function(EXPORTS) { //btcOperator v1.0.7b +(function(EXPORTS) { //btcOperator v1.0.7c /* BTC Crypto and API Operator */ const btcOperator = EXPORTS; @@ -268,26 +268,28 @@ const TMP_FEE = 0.00001; function createTransaction(senders, redeemScripts, receivers, amounts, fee, change_addr) { - let auto_fee = false, - total_amount = parseFloat(amounts.reduce((t, a) => t + a, 0).toFixed(8)); - if (fee === null) { - auto_fee = true; - fee = TMP_FEE; - } - const tx = coinjs.transaction(); - addUTXOs(tx, senders, redeemScripts, total_amount + fee).then(result => { - if (result > 0) - return reject("Insufficient Balance"); - let change = addOutputs(tx, receivers, amounts, Math.abs(result), change_addr); - if (!auto_fee) - return resolve(tx); - autoFeeCalc(tx).then(fee_calc => { - fee = Math.round((fee * 1) * 1e8); //satoshi convertion - if (!change) - tx.addoutput(change_addr, 0); - editFee(tx, fee, fee_calc); - resolve(tx); - }).catch(error => reject(error)) + return new Promise((resolve, reject) => { + let auto_fee = false, + total_amount = parseFloat(amounts.reduce((t, a) => t + a, 0).toFixed(8)); + if (fee === null) { + auto_fee = true; + fee = TMP_FEE; + } + const tx = coinjs.transaction(); + addUTXOs(tx, senders, redeemScripts, total_amount + fee).then(result => { + if (result > 0) + return reject("Insufficient Balance"); + let change = addOutputs(tx, receivers, amounts, Math.abs(result), change_addr); + if (!auto_fee) + return resolve(tx); + autoFeeCalc(tx).then(fee_calc => { + fee = Math.round((fee * 1) * 1e8); //satoshi convertion + if (!change) + tx.addoutput(change_addr, 0); + editFee(tx, fee, fee_calc); + resolve(tx); + }).catch(error => reject(error)) + }) }) } @@ -306,14 +308,17 @@ continue; required_amount -= parseFloat(utxos[i].value); var script; - if (rs) { //redeemScript for segwit/bech32 + if (!rs || !rs.length) //legacy script + script = utxos[i].script_hex; + else if (((rs.match(/^00/) && rs.length == 44)) || (rs.length == 40 && rs.match(/^[a-f0-9]+$/gi))) { + //redeemScript for segwit/bech32 let s = coinjs.script(); s.writeBytes(Crypto.util.hexToBytes(rs)); s.writeOp(0); s.writeBytes(coinjs.numToBytes((utxos[i].value * 100000000).toFixed(0), 8)); script = Crypto.util.bytesToHex(s.buffer); - } else //legacy script - script = utxos[i].script_hex; + } else //redeemScript for multisig + script = rs; tx.addinput(utxos[i].txid, utxos[i].output_no, script, 0xfffffffd /*sequence*/ ); //0xfffffffd for Replace-by-fee } addUTXOs(tx, senders, redeemScripts, required_amount, n + 1) @@ -466,7 +471,7 @@ }) } - btcOperator.signTx = function(tx, privKeys) { + function deserializeTx(tx) { if (typeof tx === 'string' || Array.isArray(tx)) { try { tx = coinjs.transaction().deserialize(tx); @@ -475,16 +480,45 @@ } } else if (typeof tx !== 'object' || typeof tx.sign !== 'function') throw "Invalid transaction object"; + return tx; + } + btcOperator.signTx = function(tx, privkeys, sighashtype = 1) { + tx = deserializeTx(tx); if (!Array.isArray(privkeys)) privkeys = [privkeys]; - for (let i in privKeys) - if (privKeys[i].length === 64) - privkeys[i] = coinjs.privkey2wif(privKeys[i]); - new Set(privKeys).forEach(key => console.debug("Signing key:", key, tx.sign(key, 1 /*sighashtype*/ ))); //Sign the tx using private key WIF + for (let i in privkeys) + if (privkeys[i].length === 64) + privkeys[i] = coinjs.privkey2wif(privkeys[i]); + new Set(privkeys).forEach(key => tx.sign(key, sighashtype)); //Sign the tx using private key WIF return tx.serialize(); } + btcOperator.checkSigned = function(tx, bool = true) { + tx = deserializeTx(tx); + let n = []; + for (let i in tx.ins) { + var s = tx.extractScriptKey(i); + if (s['type'] !== 'multisig') + n.push(s.signed == 'true' || (tx.witness[i] && tx.witness[i].length == 2)) + else { + var rs = coinjs.script().decodeRedeemScript(s.script); + let x = { + s: s['signatures'], + r: rs['signaturesRequired'], + t: rs['pubkeys'].length + }; + if (x.r > x.t) + throw "signaturesRequired is more than publicKeys"; + else if (x.s < x.r) + n.push(x); + else + n.push(true); + } + } + return bool ? !(n.filter(x => x !== true).length) : n; + } + btcOperator.getTx = txid => new Promise((resolve, reject) => { fetch_api(`get_tx/BTC/${txid}`) .then(result => resolve(result.data)) diff --git a/scripts/floCloudAPI.js b/scripts/floCloudAPI.js index 01560a1..402c0c5 100644 --- a/scripts/floCloudAPI.js +++ b/scripts/floCloudAPI.js @@ -1,4 +1,4 @@ -(function(EXPORTS) { //floCloudAPI v2.4.2b +(function(EXPORTS) { //floCloudAPI v2.4.2c /* FLO Cloud operations to send/request application data*/ 'use strict'; const floCloudAPI = EXPORTS; @@ -384,7 +384,7 @@ if (!address) return; var bytes; - if (address.length == 34) { //legacy encoding + if (address.length == 33 || address.length == 34) { //legacy encoding let decode = bitjs.Base58.decode(address); bytes = decode.slice(0, decode.length - 4); let checksum = decode.slice(decode.length - 4), diff --git a/scripts/floCrypto.js b/scripts/floCrypto.js index 4ab4d5c..01921d1 100644 --- a/scripts/floCrypto.js +++ b/scripts/floCrypto.js @@ -1,4 +1,4 @@ -(function(EXPORTS) { //floCrypto v2.3.0a +(function(EXPORTS) { //floCrypto v2.3.3b /* FLO Crypto Operators */ 'use strict'; const floCrypto = EXPORTS; @@ -7,6 +7,7 @@ const ecparams = EllipticCurve.getSECCurveByName("secp256k1"); const ascii_alternatives = `‘ '\n’ '\n“ "\n” "\n– --\n— ---\n≥ >=\n≤ <=\n≠ !=\n× *\n÷ /\n← <-\n→ ->\n↔ <->\n⇒ =>\n⇐ <=\n⇔ <=>`; const exponent1 = () => p.add(BigInteger.ONE).divide(BigInteger("4")); + coinjs.compressed = true; //defaulting coinjs compressed to true; function calculateY(x) { let exp = exponent1(); @@ -121,12 +122,8 @@ //Sign data using private-key floCrypto.signData = function(data, privateKeyHex) { var key = new Bitcoin.ECKey(privateKeyHex); - key.setCompressed(true); - var privateKeyArr = key.getBitcoinPrivateKeyByteArray(); - var privateKey = BigInteger.fromByteArrayUnsigned(privateKeyArr); var messageHash = Crypto.SHA256(data); - var messageHashBigInteger = new BigInteger(messageHash); - var messageSign = Bitcoin.ECDSA.sign(messageHashBigInteger, key.priv); + var messageSign = Bitcoin.ECDSA.sign(messageHash, key.priv); var sighex = Crypto.util.bytesToHex(messageSign); return sighex; } @@ -134,11 +131,9 @@ //Verify signatue of the data using public-key floCrypto.verifySign = function(data, signatureHex, publicKeyHex) { var msgHash = Crypto.SHA256(data); - var messageHashBigInteger = new BigInteger(msgHash); var sigBytes = Crypto.util.hexToBytes(signatureHex); - var signature = Bitcoin.ECDSA.parseSig(sigBytes); var publicKeyPoint = ecparams.getCurve().decodePointHex(publicKeyHex); - var verify = Bitcoin.ECDSA.verifyRaw(messageHashBigInteger, signature.r, signature.s, publicKeyPoint); + var verify = Bitcoin.ECDSA.verify(msgHash, sigBytes, publicKeyPoint); return verify; } @@ -153,8 +148,23 @@ } } - Object.defineProperty(floCrypto, 'newID', { - get: () => generateNewID() + Object.defineProperties(floCrypto, { + newID: { + get: () => generateNewID() + }, + tmpID: { + get: () => { + let bytes = Crypto.util.randomBytes(20); + bytes.unshift(bitjs.pub); + var hash = Crypto.SHA256(Crypto.SHA256(bytes, { + asBytes: true + }), { + asBytes: true + }); + var checksum = hash.slice(0, 4); + return bitjs.Base58.encode(bytes.concat(checksum)); + } + } }); //Returns public-key from private-key @@ -182,6 +192,25 @@ } } + floCrypto.getAddress = function(privateKeyHex, strict = false) { + if (!privateKeyHex) + return; + var key = new Bitcoin.ECKey(privateKeyHex); + if (key.priv == null) + return null; + key.setCompressed(true); + let pubKey = key.getPubKeyHex(), + version = bitjs.Base58.decode(privateKeyHex)[0]; + switch (version) { + case coinjs.priv: //BTC + return coinjs.bech32Address(pubKey).address; + case bitjs.priv: //FLO + return bitjs.pubkey2address(pubKey); + default: + return strict ? false : bitjs.pubkey2address(pubKey); //default to FLO address (if strict=false) + } + } + //Verify the private-key for the given public-key or flo-ID floCrypto.verifyPrivKey = function(privateKeyHex, pubKey_floID, isfloID = true) { if (!privateKeyHex || !pubKey_floID) @@ -202,18 +231,117 @@ } } - //Check if the given Address is valid or not - floCrypto.validateFloID = floCrypto.validateAddr = function(inpAddr) { - if (!inpAddr) + //Check if the given flo-id is valid or not + floCrypto.validateFloID = function(floID) { + if (!floID) return false; try { - let addr = new Bitcoin.Address(inpAddr); + let addr = new Bitcoin.Address(floID); return true; } catch { return false; } } + //Check if the given address (any blockchain) is valid or not + floCrypto.validateAddr = function(address, std = true, bech = true) { + if (address.length == 33 || address.length == 34) { //legacy or segwit encoding + if (std === false) + return false; + let decode = bitjs.Base58.decode(address); + var raw = decode.slice(0, decode.length - 4), + checksum = decode.slice(decode.length - 4); + var hash = Crypto.SHA256(Crypto.SHA256(raw, { + asBytes: true + }), { + asBytes: true + }); + if (hash[0] != checksum[0] || hash[1] != checksum[1] || hash[2] != checksum[2] || hash[3] != checksum[3]) + return false; + else if (std === true || (!Array.isArray(std) && std === raw[0]) || (Array.isArray(std) && std.includes(raw[0]))) + return true; + else + return false; + } else if (address.length == 42 || address.length == 62) { //bech encoding + if (bech === false) + return false; + let decode = coinjs.bech32_decode(address); + if (!decode) + return false; + var raw = decode.data; + if (bech === true || (!Array.isArray(bech) && bech === raw[0]) || (Array.isArray(bech) && bech.includes(raw[0]))) + return true; + else + return false; + } else //unknown length + return false; + } + + //Check the public-key for the address (any blockchain) + floCrypto.verifyPubKey = function(pubKeyHex, address) { + let pub_hash = Crypto.util.bytesToHex(ripemd160(Crypto.SHA256(Crypto.util.hexToBytes(pubKeyHex), { + asBytes: true + }))); + if (address.length == 33 || address.length == 34) { //legacy encoding + let decode = bitjs.Base58.decode(address); + var raw = decode.slice(0, decode.length - 4), + checksum = decode.slice(decode.length - 4); + var hash = Crypto.SHA256(Crypto.SHA256(raw, { + asBytes: true + }), { + asBytes: true + }); + if (hash[0] != checksum[0] || hash[1] != checksum[1] || hash[2] != checksum[2] || hash[3] != checksum[3]) + return false; + raw.shift(); + return pub_hash === Crypto.util.bytesToHex(raw); + } else if (address.length == 42 || address.length == 62) { //bech encoding + let decode = coinjs.bech32_decode(address); + if (!decode) + return false; + var raw = decode.data; + raw.shift(); + raw = coinjs.bech32_convert(raw, 5, 8, false); + return pub_hash === Crypto.util.bytesToHex(raw); + } else //unknown length + return false; + } + + //Convert the given address (any blockchain) to equivalent floID + floCrypto.toFloID = function(address) { + if (!address) + return; + var bytes; + if (address.length == 33 || address.length == 34) { //legacy encoding + let decode = bitjs.Base58.decode(address); + bytes = decode.slice(0, decode.length - 4); + let checksum = decode.slice(decode.length - 4), + hash = Crypto.SHA256(Crypto.SHA256(bytes, { + asBytes: true + }), { + asBytes: true + }); + hash[0] != checksum[0] || hash[1] != checksum[1] || hash[2] != checksum[2] || hash[3] != checksum[3] ? + bytes = undefined : bytes.shift(); + } else if (address.length == 42) { //bech encoding + let decode = coinjs.bech32_decode(address); + if (decode) { + bytes = decode.data; + bytes.shift(); + bytes = coinjs.bech32_convert(bytes, 5, 8, false); + } + } + if (!bytes) + return; + bytes.unshift(bitjs.pub); + let hash = Crypto.SHA256(Crypto.SHA256(bytes, { + asBytes: true + }), { + asBytes: true + }); + return bitjs.Base58.encode(bytes.concat(hash.slice(0, 4))); + } + //Split the str using shamir's Secret and Returns the shares floCrypto.createShamirsSecretShares = function(str, total_shares, threshold_limit) { try { diff --git a/scripts/floDapps.js b/scripts/floDapps.js index 0e92708..1da58b8 100644 --- a/scripts/floDapps.js +++ b/scripts/floDapps.js @@ -1,8 +1,144 @@ -(function(EXPORTS) { //floDapps v2.2.1 +(function(EXPORTS) { //floDapps v2.3.2c /* General functions for FLO Dapps*/ - //'use strict'; + 'use strict'; const floDapps = EXPORTS; + const DEFAULT = { + root: "floDapps", + application: floGlobals.application, + adminID: floGlobals.adminID + }; + + Object.defineProperties(floDapps, { + application: { + get: () => DEFAULT.application + }, + adminID: { + get: () => DEFAULT.adminID + }, + root: { + get: () => DEFAULT.root + } + }); + + var user_priv_raw, aes_key, user_priv_wrap; //private variable inside capsule + const raw_user = { + get private() { + if (!user_priv_raw) + throw "User not logged in"; + return Crypto.AES.decrypt(user_priv_raw, aes_key); + } + } + + var user_id, user_public, user_private; + const user = floDapps.user = { + get id() { + if (!user_id) + throw "User not logged in"; + return user_id; + }, + get public() { + if (!user_public) + throw "User not logged in"; + return user_public; + }, + get private() { + if (!user_private) + throw "User not logged in"; + else if (user_private instanceof Function) + return user_private(); + else + return Crypto.AES.decrypt(user_private, aes_key); + }, + sign(message) { + return floCrypto.signData(message, raw_user.private); + }, + decrypt(data) { + return floCrypto.decryptData(data, raw_user.private); + }, + encipher(message) { + return Crypto.AES.encrypt(message, raw_user.private); + }, + decipher(data) { + return Crypto.AES.decrypt(data, raw_user.private); + }, + get db_name() { + return "floDapps#" + user.id; + }, + lock() { + user_private = user_priv_wrap; + }, + async unlock() { + if (await user.private === raw_user.private) + user_private = user_priv_raw; + }, + clear() { + user_id = user_public = user_private = undefined; + user_priv_raw = aes_key = undefined; + delete user.contacts; + delete user.pubKeys; + delete user.messages; + } + }; + + Object.defineProperties(window, { + myFloID: { + get: () => { + try { + return user.id; + } catch { + return; + } + } + }, + myUserID: { + get: () => { + try { + return user.id; + } catch { + return; + } + } + }, + myPubKey: { + get: () => { + try { + return user.public; + } catch { + return; + } + } + }, + myPrivKey: { + get: () => { + try { + return user.private; + } catch { + return; + } + } + } + }); + + var subAdmins, settings + Object.defineProperties(floGlobals, { + subAdmins: { + get: () => subAdmins + }, + settings: { + get: () => settings + }, + contacts: { + get: () => user.contacts + }, + pubKeys: { + get: () => user.pubKeys + }, + messages: { + get: () => user.messages + } + }) + function initIndexedDB() { return new Promise((resolve, reject) => { var obs_g = { @@ -28,41 +164,41 @@ } //add other given objectStores initIndexedDB.appObs = initIndexedDB.appObs || {} - for (o in initIndexedDB.appObs) + for (let o in initIndexedDB.appObs) if (!(o in obs_a)) obs_a[o] = initIndexedDB.appObs[o] Promise.all([ - compactIDB.initDB(floGlobals.application, obs_a), - compactIDB.initDB("floDapps", obs_g) + compactIDB.initDB(DEFAULT.application, obs_a), + compactIDB.initDB(DEFAULT.root, obs_g) ]).then(result => { - compactIDB.setDefaultDB(floGlobals.application) + compactIDB.setDefaultDB(DEFAULT.application) resolve("IndexedDB App Storage Initated Successfully") }).catch(error => reject(error)); }) } - function initUserDB(floID) { + function initUserDB() { return new Promise((resolve, reject) => { var obs = { contacts: {}, pubKeys: {}, messages: {} } - compactIDB.initDB(`floDapps#${floID}`, obs).then(result => { + compactIDB.initDB(user.db_name, obs).then(result => { resolve("UserDB Initated Successfully") }).catch(error => reject('Init userDB failed')); }) } - function loadUserDB(floID) { + function loadUserDB() { return new Promise((resolve, reject) => { var loadData = ["contacts", "pubKeys", "messages"] var promises = [] for (var i = 0; i < loadData.length; i++) - promises[i] = compactIDB.readAllData(loadData[i], `floDapps#${floID}`) + promises[i] = compactIDB.readAllData(loadData[i], user.db_name) Promise.all(promises).then(results => { for (var i = 0; i < loadData.length; i++) - floGlobals[loadData[i]] = results[i] + user[loadData[i]] = results[i] resolve("Loaded Data from userDB") }).catch(error => reject('Load userDB failed')) }) @@ -72,7 +208,7 @@ startUpFunctions.push(function readSupernodeListFromAPI() { return new Promise((resolve, reject) => { - compactIDB.readData("lastTx", floCloudAPI.SNStorageID, "floDapps").then(lastTx => { + compactIDB.readData("lastTx", floCloudAPI.SNStorageID, DEFAULT.root).then(lastTx => { floBlockchainAPI.readData(floCloudAPI.SNStorageID, { ignoreOld: lastTx, sentOnly: true, @@ -80,14 +216,14 @@ }).then(result => { for (var i = result.data.length - 1; i >= 0; i--) { var content = JSON.parse(result.data[i]).SuperNodeStorage; - for (sn in content.removeNodes) - compactIDB.removeData("supernodes", sn, "floDapps"); - for (sn in content.newNodes) - compactIDB.writeData("supernodes", content.newNodes[sn], sn, "floDapps"); + for (let sn in content.removeNodes) + compactIDB.removeData("supernodes", sn, DEFAULT.root); + for (let sn in content.newNodes) + compactIDB.writeData("supernodes", content.newNodes[sn], sn, DEFAULT.root); } - compactIDB.writeData("lastTx", result.totalTxs, floCloudAPI.SNStorageID, "floDapps"); - compactIDB.readAllData("supernodes", "floDapps").then(result => { - floCloudAPI.init(result) + compactIDB.writeData("lastTx", result.totalTxs, floCloudAPI.SNStorageID, DEFAULT.root); + compactIDB.readAllData("supernodes", DEFAULT.root).then(nodes => { + floCloudAPI.init(nodes) .then(result => resolve("Loaded Supernode list\n" + result)) .catch(error => reject(error)) }) @@ -98,14 +234,14 @@ startUpFunctions.push(function readAppConfigFromAPI() { return new Promise((resolve, reject) => { - compactIDB.readData("lastTx", `${floGlobals.application}|${floGlobals.adminID}`, "floDapps").then(lastTx => { - floBlockchainAPI.readData(floGlobals.adminID, { + compactIDB.readData("lastTx", `${DEFAULT.application}|${DEFAULT.adminID}`, DEFAULT.root).then(lastTx => { + floBlockchainAPI.readData(DEFAULT.adminID, { ignoreOld: lastTx, sentOnly: true, - pattern: floGlobals.application + pattern: DEFAULT.application }).then(result => { for (var i = result.data.length - 1; i >= 0; i--) { - var content = JSON.parse(result.data[i])[floGlobals.application]; + var content = JSON.parse(result.data[i])[DEFAULT.application]; if (!content || typeof content !== "object") continue; if (Array.isArray(content.removeSubAdmin)) @@ -118,11 +254,11 @@ for (let l in content.settings) compactIDB.writeData("settings", content.settings[l], l) } - compactIDB.writeData("lastTx", result.totalTxs, `${floGlobals.application}|${floGlobals.adminID}`, "floDapps"); + compactIDB.writeData("lastTx", result.totalTxs, `${DEFAULT.application}|${DEFAULT.adminID}`, DEFAULT.root); compactIDB.readAllData("subAdmins").then(result => { - floGlobals.subAdmins = Object.keys(result); + subAdmins = Object.keys(result); compactIDB.readAllData("settings").then(result => { - floGlobals.settings = result; + settings = result; resolve("Read app configuration from blockchain"); }) }) @@ -186,7 +322,7 @@ }); const getPrivateKeyCredentials = () => new Promise((resolve, reject) => { - var indexArr = localStorage.getItem(`${floGlobals.application}#privKey`) + var indexArr = localStorage.getItem(`${DEFAULT.application}#privKey`) if (indexArr) { readSharesFromIDB(JSON.parse(indexArr)) .then(result => resolve(result)) @@ -197,7 +333,7 @@ if (!result) return reject("Empty Private Key") var floID = floCrypto.getFloID(result) - if (!floID || !floCrypto.validateAddr(floID)) + if (!floID || !floCrypto.validateFloID(floID)) return reject("Invalid Private Key") privKey = result; }).catch(error => { @@ -210,7 +346,7 @@ var shares = floCrypto.createShamirsSecretShares(privKey, threshold, threshold) writeSharesToIDB(shares).then(resultIndexes => { //store index keys in localStorage - localStorage.setItem(`${floGlobals.application}#privKey`, JSON.stringify(resultIndexes)) + localStorage.setItem(`${DEFAULT.application}#privKey`, JSON.stringify(resultIndexes)) //also add a dummy privatekey to the IDB var randomPrivKey = floCrypto.generateNewID().privKey var randomThreshold = floCrypto.randInt(10, 20) @@ -242,9 +378,14 @@ getPrivateKeyCredentials().then(key => { checkIfPinRequired(key).then(privKey => { try { - myPrivKey = privKey - myPubKey = floCrypto.getPubKeyHex(myPrivKey) - myFloID = floCrypto.getFloID(myPubKey) + user_public = floCrypto.getPubKeyHex(privKey); + user_id = floCrypto.getAddress(privKey); + floCloudAPI.user(user_id, privKey); //Set user for floCloudAPI + user_priv_wrap = () => checkIfPinRequired(key); + let n = floCrypto.randInt(12, 20); + aes_key = floCrypto.randString(n); + user_priv_raw = Crypto.AES.encrypt(privKey, aes_key); + user_private = user_priv_wrap; resolve('Login Credentials loaded successful') } catch (error) { console.log(error) @@ -305,8 +446,8 @@ }); let p2 = new Promise((res, rej) => { callAndLog(getCredentials()).then(r => { - callAndLog(initUserDB(myFloID)).then(r => { - callAndLog(loadUserDB(myFloID)) + callAndLog(initUserDB()).then(r => { + callAndLog(loadUserDB()) .then(r => res(true)) .catch(e => rej(false)) }).catch(e => rej(false)) @@ -315,7 +456,10 @@ Promise.all([p1, p2]) .then(r => resolve('App Startup finished successful')) .catch(e => reject('App Startup failed')) - }).catch(error => reject("App database initiation failed")) + }).catch(error => { + startUpLog(false, error); + reject("App database initiation failed") + }) }) } @@ -331,10 +475,10 @@ floDapps.storeContact = function(floID, name) { return new Promise((resolve, reject) => { - if (!floCrypto.validateAddr(floID)) + if (!floCrypto.validateFloID(floID)) return reject("Invalid floID!") - compactIDB.writeData("contacts", name, floID, `floDapps#${myFloID}`).then(result => { - floGlobals.contacts[floID] = name; + compactIDB.writeData("contacts", name, floID, user.db_name).then(result => { + user.contacts[floID] = name; resolve("Contact stored") }).catch(error => reject(error)) }); @@ -342,14 +486,14 @@ floDapps.storePubKey = function(floID, pubKey) { return new Promise((resolve, reject) => { - if (floID in floGlobals.pubKeys) + if (floID in user.pubKeys) return resolve("pubKey already stored") - if (!floCrypto.validateAddr(floID)) + if (!floCrypto.validateFloID(floID)) return reject("Invalid floID!") if (floCrypto.getFloID(pubKey) != floID) return reject("Incorrect pubKey") - compactIDB.writeData("pubKeys", pubKey, floID, `floDapps#${myFloID}`).then(result => { - floGlobals.pubKeys[floID] = pubKey; + compactIDB.writeData("pubKeys", pubKey, floID, user.db_name).then(result => { + user.pubKeys[floID] = pubKey; resolve("pubKey stored") }).catch(error => reject(error)) }); @@ -359,11 +503,11 @@ return new Promise((resolve, reject) => { let options = { receiverID: floID, - application: "floDapps", - comment: floGlobals.application + application: DEFAULT.root, + comment: DEFAULT.application } - if (floID in floGlobals.pubKeys) - message = floCrypto.encryptData(JSON.stringify(message), floGlobals.pubKeys[floID]) + if (floID in user.pubKeys) + message = floCrypto.encryptData(JSON.stringify(message), user.pubKeys[floID]) floCloudAPI.sendApplicationData(message, "Message", options) .then(result => resolve(result)) .catch(error => reject(error)) @@ -372,20 +516,21 @@ floDapps.requestInbox = function(callback) { return new Promise((resolve, reject) => { - let lastVC = Object.keys(floGlobals.messages).sort().pop() + let lastVC = Object.keys(user.messages).sort().pop() let options = { - receiverID: myFloID, - application: "floDapps", + receiverID: user.id, + application: DEFAULT.root, lowerVectorClock: lastVC + 1 } + let privKey = raw_user.private; options.callback = (d, e) => { for (let v in d) { try { if (d[v].message instanceof Object && "secret" in d[v].message) - d[v].message = floCrypto.decryptData(d[v].message, myPrivKey) + d[v].message = floCrypto.decryptData(d[v].message, privKey) } catch (error) {} - compactIDB.writeData("messages", d[v], v, `floDapps#${myFloID}`) - floGlobals.messages[v] = d[v] + compactIDB.writeData("messages", d[v], v, user.db_name) + user.messages[v] = d[v] } if (callback instanceof Function) callback(d, e) @@ -404,14 +549,14 @@ if (!addList && !rmList && !settings) return reject("No configuration change") var floData = { - [floGlobals.application]: { + [DEFAULT.application]: { addSubAdmin: addList, removeSubAdmin: rmList, settings: settings } } var floID = floCrypto.getFloID(adminPrivKey) - if (floID != floGlobals.adminID) + if (floID != DEFAULT.adminID) reject('Access Denied for Admin privilege') else floBlockchainAPI.writeData(floID, JSON.stringify(floData), adminPrivKey) @@ -422,9 +567,9 @@ const clearCredentials = floDapps.clearCredentials = function() { return new Promise((resolve, reject) => { - compactIDB.clearData('credentials', floGlobals.application).then(result => { - localStorage.removeItem(`${floGlobals.application}#privKey`) - myPrivKey = myPubKey = myFloID = undefined; + compactIDB.clearData('credentials', DEFAULT.application).then(result => { + localStorage.removeItem(`${DEFAULT.application}#privKey`); + user.clear(); resolve("privKey credentials deleted!") }).catch(error => reject(error)) }) @@ -433,7 +578,7 @@ floDapps.deleteUserData = function(credentials = false) { return new Promise((resolve, reject) => { let p = [] - p.push(compactIDB.deleteDB(`floDapps#${myFloID}`)) + p.push(compactIDB.deleteDB(user.db_name)) if (credentials) p.push(clearCredentials()) Promise.all(p) @@ -444,10 +589,10 @@ floDapps.deleteAppData = function() { return new Promise((resolve, reject) => { - compactIDB.deleteDB(floGlobals.application).then(result => { - localStorage.removeItem(`${floGlobals.application}#privKey`) - myPrivKey = myPubKey = myFloID = undefined; - compactIDB.removeData('lastTx', `${floGlobals.application}|${floGlobals.adminID}`, 'floDapps') + compactIDB.deleteDB(DEFAULT.application).then(result => { + localStorage.removeItem(`${DEFAULT.application}#privKey`) + user.clear(); + compactIDB.removeData('lastTx', `${DEFAULT.application}|${DEFAULT.adminID}`, DEFAULT.root) .then(result => resolve("App database(local) deleted")) .catch(error => reject(error)) }).catch(error => reject(error)) @@ -455,17 +600,17 @@ } floDapps.securePrivKey = function(pwd) { - return new Promise((resolve, reject) => { - let indexArr = localStorage.getItem(`${floGlobals.application}#privKey`) + return new Promise(async (resolve, reject) => { + let indexArr = localStorage.getItem(`${DEFAULT.application}#privKey`) if (!indexArr) return reject("PrivKey not found"); indexArr = JSON.parse(indexArr) - let encryptedKey = Crypto.AES.encrypt(myPrivKey, pwd); + let encryptedKey = Crypto.AES.encrypt(await user.private, pwd); let threshold = indexArr.length; let shares = floCrypto.createShamirsSecretShares(encryptedKey, threshold, threshold) let promises = []; let overwriteFn = (share, index) => - compactIDB.writeData("credentials", share, index, floGlobals.application); + compactIDB.writeData("credentials", share, index, DEFAULT.application); for (var i = 0; i < threshold; i++) promises.push(overwriteFn(shares[i], indexArr[i])); Promise.all(promises) @@ -494,7 +639,7 @@ }) } return new Promise((resolve, reject) => { - var indexArr = localStorage.getItem(`${floGlobals.application}#privKey`) + var indexArr = localStorage.getItem(`${DEFAULT.application}#privKey`) console.info(indexArr) if (!indexArr) reject('No login credentials found') @@ -535,7 +680,7 @@ filteredResult[d] = JSON.parse(JSON.stringify(floGlobals.generalData[fk][d])) } if (options.decrypt) { - let decryptionKey = (options.decrypt === true) ? myPrivKey : options.decrypt; + let decryptionKey = (options.decrypt === true) ? raw_user.private : options.decrypt; if (!Array.isArray(decryptionKey)) decryptionKey = [decryptionKey]; for (let f in filteredResult) { @@ -561,14 +706,14 @@ syncData.oldDevice = () => new Promise((resolve, reject) => { let sync = { - contacts: floGlobals.contacts, - pubKeys: floGlobals.pubKeys, - messages: floGlobals.messages + contacts: user.contacts, + pubKeys: user.pubKeys, + messages: user.messages } - let message = Crypto.AES.encrypt(JSON.stringify(sync), myPrivKey) + let message = Crypto.AES.encrypt(JSON.stringify(sync), raw_user.private) let options = { - receiverID: myFloID, - application: "floDapps" + receiverID: user.id, + application: DEFAULT.root } floCloudAPI.sendApplicationData(message, "syncData", options) .then(result => resolve(result)) @@ -577,20 +722,20 @@ syncData.newDevice = () => new Promise((resolve, reject) => { var options = { - receiverID: myFloID, - senderID: myFloID, - application: "floDapps", + receiverID: user.id, + senderID: user.id, + application: DEFAULT.root, mostRecent: true, } floCloudAPI.requestApplicationData("syncData", options).then(response => { let vc = Object.keys(response).sort().pop() - let sync = JSON.parse(Crypto.AES.decrypt(response[vc].message, myPrivKey)) + let sync = JSON.parse(Crypto.AES.decrypt(response[vc].message, raw_user.private)) let promises = [] - let store = (key, val, obs) => promises.push(compactIDB.writeData(obs, val, key, `floDapps#${floID}`)); + let store = (key, val, obs) => promises.push(compactIDB.writeData(obs, val, key, user.db_name)); ["contacts", "pubKeys", "messages"].forEach(c => { for (let i in sync[c]) { store(i, sync[c][i], c) - floGlobals[c][i] = sync[c][i] + user[c][i] = sync[c][i] } }) Promise.all(promises) diff --git a/scripts/lib.js b/scripts/lib.js index d2fd11d..1ae4ca2 100644 --- a/scripts/lib.js +++ b/scripts/lib.js @@ -1,4 +1,4 @@ -(function(GLOBAL) { //lib v1.3.0b +(function(GLOBAL) { //lib v1.3.0c 'use strict'; /* Utility Libraries required for Standard operations * All credits for these codes belong to their respective creators, moderators and owners. @@ -7814,7 +7814,7 @@ } else if (this.ins[index].script.chunks[0] == 0 && this.ins[index].script.chunks[this.ins[index].script.chunks.length - 1][this.ins[index].script.chunks[this.ins[index].script.chunks.length - 1].length - 1] == 174) { // OP_CHECKMULTISIG // multisig script, with signature(s) included var sigcount = 0; - for (i = 1; i < this.ins[index].script.chunks.length - 1; i++) { + for (let i = 1; i < this.ins[index].script.chunks.length - 1; i++) { if (this.ins[index].script.chunks[i] != 0) { sigcount++; } @@ -8057,8 +8057,8 @@ s.writeOp(0); - for (x in pubkeyList) { - for (y in sigsList) { + for (let x in pubkeyList) { + for (let y in sigsList) { this.ins[index].script.buffer = redeemScript; sighash = Crypto.util.hexToBytes(this.transactionHash(index, sigsList[y].slice(-1)[0] * 1)); if (coinjs.verifySignature(sighash, sigsList[y], pubkeyList[x])) {