add rpc probing
This commit is contained in:
parent
cd043df59a
commit
68a9e92955
@ -7,10 +7,10 @@ BitcoreHTTP:
|
|||||||
NetworkMonitor:
|
NetworkMonitor:
|
||||||
host: localhost
|
host: localhost
|
||||||
port: 8333
|
port: 8333
|
||||||
Reporter: none # none, simple, matrix
|
Reporter: none # none, simple, matrix
|
||||||
RPC:
|
RPC:
|
||||||
user: user
|
user: user
|
||||||
pass: password
|
pass: password
|
||||||
protocol: http
|
protocol: http
|
||||||
host: 127.0.0.1
|
host: 127.0.0.1
|
||||||
port: 8332
|
port: 8332
|
||||||
|
|||||||
@ -7,10 +7,10 @@ BitcoreHTTP:
|
|||||||
NetworkMonitor:
|
NetworkMonitor:
|
||||||
host: localhost
|
host: localhost
|
||||||
port: 18333
|
port: 18333
|
||||||
Reporter: none # none, simple, matrix
|
Reporter: none # none, simple, matrix
|
||||||
RPC:
|
RPC:
|
||||||
user: user
|
user: user
|
||||||
pass: password
|
pass: password
|
||||||
protocol: http
|
protocol: http
|
||||||
host: 127.0.0.1
|
host: 127.0.0.1
|
||||||
port: 18332
|
port: 18332
|
||||||
|
|||||||
@ -76,7 +76,7 @@ Blocks.list = function(req, res) {
|
|||||||
// TODO: add more parameter validation
|
// TODO: add more parameter validation
|
||||||
|
|
||||||
// TODO: return block_summary instead of block_full
|
// TODO: return block_summary instead of block_full
|
||||||
node.listBlocks(from, to, offset, limit)
|
node.blockService.listBlocks(from, to, offset, limit)
|
||||||
.then(function(blocks) {
|
.then(function(blocks) {
|
||||||
res.send(blocks);
|
res.send(blocks);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -9,7 +9,11 @@ if (require.main === module) {
|
|||||||
console.log('Starting bitcore-node-http', network, 'network');
|
console.log('Starting bitcore-node-http', network, 'network');
|
||||||
bitcore.Networks.defaultNetwork = bitcore.Networks.get(network);
|
bitcore.Networks.defaultNetwork = bitcore.Networks.get(network);
|
||||||
var http = BitcoreHTTP.create(config.get('BitcoreHTTP'));
|
var http = BitcoreHTTP.create(config.get('BitcoreHTTP'));
|
||||||
http.start();
|
http.start()
|
||||||
|
.catch(function(err) {
|
||||||
|
http.stop();
|
||||||
|
throw err;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = BitcoreHTTP;
|
module.exports = BitcoreHTTP;
|
||||||
|
|||||||
@ -98,8 +98,12 @@ BitcoreHTTP.prototype.onListening = function() {
|
|||||||
|
|
||||||
|
|
||||||
BitcoreHTTP.prototype.start = function() {
|
BitcoreHTTP.prototype.start = function() {
|
||||||
this.node.start();
|
|
||||||
this.server.listen(this.port);
|
this.server.listen(this.port);
|
||||||
|
return this.node.start();
|
||||||
|
};
|
||||||
|
|
||||||
|
BitcoreHTTP.prototype.stop = function() {
|
||||||
|
return this.node.stop();
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = BitcoreHTTP;
|
module.exports = BitcoreHTTP;
|
||||||
|
|||||||
@ -49,13 +49,13 @@ describe('BitcoreHTTP v1 blocks routes', function() {
|
|||||||
nodeMock.blockService.getLatest = function() {
|
nodeMock.blockService.getLatest = function() {
|
||||||
return Promise.resolve(lastBlock);
|
return Promise.resolve(lastBlock);
|
||||||
};
|
};
|
||||||
nodeMock.listBlocks = function(from, to, offset, limit) {
|
nodeMock.blockService.listBlocks = function(from, to, offset, limit) {
|
||||||
var start = from - 1e5;
|
var start = from - 1e5;
|
||||||
var end = to - 1e5;
|
var end = to - 1e5;
|
||||||
var section = blockList.slice(start, end);
|
var section = blockList.slice(start, end);
|
||||||
return Promise.resolve(section.slice(offset, offset + limit));
|
return Promise.resolve(section.slice(offset, offset + limit));
|
||||||
};
|
};
|
||||||
app = new BitcoreHTTP(nodeMock).app;
|
app = require('../app')(nodeMock);
|
||||||
agent = request(app);
|
agent = request(app);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -4,10 +4,10 @@ BitcoreNode:
|
|||||||
NetworkMonitor:
|
NetworkMonitor:
|
||||||
host: localhost
|
host: localhost
|
||||||
port: 8333
|
port: 8333
|
||||||
Reporter: none # none, simple, matrix
|
Reporter: none # none, simple, matrix
|
||||||
RPC:
|
RPC:
|
||||||
user: user
|
user: user
|
||||||
pass: password
|
pass: password
|
||||||
protocol: http
|
protocol: http
|
||||||
host: 127.0.0.1
|
host: 127.0.0.1
|
||||||
port: 8332
|
port: 8332
|
||||||
|
|||||||
4
index.js
4
index.js
@ -10,7 +10,9 @@ BitcoreNode.errors = require('./lib/errors');
|
|||||||
|
|
||||||
if (require.main === module) {
|
if (require.main === module) {
|
||||||
var config = require('config');
|
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'));
|
var node = BitcoreNode.create(config.get('BitcoreNode'));
|
||||||
node.start();
|
node.start();
|
||||||
|
|||||||
@ -95,7 +95,10 @@ NetworkMonitor.prototype.getConnectedPeers = function() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
NetworkMonitor.prototype.abort = function(reason) {
|
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) {
|
if (reason) {
|
||||||
throw reason;
|
throw reason;
|
||||||
}
|
}
|
||||||
|
|||||||
43
lib/node.js
43
lib/node.js
@ -78,7 +78,7 @@ BitcoreNode.prototype.initialize = function() {
|
|||||||
|
|
||||||
var prevHeight = 0;
|
var prevHeight = 0;
|
||||||
var statTimer = 5 * 1000;
|
var statTimer = 5 * 1000;
|
||||||
setInterval(function() {
|
this.interval = setInterval(function() {
|
||||||
console.log('MB used:', process.memoryUsage().heapTotal / 1024 / 1024,
|
console.log('MB used:', process.memoryUsage().heapTotal / 1024 / 1024,
|
||||||
100 * self.getSyncProgress() + '% synced');
|
100 * self.getSyncProgress() + '% synced');
|
||||||
if (!self.blockchain) {
|
if (!self.blockchain) {
|
||||||
@ -146,20 +146,40 @@ BitcoreNode.prototype.start = function() {
|
|||||||
var self = this;
|
var self = this;
|
||||||
var genesis = bitcore.Block.fromBuffer(genesisBlocks[bitcore.Networks.defaultNetwork.name]);
|
var genesis = bitcore.Block.fromBuffer(genesisBlocks[bitcore.Networks.defaultNetwork.name]);
|
||||||
|
|
||||||
this.blockService.getBlockchain().then(function(blockchain) {
|
return this.probeRPC()
|
||||||
if (!blockchain) {
|
.catch(function(err) {
|
||||||
self.blockchain = new BlockChain();
|
console.log('RPC connection unsuccessful. Please check your configuration');
|
||||||
self.bus.process(genesis);
|
throw err;
|
||||||
} else {
|
})
|
||||||
self.blockchain = blockchain;
|
.then(function() {
|
||||||
}
|
return self.blockService.getBlockchain();
|
||||||
self.sync();
|
})
|
||||||
self.networkMonitor.start();
|
.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) {
|
BitcoreNode.prototype.stop = function(reason) {
|
||||||
|
clearInterval(this.interval);
|
||||||
this.networkMonitor.abort(reason);
|
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() {
|
BitcoreNode.prototype.getStatus = function() {
|
||||||
@ -178,7 +198,6 @@ BitcoreNode.prototype.getSyncProgress = function() {
|
|||||||
|
|
||||||
BitcoreNode.prototype._requestFromTip = function() {
|
BitcoreNode.prototype._requestFromTip = function() {
|
||||||
var locator = this.blockchain.getBlockLocator();
|
var locator = this.blockchain.getBlockLocator();
|
||||||
//console.log('requesting blocks, locator size:', locator.length);
|
|
||||||
this.networkMonitor.requestBlocks(locator);
|
this.networkMonitor.requestBlocks(locator);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -4,24 +4,19 @@ var config = require('config');
|
|||||||
var LevelUp = require('levelup');
|
var LevelUp = require('levelup');
|
||||||
var Promise = require('bluebird');
|
var Promise = require('bluebird');
|
||||||
var RPC = require('bitcoind-rpc');
|
var RPC = require('bitcoind-rpc');
|
||||||
var TransactionService = require('./transaction');
|
|
||||||
var bitcore = require('bitcore');
|
var bitcore = require('bitcore');
|
||||||
var Transaction = bitcore.Transaction;
|
|
||||||
var BufferUtil = bitcore.util.buffer;
|
var BufferUtil = bitcore.util.buffer;
|
||||||
|
var Block = bitcore.Block;
|
||||||
|
|
||||||
var errors = require('../errors');
|
var errors = require('../errors');
|
||||||
var BlockChain = require('../blockchain');
|
var BlockChain = require('../blockchain');
|
||||||
|
var genesisBlocks = require('../data/genesis');
|
||||||
|
var TransactionService = require('./transaction');
|
||||||
|
|
||||||
var $ = bitcore.util.preconditions;
|
var $ = bitcore.util.preconditions;
|
||||||
var JSUtil = bitcore.util.js;
|
var JSUtil = bitcore.util.js;
|
||||||
var _ = bitcore.deps._;
|
var _ = bitcore.deps._;
|
||||||
|
|
||||||
var NULLBLOCKHASH = bitcore.util.buffer.emptyBuffer(32).toString('hex');
|
|
||||||
var GENESISPARENT = {
|
|
||||||
height: -1,
|
|
||||||
prevBlockHash: NULLBLOCKHASH
|
|
||||||
};
|
|
||||||
|
|
||||||
var helper = function(index) {
|
var helper = function(index) {
|
||||||
return function(maybeHash) {
|
return function(maybeHash) {
|
||||||
if (_.isString(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
|
* 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
|
* @return {Promise} a promise that will always be rejected
|
||||||
*/
|
*/
|
||||||
var blockNotFound = function(err) {
|
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>}
|
* @return {Promise<Block>}
|
||||||
*/
|
*/
|
||||||
BlockService.prototype.getBlockByHeight = function(height) {
|
BlockService.prototype.getBlockByHeight = function(height) {
|
||||||
|
|
||||||
$.checkArgument(_.isNumber(height), 'Block height must be a number');
|
$.checkArgument(_.isNumber(height), 'Block height must be a number');
|
||||||
var self = this;
|
var self = this;
|
||||||
|
if (height === 0) {
|
||||||
|
return Promise.resolve(
|
||||||
|
Block.fromBuffer(genesisBlocks[bitcore.Networks.defaultNetwork])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return Promise.try(function() {
|
return Promise.try(function() {
|
||||||
|
|
||||||
return self.rpc.getBlockHashAsync(height);
|
return self.rpc.getBlockHashAsync(height);
|
||||||
|
|
||||||
})
|
})
|
||||||
.catch(blockNotFound)
|
.catch(blockNotFound)
|
||||||
.then(function(result) {
|
.then(function(result) {
|
||||||
|
|
||||||
var blockHash = result.result;
|
var blockHash = result.result;
|
||||||
return self.getBlock(blockHash);
|
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;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user