From b4e7effa5741bd8dbe8ae82de4bf63af96464c46 Mon Sep 17 00:00:00 2001 From: pbca26 Date: Mon, 25 Dec 2017 02:21:16 +0300 Subject: [PATCH] zec, hush spv --- package.json | 4 +- routes/electrumjs/electrumServers.js | 35 +++-- routes/electrumjs/electrumjs.networks.js | 37 ++++-- .../electrumjs/electrumjs.txdecoder-2bytes.js | 120 ++++++++++++++++++ routes/shepherd.js | 2 +- routes/shepherd/daemonControl.js | 91 +++++++------ routes/shepherd/electrum/balance.js | 2 +- routes/shepherd/electrum/createtx.js | 5 +- routes/shepherd/electrum/keys.js | 34 ++--- routes/shepherd/electrum/listunspent.js | 5 +- routes/shepherd/electrum/merkle.js | 4 +- routes/shepherd/electrum/network.js | 13 ++ routes/shepherd/electrum/transactions.js | 6 +- 13 files changed, 260 insertions(+), 98 deletions(-) create mode 100644 routes/electrumjs/electrumjs.txdecoder-2bytes.js diff --git a/package.json b/package.json index 0c496b8..2c76e0e 100644 --- a/package.json +++ b/package.json @@ -28,14 +28,14 @@ "dependencies": { "adm-zip": "^0.4.7", "arch": "^2.1.0", + "bigi": "^1.4.2", "bip39": "^2.4.0", - "bitcoinjs-lib": "^3.2.0", "bitcoinforksjs-lib": "git://github.com/bitcoinjs/bitcoinjs-lib#opt-in-bitcoincash-sighash", + "bitcoinjs-lib": "^3.2.0", "bitcoinjs-lib-zcash": "git://github.com/karel-3d/bitcoinjs-lib#zcash", "bluebird": "^3.4.7", "body-parser": "^1.15.2", "buffer-reverse": "^1.0.1", - "coinkey": "^2.0.0", "coinselect": "github:bitcoinjs/coinselect", "electron": "1.6.5", "express": "^4.14.0", diff --git a/routes/electrumjs/electrumServers.js b/routes/electrumjs/electrumServers.js index 2329a1d..6cb351f 100644 --- a/routes/electrumjs/electrumServers.js +++ b/routes/electrumjs/electrumServers.js @@ -1,13 +1,4 @@ let electrumServers = { - /*zcash: { 2 bytes address fix is required - address: '173.212.225.176', - port: 50032, - proto: 'tcp', - serverList: [ - '173.212.225.176:50032', - '136.243.45.140:50032' - ], - },*/ coqui: { // !estimatefee address: 'electrum1.cipig.net', port: 10011, @@ -298,7 +289,7 @@ let electrumServers = { '94.130.224.11:10052' ], }, - /*blk: { can't decode tx! + blk: { // can't decode tx! address: 'electrum1.cipig.net', port: 10054, proto: 'tcp', @@ -308,7 +299,7 @@ let electrumServers = { 'electrum1.cipig.net:10054', 'electrum2.cipig.net:10054' ], - },*/ + }, sib: { address: 'electrum1.cipig.net', port: 10050, @@ -353,6 +344,28 @@ let electrumServers = { 'electrum2.cipig.net:10053' ], }, + zec: { + address: '173.212.225.176', + port: 50032, + proto: 'tcp', + txfee: 10000, + abbr: 'ZEC', + serverList: [ + '173.212.225.176:50032', + '136.243.45.140:50032' + ], + }, + hush: { + address: '173.212.225.176', + port: 50013, + proto: 'tcp', + txfee: 10000, + abbr: 'HUSH', + serverList: [ + '173.212.225.176:50013', + '136.243.45.140:50013' + ], + }, }; electrumServers.crw = electrumServers.crown; diff --git a/routes/electrumjs/electrumjs.networks.js b/routes/electrumjs/electrumjs.networks.js index 7f1d50a..e82295c 100644 --- a/routes/electrumjs/electrumjs.networks.js +++ b/routes/electrumjs/electrumjs.networks.js @@ -240,19 +240,32 @@ networks.sib = { dustThreshold: 1000, }; +networks.zcash = { + messagePrefix: '\x19Zcash Signed Message:\n', + bip32: { + public: 0x0488b21e, + private: 0x05358394, + }, + pubKeyHash: 0x1cb8, + scriptHash: 0x1cbd, + wif: 0x80, + dustThreshold: 1000, +}; + +networks.hush = { + messagePrefix: '\Hush Signed Message:\n', + bip32: { + public: 0x0488b21e, + private: 0x0488ade4, + }, + pubKeyHash: 0x1cb8, + scriptHash: 0x1cbd, + wif: 0x80, + dustThreshold: 1000, +}; + networks.btc = networks.bitcoin; networks.crw = networks.crown; networks.dgb = networks.digibyte; networks.arg = networks.argentum; - -/*networks.zcash = { - messagePrefix: '\x19Zcash Signed Message:\n', - bip32: { - public: 0x0488b21e, - private: 0x0488ade4, - }, - pubKeyHash: 0x1cb8, - scriptHash: 0x1cbd, - wif: 0x80, - dustThreshold: 1000, -};*/ \ No newline at end of file +networks.zec = networks.zcash; \ No newline at end of file diff --git a/routes/electrumjs/electrumjs.txdecoder-2bytes.js b/routes/electrumjs/electrumjs.txdecoder-2bytes.js new file mode 100644 index 0000000..f96199a --- /dev/null +++ b/routes/electrumjs/electrumjs.txdecoder-2bytes.js @@ -0,0 +1,120 @@ +/* +MIT License + +Copyright (c) 2017 Yuki Akiyama, SuperNET + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +var bitcoin = require('bitcoinjs-lib-zcash'); + +var decodeFormat = function(tx) { + var result = { + txid: tx.getId(), + version: tx.version, + locktime: tx.locktime, + }; + + return result; +} + +var decodeInput = function(tx) { + var result = []; + + tx.ins.forEach(function(input, n) { + var vin = { + txid: input.hash.reverse().toString('hex'), + n: input.index, + script: bitcoin.script.toASM(input.script), + sequence: input.sequence, + }; + + result.push(vin); + }); + + return result; +} + +var decodeOutput = function(tx, network) { + var format = function(out, n, network) { + var vout = { + satoshi: out.value, + value: (1e-8 * out.value).toFixed(8), + n: n, + scriptPubKey: { + asm: bitcoin.script.toASM(out.script), + hex: out.script.toString('hex'), + type: bitcoin.script.classifyOutput(out.script), + addresses: [], + }, + }; + + switch(vout.scriptPubKey.type) { + case 'pubkeyhash': + vout.scriptPubKey.addresses.push(bitcoin.address.fromOutputScript(out.script, network)); + break; + case 'pubkey': + const pubKeyBuffer = new Buffer(vout.scriptPubKey.asm.split(' ')[0], 'hex'); + vout.scriptPubKey.addresses.push(bitcoin.ECPair.fromPublicKeyBuffer(pubKeyBuffer, network).getAddress()); + break; + case 'scripthash': + vout.scriptPubKey.addresses.push(bitcoin.address.fromOutputScript(out.script, network)); + break; + } + + return vout; + } + + var result = []; + + tx.outs.forEach(function(out, n) { + result.push(format(out, n, network)); + }); + + return result; +} + +var TxDecoder = module.exports = function(rawtx, network) { + try { + const _tx = bitcoin.Transaction.fromHex(rawtx); + + return { + tx: _tx, + network: network, + format: decodeFormat(_tx), + inputs: decodeInput(_tx), + outputs: decodeOutput(_tx, network), + }; + } catch (e) { + return false; + } +} + +TxDecoder.prototype.decode = function() { + var result = {}; + var self = this; + + Object.keys(self.format).forEach(function(key) { + result[key] = self.format[key]; + }); + + result.outputs = self.outputs; + + return result; +} \ No newline at end of file diff --git a/routes/shepherd.js b/routes/shepherd.js index ee070b7..fa38930 100644 --- a/routes/shepherd.js +++ b/routes/shepherd.js @@ -18,7 +18,6 @@ shepherd.Promise = require('bluebird'); shepherd.exec = require('child_process').exec; shepherd.execFile = require('child_process').execFile; shepherd.sha256 = require('sha256'); -shepherd.CoinKey = require('coinkey'); shepherd.bitcoinJS = require('bitcoinjs-lib'); shepherd.coinSelect = require('coinselect'); shepherd.fixPath = require('fix-path'); @@ -63,6 +62,7 @@ shepherd.electrumKeys = {}; shepherd.electrumJSCore = require('./electrumjs/electrumjs.core.js'); shepherd.electrumJSNetworks = require('./electrumjs/electrumjs.networks.js'); shepherd.electrumJSTxDecoder = require('./electrumjs/electrumjs.txdecoder.js'); +shepherd.electrumJSTxDecoderZ = require('./electrumjs/electrumjs.txdecoder-2bytes.js'); shepherd.electrumServers = require('./electrumjs/electrumServers.js'); shepherd.CONNECTION_ERROR_OR_INCOMPLETE_DATA = 'connection error or incomplete data'; diff --git a/routes/shepherd/daemonControl.js b/routes/shepherd/daemonControl.js index 5c58e08..9bb0143 100644 --- a/routes/shepherd/daemonControl.js +++ b/routes/shepherd/daemonControl.js @@ -11,6 +11,7 @@ const md5 = require('../md5.js'); module.exports = (shepherd) => { const getConf = (flock, coind) => { + const _platform = os.platform(); let DaemonConfPath = ''; let nativeCoindDir; @@ -23,7 +24,7 @@ module.exports = (shepherd) => { shepherd.writeLog(`getconf flock: ${flock}`); if (coind) { - switch (os.platform()) { + switch (_platform) { case 'darwin': nativeCoindDir = `${process.env.HOME}/Library/Application Support/${shepherd.nativeCoindList[coind.toLowerCase()].bin}`; break; @@ -39,29 +40,29 @@ module.exports = (shepherd) => { switch (flock) { case 'komodod': DaemonConfPath = shepherd.komodoDir; - if (os.platform() === 'win32') { + if (_platform === 'win32') { DaemonConfPath = path.normalize(DaemonConfPath); shepherd.log('===>>> SHEPHERD API OUTPUT ===>>>'); } break; case 'zcashd': DaemonConfPath = shepherd.ZcashDir; - if (os.platform() === 'win32') { + if (_platform === 'win32') { DaemonConfPath = path.normalize(DaemonConfPath); } break; case 'chipsd': DaemonConfPath = shepherd.chipsDir; - if (os.platform() === 'win32') { + if (_platform === 'win32') { DaemonConfPath = path.normalize(DaemonConfPath); } break; case 'coind': - DaemonConfPath = os.platform() === 'win32' ? shepherd.path.normalize(`${shepherd.coindRootDir}/${coind.toLowerCase()}`) : `${shepherd.coindRootDir}/${coind.toLowerCase()}`; + DaemonConfPath = _platform === 'win32' ? shepherd.path.normalize(`${shepherd.coindRootDir}/${coind.toLowerCase()}`) : `${shepherd.coindRootDir}/${coind.toLowerCase()}`; break; default: DaemonConfPath = `${shepherd.komodoDir}/${flock}`; - if (os.platform() === 'win32') { + if (_platform === 'win32') { DaemonConfPath = shepherd.path.normalize(DaemonConfPath); } } @@ -482,57 +483,58 @@ module.exports = (shepherd) => { } const setConf = (flock, coind) => { + const _platform = os.platform(); let nativeCoindDir; let DaemonConfPath; shepherd.log(flock); shepherd.writeLog(`setconf ${flock}`); - if (os.platform() === 'darwin') { - nativeCoindDir = coind ? `${process.env.HOME}/Library/Application Support/${shepherd.nativeCoindList[coind.toLowerCase()].bin}` : null; - } - - if (os.platform() === 'linux') { - nativeCoindDir = coind ? `${process.env.HOME}/.${shepherd.nativeCoindList[coind.toLowerCase()].bin.toLowerCase()}` : null; - } - - if (os.platform() === 'win32') { - nativeCoindDir = coind ? `${process.env.APPDATA}/${shepherd.nativeCoindList[coind.toLowerCase()].bin}` : null; + switch (_platform) { + case 'darwin': + nativeCoindDir = coind ? `${process.env.HOME}/Library/Application Support/${shepherd.nativeCoindList[coind.toLowerCase()].bin}` : null; + break; + case 'linux': + nativeCoindDir = coind ? `${process.env.HOME}/.${shepherd.nativeCoindList[coind.toLowerCase()].bin.toLowerCase()}` : null; + break; + case 'win32': + nativeCoindDir = coind ? `${process.env.APPDATA}/${shepherd.nativeCoindList[coind.toLowerCase()].bin}` : null; + break; } switch (flock) { case 'komodod': DaemonConfPath = `${shepherd.komodoDir}/komodo.conf`; - if (os.platform() === 'win32') { + if (_platform === 'win32') { DaemonConfPath = path.normalize(DaemonConfPath); } break; case 'zcashd': DaemonConfPath = `${shepherd.ZcashDir}/zcash.conf`; - if (os.platform() === 'win32') { + if (_platform === 'win32') { DaemonConfPath = path.normalize(DaemonConfPath); } break; case 'chipsd': DaemonConfPath = `${shepherd.chipsDir}/chips.conf`; - if (os.platform() === 'win32') { + if (_platform === 'win32') { DaemonConfPath = path.normalize(DaemonConfPath); } break; case 'coind': DaemonConfPath = `${nativeCoindDir}/${shepherd.nativeCoindList[coind.toLowerCase()].bin.toLowerCase()}.conf`; - if (os.platform() === 'win32') { + if (_platform === 'win32') { DaemonConfPath = path.normalize(DaemonConfPath); } break; default: DaemonConfPath = `${shepherd.komodoDir}/${flock}/${flock}.conf`; - if (os.platform() === 'win32') { + if (_platform === 'win32') { DaemonConfPath = path.normalize(DaemonConfPath); } } @@ -790,14 +792,17 @@ module.exports = (shepherd) => { * params: herd */ shepherd.post('/herd', (req, res) => { - shepherd.log('======= req.body ======='); - shepherd.log(req.body); + const _body = req.body; + shepherd.log('herd req.body =>'); + shepherd.log(_body); - if (req.body.options && + if (_body.options && !shepherd.kmdMainPassiveMode) { const testCoindPort = (skipError) => { + const _acName = req.body.options.ac_name; + if (!shepherd.lockDownAddCoin) { - const _port = shepherd.assetChainPorts[req.body.options.ac_name]; + const _port = shepherd.assetChainPorts[_acName]; portscanner.checkPortStatus(_port, '127.0.0.1', (error, status) => { // Status is 'open' if currently in use or 'closed' if available @@ -808,13 +813,13 @@ module.exports = (shepherd) => { shepherd.writeLog(`komodod service start error at port ${_port}, reason: port is closed`); shepherd.io.emit('service', { komodod: { - error: `error starting ${req.body.herd} ${req.body.options.ac_name} daemon. Port ${_port} is already taken!`, + error: `error starting ${_body.herd} ${_acName} daemon. Port ${_port} is already taken!`, }, }); const obj = { msg: 'error', - result: `error starting ${req.body.herd} ${req.body.options.ac_name} daemon. Port ${_port} is already taken!`, + result: `error starting ${_body.herd} ${_acName} daemon. Port ${_port} is already taken!`, }; res.status(500); @@ -825,7 +830,7 @@ module.exports = (shepherd) => { } } else { if (!skipError) { - herder(req.body.herd, req.body.options); + herder(_body.herd, _body.options); const obj = { msg: 'success', @@ -842,14 +847,14 @@ module.exports = (shepherd) => { } } - if (req.body.herd === 'komodod') { + if (_body.herd === 'komodod') { // check if komodod instance is already running testCoindPort(); setTimeout(() => { testCoindPort(true); }, 10000); } else { - herder(req.body.herd, req.body.options, req.body.coind); + herder(_body.herd, _body.options, _body.coind); const obj = { msg: 'success', @@ -860,7 +865,7 @@ module.exports = (shepherd) => { } } else { // (?) - herder(req.body.herd, req.body.options); + herder(_body.herd, _body.options); const obj = { msg: 'success', @@ -875,14 +880,16 @@ module.exports = (shepherd) => { * type: POST */ shepherd.post('/setconf', (req, res) => { - shepherd.log('======= req.body ======='); - shepherd.log(req.body); + const _body = req.body; + + shepherd.log('setconf req.body =>'); + shepherd.log(_body); if (os.platform() === 'win32' && - req.body.chain == 'komodod') { + _body.chain == 'komodod') { setkomodoconf = spawn(path.join(__dirname, '../assets/bin/win64/genkmdconf.bat')); } else { - shepherd.setConf(req.body.chain); + shepherd.setConf(_body.chain); } const obj = { @@ -897,15 +904,15 @@ module.exports = (shepherd) => { * type: POST */ shepherd.post('/getconf', (req, res) => { - shepherd.log('======= req.body ======='); - shepherd.log(req.body); + const _body = req.body; + + shepherd.log('getconf req.body =>'); + shepherd.log(_body); - const confpath = getConf(req.body.chain, req.body.coind); + const confpath = getConf(_body.chain, _body.coind); - shepherd.log('got conf path is:'); - shepherd.log(confpath); - shepherd.writeLog('got conf path is:'); - shepherd.writeLog(confpath); + shepherd.log(`getconf path is: ${confpath}`); + shepherd.writeLog(`getconf path is: ${confpath}`); const obj = { msg: 'success', diff --git a/routes/shepherd/electrum/balance.js b/routes/shepherd/electrum/balance.js index 9291a7f..5f9b099 100644 --- a/routes/shepherd/electrum/balance.js +++ b/routes/shepherd/electrum/balance.js @@ -45,7 +45,7 @@ module.exports = (shepherd) => { // decode tx const _network = shepherd.getNetworkData(network); - const decodedTx = shepherd.electrumJSTxDecoder(_rawtxJSON, _network); + const decodedTx = shepherd.isZcash(network) ? shepherd.electrumJSTxDecoderZ(_rawtxJSON, _network) : shepherd.electrumJSTxDecoder(_rawtxJSON, _network); if (decodedTx && decodedTx.format && diff --git a/routes/shepherd/electrum/createtx.js b/routes/shepherd/electrum/createtx.js index a87da8a..f109f84 100644 --- a/routes/shepherd/electrum/createtx.js +++ b/routes/shepherd/electrum/createtx.js @@ -1,4 +1,5 @@ const bitcoinJSForks = require('bitcoinforksjs-lib'); +const bitcoinZcash = require('bitcoinjs-lib-zcash'); module.exports = (shepherd) => { // unsigned tx @@ -52,8 +53,8 @@ module.exports = (shepherd) => { // single sig shepherd.buildSignedTx = (sendTo, changeAddress, wif, network, utxo, changeValue, spendValue) => { - let key = shepherd.bitcoinJS.ECPair.fromWIF(wif, shepherd.getNetworkData(network)); - let tx = new shepherd.bitcoinJS.TransactionBuilder(shepherd.getNetworkData(network)); + let key = shepherd.isZcash(network) ? bitcoinZcash.ECPair.fromWIF(wif, shepherd.getNetworkData(network)) : shepherd.bitcoinJS.ECPair.fromWIF(wif, shepherd.getNetworkData(network)); + let tx = shepherd.isZcash(network) ? new bitcoinZcash.TransactionBuilder(shepherd.getNetworkData(network)) : new shepherd.bitcoinJS.TransactionBuilder(shepherd.getNetworkData(network)); shepherd.log('buildSignedTx'); // console.log(`buildSignedTx priv key ${wif}`); diff --git a/routes/shepherd/electrum/keys.js b/routes/shepherd/electrum/keys.js index c347a12..6ad3eb5 100644 --- a/routes/shepherd/electrum/keys.js +++ b/routes/shepherd/electrum/keys.js @@ -1,6 +1,9 @@ const sha256 = require('js-sha256'); const bip39 = require('bip39'); const crypto = require('crypto'); +const bigi = require('bigi'); +const bitcoinZcash = require('bitcoinjs-lib-zcash'); +const bitcoin = require('bitcoinjs-lib'); module.exports = (shepherd) => { shepherd.seedToWif = (seed, network, iguana) => { @@ -19,30 +22,19 @@ module.exports = (shepherd) => { bytes[31] |= 64; } - const toHexString = (byteArray) => { - return Array.from(byteArray, (byte) => { - return ('0' + (byte & 0xFF).toString(16)).slice(-2); - }).join(''); - } - - const hex = toHexString(bytes); - - const key = new shepherd.CoinKey(new Buffer(hex, 'hex'), { - private: shepherd.getNetworkData(network).wif, - public: shepherd.getNetworkData(network).pubKeyHash, - }); - - key.compressed = true; + const d = bigi.fromBuffer(bytes); + const keyPair = shepherd.isZcash(network) ? new bitcoinZcash.ECPair(d, null, { network: shepherd.getNetworkData(network) }) : new bitcoinZcash.ECPair(d, null, { network: shepherd.getNetworkData(network) }); + const keys = { + pub: keyPair.getAddress(), + priv: keyPair.toWIF(), + }; /*shepherd.log(`seed: ${seed}`, true); shepherd.log(`network ${network}`, true); - shepherd.log(`seedtowif priv key ${key.privateWif}`, true); - shepherd.log(`seedtowif pub key ${key.publicAddress}`, true);*/ + shepherd.log(`seedtowif priv key ${keys.priv}`, true); + shepherd.log(`seedtowif pub key ${keys.pub}`, true);*/ - return { - priv: key.privateWif, - pub: key.publicAddress, - }; + return keys; } shepherd.get('/electrum/wiftopub', (req, res, next) => { @@ -63,7 +55,7 @@ module.exports = (shepherd) => { }); shepherd.get('/electrum/seedtowif', (req, res, next) => { - const keys = shepherd.seedToWif(req.query.seed, req.query.network, req.query.iguana); + let keys = shepherd.seedToWif(req.query.seed, req.query.network, req.query.iguana); const successObj = { msg: 'success', diff --git a/routes/shepherd/electrum/listunspent.js b/routes/shepherd/electrum/listunspent.js index b0a645b..b3262e0 100644 --- a/routes/shepherd/electrum/listunspent.js +++ b/routes/shepherd/electrum/listunspent.js @@ -36,7 +36,7 @@ module.exports = (shepherd) => { // decode tx const _network = shepherd.getNetworkData(network); - const decodedTx = shepherd.electrumJSTxDecoder(_rawtxJSON, _network); + const decodedTx = shepherd.isZcash(network) ? shepherd.electrumJSTxDecoderZ(_rawtxJSON, _network) : shepherd.electrumJSTxDecoder(_rawtxJSON, _network); shepherd.log('decoded tx =>', true); shepherd.log(decodedTx, true); @@ -71,7 +71,8 @@ module.exports = (shepherd) => { if (verify) { shepherd.verifyMerkleByCoin(shepherd.findCoinName(network), _utxoItem['tx_hash'], _utxoItem.height) .then((verifyMerkleRes) => { - if (verifyMerkleRes && verifyMerkleRes === shepherd.CONNECTION_ERROR_OR_INCOMPLETE_DATA) { + if (verifyMerkleRes && + verifyMerkleRes === shepherd.CONNECTION_ERROR_OR_INCOMPLETE_DATA) { verifyMerkleRes = false; } diff --git a/routes/shepherd/electrum/merkle.js b/routes/shepherd/electrum/merkle.js index b3fbe03..5f428e9 100644 --- a/routes/shepherd/electrum/merkle.js +++ b/routes/shepherd/electrum/merkle.js @@ -2,11 +2,11 @@ module.exports = (shepherd) => { // get merkle root shepherd.getMerkleRoot = (txid, proof, pos) => { const reverse = require('buffer-reverse'); - let hash = txid; - let serialized; const _sha256 = (data) => { return shepherd.crypto.createHash('sha256').update(data).digest(); } + let hash = txid; + let serialized; shepherd.log(`getMerkleRoot txid ${txid}`, true); shepherd.log(`getMerkleRoot pos ${pos}`, true); diff --git a/routes/shepherd/electrum/network.js b/routes/shepherd/electrum/network.js index ad37672..0937079 100644 --- a/routes/shepherd/electrum/network.js +++ b/routes/shepherd/electrum/network.js @@ -1,4 +1,17 @@ module.exports = (shepherd) => { + shepherd.isZcash = (network) => { + if (network === 'ZEC' || + network === 'zec' || + network === 'zcash' || + network === 'ZCASH' || + network === 'HUSH' || + network === 'hush' || + network === 'blk' || + network === 'BLK') { + return true; + } + }; + shepherd.getNetworkData = (network) => { const coin = shepherd.findNetworkObj(network) || shepherd.findNetworkObj(network.toUpperCase()) || shepherd.findNetworkObj(network.toLowerCase()); const coinUC = coin ? coin.toUpperCase() : null; diff --git a/routes/shepherd/electrum/transactions.js b/routes/shepherd/electrum/transactions.js index df5725f..8142f0f 100644 --- a/routes/shepherd/electrum/transactions.js +++ b/routes/shepherd/electrum/transactions.js @@ -69,9 +69,10 @@ module.exports = (shepherd) => { // decode tx const _network = shepherd.getNetworkData(network); - const decodedTx = shepherd.electrumJSTxDecoder(_rawtxJSON, _network); + const decodedTx = shepherd.isZcash(network) ? shepherd.electrumJSTxDecoderZ(_rawtxJSON, _network) : shepherd.electrumJSTxDecoder(_rawtxJSON, _network); let txInputs = []; + shepherd.log(`decodedtx network ${network}`, true); shepherd.log('decodedtx =>', true); shepherd.log(decodedTx.outputs, true); @@ -83,7 +84,7 @@ module.exports = (shepherd) => { if (_decodedInput.txid !== '0000000000000000000000000000000000000000000000000000000000000000') { ecl.blockchainTransactionGet(_decodedInput.txid) .then((rawInput) => { - const decodedVinVout = shepherd.electrumJSTxDecoder(rawInput, _network); + const decodedVinVout = shepherd.isZcash(network) ? shepherd.electrumJSTxDecoderZ(rawInput, _network) : shepherd.electrumJSTxDecoder(rawInput, _network); shepherd.log('electrum raw input tx ==>', true); @@ -352,6 +353,7 @@ module.exports = (shepherd) => { shepherd.log('electrum decoderawtx input tx ==>', true); + if (req.query.parseonly || decodedTx.inputs[0].txid === '0000000000000000000000000000000000000000000000000000000000000000') { const successObj = {