Skip to content

Commit f91fbe5

Browse files
author
Braydon Fuller
committed
Merge pull request #165 from pnagurny/feature/web-service
Web Service and other changes in preparation for insight-api
2 parents 01ef98e + 4ae6377 commit f91fbe5

File tree

15 files changed

+568
-150
lines changed

15 files changed

+568
-150
lines changed

integration/regtest-node.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,17 +69,17 @@ describe('Node Functionality', function() {
6969
{
7070
name: 'db',
7171
module: DBService,
72-
dependencies: DBService.dependencies
72+
config: {}
7373
},
7474
{
7575
name: 'bitcoind',
7676
module: BitcoinService,
77-
dependencies: BitcoinService.dependencies
77+
config: {}
7878
},
7979
{
8080
name: 'address',
8181
module: AddressService,
82-
dependencies: AddressService.dependencies
82+
config: {}
8383
}
8484
]
8585
};

integration/regtest.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,27 @@ describe('Daemon Binding Functionality', function() {
227227
work.cmp(expectedWork).should.equal(0);
228228
expectedWork = expectedWork.add(new BN(2));
229229
should.exist(blockIndex.prevHash);
230+
blockIndex.hash.should.equal(blockHashes[i]);
230231
blockIndex.prevHash.should.equal(blockHashes[i - 1]);
232+
blockIndex.height.should.equal(i + 1);
233+
});
234+
});
235+
});
236+
237+
describe('get block index by height', function() {
238+
var expectedWork = new BN(6);
239+
[2,3,4,5,6,7,8,9].forEach(function(i) {
240+
it('generate block ' + i, function() {
241+
var blockIndex = bitcoind.getBlockIndex(i);
242+
should.exist(blockIndex);
243+
should.exist(blockIndex.chainWork);
244+
var work = new BN(blockIndex.chainWork, 'hex');
245+
work.cmp(expectedWork).should.equal(0);
246+
expectedWork = expectedWork.add(new BN(2));
247+
should.exist(blockIndex.prevHash);
248+
blockIndex.hash.should.equal(blockHashes[i - 1]);
249+
blockIndex.prevHash.should.equal(blockHashes[i - 2]);
250+
blockIndex.height.should.equal(i);
231251
});
232252
});
233253
});

lib/node.js

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@ var async = require('async');
66
var bitcore = require('bitcore');
77
var Networks = bitcore.Networks;
88
var $ = bitcore.util.preconditions;
9+
var _ = bitcore.deps._;
910
var index = require('./');
1011
var log = index.log;
1112
var Bus = require('./bus');
1213
var BaseService = require('./service');
14+
var errors = require('./errors');
1315

