Browse Source

tx decoder wrapper; spv pos coins support

pkg_automation_electrum
pbca26 7 years ago
parent
commit
dd937ab198
  1. 2
      gui/EasyDEX-GUI
  2. 5
      package.json
  3. 1
      routes/electrumjs/electrumjs.networks.js
  4. 124
      routes/electrumjs/electrumjs.txdecoder-pos.js
  5. 2
      routes/shepherd.js
  6. 2
      routes/shepherd/electrum/balance.js
  7. 30
      routes/shepherd/electrum/createtx.js
  8. 2
      routes/shepherd/electrum/interest.js
  9. 2
      routes/shepherd/electrum/listunspent.js
  10. 27
      routes/shepherd/electrum/network.js
  11. 14
      routes/shepherd/electrum/transactions.js
  12. 4
      version
  13. 2
      version_build

2
gui/EasyDEX-GUI

@ -1 +1 @@
Subproject commit 0092ac50871b6964e6462f3ba68ac7d1cd8c1421
Subproject commit ba9ec3ad4d56a9454648b7396afcd16aadc61456

5
package.json

@ -16,7 +16,9 @@
"agama",
"SuperNET",
"komodo",
"pax"
"multicoin",
"wallet",
"spv"
],
"author": "SuperNET",
"license": "MIT",
@ -33,6 +35,7 @@
"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",
"bitcoinjs-lib-pos": "git://github.com/KomodoPlatform/bitcoinjs-lib-pos",
"bluebird": "^3.4.7",
"body-parser": "^1.15.2",
"buffer-reverse": "^1.0.1",

1
routes/electrumjs/electrumjs.networks.js

