From 2c595867e4416315b354596ceb5bac3b080ee266 Mon Sep 17 00:00:00 2001 From: pbca26 Date: Mon, 23 Apr 2018 12:51:09 +0300 Subject: [PATCH] spv decode shielded txs --- package.json | 3 +- routes/electrumjs/electrumjs.networks.js | 11 ++++ .../electrumjs/electrumjs.txdecoder-2bytes.js | 61 ++++++++++++++++++- routes/electrumjs/electrumjs.txdecoder.js | 61 ++++++++++++++++++- routes/shepherd/electrum/transactions.js | 4 ++ 5 files changed, 133 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index d03589d..23bbbd0 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "agama-app", "productName": "Agama", - "version": "0.2.34", + "version": "0.2.35", "description": "Agama Wallet Desktop App", "main": "main.js", "scripts": { @@ -36,6 +36,7 @@ "bitcoinjs-lib": "git://github.com/SuperNETorg/bitcoinjs-lib", "bitcoinjs-lib-pos": "git://github.com/KomodoPlatform/bitcoinjs-lib-pos", "bitcoinjs-lib-zcash": "git://github.com/pbca26/bitcoinjs-lib#zcash", + "tx-decoder": "git://github.com/pbca26/tx-decoder", "bluebird": "^3.4.7", "body-parser": "^1.15.2", "buffer-reverse": "^1.0.1", diff --git a/routes/electrumjs/electrumjs.networks.js b/routes/electrumjs/electrumjs.networks.js index 839d4ff..b1ad7d6 100644 --- a/routes/electrumjs/electrumjs.networks.js +++ b/routes/electrumjs/electrumjs.networks.js @@ -92,6 +92,7 @@ networks.xzc = { scriptHash: 0x07, wif: 0x52 + 128, dustThreshold: 1000, // https://github.com/zcoinofficial/zcoin/blob/f755f95a036eedfef7c96bcfb6769cb79278939f/src/main.h#L59 + isZcash: true, }; // https://raw.githubusercontent.com/jl777/komodo/beta/src/chainparams.cpp @@ -105,6 +106,7 @@ networks.komodo = { scriptHash: 0x55, wif: 0xbc, dustThreshold: 1000, + isZcash: true, }; networks.viacoin = { @@ -262,6 +264,7 @@ networks.zcash = { scriptHash: 0x1cbd, wif: 0x80, dustThreshold: 1000, + isZcash: true, }; networks.hush = { @@ -274,6 +277,7 @@ networks.hush = { scriptHash: 0x1cbd, wif: 0x80, dustThreshold: 1000, + isZcash: true, }; networks.zcl = { @@ -286,6 +290,7 @@ networks.zcl = { scriptHash: 0x1cbd, wif: 0x80, dustThreshold: 1000, + isZcash: true, }; networks.sng = { @@ -298,6 +303,7 @@ networks.sng = { scriptHash: 0x1c2D, wif: 0x80, dustThreshold: 1000, + isZcash: true, }; networks.xmy = { @@ -358,6 +364,7 @@ networks.btcz = { scriptHash: 0x1cbd, wif: 0x80, dustThreshold: 1000, + isZcash: true, }; networks.grs = { // fails to gen a proper addr @@ -406,6 +413,7 @@ networks.vot = { scriptHash: 0x1cbd, wif: 0x80, dustThreshold: 1000, + isZcash: true, }; networks.iop = { @@ -455,6 +463,7 @@ networks.zen = { // new address type scriptHash: 0x2086, wif: 0x80, dustThreshold: 1000, + isZcash: true, }; networks.sys = { // zec based @@ -467,6 +476,7 @@ networks.sys = { // zec based scriptHash: 0x5, wif: 0x80, dustThreshold: 1000, + isZcash: true, }; networks.emc2 = { @@ -632,6 +642,7 @@ networks.smart = { // wrong address generated scriptHash: 0x12, wif: 0xBF, dustThreshold: 1000, + isZcash: true, }; // https://github.com/reddcoin-project/reddcoin/blob/master/src/chainparams.cpp#L79 diff --git a/routes/electrumjs/electrumjs.txdecoder-2bytes.js b/routes/electrumjs/electrumjs.txdecoder-2bytes.js index f96199a..f59d8d1 100644 --- a/routes/electrumjs/electrumjs.txdecoder-2bytes.js +++ b/routes/electrumjs/electrumjs.txdecoder-2bytes.js @@ -1,7 +1,8 @@ /* MIT License -Copyright (c) 2017 Yuki Akiyama, SuperNET +Copyright (c) 2017 Yuki Akiyama +Copyright (c) 2017 - 2018 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 @@ -23,6 +24,26 @@ SOFTWARE. */ var bitcoin = require('bitcoinjs-lib-zcash'); +// zcash fallback +const Buffer = require('safe-buffer').Buffer; +const { + readSlice, + readInt32, + readUInt32, +} = require('tx-decoder/src/buffer-utils'); +const { + compose, + addProp, +} = require('tx-decoder/src/compose'); +const { + readInputs, + readInput, + readOutput, +} = require('tx-decoder/src/tx-decoder'); +const crypto = require('crypto'); +const _sha256 = (data) => { + return crypto.createHash('sha256').update(data).digest(); +}; var decodeFormat = function(tx) { var result = { @@ -39,7 +60,7 @@ var decodeInput = function(tx) { tx.ins.forEach(function(input, n) { var vin = { - txid: input.hash.reverse().toString('hex'), + txid: !input.hash.reverse ? input.hash : input.hash.reverse().toString('hex'), n: input.index, script: bitcoin.script.toASM(input.script), sequence: input.sequence, @@ -102,7 +123,41 @@ var TxDecoder = module.exports = function(rawtx, network) { outputs: decodeOutput(_tx, network), }; } catch (e) { - return false; + if (network.isZcash) { + console.log('z tx decode fallback'); + + const buffer = Buffer.from(rawtx, 'hex'); + + const decodeTx = buffer => ( + compose([ + addProp('version', readInt32), // 4 bytes + addProp('ins', readInputs(readInput)), // 1-9 bytes (VarInt), Input counter; Variable, Inputs + addProp('outs', readInputs(readOutput)), // 1-9 bytes (VarInt), Output counter; Variable, Outputs + addProp('locktime', readUInt32) // 4 bytes + ])({}, buffer) + ); + + const readHash = buffer => { + const [res, bufferLeft] = readSlice(32)(_sha256(_sha256(buffer))); + const hash = Buffer.from(res, 'hex').reverse().toString('hex'); + return [hash, bufferLeft]; + }; + + let decodedtx = decodeTx(buffer); + decodedtx[0].getId = () => { + return readHash(buffer)[0]; + }; + + return { + tx: decodedtx[0], + network: network, + format: decodeFormat(decodedtx[0]), + inputs: !decodedtx[0].ins.length ? [{ txid: '0000000000000000000000000000000000000000000000000000000000000000' }] : decodeInput(decodedtx[0]), + outputs: decodeOutput(decodedtx[0], network), + }; + } else { + return false; + } } } diff --git a/routes/electrumjs/electrumjs.txdecoder.js b/routes/electrumjs/electrumjs.txdecoder.js index f956249..14204d5 100644 --- a/routes/electrumjs/electrumjs.txdecoder.js +++ b/routes/electrumjs/electrumjs.txdecoder.js @@ -1,7 +1,8 @@ /* MIT License -Copyright (c) 2017 Yuki Akiyama, SuperNET +Copyright (c) 2017 Yuki Akiyama +Copyright (c) 2017 - 2018 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 @@ -23,6 +24,26 @@ SOFTWARE. */ var bitcoin = require('bitcoinjs-lib'); +// zcash fallback +const Buffer = require('safe-buffer').Buffer; +const { + readSlice, + readInt32, + readUInt32, +} = require('tx-decoder/src/buffer-utils'); +const { + compose, + addProp, +} = require('tx-decoder/src/compose'); +const { + readInputs, + readInput, + readOutput, +} = require('tx-decoder/src/tx-decoder'); +const crypto = require('crypto'); +const _sha256 = (data) => { + return crypto.createHash('sha256').update(data).digest(); +}; var decodeFormat = function(tx) { var result = { @@ -39,7 +60,7 @@ var decodeInput = function(tx) { tx.ins.forEach(function(input, n) { var vin = { - txid: input.hash.reverse().toString('hex'), + txid: !input.hash.reverse ? input.hash : input.hash.reverse().toString('hex'), n: input.index, script: bitcoin.script.toASM(input.script), sequence: input.sequence, @@ -102,7 +123,41 @@ var TxDecoder = module.exports = function(rawtx, network) { outputs: decodeOutput(_tx, network), }; } catch (e) { - return false; + if (network.isZcash) { + console.log('z tx decode fallback'); + + const buffer = Buffer.from(rawtx, 'hex'); + + const decodeTx = buffer => ( + compose([ + addProp('version', readInt32), // 4 bytes + addProp('ins', readInputs(readInput)), // 1-9 bytes (VarInt), Input counter; Variable, Inputs + addProp('outs', readInputs(readOutput)), // 1-9 bytes (VarInt), Output counter; Variable, Outputs + addProp('locktime', readUInt32) // 4 bytes + ])({}, buffer) + ); + + const readHash = buffer => { + const [res, bufferLeft] = readSlice(32)(_sha256(_sha256(buffer))) + const hash = Buffer.from(res, 'hex').reverse().toString('hex') + return [hash, bufferLeft] + }; + + let decodedtx = decodeTx(buffer); + decodedtx[0].getId = () => { + return readHash(buffer)[0]; + }; + + return { + tx: decodedtx[0], + network: network, + format: decodeFormat(decodedtx[0]), + inputs: !decodedtx[0].ins.length ? [{ txid: '0000000000000000000000000000000000000000000000000000000000000000' }] : decodeInput(decodedtx[0]), + outputs: decodeOutput(decodedtx[0], network), + }; + } else { + return false; + } } } diff --git a/routes/shepherd/electrum/transactions.js b/routes/shepherd/electrum/transactions.js index ed3caa3..fd02e45 100644 --- a/routes/shepherd/electrum/transactions.js +++ b/routes/shepherd/electrum/transactions.js @@ -244,6 +244,10 @@ module.exports = (shepherd) => { } }); } else { + /*if (_network.isZcash) { + + } else {*/ + const _parsedTx = { network: decodedTx.network, format: 'cant parse',