From d6d8c0444b02141fe27a1970a0e7d7b0bfaab709 Mon Sep 17 00:00:00 2001 From: michaelftout Date: Sun, 28 Oct 2018 17:14:50 -0700 Subject: [PATCH 1/3] Switched dependencies to bitgo-utxo-lib to support sapling, and changed transaction builder and data accordingly --- routes/appConfig.js | 9 +++ routes/electrumjs/electrumjs.networks.js | 5 +- routes/electrumjs/electrumjs.txdecoder-pos.js | 3 +- routes/electrumjs/electrumjs.txdecoder.js | 38 +++++++++-- routes/shepherd.js | 3 +- routes/shepherd/coindWalletKeys.js | 3 +- routes/shepherd/elections.js | 3 +- routes/shepherd/electrum/auth.js | 3 +- routes/shepherd/electrum/coins.js | 4 ++ routes/shepherd/electrum/createtx-multi.js | 3 +- routes/shepherd/electrum/createtx-split.js | 3 +- routes/shepherd/electrum/createtx.js | 67 +++++++++++++++++-- routes/shepherd/electrum/keys.js | 6 +- routes/shepherd/electrum/listunspent.js | 2 + routes/shepherd/electrum/merkle.js | 2 + routes/shepherd/electrum/network.js | 14 +++- routes/shepherd/pin.js | 3 +- 17 files changed, 148 insertions(+), 23 deletions(-) diff --git a/routes/appConfig.js b/routes/appConfig.js index f2b08adf2..22da755a0 100644 --- a/routes/appConfig.js +++ b/routes/appConfig.js @@ -13,6 +13,7 @@ const appConfig = { dataDir: '', autoStartVRSC: false, autoStakeVRSC: false, + //darkMode: false, cheatCatcher: '', dex: { walletUnlockTimeout: 3600, @@ -99,6 +100,14 @@ const appConfig = { displayName: 'Automatically start staking VerusCoin when it is launched in native mode', type: 'boolean', }, + /* + darkMode: { + display: true, + initDisplay: true, + displayName: 'Change UI to dark mode', + type: 'boolean', + }, + */ cheatCatcher: { display: true, info: 'As part of the VerusCoin Something at Stake solution, you can enter a Verus sapling address in this field, so when you catch them, you get their staking reward.', diff --git a/routes/electrumjs/electrumjs.networks.js b/routes/electrumjs/electrumjs.networks.js index 15634e4ad..ad7a27c4f 100644 --- a/routes/electrumjs/electrumjs.networks.js +++ b/routes/electrumjs/electrumjs.networks.js @@ -1,5 +1,6 @@ -let networks = require('agama-wallet-lib/src/bitcoinjs-networks'); +//let networks = require('agama-wallet-lib/src/bitcoinjs-networks'); +let networks = require('bitgo-utxo-lib'); -networks.komodo = networks.kmd; +//networks.komodo = networks.kmd; module.exports = networks; \ No newline at end of file diff --git a/routes/electrumjs/electrumjs.txdecoder-pos.js b/routes/electrumjs/electrumjs.txdecoder-pos.js index e0495a89c..1c84ab459 100644 --- a/routes/electrumjs/electrumjs.txdecoder-pos.js +++ b/routes/electrumjs/electrumjs.txdecoder-pos.js @@ -25,7 +25,8 @@ SOFTWARE. var bitcoin = require('bitcoinjs-lib-pos'); var script = require('bitcoinjs-lib-pos/src/script'); var address = require('bitcoinjs-lib-pos/src/address'); -var bitcoinJS = require('bitcoinjs-lib'); +//var bitcoinJS = require('bitcoinjs-lib'); +var bitcoinJS = require('bitgo-utxo-lib'); var decodeFormat = function(tx) { var result = { diff --git a/routes/electrumjs/electrumjs.txdecoder.js b/routes/electrumjs/electrumjs.txdecoder.js index 14204d517..d4a0eef57 100644 --- a/routes/electrumjs/electrumjs.txdecoder.js +++ b/routes/electrumjs/electrumjs.txdecoder.js @@ -23,7 +23,8 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -var bitcoin = require('bitcoinjs-lib'); +//var bitcoin = require('bitcoinjs-lib'); +var bitcoin = require('bitgo-utxo-lib'); // zcash fallback const Buffer = require('safe-buffer').Buffer; const { @@ -74,6 +75,7 @@ var decodeInput = function(tx) { var decodeOutput = function(tx, network) { var format = function(out, n, network) { + console.log('OUT VALUE IS ' + out.value) var vout = { satoshi: out.value, value: (1e-8 * out.value).toFixed(8), @@ -113,16 +115,42 @@ var decodeOutput = function(tx, network) { var TxDecoder = module.exports = function(rawtx, network) { try { - const _tx = bitcoin.Transaction.fromHex(rawtx); + /* + console.log('Decoding transaction on network: ') + console.log(network) + */ + const _tx = bitcoin.Transaction.fromHex(rawtx, network); + /* + console.log('------------------------------------------------------------------------------------') + console.log(_tx) + console.log('------------------------------------------------------------------------------------') + */ + + if (network.isZcash && (_tx.joinsplits || (_tx.vShieldedSpend || _tx.vShieldedOutput))) { + console.log('ZTx Detected, decoding'); + + const buffer = Buffer.from(rawtx, 'hex'); + + const readHash = buffer => { + const [res, bufferLeft] = readSlice(32)(_sha256(_sha256(buffer))) + const hash = Buffer.from(res, 'hex').reverse().toString('hex') + return hash + }; + + _tx.getId = () => { + return readHash(buffer); + }; + } return { tx: _tx, network: network, format: decodeFormat(_tx), - inputs: decodeInput(_tx), + inputs: !_tx.ins.length ? [{ txid: '0000000000000000000000000000000000000000000000000000000000000000' }] : decodeInput(_tx), outputs: decodeOutput(_tx, network), }; } catch (e) { + console.log(e); if (network.isZcash) { console.log('z tx decode fallback'); @@ -140,12 +168,12 @@ var TxDecoder = module.exports = function(rawtx, network) { const readHash = buffer => { const [res, bufferLeft] = readSlice(32)(_sha256(_sha256(buffer))) const hash = Buffer.from(res, 'hex').reverse().toString('hex') - return [hash, bufferLeft] + return hash }; let decodedtx = decodeTx(buffer); decodedtx[0].getId = () => { - return readHash(buffer)[0]; + return readHash(buffer); }; return { diff --git a/routes/shepherd.js b/routes/shepherd.js index e222661f5..68b6732f2 100644 --- a/routes/shepherd.js +++ b/routes/shepherd.js @@ -17,7 +17,8 @@ shepherd.Promise = require('bluebird'); shepherd.exec = require('child_process').exec; shepherd.execFile = require('child_process').execFile; shepherd.sha256 = require('sha256'); -shepherd.bitcoinJS = require('bitcoinjs-lib'); +//shepherd.bitcoinJS = require('bitcoinjs-lib'); +shepherd.bitcoinJS = require('bitgo-utxo-lib'); shepherd.coinSelect = require('coinselect'); shepherd.fixPath = require('fix-path'); shepherd.crypto = require('crypto'); diff --git a/routes/shepherd/coindWalletKeys.js b/routes/shepherd/coindWalletKeys.js index 3fc4a578c..4d8f2bded 100644 --- a/routes/shepherd/coindWalletKeys.js +++ b/routes/shepherd/coindWalletKeys.js @@ -1,7 +1,8 @@ const fs = require('fs-extra'); const _fs = require('graceful-fs'); const wif = require('wif'); -const bitcoinJS = require('bitcoinjs-lib'); +//const bitcoinJS = require('bitcoinjs-lib'); +const bitcoinJS = require('bitgo-utxo-lib'); module.exports = (shepherd) => { /* diff --git a/routes/shepherd/elections.js b/routes/shepherd/elections.js index 192aabb68..d0239befc 100644 --- a/routes/shepherd/elections.js +++ b/routes/shepherd/elections.js @@ -1,5 +1,6 @@ const bs58check = require('bs58check'); -const bitcoin = require('bitcoinjs-lib'); +//const bitcoin = require('bitcoinjs-lib'); +const bitcoin = require('bitgo-utxo-lib'); const Promise = require('bluebird'); module.exports = (shepherd) => { diff --git a/routes/shepherd/electrum/auth.js b/routes/shepherd/electrum/auth.js index a133ee667..067694ce5 100644 --- a/routes/shepherd/electrum/auth.js +++ b/routes/shepherd/electrum/auth.js @@ -1,6 +1,7 @@ const bs58check = require('bs58check'); const bitcoinZcash = require('bitcoinjs-lib-zcash'); -const bitcoin = require('bitcoinjs-lib'); +//const bitcoin = require('bitcoinjs-lib'); +const bitcoin = require('bitgo-utxo-lib'); module.exports = (shepherd) => { shepherd.post('/electrum/login', (req, res, next) => { diff --git a/routes/shepherd/electrum/coins.js b/routes/shepherd/electrum/coins.js index ced3f9e95..4f9ad76d0 100644 --- a/routes/shepherd/electrum/coins.js +++ b/routes/shepherd/electrum/coins.js @@ -54,7 +54,11 @@ module.exports = (shepherd) => { shepherd.log(`${coin} doesnt have any backup electrum servers`, true); } + //console.log(shepherd.electrumKeys) + if (Object.keys(shepherd.electrumKeys).length > 0) { + //console.log('Attempting to add ' + coin + ', with wif key: ') + //console.log(shepherd.electrumKeys[Object.keys(shepherd.electrumKeys)[0]].priv) const _keys = shepherd.wifToWif(shepherd.electrumKeys[Object.keys(shepherd.electrumKeys)[0]].priv, coin); shepherd.electrumKeys[coin] = { diff --git a/routes/shepherd/electrum/createtx-multi.js b/routes/shepherd/electrum/createtx-multi.js index 30b52af5b..b4154109b 100644 --- a/routes/shepherd/electrum/createtx-multi.js +++ b/routes/shepherd/electrum/createtx-multi.js @@ -1,4 +1,5 @@ -const bitcoinJS = require('bitcoinjs-lib'); +//const bitcoinJS = require('bitcoinjs-lib'); +const bitcoinJS = require('bitgo-utxo-lib'); const bitcoinJSForks = require('bitcoinforksjs-lib'); const bitcoinZcash = require('bitcoinjs-lib-zcash'); const bitcoinPos = require('bitcoinjs-lib-pos'); diff --git a/routes/shepherd/electrum/createtx-split.js b/routes/shepherd/electrum/createtx-split.js index 58698d636..6b7b2a41a 100644 --- a/routes/shepherd/electrum/createtx-split.js +++ b/routes/shepherd/electrum/createtx-split.js @@ -1,4 +1,5 @@ -const bitcoinJS = require('bitcoinjs-lib'); +//const bitcoinJS = require('bitcoinjs-lib'); +const bitcoinJS = require('bitgo-utxo-lib'); const bitcoinJSForks = require('bitcoinforksjs-lib'); const bitcoinZcash = require('bitcoinjs-lib-zcash'); const bitcoinPos = require('bitcoinjs-lib-pos'); diff --git a/routes/shepherd/electrum/createtx.js b/routes/shepherd/electrum/createtx.js index f4db24c12..fd5c1f281 100644 --- a/routes/shepherd/electrum/createtx.js +++ b/routes/shepherd/electrum/createtx.js @@ -1,4 +1,6 @@ -const bitcoinJS = require('bitcoinjs-lib'); +//const bitcoinJS = require('bitcoinjs-lib'); +const bitcoinJS = require('bitgo-utxo-lib'); +const bitcoin = require('bitgo-utxo-lib'); const bitcoinJSForks = require('bitcoinforksjs-lib'); const bitcoinZcash = require('bitcoinjs-lib-zcash'); const bitcoinPos = require('bitcoinjs-lib-pos'); @@ -56,18 +58,28 @@ module.exports = (shepherd) => { } // single sig - shepherd.buildSignedTx = (sendTo, changeAddress, wif, network, utxo, changeValue, spendValue, opreturn) => { - let key = shepherd.isZcash(network) ? bitcoinZcash.ECPair.fromWIF(wif, shepherd.getNetworkData(network)) : bitcoinJS.ECPair.fromWIF(wif, shepherd.getNetworkData(network)); + shepherd.buildSignedTx = (sendTo, changeAddress, wif, network, utxo, changeValue, spendValue, opreturn, blockheight) => { + console.log('Initiating transaction build procedure') + + let key = bitcoinJS.ECPair.fromWIF(wif, bitcoin.networks[network]); let tx; + + + console.log('Keypair intialized and transaction defined') if (shepherd.isZcash(network)) { + console.log('network isZcash', true); tx = new bitcoinZcash.TransactionBuilder(shepherd.getNetworkData(network)); } else if (shepherd.isPos(network)) { + console.log('network isPos', true); tx = new bitcoinPos.TransactionBuilder(shepherd.getNetworkData(network)); } else { + console.log('network bitcoinJS', true); tx = new bitcoinJS.TransactionBuilder(shepherd.getNetworkData(network)); } + console.log('Unsigned transaction structure constructed successfully'); + shepherd.log('buildSignedTx', true); // console.log(`buildSignedTx priv key ${wif}`); shepherd.log(`buildSignedTx pub key ${key.getAddress().toString()}`, true); @@ -77,29 +89,40 @@ module.exports = (shepherd) => { tx.addInput(utxo[i].txid, utxo[i].vout); } + console.log(utxo); + + console.log('UTXOs added to transaction') + if (shepherd.isPos(network)) { + console.log('Network is Pos, adding special output') tx.addOutput( sendTo, Number(spendValue), shepherd.getNetworkData(network) ); } else { + console.log('Adding output to transaction') tx.addOutput(sendTo, Number(spendValue)); } if (changeValue > 0) { + console.log('Change value larger than 0, adding change value output') if (shepherd.isPos(network)) { + console.log('Special case for Pos on adding change value') tx.addOutput( changeAddress, Number(changeValue), shepherd.getNetworkData(network) ); } else { + console.log('Adding change value for standard network') tx.addOutput(changeAddress, Number(changeValue)); } } if (opreturn) { + console.log('Opreturn detected, adding to outputs:') + console.log(opreturn) const data = Buffer.from(opreturn, 'utf8'); const dataScript = shepherd.bitcoinJS.script.nullData.output.encode(data); tx.addOutput(dataScript, 1000); @@ -108,17 +131,40 @@ module.exports = (shepherd) => { if (network === 'komodo' || network.toUpperCase() === 'KMD') { + console.log('Network detected as ' + network) const _locktime = Math.floor(Date.now() / 1000) - 777; tx.setLockTime(_locktime); shepherd.log(`kmd tx locktime set to ${_locktime}`, true); } + console.log('Current block height: ' + blockheight); + + let versionNum; + if ((blockheight === 419200 && network === 'zec') || + (blockheight === 227520 && network === 'vrsc')){ + versionNum = 4; + } + else { + if (network === 'zec') { + versionNum = 3; + } + else { + versionNum = 1; + } + } + + tx.setVersion(versionNum); + + console.log('Set version to ' + versionNum) + + /* shepherd.log('buildSignedTx unsigned tx data vin', true); shepherd.log(tx.tx.ins, true); shepherd.log('buildSignedTx unsigned tx data vout', true); shepherd.log(tx.tx.outs, true); shepherd.log('buildSignedTx unsigned tx data', true); shepherd.log(tx, true); + */ for (let i = 0; i < utxo.length; i++) { if (shepherd.isPos(network)) { @@ -128,14 +174,21 @@ module.exports = (shepherd) => { key ); } else { - tx.sign(i, key); + console.log('________________________________________________________'); + console.log('KEYPAIR NETWORK: ') + console.log(key.network) + console.log('________________________________________________________'); + tx.sign(i, key, '', null, utxo[i].value); + console.log('Standard transaction signed') } } const rawtx = tx.build().toHex(); + /* shepherd.log('buildSignedTx signed tx hex', true); shepherd.log(rawtx, true); +*/ return rawtx; } @@ -307,6 +360,7 @@ module.exports = (shepherd) => { value: Number(utxoList[i].amountSats), interestSats: Number(utxoList[i].interestSats), verified: utxoList[i].verified ? utxoList[i].verified : false, + blockheight: utxoList[i].blockheight }); } else { utxoListFormatted.push({ @@ -314,6 +368,7 @@ module.exports = (shepherd) => { vout: utxoList[i].vout, value: Number(utxoList[i].amountSats), verified: utxoList[i].verified ? utxoList[i].verified : false, + blockheight: utxoList[i].blockheight }); } } @@ -348,6 +403,7 @@ module.exports = (shepherd) => { ); let inputs = firstRun.inputs; let outputs = firstRun.outputs; + let currentheight = utxoListFormatted[0].blockheight; if (btcFee) { shepherd.log(`btc fee per byte ${btcFee}`, true); @@ -554,7 +610,8 @@ module.exports = (shepherd) => { inputs, _change, value, - opreturn + opreturn, + currentheight ); } } diff --git a/routes/shepherd/electrum/keys.js b/routes/shepherd/electrum/keys.js index f7247fe51..77ad5ec6d 100644 --- a/routes/shepherd/electrum/keys.js +++ b/routes/shepherd/electrum/keys.js @@ -4,13 +4,15 @@ const bip39 = require('bip39'); const crypto = require('crypto'); const bigi = require('bigi'); const bitcoinZcash = require('bitcoinjs-lib-zcash'); -const bitcoin = require('bitcoinjs-lib'); +//const bitcoin = require('bitcoinjs-lib'); +const bitcoin = require('bitgo-utxo-lib'); const bs58check = require('bs58check'); module.exports = (shepherd) => { shepherd.wifToWif = (wif, network) => { network = network.toLowerCase(); - const key = shepherd.isZcash(network) ? new bitcoinZcash.ECPair.fromWIF(wif, shepherd.getNetworkData(network), true) : new bitcoin.ECPair.fromWIF(wif, shepherd.getNetworkData(network), true); + //const key = shepherd.isZcash(network) ? new bitcoinZcash.ECPair.fromWIF(wif, shepherd.getNetworkData(network), true) : new bitcoin.ECPair.fromWIF(wif, shepherd.getNetworkData(network), true); + const key = new bitcoin.ECPair.fromWIF(wif, bitcoin.networks[network], true); return { pub: key.getAddress(), diff --git a/routes/shepherd/electrum/listunspent.js b/routes/shepherd/electrum/listunspent.js index a5f8ca01a..bb4175550 100644 --- a/routes/shepherd/electrum/listunspent.js +++ b/routes/shepherd/electrum/listunspent.js @@ -70,6 +70,7 @@ module.exports = (shepherd) => { interest: Number(interest.toFixed(8)), interestSats: Math.floor(interest * 100000000), confirmations: Number(_utxoItem.height) === 0 ? 0 : currentHeight - _utxoItem.height, + blockheight: currentHeight, spendable: true, verified: false, }; @@ -101,6 +102,7 @@ module.exports = (shepherd) => { amount: Number(_utxoItem.value) * 0.00000001, amountSats: _utxoItem.value, confirmations: Number(_utxoItem.height) === 0 ? 0 : currentHeight - _utxoItem.height, + blockheight: currentHeight, spendable: true, verified: false, }; diff --git a/routes/shepherd/electrum/merkle.js b/routes/shepherd/electrum/merkle.js index c5e163a23..1835d0746 100644 --- a/routes/shepherd/electrum/merkle.js +++ b/routes/shepherd/electrum/merkle.js @@ -43,7 +43,9 @@ module.exports = (shepherd) => { } const _rnd = getRandomIntInclusive(0, serverList.length - 1); + console.log('SERVER LIST LENGTH: ' + serverList.length + ', CHOSEN SERVER INDEX: ' + _rnd) const randomServer = serverList[_rnd]; + console.log(randomServer) const _randomServer = randomServer.split(':'); const _mainServer = mainServer.split(':'); diff --git a/routes/shepherd/electrum/network.js b/routes/shepherd/electrum/network.js index 060909388..55a155a95 100644 --- a/routes/shepherd/electrum/network.js +++ b/routes/shepherd/electrum/network.js @@ -1,4 +1,5 @@ const { isKomodoCoin } = require('agama-wallet-lib/src/coin-helpers'); +const bitcoin = require('bitgo-utxo-lib'); const txDecoder = { default: require('../../electrumjs/electrumjs.txdecoder.js'), @@ -35,6 +36,16 @@ module.exports = (shepherd) => { shepherd.getNetworkData = (network) => { let coin = shepherd.findNetworkObj(network) || shepherd.findNetworkObj(network.toUpperCase()) || shepherd.findNetworkObj(network.toLowerCase()); + console.log('searching for ' + coin + ' network data...'); + try { + console.log('Nework data retreived for ' + bitcoin.networks[coin].messagePrefix) + return bitcoin.networks[coin] + } + catch(e) { + console.log("Error finding " + coin + ' network data! Defaulting to default network data...'); + return bitcoin.networks['default'] + } +/* const coinUC = coin ? coin.toUpperCase() : null; if (!coin && @@ -48,6 +59,7 @@ module.exports = (shepherd) => { } else { return shepherd.electrumJSNetworks[network]; } +*/ } shepherd.findNetworkObj = (coin) => { @@ -99,7 +111,7 @@ module.exports = (shepherd) => { const _coin = req.query.coin; if (shepherd.checkToken(req.query.token)) { - shepherd.electrumCoins[_coin].server = { + shepherd.electrumCoins[_coin.toLowerCase()].server = { ip: req.query.address, port: req.query.port, proto: req.query.proto, diff --git a/routes/shepherd/pin.js b/routes/shepherd/pin.js index 954304549..33fa2b587 100644 --- a/routes/shepherd/pin.js +++ b/routes/shepherd/pin.js @@ -1,6 +1,7 @@ const fs = require('fs-extra'); const passwdStrength = require('passwd-strength'); -const bitcoin = require('bitcoinjs-lib'); +//const bitcoin = require('bitcoinjs-lib'); +const bitcoin = require('bitgo-utxo-lib'); const sha256 = require('js-sha256'); const bigi = require('bigi'); const aes256 = require('nodejs-aes256'); From 69e660e1804de3b27e2529dd29ba98a73376e3b7 Mon Sep 17 00:00:00 2001 From: michaelftout Date: Sun, 28 Oct 2018 18:58:54 -0700 Subject: [PATCH 2/3] Commented out large output message --- routes/shepherd/electrum/parseTxAddresses.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/routes/shepherd/electrum/parseTxAddresses.js b/routes/shepherd/electrum/parseTxAddresses.js index d5a9a6437..920471420 100644 --- a/routes/shepherd/electrum/parseTxAddresses.js +++ b/routes/shepherd/electrum/parseTxAddresses.js @@ -74,12 +74,12 @@ module.exports = (shepherd) => { _addresses.inputs = [ ...new Set(_addresses.inputs) ]; _addresses.outputs = [ ...new Set(_addresses.outputs) ]; - +/* shepherd.log('addresses in =>', true); shepherd.log(_addresses.inputs, true); shepherd.log('addresses out =>', true); shepherd.log(_addresses.outputs, true); - +*/ let isSelfSend = { inputs: false, outputs: false, From aee755472df8b2b0f98ddda8c8ff54e67d4f0ee9 Mon Sep 17 00:00:00 2001 From: michaelftout Date: Sun, 28 Oct 2018 19:03:24 -0700 Subject: [PATCH 3/3] Add bitgo-utxo-lib to package.json --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index e4eda4b05..950bda553 100644 --- a/package.json +++ b/package.json @@ -41,6 +41,7 @@ "dependencies": { "adm-zip": "^0.4.7", "agama-wallet-lib": "git+https://github.com/VerusCoin/agama-wallet-lib.git", + "bitgo-utxo-lib": "git+https://github.com/miketout/bitgo-utxo-lib.git", "arch": "^2.1.0", "async": "^2.6.0", "bigi": "^1.4.2",