Merge pull request #55 from maraoz/api/polish

polish API: /v1/node
This commit is contained in:
Manuel Aráoz 2015-04-27 15:58:17 -03:00
commit 47c5b9b336
14 changed files with 69 additions and 43 deletions

12
.gitignore vendored
View File

@ -29,16 +29,10 @@ npm-debug.log
.nodemonignore .nodemonignore
.DS_Store .DS_Store
db/txs/* db/
db/txs
db/testnet/txs/*
db/testnet/txs
db/blocks/*
db/blocks
db/testnet/blocks/*
db/testnet/blocks
db/*
db-test/ db-test/
testnet-db/
db.bkp/
README.html README.html
public public

View File

@ -2,7 +2,15 @@ BitcoreHTTP:
port: 8080 port: 8080
logging: true logging: true
BitcoreNode: BitcoreNode:
LevelUp: ./testnet-db
network: testnet
NetworkMonitor: NetworkMonitor:
network: livenet
host: localhost host: localhost
port: 8333 port: 18333
Reporter: none # none, simple, matrix
RPC:
user: user
pass: password
protocol: http
host: 127.0.0.1
port: 18332

8
api/config/livenet.yml Normal file
View File

@ -0,0 +1,8 @@
BitcoreHTTP:
port: 8080
logging: true
BitcoreNode:
NetworkMonitor:
network: livenet
host: localhost
port: 8333

8
api/config/testnet.yml Normal file
View File

@ -0,0 +1,8 @@
BitcoreHTTP:
port: 8080
logging: true
BitcoreNode:
NetworkMonitor:
network: livenet
host: localhost
port: 8333

View File

@ -98,6 +98,7 @@ 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);
}; };

View File

@ -2,6 +2,7 @@
var chai = require('chai'); var chai = require('chai');
var should = chai.should(); var should = chai.should();
var sinon = require('sinon');
var EventEmitter = require('eventemitter2').EventEmitter2; var EventEmitter = require('eventemitter2').EventEmitter2;
@ -19,6 +20,7 @@ describe('BitcoreHTTP', function() {
var nodeMock; var nodeMock;
beforeEach(function() { beforeEach(function() {
nodeMock = new EventEmitter(); nodeMock = new EventEmitter();
nodeMock.start = sinon.spy();
}); });
describe('instantiates', function() { describe('instantiates', function() {
it('from constructor', function() { it('from constructor', function() {

View File

@ -18,7 +18,7 @@ describe('BitcoreHTTP v1 node routes', function() {
nodeMock = new EventEmitter(); nodeMock = new EventEmitter();
nodeMock.status = { nodeMock.status = {
sync: 0.75, sync: 0.75,
peer_count: 8, peerCount: 8,
version: 'test' version: 'test'
}; };
nodeMock.getStatus = function() { nodeMock.getStatus = function() {

View File

@ -5,9 +5,6 @@ BitcoreNode:
host: localhost host: localhost
port: 8333 port: 8333
Reporter: none # none, simple, matrix Reporter: none # none, simple, matrix
BitcoreHTTP:
host: localhost
port: 8080
RPC: RPC:
user: user user: user
pass: password pass: password

View File

@ -5,9 +5,6 @@ BitcoreNode:
host: localhost host: localhost
port: 8333 port: 8333
Reporter: none # none, simple, matrix Reporter: none # none, simple, matrix
BitcoreHTTP:
host: localhost
port: 8080
RPC: RPC:
user: user user: user
pass: password pass: password

View File

@ -5,9 +5,6 @@ BitcoreNode:
host: localhost host: localhost
port: 18333 port: 18333
Reporter: none # none, simple, matrix Reporter: none # none, simple, matrix
BitcoreHTTP:
host: localhost
port: 8080
RPC: RPC:
user: user user: user
pass: password pass: password

View File

@ -159,7 +159,7 @@ BlockChain.prototype.getBlockLocator = function() {
$.checkState(!_.isUndefined(this.height[this.tip])); $.checkState(!_.isUndefined(this.height[this.tip]));
var result = []; var result = [];
var currentHeight = this.height[this.tip]; var currentHeight = this.getCurrentHeight();
var exponentialBackOff = 1; var exponentialBackOff = 1;
for (var i = 0; i < 10; i++) { for (var i = 0; i < 10; i++) {
if (currentHeight >= 0) { if (currentHeight >= 0) {
@ -174,4 +174,8 @@ BlockChain.prototype.getBlockLocator = function() {
return result; return result;
}; };
BlockChain.prototype.getCurrentHeight = function() {
return this.height[this.tip];
};
module.exports = BlockChain; module.exports = BlockChain;

View File

@ -38,7 +38,10 @@ NetworkMonitor.prototype.setupPeer = function(peer) {
var self = this; var self = this;
peer.on('ready', function() { peer.on('ready', function() {
self.emit('ready'); self.emit('ready', self.maxHeight);
});
peer.on('version', function(m) {
self.maxHeight = m.startHeight;
}); });
peer.on('inv', function(m) { peer.on('inv', function(m) {
self.emit('inv', m.inventory); self.emit('inv', m.inventory);
@ -73,7 +76,6 @@ NetworkMonitor.prototype.requestBlocks = function(locator) {
_.isString(locator[0]), 'start must be a block hash string array'); _.isString(locator[0]), 'start must be a block hash string array');
this.peer.sendMessage(this.messages.GetBlocks({ this.peer.sendMessage(this.messages.GetBlocks({
starts: locator, starts: locator,
//stop: '000000002c05cc2e78923c34df87fd108b22221ac6076c18f3ade378a4d915e9' // TODO: remove this!!!
})); }));
}; };
@ -87,6 +89,11 @@ NetworkMonitor.prototype.stop = function(reason) {
console.log('Stopping network, reason:', reason); console.log('Stopping network, reason:', reason);
}; };
NetworkMonitor.prototype.getConnectedPeers = function() {
// TODO: update when using Pool instead of Peer
return this.peer.status === Peer.STATUS.READY ? 1 : 0;
};
NetworkMonitor.prototype.abort = function(reason) { NetworkMonitor.prototype.abort = function(reason) {
this.peer.disconnect(); this.peer.disconnect();
if (reason) { if (reason) {

View File

@ -2,6 +2,7 @@
var util = require('util'); var util = require('util');
var EventEmitter = require('eventemitter2').EventEmitter2; var EventEmitter = require('eventemitter2').EventEmitter2;
var pjson = require('../package.json');
var bitcore = require('bitcore'); var bitcore = require('bitcore');
var _ = bitcore.deps._; var _ = bitcore.deps._;
@ -36,7 +37,6 @@ var BitcoreNode = function(bus, networkMonitor, blockService, transactionService
this.blockService = blockService; this.blockService = blockService;
this.blockCache = {}; this.blockCache = {};
this.inventory = {}; // blockHash -> bool (has data)
this.initialize(); this.initialize();
}; };
util.inherits(BitcoreNode, EventEmitter); util.inherits(BitcoreNode, EventEmitter);
@ -79,7 +79,8 @@ BitcoreNode.prototype.initialize = function() {
var prevHeight = 0; var prevHeight = 0;
var statTimer = 5 * 1000; var statTimer = 5 * 1000;
setInterval(function() { setInterval(function() {
console.log(process.memoryUsage().heapTotal / 1024 / 1024, 'mb used'); console.log('MB used:', process.memoryUsage().heapTotal / 1024 / 1024,
100 * self.getSyncProgress() + '% synced');
if (!self.blockchain) { if (!self.blockchain) {
// not ready yet // not ready yet
console.log('No blockchain yet'); console.log('No blockchain yet');
@ -100,9 +101,8 @@ BitcoreNode.prototype.initialize = function() {
var prevHash = bitcore.util.buffer.reverse(block.header.prevHash).toString('hex'); var prevHash = bitcore.util.buffer.reverse(block.header.prevHash).toString('hex');
self.blockCache[block.hash] = block; self.blockCache[block.hash] = block;
self.inventory[block.hash] = true;
if (!self.blockchain.hasData(prevHash)) { if (!self.blockchain.hasData(prevHash)) {
self.requestFromTip(); self._requestFromTip();
return; return;
} }
var blockchainChanges = self.blockchain.proposeNewBlock(block); var blockchainChanges = self.blockchain.proposeNewBlock(block);
@ -111,8 +111,6 @@ BitcoreNode.prototype.initialize = function() {
block.height = self.blockchain.height[block.id]; block.height = self.blockchain.height[block.id];
block.work = self.blockchain.work[block.id]; block.work = self.blockchain.work[block.id];
//console.log('block', block.id, block.height);
return Promise.each(blockchainChanges.unconfirmed, function(hash) { return Promise.each(blockchainChanges.unconfirmed, function(hash) {
return self.blockService.unconfirm(self.blockCache[hash]); return self.blockService.unconfirm(self.blockCache[hash]);
}) })
@ -128,13 +126,6 @@ BitcoreNode.prototype.initialize = function() {
delete self.blockCache[deleteHash]; delete self.blockCache[deleteHash];
} }
}) })
.then(function() {
// TODO: include this
if (false && _.size(self.inventory) && _.all(_.values(self.inventory))) {
self.inventory = {};
self.requestFromTip();
}
})
.catch(function(error) { .catch(function(error) {
self.stop(error); self.stop(error);
}); });
@ -155,9 +146,7 @@ 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]);
console.log('getting blockchain');
this.blockService.getBlockchain().then(function(blockchain) { this.blockService.getBlockchain().then(function(blockchain) {
console.log('got blockchain', !!blockchain);
if (!blockchain) { if (!blockchain) {
self.blockchain = new BlockChain(); self.blockchain = new BlockChain();
self.bus.process(genesis); self.bus.process(genesis);
@ -173,7 +162,20 @@ BitcoreNode.prototype.stop = function(reason) {
this.networkMonitor.abort(reason); this.networkMonitor.abort(reason);
}; };
BitcoreNode.prototype.requestFromTip = function() { BitcoreNode.prototype.getStatus = function() {
return Promise.resolve({
sync: this.getSyncProgress(),
peerCount: this.networkMonitor.getConnectedPeers(),
version: pjson.version,
});
};
BitcoreNode.prototype.getSyncProgress = function() {
return !_.isUndefined(this.reportedMaxHeight) ?
(this.blockchain.getCurrentHeight() / this.reportedMaxHeight) : 0;
};
BitcoreNode.prototype._requestFromTip = function() {
var locator = this.blockchain.getBlockLocator(); var locator = this.blockchain.getBlockLocator();
//console.log('requesting blocks, locator size:', locator.length); //console.log('requesting blocks, locator size:', locator.length);
this.networkMonitor.requestBlocks(locator); this.networkMonitor.requestBlocks(locator);
@ -181,8 +183,9 @@ BitcoreNode.prototype.requestFromTip = function() {
BitcoreNode.prototype.sync = function() { BitcoreNode.prototype.sync = function() {
var self = this; var self = this;
this.networkMonitor.on('ready', function() { this.networkMonitor.on('ready', function(reportedMaxHeight) {
self.requestFromTip(); self.reportedMaxHeight = reportedMaxHeight;
self._requestFromTip();
}); });
}; };

View File

@ -475,7 +475,7 @@ BlockService.prototype.getBlockchain = function() {
return self._getLatestHash() return self._getLatestHash()
.then(function(tip) { .then(function(tip) {
if (!tip) { if (!tip) {
console.log('No tip found'); console.log('No tip found, syncing blockchain from genesis block');
return null; return null;
} }
console.log('Tip is', tip); console.log('Tip is', tip);