Browse Source

spv cache block headers, use cache in linstunspent and merkle

v0.25
pbca26 7 years ago
parent
commit
163a7e0156
  1. 2
      routes/shepherd/electrum/balance.js
  2. 6
      routes/shepherd/electrum/listunspent.js
  3. 7
      routes/shepherd/electrum/merkle.js
  4. 39
      routes/shepherd/electrum/transactions.js

2
routes/shepherd/electrum/balance.js

@ -37,7 +37,7 @@ module.exports = (shepherd) => {
shepherd.Promise.all(_utxo.map((_utxoItem, index) => { shepherd.Promise.all(_utxo.map((_utxoItem, index) => {
return new shepherd.Promise((resolve, reject) => { return new shepherd.Promise((resolve, reject) => {
ecl.blockchainTransactionGet(_utxoItem['tx_hash']) shepherd.getTransaction(_utxoItem['tx_hash'], network, ecl)
.then((_rawtxJSON) => { .then((_rawtxJSON) => {
shepherd.log('electrum gettransaction ==>', true); shepherd.log('electrum gettransaction ==>', true);
shepherd.log((index + ' | ' + (_rawtxJSON.length - 1)), true); shepherd.log((index + ' | ' + (_rawtxJSON.length - 1)), true);

6
routes/shepherd/electrum/listunspent.js

@ -31,7 +31,7 @@ module.exports = (shepherd) => {
} else { } else {
shepherd.Promise.all(_utxo.map((_utxoItem, index) => { shepherd.Promise.all(_utxo.map((_utxoItem, index) => {
return new shepherd.Promise((resolve, reject) => { return new shepherd.Promise((resolve, reject) => {
ecl.blockchainTransactionGet(_utxoItem['tx_hash']) shepherd.getTransaction(_utxoItem['tx_hash'], network, ecl)
.then((_rawtxJSON) => { .then((_rawtxJSON) => {
shepherd.log('electrum gettransaction ==>', true); shepherd.log('electrum gettransaction ==>', true);
shepherd.log(index + ' | ' + (_rawtxJSON.length - 1), true); shepherd.log(index + ' | ' + (_rawtxJSON.length - 1), true);
@ -70,7 +70,7 @@ module.exports = (shepherd) => {
verified: false, verified: false,
}; };
// merkle root verification agains another electrum server // merkle root verification against another electrum server
if (verify) { if (verify) {
shepherd.verifyMerkleByCoin(shepherd.findCoinName(network), _utxoItem['tx_hash'], _utxoItem.height) shepherd.verifyMerkleByCoin(shepherd.findCoinName(network), _utxoItem['tx_hash'], _utxoItem.height)
.then((verifyMerkleRes) => { .then((verifyMerkleRes) => {
@ -97,7 +97,7 @@ module.exports = (shepherd) => {
verified: false, verified: false,
}; };
// merkle root verification agains another electrum server // merkle root verification against another electrum server
if (verify) { if (verify) {
shepherd.verifyMerkleByCoin(shepherd.findCoinName(network), _utxoItem['tx_hash'], _utxoItem.height) shepherd.verifyMerkleByCoin(shepherd.findCoinName(network), _utxoItem['tx_hash'], _utxoItem.height)
.then((verifyMerkleRes) => { .then((verifyMerkleRes) => {

7
routes/shepherd/electrum/merkle.js

@ -30,7 +30,7 @@ module.exports = (shepherd) => {
return hash; return hash;
} }
shepherd.verifyMerkle = (txid, height, serverList, mainServer) => { shepherd.verifyMerkle = (txid, height, serverList, mainServer, network) => {
// select random server // select random server
const getRandomIntInclusive = (min, max) => { const getRandomIntInclusive = (min, max) => {
min = Math.ceil(min); min = Math.ceil(min);
@ -66,7 +66,7 @@ module.exports = (shepherd) => {
ecl = new shepherd.electrumJSCore(_randomServer[1], _randomServer[0], _mainServer[2]); ecl = new shepherd.electrumJSCore(_randomServer[1], _randomServer[0], _mainServer[2]);
ecl.connect(); ecl.connect();
ecl.blockchainBlockGetHeader(height) shepherd.getBlockHeader(height, network, ecl)
.then((blockInfo) => { .then((blockInfo) => {
if (blockInfo && if (blockInfo &&
blockInfo['merkle_root']) { blockInfo['merkle_root']) {
@ -120,7 +120,8 @@ module.exports = (shepherd) => {
txid, txid,
height, height,
_filteredServerList, _filteredServerList,
shepherd.electrumCoins[coin].server.ip + ':' + shepherd.electrumCoins[coin].server.port + ':' + shepherd.electrumServers[coin === 'KMD' || coin === 'komodo' ? 'komodo' : coin.toLowerCase()].proto shepherd.electrumCoins[coin].server.ip + ':' + shepherd.electrumCoins[coin].server.port + ':' + shepherd.electrumServers[coin === 'KMD' || coin === 'komodo' ? 'komodo' : coin.toLowerCase()].proto,
coin
) )
.then((proof) => { .then((proof) => {
resolve(proof); resolve(proof);

39
routes/shepherd/electrum/transactions.js

@ -18,24 +18,51 @@ module.exports = (shepherd) => {
shepherd.getTransaction = (txid, network, ecl) => { shepherd.getTransaction = (txid, network, ecl) => {
return new shepherd.Promise((resolve, reject) => { return new shepherd.Promise((resolve, reject) => {
if (!shepherd.electrumCache[network]) { if (!shepherd.electrumCache[network]) {
shepherd.electrumCache[network] = { shepherd.electrumCache[network] = {};
tx: {}, }
blocksHeaders: {}, if (!shepherd.electrumCache[network].tx) {
}; shepherd.electrumCache[network]['tx'] = {};
} }
if (!shepherd.electrumCache[network].tx[txid]) { if (!shepherd.electrumCache[network].tx[txid]) {
shepherd.log(`electrum raw input tx ${txid}`, true);
ecl.blockchainTransactionGet(txid) ecl.blockchainTransactionGet(txid)
.then((_rawtxJSON) => { .then((_rawtxJSON) => {
shepherd.electrumCache[network].tx[txid] = _rawtxJSON; shepherd.electrumCache[network].tx[txid] = _rawtxJSON;
resolve(_rawtxJSON); resolve(_rawtxJSON);
}); });
} else { } else {
shepherd.log(`electrum cached raw input tx ${txid}`, true);
resolve(shepherd.electrumCache[network].tx[txid]); resolve(shepherd.electrumCache[network].tx[txid]);
} }
}); });
} }
shepherd.getBlockHeader = (height, network, ecl) => {
return new shepherd.Promise((resolve, reject) => {
if (!shepherd.electrumCache[network]) {
shepherd.electrumCache[network] = {};
}
if (!shepherd.electrumCache[network].blockHeader) {
shepherd.electrumCache[network]['blockHeader'] = {};
}
if (!shepherd.electrumCache[network].blockHeader[height]) {
shepherd.log(`electrum raw block ${height}`, true);
ecl.blockchainBlockGetHeader(height)
.then((_rawtxJSON) => {
shepherd.electrumCache[network].blockHeader[height] = _rawtxJSON;
resolve(_rawtxJSON);
});
} else {
shepherd.log(`electrum cached raw block ${height}`, true);
resolve(shepherd.electrumCache[network].blockHeader[height]);
}
});
}
shepherd.get('/electrum/listtransactions', (req, res, next) => { shepherd.get('/electrum/listtransactions', (req, res, next) => {
if (shepherd.checkToken(req.query.token)) { if (shepherd.checkToken(req.query.token)) {
const network = req.query.network || shepherd.findNetworkObj(req.query.coin); const network = req.query.network || shepherd.findNetworkObj(req.query.coin);
@ -82,7 +109,7 @@ module.exports = (shepherd) => {
let index = 0; let index = 0;
async.eachOfSeries(json, (transaction, ind, callback) => { async.eachOfSeries(json, (transaction, ind, callback) => {
ecl.blockchainBlockGetHeader(transaction.height) shepherd.getBlockHeader(transaction.height, network, ecl)
.then((blockInfo) => { .then((blockInfo) => {
if (blockInfo && if (blockInfo &&
blockInfo.timestamp) { blockInfo.timestamp) {
@ -175,8 +202,6 @@ module.exports = (shepherd) => {
.then((rawInput) => { .then((rawInput) => {
const decodedVinVout = shepherd.electrumJSTxDecoder(rawInput, network, _network); const decodedVinVout = shepherd.electrumJSTxDecoder(rawInput, network, _network);
shepherd.log(`electrum raw input tx ${_decodedInput.txid} ==>`, true);
if (decodedVinVout) { if (decodedVinVout) {
shepherd.log(decodedVinVout.outputs[_decodedInput.n], true); shepherd.log(decodedVinVout.outputs[_decodedInput.n], true);
txInputs.push(decodedVinVout.outputs[_decodedInput.n]); txInputs.push(decodedVinVout.outputs[_decodedInput.n]);

Loading…
Cancel
Save