1416
function Node(config) {
1517
if(!(this instanceof Node)) {
@@ -18,6 +20,8 @@ function Node(config) {
1820

1921
var self = this;
2022

23+
this.errors = errors; // So services can use errors without having to have bitcore-node as a dependency
24+
this.log = log;
2125
this.network = null;
2226
this.services = {};
2327
this._unloadedServices = [];
@@ -30,6 +34,7 @@ function Node(config) {
3034

3135
$.checkState(config.datadir, 'Node config expects "datadir"');
3236
this.datadir = config.datadir;
37+
this.port = config.port;
3338

3439
this._setNetwork(config);
3540

@@ -116,7 +121,7 @@ Node.prototype.getServiceOrder = function() {
116121
$.checkState(service, 'Required dependency "' + name + '" not available.');
117122

118123
// first add the dependencies
119-
addToStack(service.dependencies);
124+
addToStack(service.module.dependencies);
120125

121126
// add to the stack if it hasn't been added
122127
if(!stackNames[name]) {
@@ -134,9 +139,13 @@ Node.prototype.getServiceOrder = function() {
134139

135140
Node.prototype._instantiateService = function(service) {
136141
var self = this;
137-
var mod = new service.module({
138-
node: this
139-
});
142+
143+
$.checkState(_.isObject(service.config));
144+
$.checkState(!service.config.node);
145+
146+
var config = service.config;
147+
config.node = this;
148+
var mod = new service.module(config);
140149

141150
$.checkState(
142151
mod instanceof BaseService,

lib/scaffold/default-config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ function getDefaultConfig() {
1313
datadir: process.env.BITCORENODE_DIR || path.resolve(process.env.HOME, '.bitcoin'),
1414
network: process.env.BITCORENODE_NETWORK || 'livenet',
1515
port: process.env.BITCORENODE_PORT || 3001,
16-
services: ['bitcoind', 'db', 'address']
16+
services: ['bitcoind', 'db', 'address', 'web']
1717
}
1818
};
1919
}

lib/scaffold/start.js

Lines changed: 23 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ var BitcoreNode = require('../node');
66
var index = require('../');
77
var bitcore = require('bitcore');
88
var _ = bitcore.deps._;
9+
var $ = bitcore.util.preconditions;
910
var log = index.log;
1011
log.debug = function() {};
1112

@@ -22,37 +23,35 @@ function start(options) {
2223

2324
if (config.services) {
2425
for (var i = 0; i < config.services.length; i++) {
25-
var serviceName = config.services[i];
26-
var service;
26+
var service = {};
27+
service.name = config.services[i];
28+
service.config = config.servicesConfig && config.servicesConfig[service.name] ? config.servicesConfig[service.name] : {};
29+
2730
try {
2831
// first try in the built-in bitcore-node services directory
29-
service = require(path.resolve(__dirname, '../services/' + serviceName));
32+
service.module = require(path.resolve(__dirname, '../services/' + service.name));
3033
} catch(e) {
3134

3235
// check if the package.json specifies a specific file to use
33-
var servicePackage = require(serviceName + '/package.json');
34-
var serviceModule = serviceName;
36+
var servicePackage = require(service.name + '/package.json');
37+
var serviceModule = service.name;
3538
if (servicePackage.bitcoreNode) {
36-
serviceModule = serviceName + '/' + servicePackage.bitcoreNode;
39+
serviceModule = service.name + '/' + servicePackage.bitcoreNode;
3740
}
38-
service = require(serviceModule);
41+
service.module = require(serviceModule);
3942
}
4043

4144
// check that the service supports expected methods
42-
if (!service.prototype ||
43-
!service.dependencies ||
44-
!service.prototype.start ||
45-
!service.prototype.stop) {
45+
if (!service.module.prototype ||
46+
!service.module.dependencies ||
47+
!service.module.prototype.start ||
48+
!service.module.prototype.stop) {
4649
throw new Error(
47-
'Could not load service "' + serviceName + '" as it does not support necessary methods.'
50+
'Could not load service "' + service.name + '" as it does not support necessary methods.'
4851
);
4952
}
50-
services.push({
51-
name: serviceName,
52-
module: service,
53-
dependencies: service.dependencies
54-
});
5553

54+
services.push(service);
5655
}
5756
}
5857

@@ -82,102 +81,7 @@ function start(options) {
8281
});
8382

8483
node.on('ready', function() {
85-
86-
var io = socketio(fullConfig.port);
87-
88-
io.on('connection', function(socket) {
89-
90-
var bus = node.openBus();
91-
92-
var methods = node.getAllAPIMethods();
93-
var methodsMap = {};
94-
95-
methods.forEach(function(data) {
96-
var name = data[0];
97-
var instance = data[1];
98-
var method = data[2];
99-
var args = data[3];
100-
methodsMap[name] = {
101-
fn: function() {
102-
return method.apply(instance, arguments);
103-
},
104-
args: args
105-
};
106-
});
107-
108-
socket.on('message', function(message, socketCallback) {
109-
if (methodsMap[message.method]) {
110-
var params = message.params;
111-
112-
if(!params || !params.length) {
113-
params = [];
114-
}
115-
116-
if(params.length !== methodsMap[message.method].args) {
117-
return socketCallback({
118-
error: {
119-
message: 'Expected ' + methodsMap[message.method].args + ' parameters'
120-
}
121-
});
122-
}
123-
124-
var callback = function(err, result) {
125-
var response = {};
126-
if(err) {
127-
response.error = {
128-
message: err.toString()
129-
};
130-
}
131-
132-
if(result) {
133-
response.result = result;
134-
}
135-
136-
socketCallback(response);
137-
};
138-
139-
params = params.concat(callback);
140-
methodsMap[message.method].fn.apply(this, params);
141-
} else {
142-
socketCallback({
143-
error: {
144-
message: 'Method Not Found'
145-
}
146-
});
147-
}
148-
});
149-
150-
socket.on('subscribe', function(name, params) {
151-
bus.subscribe(name, params);
152-
});
153-
154-
socket.on('unsubscribe', function(name, params) {
155-
bus.unsubscribe(name, params);
156-
});
157-
158-
var events = node.getAllPublishEvents();
159-
160-
events.forEach(function(event) {
161-
bus.on(event.name, function() {
162-
if(socket.connected) {
163-
var results = [];
164-
165-
for(var i = 0; i < arguments.length; i++) {
166-
results.push(arguments[i]);
167-
}
168-
169-
var params = [event.name].concat(results);
170-
socket.emit.apply(socket, params);
171-
}
172-
});
173-
});
174-
175-
socket.on('disconnect', function() {
176-
bus.close();
177-
});
178-
179-
});
180-
84+
log.info('Bitcore Node ready');
18185
});
18286

18387
node.on('error', function(err) {
@@ -207,7 +111,12 @@ function start(options) {
207111
if(err.stack) {
208112
console.log(err.stack);
209113
}
210-
process.exit(-1);
114+
node.stop(function(err) {
115+
if(err) {
116+
log.error('Failed to stop services: ' + err);
117+
}
118+
process.exit(-1);
119+
});
211120
}
212121
if (options.sigint) {
213122
node.stop(function(err) {

lib/service.js

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@ Service.dependencies = [];
2424
*/
2525
Service.prototype.blockHandler = function(block, add, callback) {
2626
// implement in the child class
27-
setImmediate(callback);
27+
setImmediate(function() {
28+
callback(null, []);
29+
});
2830
};
2931

3032
/**
@@ -57,12 +59,26 @@ Service.prototype.getAPIMethods = function() {
5759
//
5860
// };
5961

62+
/**
63+
* Function which is called when module is first initialized
64+
*/
6065
Service.prototype.start = function(done) {
6166
setImmediate(done);
6267
};
6368

69+
/**
70+
* Function to be called when bitcore-node is stopped
71+
*/
6472
Service.prototype.stop = function(done) {
6573
setImmediate(done);
6674
};
6775

76+
/**
77+
* Setup express routes
78+
* @param {Express} app
79+
*/
80+
Service.prototype.setupRoutes = function(app) {
81+
// Setup express routes here
82+
};
83+
6884
module.exports = Service;

lib/services/address.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,7 @@ AddressService.prototype.getAddressHistoryForAddress = function(address, queryMe
505505
var confirmations = 0;
506506
if(transaction.__height >= 0) {
507507
confirmations = self.node.services.db.tip.__height - transaction.__height;
508+
confirmations = self.node.services.db.tip.__height - transaction.__height + 1;
508509
}
509510

510511
txinfos[transaction.hash] = {

lib/services/db.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,7 @@ DB.prototype.getTransactionWithBlockInfo = function(txid, queryMempool, callback
217217
}
218218

219219
var tx = Transaction().fromBuffer(obj.buffer);
220+
tx.__blockHash = obj.blockHash;
220221
tx.__height = obj.height;
221222
tx.__timestamp = obj.timestamp;
222223

@@ -657,6 +658,7 @@ DB.prototype.sync = function() {
657658

658659
self.bitcoindSyncing = false;
659660
self.lastSavedMetadataThreshold = 0;
661+
self.saveMetadata();
660662

661663
// If bitcoind is completely synced
662664
if (self.node.services.bitcoind.isSynced()) {

0 commit comments

Comments
 (0)