@ -226,6 +226,7 @@ networks.blk = {
scriptHash: 0x55,
wif: 0x99,
dustThreshold: 1000,
isPoS: true,
};
networks.sib = {

124
routes/electrumjs/electrumjs.txdecoder-pos.js

@ -0,0 +1,124 @@
/*
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-pos');
var script = require('bitcoinjs-lib-pos/src/script');
var address = require('bitcoinjs-lib-pos/src/address');
var bitcoinJS = require('bitcoinjs-lib');
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: script.fromHex(input.hash),
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: bitcoinJS.script.toASM(out.script.chunks),
hex: out.script.toHex(),
type: bitcoin.scripts.classifyOutput(out.script),
addresses: [],
},
};
switch(vout.scriptPubKey.type) {
case 'pubkeyhash':
vout.scriptPubKey.addresses.push(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(address.fromOutputScript(out.script, network));
break;
}
console.log(vout);
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, network);
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;
}

2
routes/shepherd.js

@ -61,8 +61,6 @@ 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';

2
routes/shepherd/electrum/balance.js

@ -45,7 +45,7 @@ module.exports = (shepherd) => {
// decode tx
const _network = shepherd.getNetworkData(network);
const decodedTx = shepherd.isZcash(network) ? shepherd.electrumJSTxDecoderZ(_rawtxJSON, _network) : shepherd.electrumJSTxDecoder(_rawtxJSON, _network);
const decodedTx = shepherd.electrumJSTxDecoder(_rawtxJSON, network, _network);
if (decodedTx &&
decodedTx.format &&

30
routes/shepherd/electrum/createtx.js

@ -1,11 +1,13 @@
const bitcoinJSForks = require('bitcoinforksjs-lib');
const bitcoinZcash = require('bitcoinjs-lib-zcash');
const bitcoinPos = require('bitcoinjs-lib-pos');
module.exports = (shepherd) => {
// unsigned tx
shepherd.buildUnsignedTx = (sendTo, changeAddress, network, utxo, changeValue, spendValue) => {
let tx;
// TODO: finish unsigned for zcash, btc forks and pos coins
if (network === 'btg') {
shepherd.log('enable btg');
tx = new bitcoinJSForks.TransactionBuilder(shepherd.getNetworkData(network));
@ -54,7 +56,15 @@ module.exports = (shepherd) => {
// single sig
shepherd.buildSignedTx = (sendTo, changeAddress, wif, network, utxo, changeValue, spendValue) => {
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));
let tx;
if (shepherd.isZcash(network)) {
tx = new bitcoinZcash.TransactionBuilder(shepherd.getNetworkData(network));
} else if (shepherd.isPos(network)) {
tx = new bitcoinPos.TransactionBuilder(shepherd.getNetworkData(network));
} else {
tx = new shepherd.bitcoinJS.TransactionBuilder(shepherd.getNetworkData(network));
}
shepherd.log('buildSignedTx');
// console.log(`buildSignedTx priv key ${wif}`);
@ -65,10 +75,18 @@ module.exports = (shepherd) => {
tx.addInput(utxo[i].txid, utxo[i].vout);
}
tx.addOutput(sendTo, Number(spendValue));
if (shepherd.isPos(network)) {
tx.addOutput(sendTo, Number(spendValue), shepherd.getNetworkData(network));
} else {
tx.addOutput(sendTo, Number(spendValue));
}
if (changeValue > 0) {
tx.addOutput(changeAddress, Number(changeValue));
if (shepherd.isPos(network)) {
tx.addOutput(changeAddress, Number(changeValue), shepherd.getNetworkData(network));
} else {
tx.addOutput(changeAddress, Number(changeValue));
}
}
if (network === 'komodo' ||
@ -86,7 +104,11 @@ module.exports = (shepherd) => {
shepherd.log(tx, true);
for (let i = 0; i < utxo.length; i++) {
tx.sign(i, key);
if (shepherd.isPos(network)) {
tx.sign(shepherd.getNetworkData(network), i, key);
} else {
tx.sign(i, key);
}
}
const rawtx = tx.build().toHex();

2
routes/shepherd/electrum/interest.js

@ -19,7 +19,7 @@ module.exports = (shepherd) => {
}
timestampDiffMinutes -= 59;
shepherd.log(`minutes if statement ${timestampDiffMinutes}`, true);
// shepherd.log(`minutes if statement ${timestampDiffMinutes}`, true);
// TODO: check if interest is > 5% yr
// calc ytd and 5% for 1 yr

2
routes/shepherd/electrum/listunspent.js

@ -36,7 +36,7 @@ module.exports = (shepherd) => {
// decode tx
const _network = shepherd.getNetworkData(network);
const decodedTx = shepherd.isZcash(network) ? shepherd.electrumJSTxDecoderZ(_rawtxJSON, _network) : shepherd.electrumJSTxDecoder(_rawtxJSON, _network);
const decodedTx = shepherd.electrumJSTxDecoder(_rawtxJSON, network, _network);
shepherd.log('decoded tx =>', true);
shepherd.log(decodedTx, true);

27
routes/shepherd/electrum/network.js

@ -1,3 +1,9 @@
const txDecoder = {
default: require('../../electrumjs/electrumjs.txdecoder.js'),
zcash: require('../../electrumjs/electrumjs.txdecoder-2bytes.js'),
pos: require('../../electrumjs/electrumjs.txdecoder-pos.js'),
};
module.exports = (shepherd) => {
shepherd.isZcash = (network) => {
if (network === 'ZEC' ||
@ -5,13 +11,28 @@ module.exports = (shepherd) => {
network === 'zcash' ||
network === 'ZCASH' ||
network === 'HUSH' ||
network === 'hush' ||
network === 'blk' ||
network === 'BLK') {
network === 'hush') {
return true;
}
};
shepherd.isPos = (network) => {
if (network === 'BLK' ||
network === 'blk') {
return true;
}
};
shepherd.electrumJSTxDecoder = (rawtx, networkName, network) => {
if (shepherd.isZcash(networkName)) {
return txDecoder.zcash(rawtx, network);
} else if (shepherd.isPos(networkName)) {
return txDecoder.pos(rawtx, network);
} else {
return txDecoder.default(rawtx, network);
}
};
shepherd.getNetworkData = (network) => {
const coin = shepherd.findNetworkObj(network) || shepherd.findNetworkObj(network.toUpperCase()) || shepherd.findNetworkObj(network.toLowerCase());
const coinUC = coin ? coin.toUpperCase() : null;

14
routes/shepherd/electrum/transactions.js

@ -69,7 +69,7 @@ module.exports = (shepherd) => {
// decode tx
const _network = shepherd.getNetworkData(network);
const decodedTx = shepherd.isZcash(network) ? shepherd.electrumJSTxDecoderZ(_rawtxJSON, _network) : shepherd.electrumJSTxDecoder(_rawtxJSON, _network);
const decodedTx = shepherd.electrumJSTxDecoder(_rawtxJSON, network, _network);
let txInputs = [];
shepherd.log(`decodedtx network ${network}`, true);
@ -84,7 +84,7 @@ module.exports = (shepherd) => {
if (_decodedInput.txid !== '0000000000000000000000000000000000000000000000000000000000000000') {
ecl.blockchainTransactionGet(_decodedInput.txid)
.then((rawInput) => {
const decodedVinVout = shepherd.isZcash(network) ? shepherd.electrumJSTxDecoderZ(rawInput, _network) : shepherd.electrumJSTxDecoder(rawInput, _network);
const decodedVinVout = shepherd.electrumJSTxDecoder(rawInput, network, _network);
shepherd.log('electrum raw input tx ==>', true);
@ -348,12 +348,12 @@ module.exports = (shepherd) => {
shepherd.get('/electrum/decoderawtx', (req, res, next) => {
const _network = shepherd.getNetworkData(req.query.network);
const _rawtx = req.query.rawtx;
// const _rawtx = '0100000001dd6d064f5665f8454293ecaa9dbb55accf4f7e443d35f3b5ab7760f54b6c15fe000000006a473044022056355585a4a501ec9afc96aa5df124cf29ad3ac6454b47cd07cd7d89ec95ec2b022074c4604ee349d30e5336f210598e4dc576bf16ebeb67eeac3f4e82f56e930fee012103b90ba01af308757054e0484bb578765d5df59c4a57adbb94e2419df5e7232a63feffffff0289fc923b000000001976a91424af38fcb13bbc171b0b42bb017244a53b6bb2fa88ac20a10700000000001976a9142f4c0f91fc06ac228c120aee41741d0d3909683288ac49258b58';
const decodedTx = shepherd.electrumJSTxDecoder(_rawtx, _network);
console.log(_network);
//const _rawtx = '010000006f2c395a02d81487fc7f9d1be3ea900316730133c044af70cd76d21e988e71de0e9e85918f010000006a47304402202097acd391e1d0eaaf91844bd596e918fb71320e3e0c51554acb71a39e4ee98b0220548fd61d4ae77a08d70b01bf5340983a1ba63f6b71ad71d478af77011f96fd510121031ffc010d8abc4180b4c1a13962bf9153a78082e7f2ac18f7d14cb6a6634ca218feffffff2b31f6c9a7916f7cf128cae94b3fc10e4c74ca3a740e1a7a6fd6624e4e9a5c8b010000006a473044022063f014c5fbaa7614732e0ae486179a854215fc32c02230e13f69b7e81fa000e50220236a2ba6373b1854aafc59c5391ab7505062067f3d293c016cbb5d252b35a56a012102f307f17d282fc0eabf99227c2e0f3122ae9ecd7da0de099f0c6007d4c941b57bfeffffff021b797ad7120000001976a914c7a7142d743b3e6eebe76923f43bae477d3ce31a88acff086d66000000001976a91463800ff36b9c52b2ffe5564af1c2a38df4f0126788ac16381d00';
const decodedTx = shepherd.electrumJSTxDecoder(_rawtx, req.query.network, _network);
shepherd.log('electrum decoderawtx input tx ==>', true);
if (req.query.parseonly ||
decodedTx.inputs[0].txid === '0000000000000000000000000000000000000000000000000000000000000000') {
const successObj = {
@ -373,12 +373,14 @@ module.exports = (shepherd) => {
const ecl = new shepherd.electrumJSCore(shepherd.electrumServers[req.query.network].port, shepherd.electrumServers[req.query.network].address, shepherd.electrumServers[req.query.network].proto); // tcp or tls
ecl.connect();
shepherd.log(decodedTx.inputs[0]);
shepherd.log(decodedTx.inputs[0].txid);
ecl.blockchainTransactionGet(decodedTx.inputs[0].txid)
.then((json) => {
ecl.close();
shepherd.log(json, true);
const decodedVin = shepherd.electrumJSTxDecoder(json, _network);
const decodedVin = shepherd.electrumJSTxDecoder(json, req.query.network, _network);
const successObj = {
msg: 'success',

4
version

@ -1,3 +1,3 @@
version=0.2.0.25h
type=h-beta
version=0.2.0.25i
type=i-beta
minversion=0.2.0.2

2
version_build

@ -1 +1 @@
0.2.0.25h-beta
0.2.0.25i-beta
Loading…
Cancel
Save