add rpc probing

This commit is contained in:
Manuel Araoz 2015-04-28 12:33:46 -03:00
parent cd043df59a
commit 68a9e92955
11 changed files with 127 additions and 54 deletions

View File

@ -7,10 +7,10 @@ BitcoreHTTP:
NetworkMonitor:
host: localhost
port: 8333
Reporter: none # none, simple, matrix
RPC:
user: user
pass: password
protocol: http
host: 127.0.0.1
port: 8332
Reporter: none # none, simple, matrix
RPC:
user: user
pass: password
protocol: http
host: 127.0.0.1
port: 8332

View File

@ -7,10 +7,10 @@ BitcoreHTTP:
NetworkMonitor:
host: localhost
port: 18333
Reporter: none # none, simple, matrix
RPC:
user: user
pass: password
protocol: http
host: 127.0.0.1
port: 18332
Reporter: none # none, simple, matrix
RPC:
user: user
pass: password
protocol: http
host: 127.0.0.1
port: 18332

View File

@ -76,7 +76,7 @@ Blocks.list = function(req, res) {
// TODO: add more parameter validation
// TODO: return block_summary instead of block_full
node.listBlocks(from, to, offset, limit)
node.blockService.listBlocks(from, to, offset, limit)
.then(function(blocks) {
res.send(blocks);
});

View File

@ -9,7 +9,11 @@ if (require.main === module) {
console.log('Starting bitcore-node-http', network, 'network');
bitcore.Networks.defaultNetwork = bitcore.Networks.get(network);
var http = BitcoreHTTP.create(config.get('BitcoreHTTP'));
http.start();
http.start()
.catch(function(err) {
http.stop();
throw err;
});
}
module.exports = BitcoreHTTP;

View File

@ -98,8 +98,12 @@ BitcoreHTTP.prototype.onListening = function() {
BitcoreHTTP.prototype.start = function() {
this.node.start();
this.server.listen(this.port);
return this.node.start();
};
BitcoreHTTP.prototype.stop = function() {
return this.node.stop();
};
module.exports = BitcoreHTTP;

View File

@ -49,13 +49,13 @@ describe('BitcoreHTTP v1 blocks routes', function() {
nodeMock.blockService.getLatest = function() {
return Promise.resolve(lastBlock);
};
nodeMock.listBlocks = function(from, to, offset, limit) {
nodeMock.blockService.listBlocks = function(from, to, offset, limit) {
var start = from - 1e5;
var end = to - 1e5;
var section = blockList.slice(start, end);
return Promise.resolve(section.slice(offset, offset + limit));
};
app = new BitcoreHTTP(nodeMock).app;
app = require('../app')(nodeMock);
agent = request(app);
});

View File

@ -4,10 +4,10 @@ BitcoreNode:
NetworkMonitor:
host: localhost
port: 8333
Reporter: none # none, simple, matrix
RPC:
user: user
pass: password
protocol: http
host: 127.0.0.1
port: 8332
Reporter: none # none, simple, matrix
RPC:
user: user
pass: password
protocol: http
host: 127.0.0.1
port: 8332

View File

@ -10,7 +10,9 @@ BitcoreNode.errors = require('./lib/errors');
if (require.main === module) {
var config = require('config');
bitcore.Networks.defaultNetwork = bitcore.Networks.get(config.get('BitcoreNode').network);
var network = config.get('BitcoreHTTP.BitcoreNode').network;
console.log('Starting bitcore-node', network, 'network');
bitcore.Networks.defaultNetwork = bitcore.Networks.get(network);
var node = BitcoreNode.create(config.get('BitcoreNode'));
node.start();

View File

@ -95,7 +95,10 @@ NetworkMonitor.prototype.getConnectedPeers = function() {
};
NetworkMonitor.prototype.abort = function(reason) {
this.peer.disconnect();
// TODO: improve Peer interface to know if it's connected
if (this.peer.socket) {
this.peer.disconnect();
}
if (reason) {
throw reason;
}

View File

@ -78,7 +78,7 @@ BitcoreNode.prototype.initialize = function() {
var prevHeight = 0;
var statTimer = 5 * 1000;
setInterval(function() {
this.interval = setInterval(function() {
console.log('MB used:', process.memoryUsage().heapTotal / 1024 / 1024,
100 * self.getSyncProgress() + '% synced');
if (!self.blockchain) {
@ -146,20 +146,40 @@ BitcoreNode.prototype.start = function() {
var self = this;
var genesis = bitcore.Block.fromBuffer(genesisBlocks[bitcore.Networks.defaultNetwork.name]);
this.blockService.getBlockchain().then(function(blockchain) {
if (!blockchain) {
self.blockchain = new BlockChain();
self.bus.process(genesis);
} else {
self.blockchain = blockchain;
}
self.sync();
self.networkMonitor.start();
});
return this.probeRPC()
.catch(function(err) {
console.log('RPC connection unsuccessful. Please check your configuration');
throw err;
})
.then(function() {
return self.blockService.getBlockchain();
})
.then(function(blockchain) {
if (!blockchain) {
self.blockchain = new BlockChain();
self.bus.process(genesis);
} else {
self.blockchain = blockchain;
}
self.sync();
return self.networkMonitor.start();
});
};
BitcoreNode.prototype.stop = function(reason) {
clearInterval(this.interval);
this.networkMonitor.abort(reason);
return this.blockService.database.closeAsync();
};
BitcoreNode.prototype.probeRPC = function() {
// TODO: nicer way to do this?
console.log('Probing RPC connection to check health...');
return this.blockService.rpc.getBlockHashAsync(1)
.then(function() {
return true;
});
};
BitcoreNode.prototype.getStatus = function() {
@ -178,7 +198,6 @@ BitcoreNode.prototype.getSyncProgress = function() {
BitcoreNode.prototype._requestFromTip = function() {
var locator = this.blockchain.getBlockLocator();
//console.log('requesting blocks, locator size:', locator.length);
this.networkMonitor.requestBlocks(locator);
};

View File

@ -4,24 +4,19 @@ var config = require('config');
var LevelUp = require('levelup');
var Promise = require('bluebird');
var RPC = require('bitcoind-rpc');
var TransactionService = require('./transaction');
var bitcore = require('bitcore');
var Transaction = bitcore.Transaction;
var BufferUtil = bitcore.util.buffer;
var Block = bitcore.Block;
var errors = require('../errors');
var BlockChain = require('../blockchain');
var genesisBlocks = require('../data/genesis');
var TransactionService = require('./transaction');
var $ = bitcore.util.preconditions;
var JSUtil = bitcore.util.js;
var _ = bitcore.deps._;
var NULLBLOCKHASH = bitcore.util.buffer.emptyBuffer(32).toString('hex');
var GENESISPARENT = {
height: -1,
prevBlockHash: NULLBLOCKHASH
};
var helper = function(index) {
return function(maybeHash) {
if (_.isString(maybeHash)) {
@ -110,11 +105,15 @@ BlockService.blockRPCtoBitcore = function(blockData) {
/**
* A helper function to return an error when a block couldn't be found
*
* @param {*} err
* @param {*} err an error message or the block hash
* @return {Promise} a promise that will always be rejected
*/
var blockNotFound = function(err) {
throw new errors.Blocks.NotFound(err);
if (err) {
throw err;
}
var hash = err;
throw new errors.Blocks.NotFound(hash);
};
/**
@ -167,21 +166,63 @@ BlockService.prototype.getBlock = function(blockHash, opts) {
* @return {Promise<Block>}
*/
BlockService.prototype.getBlockByHeight = function(height) {
$.checkArgument(_.isNumber(height), 'Block height must be a number');
var self = this;
if (height === 0) {
return Promise.resolve(
Block.fromBuffer(genesisBlocks[bitcore.Networks.defaultNetwork])
);
}
return Promise.try(function() {
return self.rpc.getBlockHashAsync(height);
})
.catch(blockNotFound)
.then(function(result) {
var blockHash = result.result;
return self.getBlock(blockHash);
});
};
/**
* Returns a list of blocks given certain required query options.
*
* @param {Number} from block height as lower limit
* @param {Number} to ditto, but for the upper limit, non inclusive
* @param {Number} offset skip the first offset blocks
* @param {Number} limit max amount of blocks returned
*
*/
BlockService.prototype.listBlocks = function(from, to, offset, limit) {
$.checkArgument(_.isNumber(from), 'from is required, and must be a number');
$.checkArgument(_.isNumber(to), 'to is required, and must be a number');
$.checkArgument(_.isNumber(offset), 'offset is required, and must be a number');
$.checkArgument(_.isNumber(limit), 'limit is required, and must be a number');
$.checkArgument(from <= to, 'from must be <= to');
var self = this;
var start = from + offset;
var end = Math.min(to, start + limit - 1);
var blocks = [];
var fetchBlock = function(height) {
if (height > end) {
return;
}
console.log('fetching block', height);
return self.getBlockByHeight(height)
.then(function(block) {
if (!block) {
// TODO: report?
return;
}
blocks.push(block);
return fetchBlock(height + 1);
});
};
return fetchBlock(start)
.then(function() {
return blocks;
});
};