Added performance tests.
Changed getInfo from header service to block service.
This commit is contained in:
parent
27b32efbf0
commit
ee1ea93195
@ -48,7 +48,7 @@ StatusController.prototype.show = function(req, res) {
|
||||
};
|
||||
|
||||
StatusController.prototype.getInfo = function(callback) {
|
||||
this._header.getInfo(function(err, result) {
|
||||
this._block.getInfo(function(err, result) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
2
package-lock.json
generated
2
package-lock.json
generated
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "insight-api",
|
||||
"version": "5.0.0-beta.1",
|
||||
"version": "5.0.0-beta.3",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "insight-api",
|
||||
"description": "A Bitcoin blockchain REST and web socket API service for Bitcore Node.",
|
||||
"version": "5.0.0-beta.2",
|
||||
"version": "5.0.0-beta.3",
|
||||
"repository": "git://github.com/bitpay/insight-api.git",
|
||||
"bugs": {
|
||||
"url": "https://github.com/bitpay/insight-api/issues"
|
||||
|
||||
459
perf/perf.js
Normal file
459
perf/perf.js
Normal file
@ -0,0 +1,459 @@
|
||||
'use strict';
|
||||
|
||||
var expect = require('chai').expect;
|
||||
var spawn = require('child_process').spawn;
|
||||
var rimraf = require('rimraf');
|
||||
var mkdirp = require('mkdirp');
|
||||
var fs = require('fs');
|
||||
var async = require('async');
|
||||
var RPC = require('bitcoind-rpc');
|
||||
var http = require('http');
|
||||
var bitcore = require('bitcore-lib');
|
||||
var PrivateKey = bitcore.PrivateKey;
|
||||
var Transaction = bitcore.Transaction;
|
||||
|
||||
var rpcConfig = {
|
||||
protocol: 'http',
|
||||
user: 'local',
|
||||
pass: 'localtest',
|
||||
host: '127.0.0.1',
|
||||
port: 58332,
|
||||
rejectUnauthorized: false
|
||||
};
|
||||
|
||||
var blocksGenerated = 0;
|
||||
var startingAddr;
|
||||
var startingTx;
|
||||
var amtToSendToEach;
|
||||
var utxoCount = 3000;
|
||||
var outputKeys = [];
|
||||
var rpc1 = new RPC(rpcConfig);
|
||||
var debug = true;
|
||||
var bitcoreDataDir = '/tmp/bitcore';
|
||||
var bitcoinDataDirs = ['/tmp/bitcoin'];
|
||||
|
||||
var bitcoin = {
|
||||
args: {
|
||||
datadir: null,
|
||||
listen: 1,
|
||||
regtest: 1,
|
||||
server: 1,
|
||||
rpcuser: 'local',
|
||||
rpcpassword: 'localtest',
|
||||
//printtoconsole: 1
|
||||
rpcport: 58332,
|
||||
},
|
||||
datadir: null,
|
||||
exec: 'bitcoind', //if this isn't on your PATH, then provide the absolute path, e.g. /usr/local/bin/bitcoind
|
||||
processes: []
|
||||
};
|
||||
|
||||
var bitcore = {
|
||||
configFile: {
|
||||
file: bitcoreDataDir + '/bitcore-node.json',
|
||||
conf: {
|
||||
network: 'regtest',
|
||||
port: 53001,
|
||||
datadir: bitcoreDataDir,
|
||||
services: [
|
||||
'p2p',
|
||||
'db',
|
||||
'header',
|
||||
'block',
|
||||
'address',
|
||||
'transaction',
|
||||
'mempool',
|
||||
'web',
|
||||
'insight-api',
|
||||
'fee',
|
||||
'timestamp'
|
||||
],
|
||||
servicesConfig: {
|
||||
'p2p': {
|
||||
'peers': [
|
||||
{ 'ip': { 'v4': '127.0.0.1' }, port: 18444 }
|
||||
]
|
||||
},
|
||||
'insight-api': {
|
||||
'routePrefix': 'api'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
httpOpts: {
|
||||
protocol: 'http:',
|
||||
hostname: 'localhost',
|
||||
port: 53001,
|
||||
},
|
||||
opts: { cwd: bitcoreDataDir },
|
||||
datadir: bitcoreDataDir,
|
||||
exec: 'bitcored', //if this isn't on your PATH, then provide the absolute path, e.g. /usr/local/bin/bitcored
|
||||
args: ['start'],
|
||||
process: null
|
||||
};
|
||||
|
||||
var startBitcoind = function(count, callback) {
|
||||
|
||||
var listenCount = 0;
|
||||
async.timesSeries(count, function(n, next) {
|
||||
|
||||
var datadir = bitcoinDataDirs.shift();
|
||||
|
||||
bitcoin.datadir = datadir;
|
||||
bitcoin.args.datadir = datadir;
|
||||
|
||||
if (listenCount++ > 0) {
|
||||
bitcoin.args.listen = 0;
|
||||
bitcoin.args.rpcport++;
|
||||
bitcoin.args.connect = '127.0.0.1';
|
||||
}
|
||||
|
||||
rimraf(datadir, function(err) {
|
||||
|
||||
if(err) {
|
||||
return next(err);
|
||||
}
|
||||
|
||||
mkdirp(datadir, function(err) {
|
||||
|
||||
if(err) {
|
||||
return next(err);
|
||||
}
|
||||
|
||||
var args = bitcoin.args;
|
||||
var argList = Object.keys(args).map(function(key) {
|
||||
return '-' + key + '=' + args[key];
|
||||
});
|
||||
|
||||
var bitcoinProcess = spawn(bitcoin.exec, argList, bitcoin.opts);
|
||||
bitcoin.processes.push(bitcoinProcess);
|
||||
|
||||
bitcoinProcess.stdout.on('data', function(data) {
|
||||
|
||||
if (debug) {
|
||||
process.stdout.write(data.toString());
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
bitcoinProcess.stderr.on('data', function(data) {
|
||||
|
||||
if (debug) {
|
||||
process.stderr.write(data.toString());
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
next();
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
}, function(err) {
|
||||
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
var pids = bitcoin.processes.map(function(process) {
|
||||
return process.pid;
|
||||
});
|
||||
|
||||
console.log(count + ' bitcoind\'s started at pid(s): ' + pids);
|
||||
callback();
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
var request = function(httpOpts, callback) {
|
||||
|
||||
var request = http.request(httpOpts, function(res) {
|
||||
|
||||
if (res.statusCode !== 200 && res.statusCode !== 201) {
|
||||
return callback('Error from bitcore-node webserver: ' + res.statusCode);
|
||||
}
|
||||
|
||||
var resError;
|
||||
var resData = '';
|
||||
|
||||
res.on('error', function(e) {
|
||||
resError = e;
|
||||
});
|
||||
|
||||
res.on('data', function(data) {
|
||||
resData += data;
|
||||
});
|
||||
|
||||
res.on('end', function() {
|
||||
|
||||
if (resError) {
|
||||
return callback(resError);
|
||||
}
|
||||
var data = JSON.parse(resData);
|
||||
callback(null, data);
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
request.on('error', function(err) {
|
||||
callback(err);
|
||||
});
|
||||
request.write('');
|
||||
request.end();
|
||||
};
|
||||
|
||||
var shutdownBitcoind = function(callback) {
|
||||
bitcoin.processes.forEach(function(process) {
|
||||
process.kill();
|
||||
});
|
||||
setTimeout(callback, 3000);
|
||||
};
|
||||
|
||||
var shutdownBitcore = function(callback) {
|
||||
if (bitcore.process) {
|
||||
bitcore.process.kill();
|
||||
}
|
||||
callback();
|
||||
};
|
||||
|
||||
|
||||
var buildInitialTx = function(utxo, key) {
|
||||
|
||||
amtToSendToEach = Math.floor(utxo.satoshis / outputKeys.length) - 100;
|
||||
|
||||
var tx = new Transaction().from(utxo);
|
||||
|
||||
outputKeys.forEach(function(key) {
|
||||
tx.to(key.toAddress(), amtToSendToEach);
|
||||
});
|
||||
|
||||
tx.sign(key);
|
||||
|
||||
return tx;
|
||||
|
||||
};
|
||||
|
||||
var buildOutputKeys = function() {
|
||||
for(var i = 0; i < utxoCount; i++) {
|
||||
outputKeys.push(new PrivateKey('testnet'));
|
||||
}
|
||||
};
|
||||
|
||||
var buildReturnTxs = function() {
|
||||
|
||||
console.log('Building return txs...');
|
||||
var txs = [];
|
||||
|
||||
for(var i = 0; i < outputKeys.length; i++) {
|
||||
var key = outputKeys[i];
|
||||
var address = key.toAddress();
|
||||
var utxo = {
|
||||
txId: startingTx.hash,
|
||||
outputIndex: i,
|
||||
address: address,
|
||||
script: startingTx.outputs[i].script.toHex(),
|
||||
satoshis: startingTx.outputs[i].satoshis
|
||||
};
|
||||
var tx = new Transaction().from(utxo).to(startingAddr, amtToSendToEach - 1000).sign(key);
|
||||
txs.push(tx);
|
||||
}
|
||||
return txs;
|
||||
};
|
||||
|
||||
var buildInitialChain = function(callback) {
|
||||
|
||||
async.waterfall([
|
||||
|
||||
function(next) {
|
||||
buildOutputKeys();
|
||||
next();
|
||||
},
|
||||
function(next) {
|
||||
blocksGenerated += 101;
|
||||
rpc1.generate(101, next);
|
||||
},
|
||||
function(res, next) {
|
||||
rpc1.listUnspent(next);
|
||||
},
|
||||
function(res, next) {
|
||||
rpc1.dumpPrivKey(res.result[0].address, function(err, result) {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
next(null, res.result[0], result.result);
|
||||
});
|
||||
},
|
||||
function(unspent, key, next) {
|
||||
startingAddr = unspent.address;
|
||||
var utxo = { txId: unspent.txid, address: startingAddr, satoshis: unspent.amount * 1e8, script: unspent.scriptPubKey, outputIndex: unspent.vout };
|
||||
startingTx = buildInitialTx(utxo, key, next);
|
||||
rpc1.sendRawTransaction(startingTx.uncheckedSerialize(), next);
|
||||
},
|
||||
function(res, next) {
|
||||
console.log('generated: ' + outputKeys.length + ' utxos.');
|
||||
blocksGenerated += 6;
|
||||
rpc1.generate(6, next);
|
||||
},
|
||||
function(res, next) {
|
||||
// send it all back
|
||||
var txs = buildReturnTxs();
|
||||
var txCount = 0;
|
||||
async.eachSeries(txs, function(tx, next) {
|
||||
if (++txCount % 100 === 0) {
|
||||
console.log('sent: ', txCount, ' txs');
|
||||
}
|
||||
rpc1.sendRawTransaction(tx.uncheckedSerialize(), next);
|
||||
}, next);
|
||||
},
|
||||
function(next) {
|
||||
blocksGenerated += 6;
|
||||
rpc1.generate(6, next);
|
||||
}
|
||||
], function(err) {
|
||||
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
callback();
|
||||
});
|
||||
};
|
||||
|
||||
var startBitcore = function(callback) {
|
||||
|
||||
rimraf(bitcoreDataDir, function(err) {
|
||||
|
||||
if(err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
mkdirp(bitcoreDataDir, function(err) {
|
||||
|
||||
if(err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
fs.writeFileSync(bitcore.configFile.file, JSON.stringify(bitcore.configFile.conf));
|
||||
|
||||
var args = bitcore.args;
|
||||
bitcore.process = spawn(bitcore.exec, args, bitcore.opts);
|
||||
|
||||
bitcore.process.stdout.on('data', function(data) {
|
||||
|
||||
if (debug) {
|
||||
process.stdout.write(data.toString());
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
bitcore.process.stderr.on('data', function(data) {
|
||||
|
||||
if (debug) {
|
||||
process.stderr.write(data.toString());
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
var httpOpts = {
|
||||
hostname: 'localhost',
|
||||
port: 53001,
|
||||
path: '/api/status',
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
};
|
||||
|
||||
async.retry({ interval: 1000, times: 100 }, function(next) {
|
||||
request(httpOpts, function(err, data) {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
if (data.info.blocks < blocksGenerated) {
|
||||
return next(data);
|
||||
}
|
||||
next();
|
||||
});
|
||||
}, callback);
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
describe('Address Performance', function() {
|
||||
|
||||
this.timeout(80000);
|
||||
|
||||
before(function(done) {
|
||||
|
||||
async.series([
|
||||
function(next) {
|
||||
startBitcoind(bitcoinDataDirs.length, next);
|
||||
},
|
||||
function(next) {
|
||||
setTimeout(function() {
|
||||
buildInitialChain(next);
|
||||
}, 8000);
|
||||
},
|
||||
function(next) {
|
||||
startBitcore(next);
|
||||
}
|
||||
], function(err) {
|
||||
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
|
||||
setTimeout(done, 2000);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
after(function(done) {
|
||||
shutdownBitcore(function() {
|
||||
shutdownBitcoind(done);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it('should get address info correctly: /addr/:addr', function(done) {
|
||||
|
||||
var httpOpts = {
|
||||
hostname: 'localhost',
|
||||
port: 53001,
|
||||
path: '/api/addr/' + startingAddr,
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
async.timesSeries(1, function(n, next) {
|
||||
|
||||
var startTime = process.hrtime();
|
||||
request(httpOpts, function(err) {
|
||||
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
|
||||
var endTime = process.hrtime(startTime);
|
||||
// under 1 sec?
|
||||
expect(endTime[0]).to.equal(0);
|
||||
next();
|
||||
|
||||
});
|
||||
}, done);
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user