http: remove use of callbacks.

This commit is contained in:
Christopher Jeffrey 2017-01-12 02:23:16 -08:00
parent c28589d0e6
commit fed7d0de54
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
8 changed files with 747 additions and 604 deletions

View File

@ -22,28 +22,28 @@ proxy.on('error', function(err) {
server = new HTTPBase();
server.get('/favicon.ico', function(req, res, send, next) {
send(404, '', 'txt');
server.get('/favicon.ico', function(req, res) {
res.send(404, '', 'txt');
});
server.get('/', function(req, res, send, next) {
send(200, index, 'html');
server.get('/', function(req, res) {
res.send(200, index, 'html');
});
server.get('/index.js', function(req, res, send, next) {
send(200, indexjs, 'js');
server.get('/index.js', function(req, res) {
res.send(200, indexjs, 'js');
});
server.get('/bcoin.js', function(req, res, send, next) {
send(200, bcoin, 'js');
server.get('/bcoin.js', function(req, res) {
res.send(200, bcoin, 'js');
});
server.get('/bcoin-master.js', function(req, res, send, next) {
send(200, master, 'js');
server.get('/bcoin-master.js', function(req, res) {
res.send(200, master, 'js');
});
server.get('/bcoin-worker.js', function(req, res, send, next) {
send(200, worker, 'js');
server.get('/bcoin-worker.js', function(req, res) {
res.send(200, worker, 'js');
});
server.on('error', function(err) {

View File

@ -11,6 +11,7 @@ var assert = require('assert');
var AsyncObject = require('../utils/async');
var util = require('../utils/util');
var URL = require('url');
var co = require('../utils/co');
/**
* HTTPBase
@ -35,6 +36,9 @@ function HTTPBase(options) {
this.routes = new Routes();
this.stack = [];
this.keyLimit = 100;
this.bodyLimit = 20 << 20;
this.server = options.key
? require('https').createServer(options)
: require('http').createServer();
@ -89,85 +93,194 @@ HTTPBase.prototype._init = function _init() {
HTTPBase.prototype._initRouter = function _initRouter() {
var self = this;
this.server.on('request', function(req, res) {
var i, j, routes, route, match, item;
function send(code, msg, type) {
sendResponse(res, code, msg, type);
}
function done(err) {
if (err) {
send(err.statusCode || 400, { error: err.message + '' });
try {
req.destroy();
req.socket.destroy();
} catch (e) {
;
}
self.emit('error', err);
}
}
this.server.on('request', co(function* (req, res) {
try {
parsePath(req, 100);
yield self.handleRequest(req, res);
} catch (e) {
return done(e);
if (!res.sent)
res.error(e);
self.emit('error', e);
}
}));
};
/**
* Handle a request.
* @private
* @param {ServerRequest} req
* @param {ServerResponse} res
* @returns {Promise}
*/
HTTPBase.prototype.handleRequest = co(function* handleRequest(req, res) {
var i, routes, route, params;
initRequest(req, res, this.keyLimit);
this.emit('request', req, res);
req.body = yield this.parseBody(req);
routes = this.routes.getHandlers(req.method);
if (!routes)
throw new Error('No routes found for method: ' + req.method);
for (i = 0; i < routes.length; i++) {
route = routes[i];
params = route.match(req.pathname);
if (!params)
continue;
req.params = params;
if (yield this.handleStack(req, res))
return;
if (yield route.call(req, res))
return;
}
throw new Error('No routes found for path: ' + req.pathname);
});
/**
* Parse request body.
* @private
* @param {ServerRequest} req
* @returns {Promise}
*/
HTTPBase.prototype.parseBody = co(function* parseBody(req) {
var body = Object.create(null);
var data;
if (req.method === 'GET')
return body;
data = yield this.readBody(req, 'utf8');
if (!data)
return body;
switch (req.contentType) {
case 'json':
body = JSON.parse(data);
break;
case 'form':
body = parsePairs(data, this.keyLimit);
break;
default:
break;
}
return body;
});
/**
* Handle middleware stack.
* @private
* @param {HTTPRequest} req
* @param {HTTPResponse} res
* @returns {Promise}
*/
HTTPBase.prototype.handleStack = co(function* handleStack(req, res) {
var i, route;
for (i = 0; i < this.stack.length; i++) {
route = this.stack[i];
if (!route.hasPrefix(req.pathname))
continue;
if (yield route.call(req, res))
return true;
}
return false;
});
/**
* Read and buffer request body.
* @param {ServerRequest} req
* @param {String} enc
* @returns {Promise}
*/
HTTPBase.prototype.readBody = function readBody(req, enc) {
var self = this;
return new Promise(function(resolve, reject) {
return self._readBody(req, enc, resolve, reject);
});
};
/**
* Read and buffer request body.
* @private
* @param {ServerRequest} req
* @param {String} enc
* @param {Function} resolve
* @param {Function} reject
*/
HTTPBase.prototype._readBody = function _readBody(req, enc, resolve, reject) {
var self = this;
var StringDecoder = require('string_decoder').StringDecoder;
var decode = new StringDecoder(enc);
var hasData = false;
var total = 0;
var body = '';
var timer;
timer = setTimeout(function() {
timer = null;
cleanup();
reject(new Error('Request body timed out.'));
}, 10 * 1000);
function cleanup() {
req.removeListener('data', onData);
req.removeListener('error', onError);
req.removeListener('end', onEnd);
if (timer != null)
clearTimeout(timer);
}
function onData(data) {
total += data.length;
hasData = true;
if (total > self.bodyLimit) {
reject(new Error('Request body overflow.'));
return;
}
self.emit('request', req, res);
body += decode.write(data);
}
i = 0;
routes = self.routes.getHandlers(req.method);
function onError(err) {
cleanup();
reject(err);
}
if (!routes)
return done(new Error('No routes found.'));
function onEnd() {
cleanup();
parseBody(req, function(err) {
if (err)
return done(err);
if (hasData) {
resolve(body);
return;
}
(function next(err) {
if (err)
return done(err);
resolve(null);
}
if (i === routes.length)
return done(new Error('Route not found.'));
route = routes[i++];
match = route.match(req.pathname);
if (!match)
return next();
req.params = Object.create(null);
for (j = 0; j < match.length; j++) {
item = match[j];
if (route.map[j])
req.params[route.map[j]] = item;
req.params[j] = item;
}
self.handleStack(req, res, send, function(err) {
if (err)
return done(err);
// Avoid stack overflows
util.nextTick(function() {
try {
route.call(req, res, send, next);
} catch (e) {
done(e);
}
});
});
})();
});
});
req.on('data', onData);
req.on('error', onError);
req.on('end', onEnd);
};
/**
@ -219,7 +332,7 @@ HTTPBase.prototype._open = function open() {
* @returns {Promise}
*/
HTTPBase.prototype._close = function close(callback) {
HTTPBase.prototype._close = function close() {
var self = this;
return new Promise(function(resolve, reject) {
@ -230,104 +343,72 @@ HTTPBase.prototype._close = function close(callback) {
}
self.server.close(function(err) {
if (err)
return reject(err);
if (err) {
reject(err);
return;
}
resolve();
});
});
};
/**
* Handle middleware stack.
* @private
* @param {HTTPRequest} req
* @param {HTTPResponse} res
* @param {Function} send
* @returns {Promise}
*/
HTTPBase.prototype.handleStack = function handleStack(req, res, send, callback) {
var self = this;
var i = 0;
var route;
(function next(err) {
if (err)
return callback(err);
if (i === self.stack.length)
return callback();
route = self.stack[i++];
util.nextTick(function() {
if (!route.hasPrefix(req.pathname))
return next();
try {
route.call(req, res, send, next);
} catch (e) {
next(e);
}
});
})();
};
/**
* Add a middleware to the stack.
* @param {String?} path
* @param {RouteCallback} callback
* @param {Function} handler
* @param {Object?} ctx
*/
HTTPBase.prototype.use = function use(path, callback, ctx) {
var i;
if (!callback) {
callback = path;
HTTPBase.prototype.use = function use(path, handler, ctx) {
if (!handler) {
handler = path;
path = null;
}
this.stack.push(new Route(ctx, path, callback));
this.stack.push(new Route(ctx, path, handler));
};
/**
* Add a GET route.
* @param {String?} path
* @param {RouteCallback} callback
* @param {String} path
* @param {Function} handler
* @param {Object?} ctx
*/
HTTPBase.prototype.get = function get(path, callback, ctx) {
this.routes.get.push(new Route(ctx, path, callback));
HTTPBase.prototype.get = function get(path, handler, ctx) {
this.routes.get.push(new Route(ctx, path, handler));
};
/**
* Add a POST route.
* @param {String?} path
* @param {RouteCallback} callback
* @param {String} path
* @param {Function} handler
* @param {Object?} ctx
*/
HTTPBase.prototype.post = function post(path, callback, ctx) {
this.routes.post.push(new Route(ctx, path, callback));
HTTPBase.prototype.post = function post(path, handler, ctx) {
this.routes.post.push(new Route(ctx, path, handler));
};
/**
* Add a PUT route.
* @param {String?} path
* @param {RouteCallback} callback
* @param {String} path
* @param {Function} handler
* @param {Object?} ctx
*/
HTTPBase.prototype.put = function put(path, callback, ctx) {
this.routes.put.push(new Route(ctx, path, callback));
HTTPBase.prototype.put = function put(path, handler, ctx) {
this.routes.put.push(new Route(ctx, path, handler));
};
/**
* Add a DELETE route.
* @param {String?} path
* @param {RouteCallback} callback
* @param {String} path
* @param {Function} handler
* @param {Object?} ctx
*/
HTTPBase.prototype.del = function del(path, callback, ctx) {
this.routes.del.push(new Route(ctx, path, callback));
HTTPBase.prototype.del = function del(path, handler, ctx) {
this.routes.del.push(new Route(ctx, path, handler));
};
/**
@ -342,7 +423,7 @@ HTTPBase.prototype.address = function address() {
/**
* Listen on port and host.
* @param {Number} port
* @param {String?} host
* @param {String} host
* @returns {Promise}
*/
@ -369,13 +450,13 @@ HTTPBase.prototype.listen = function listen(port, host) {
* @constructor
*/
function Route(ctx, path, callback) {
function Route(ctx, path, handler) {
if (!(this instanceof Route))
return new Route(ctx, path, callback);
return new Route(ctx, path, handler);
this.ctx = null;
this.path = null;
this.callback = null;
this.handler = null;
this.regex = /^/;
this.map = [];
@ -396,8 +477,8 @@ function Route(ctx, path, callback) {
}
}
assert(typeof callback === 'function');
this.callback = callback;
assert(typeof handler === 'function');
this.handler = handler;
}
Route.prototype.compile = function compile() {
@ -426,7 +507,7 @@ Route.prototype.compile = function compile() {
};
Route.prototype.match = function match(pathname) {
var match;
var i, match, item, params, key;
this.compile();
@ -437,7 +518,19 @@ Route.prototype.match = function match(pathname) {
if (!match)
return;
return match.slice(1);
params = Object.create(null);
for (i = 1; i < match.length; i++) {
item = match[i];
key = this.map[i - 1];
if (key)
params[key] = item;
params[i] = item;
}
return params;
};
Route.prototype.hasPrefix = function hasPrefix(pathname) {
@ -447,9 +540,10 @@ Route.prototype.hasPrefix = function hasPrefix(pathname) {
return pathname.indexOf(this.path) === 0;
};
Route.prototype.call = function call(req, res, send, next) {
this.callback.call(this.ctx, req, res, send, next);
};
Route.prototype.call = co(function* call(req, res) {
yield this.handler.call(this.ctx, req, res);
return res.sent;
});
/**
* Routes
@ -490,9 +584,60 @@ Routes.prototype.getHandlers = function getHandlers(method) {
* Helpers
*/
function nop() {}
function initRequest(req, res, limit) {
req.on('error', nop);
assert(req.contentType == null);
assert(req.pathname == null);
assert(req.path == null);
assert(req.query == null);
assert(req.params == null);
assert(req.body == null);
req.contentType = parseType(req.headers['content-type']);
req.pathname = '';
req.path = [];
req.query = Object.create(null);
req.params = Object.create(null);
req.body = Object.create(null);
assert(req.options == null);
assert(req.username == null);
assert(req.password == null);
assert(req.admin == null);
assert(req.wallet == null);
req.options = Object.create(null);
req.username = null;
req.password = null;
req.admin = false;
req.wallet = null;
assert(res.sent == null);
assert(res.send == null);
assert(res.error == null);
res.sent = false;
res.send = makeSend(res);
res.error = makeSendError(req, res);
parsePath(req, limit);
}
function makeSend(res) {
return function send(code, msg, type) {
return sendResponse(res, code, msg, type);
};
}
function sendResponse(res, code, msg, type) {
var len;
if (res.sent)
return;
assert(typeof code === 'number', 'Code must be a number.');
if (msg == null)
@ -510,6 +655,7 @@ function sendResponse(res, code, msg, type) {
res.statusCode = code;
res.setHeader('Content-Type', getType(type));
res.sent = true;
if (typeof msg === 'string') {
len = Buffer.byteLength(msg, 'utf8');
@ -537,45 +683,35 @@ function sendResponse(res, code, msg, type) {
assert(false, 'Bad object passed to send.');
}
function parseBody(req, callback) {
var StringDecoder = require('string_decoder').StringDecoder;
var decode = new StringDecoder('utf8');
var total = 0;
var body = '';
function makeSendError(req, res) {
return function error(err) {
return sendError(req, res, err);
};
}
req.body = Object.create(null);
function sendError(req, res, err) {
var code, msg;
if (req.method === 'GET')
return callback();
if (res.sent)
return;
req.on('data', function(data) {
total += data.length;
code = err.statusCode;
msg = err.message;
if (total > 20 * 1024 * 1024)
return callback(new Error('Overflow.'));
if (!code)
code = 400;
body += decode.write(data);
});
if (typeof msg !== 'string')
msg += '';
req.on('error', function(err) {
try {
req.destroy();
req.socket.destroy();
} catch (e) {
;
}
callback(err);
});
res.send(code, { error: msg });
req.on('end', function() {
try {
if (body)
req.body = JSON.parse(body);
} catch (e) {
return callback(e);
}
callback();
});
try {
req.destroy();
req.socket.destroy();
} catch (e) {
;
}
}
function parsePairs(str, limit) {
@ -672,7 +808,6 @@ function parsePath(req, limit) {
req.pathname = pathname;
req.path = parts;
req.query = query;
req.params = Object.create(null);
}
function unescape(str) {
@ -703,6 +838,35 @@ function getType(type) {
}
}
function parseType(type) {
type = type || '';
type = type.split(';')[0];
type = type.toLowerCase();
type = type.trim();
switch (type) {
case 'text/x-json':
case 'application/json':
return 'json';
case 'application/x-www-form-urlencoded':
return 'form';
case 'text/html':
case 'application/xhtml+xml':
return 'html';
case 'text/javascript':
case 'application/javascript':
return 'js';
case 'text/css':
return 'css';
case 'text/plain':
return 'txt';
case 'application/octet-stream':
return 'bin';
default:
return 'bin';
}
}
/*
* Expose
*/

File diff suppressed because it is too large Load Diff

View File

@ -119,38 +119,11 @@ function cob(generator) {
gen = generator.apply(this, args);
return cb(exec(gen), callback);
};
}
/**
* Wrap a generator function to be
* executed into a function that
* accepts a node.js style callback.
* Only executes callback on error.
* @param {GeneratorFunction}
* @returns {Function}
*/
function con(generator) {
return function() {
var i, args, callback, gen;
if (arguments.length === 0
|| typeof arguments[arguments.length - 1] !== 'function') {
throw new Error((generator.name || 'Function') + ' requires a callback.');
}
args = new Array(arguments.length);
callback = arguments[arguments.length - 1];
for (i = 0; i < args.length; i++)
args[i] = arguments[i];
gen = generator.apply(this, args);
return exec(gen).catch(function(err) {
// Escape the promise's scope:
exec(gen).then(function(value) {
nextTick(function() {
callback(null, value);
});
}, function(err) {
nextTick(function() {
callback(err);
});
@ -158,25 +131,6 @@ function con(generator) {
};
}
/**
* Wait for promise to resolve and
* execute a node.js style callback.
* @param {Promise} promise
* @returns {Promise}
*/
function cb(promise, callback) {
promise.then(function(value) {
nextTick(function() {
callback(null, value);
});
}, function(err) {
nextTick(function() {
callback(err);
});
});
}
/**
* Wait for a nextTick with a promise.
* @returns {Promise}
@ -188,6 +142,7 @@ function wait() {
/**
* Wait for a nextTick.
* @private
* @param {Function} resolve
* @param {Function} reject
*/
@ -316,8 +271,6 @@ exports.exec = exec;
exports.spawn = spawn;
exports.co = co;
exports.cob = cob;
exports.con = con;
exports.cb = cb;
exports.wait = wait;
exports.timeout = timeout;
exports.wrap = wrap;

View File

@ -9,7 +9,6 @@ var Script = require('../lib/script/script');
var FullNode = require('../lib/node/fullnode');
var MTX = require('../lib/primitives/mtx');
// var Client = require('../lib/wallet/client');
var cob = co.cob;
describe('Chain', function() {
var node = new FullNode({ db: 'memory', apiKey: 'foo', network: 'regtest' });
@ -48,25 +47,25 @@ describe('Chain', function() {
return yield attempt.mineAsync();
});
it('should open chain and miner', cob(function* () {
it('should open chain and miner', co(function* () {
miner.mempool = null;
consensus.COINBASE_MATURITY = 0;
yield node.open();
}));
it('should open walletdb', cob(function* () {
it('should open walletdb', co(function* () {
wallet = yield walletdb.create();
miner.addresses.length = 0;
miner.addAddress(wallet.getReceive());
}));
it('should mine a block', cob(function* () {
it('should mine a block', co(function* () {
var block = yield miner.mineBlock();
assert(block);
yield chain.add(block);
}));
it('should mine competing chains', cob(function* () {
it('should mine competing chains', co(function* () {
var i, block1, block2;
for (i = 0; i < 10; i++) {
@ -89,6 +88,8 @@ describe('Chain', function() {
assert(tip2);
assert(!(yield tip2.isMainChain()));
yield co.wait();
}
}));
@ -98,7 +99,7 @@ describe('Chain', function() {
assert.equal(chain.db.state.tx, 21);
});
it('should have correct balance', cob(function* () {
it('should have correct balance', co(function* () {
var balance;
yield co.timeout(100);
@ -108,7 +109,7 @@ describe('Chain', function() {
assert.equal(balance.confirmed, 550 * 1e8);
}));
it('should handle a reorg', cob(function* () {
it('should handle a reorg', co(function* () {
var entry, block, forked;
assert.equal(walletdb.state.height, chain.height);
@ -139,7 +140,7 @@ describe('Chain', function() {
assert.equal(chain.db.state.tx, 22);
});
it('should have correct balance', cob(function* () {
it('should have correct balance', co(function* () {
var balance;
yield co.timeout(100);
@ -149,12 +150,12 @@ describe('Chain', function() {
assert.equal(balance.confirmed, 600 * 1e8);
}));
it('should check main chain', cob(function* () {
it('should check main chain', co(function* () {
var result = yield tip1.isMainChain();
assert(!result);
}));
it('should mine a block after a reorg', cob(function* () {
it('should mine a block after a reorg', co(function* () {
var block = yield mineBlock(null, cb2);
var entry, result;
@ -168,7 +169,7 @@ describe('Chain', function() {
assert(result);
}));
it('should prevent double spend on new chain', cob(function* () {
it('should prevent double spend on new chain', co(function* () {
var block = yield mineBlock(null, cb2);
var tip = chain.tip;
var err;
@ -184,7 +185,7 @@ describe('Chain', function() {
assert(chain.tip === tip);
}));
it('should fail to mine a block with coins on an alternate chain', cob(function* () {
it('should fail to mine a block with coins on an alternate chain', co(function* () {
var block = yield mineBlock(null, cb1);
var tip = chain.tip;
var err;
@ -206,7 +207,7 @@ describe('Chain', function() {
assert.equal(chain.db.state.tx, 24);
});
it('should get coin', cob(function* () {
it('should get coin', co(function* () {
var block, tx, output, coin;
block = yield mineBlock();
@ -223,7 +224,7 @@ describe('Chain', function() {
assert.deepEqual(coin.toRaw(), output.toRaw());
}));
it('should get balance', cob(function* () {
it('should get balance', co(function* () {
var balance, txs;
yield co.timeout(100);
@ -241,7 +242,7 @@ describe('Chain', function() {
assert.equal(txs.length, 45);
}));
it('should get tips and remove chains', cob(function* () {
it('should get tips and remove chains', co(function* () {
var tips = yield chain.db.getTips();
assert.notEqual(tips.indexOf(chain.tip.hash), -1);
@ -255,7 +256,7 @@ describe('Chain', function() {
assert.equal(tips.length, 1);
}));
it('should rescan for transactions', cob(function* () {
it('should rescan for transactions', co(function* () {
var total = 0;
yield chain.db.scan(0, walletdb.filter, function(block, txs) {
@ -266,7 +267,7 @@ describe('Chain', function() {
assert.equal(total, 26);
}));
it('should activate csv', cob(function* () {
it('should activate csv', co(function* () {
var deployments = chain.network.deployments;
var i, block, prev, state, cache;
@ -330,7 +331,7 @@ describe('Chain', function() {
return yield attempt.mineAsync();
});
it('should test csv', cob(function* () {
it('should test csv', co(function* () {
var tx = (yield chain.db.getBlock(chain.height)).txs[0];
var block = yield mineCSV(tx);
var csv, attempt, redeemer;
@ -361,7 +362,7 @@ describe('Chain', function() {
yield chain.add(block);
}));
it('should fail csv with bad sequence', cob(function* () {
it('should fail csv with bad sequence', co(function* () {
var csv = (yield chain.db.getBlock(chain.height)).txs[1];
var block, attempt, redeemer, err;
@ -394,13 +395,13 @@ describe('Chain', function() {
assert(err.reason, 'mandatory-script-verify-flag-failed');
}));
it('should mine a block', cob(function* () {
it('should mine a block', co(function* () {
var block = yield miner.mineBlock();
assert(block);
yield chain.add(block);
}));
it('should fail csv lock checks', cob(function* () {
it('should fail csv lock checks', co(function* () {
var tx = (yield chain.db.getBlock(chain.height)).txs[0];
var block = yield mineCSV(tx);
var csv, attempt, redeemer, err;
@ -438,12 +439,12 @@ describe('Chain', function() {
assert.equal(err.reason, 'bad-txns-nonfinal');
}));
it('should rescan for transactions', cob(function* () {
it('should rescan for transactions', co(function* () {
yield walletdb.rescan(0);
assert.equal(wallet.txdb.state.confirmed, 1289250000000);
}));
it('should cleanup', cob(function* () {
it('should cleanup', co(function* () {
consensus.COINBASE_MATURITY = 100;
yield node.close();
}));

View File

@ -11,7 +11,6 @@ var MTX = require('../lib/primitives/mtx');
var HTTP = require('../lib/http');
var FullNode = require('../lib/node/fullnode');
var USER_VERSION = require('../package.json').version;
var cob = co.cob;
describe('HTTP', function() {
var node, wallet, addr, hash;
@ -32,17 +31,17 @@ describe('HTTP', function() {
this.timeout(15000);
it('should open node', cob(function* () {
it('should open node', co(function* () {
consensus.COINBASE_MATURITY = 0;
yield node.open();
}));
it('should create wallet', cob(function* () {
it('should create wallet', co(function* () {
var info = yield wallet.create({ id: 'test' });
assert.equal(info.id, 'test');
}));
it('should get info', cob(function* () {
it('should get info', co(function* () {
var info = yield wallet.client.getInfo();
assert.equal(info.network, node.network.type);
assert.equal(info.version, USER_VERSION);
@ -51,7 +50,7 @@ describe('HTTP', function() {
assert.equal(info.chain.height, 0);
}));
it('should get wallet info', cob(function* () {
it('should get wallet info', co(function* () {
var info = yield wallet.getInfo();
assert.equal(info.id, 'test');
addr = info.account.receiveAddress;
@ -59,7 +58,7 @@ describe('HTTP', function() {
addr = Address.fromBase58(addr);
}));
it('should fill with funds', cob(function* () {
it('should fill with funds', co(function* () {
var tx, balance, receive, details;
// Coinbase
@ -97,13 +96,13 @@ describe('HTTP', function() {
assert.equal(details.hash, tx.rhash());
}));
it('should get balance', cob(function* () {
it('should get balance', co(function* () {
var balance = yield wallet.getBalance();
assert.equal(Amount.value(balance.confirmed), 0);
assert.equal(Amount.value(balance.unconfirmed), 201840);
}));
it('should send a tx', cob(function* () {
it('should send a tx', co(function* () {
var value = 0;
var options, tx;
@ -128,30 +127,30 @@ describe('HTTP', function() {
hash = tx.hash;
}));
it('should get a tx', cob(function* () {
it('should get a tx', co(function* () {
var tx = yield wallet.getTX(hash);
assert(tx);
assert.equal(tx.hash, hash);
}));
it('should generate new api key', cob(function* () {
it('should generate new api key', co(function* () {
var t = wallet.token.toString('hex');
var token = yield wallet.retoken(null);
assert(token.length === 64);
assert.notEqual(token, t);
}));
it('should get balance', cob(function* () {
it('should get balance', co(function* () {
var balance = yield wallet.getBalance();
assert.equal(Amount.value(balance.unconfirmed), 199570);
}));
it('should execute an rpc call', cob(function* () {
it('should execute an rpc call', co(function* () {
var info = yield wallet.client.rpc.call('getblockchaininfo', []);
assert.equal(info.blocks, 0);
}));
it('should cleanup', cob(function* () {
it('should cleanup', co(function* () {
consensus.COINBASE_MATURITY = 100;
yield wallet.close();
yield node.close();

View File

@ -17,7 +17,6 @@ var Script = require('../lib/script/script');
var Witness = require('../lib/script/witness');
var Block = require('../lib/primitives/block');
var opcodes = Script.opcodes;
var cob = co.cob;
describe('Mempool', function() {
var chain, mempool, walletdb, wallet, cached;
@ -65,20 +64,20 @@ describe('Mempool', function() {
return Coin.fromTX(fund, 0, -1);
}
it('should open mempool', cob(function* () {
it('should open mempool', co(function* () {
yield mempool.open();
chain.state.flags |= Script.flags.VERIFY_WITNESS;
}));
it('should open walletdb', cob(function* () {
it('should open walletdb', co(function* () {
yield walletdb.open();
}));
it('should open wallet', cob(function* () {
it('should open wallet', co(function* () {
wallet = yield walletdb.create();
}));
it('should handle incoming orphans and TXs', cob(function* () {
it('should handle incoming orphans and TXs', co(function* () {
var kp = KeyRing.generate();
var w = wallet;
var t1, t2, t3, t4, f1, fake, prev, sig, balance, txs;
@ -177,7 +176,7 @@ describe('Mempool', function() {
}));
}));
it('should handle locktime', cob(function* () {
it('should handle locktime', co(function* () {
var w = wallet;
var kp = KeyRing.generate();
var tx, prev, prevHash, sig;
@ -203,7 +202,7 @@ describe('Mempool', function() {
chain.tip.height = 0;
}));
it('should handle invalid locktime', cob(function* () {
it('should handle invalid locktime', co(function* () {
var w = wallet;
var kp = KeyRing.generate();
var tx, prev, prevHash, sig, err;
@ -234,7 +233,7 @@ describe('Mempool', function() {
chain.tip.height = 0;
}));
it('should not cache a malleated wtx with mutated sig', cob(function* () {
it('should not cache a malleated wtx with mutated sig', co(function* () {
var w = wallet;
var kp = KeyRing.generate();
var tx, prev, prevHash, prevs, sig, err;
@ -268,7 +267,7 @@ describe('Mempool', function() {
assert(!mempool.hasReject(tx.hash()));
}));
it('should not cache a malleated tx with unnecessary witness', cob(function* () {
it('should not cache a malleated tx with unnecessary witness', co(function* () {
var w = wallet;
var kp = KeyRing.generate();
var tx, prev, prevHash, sig, err;
@ -297,7 +296,7 @@ describe('Mempool', function() {
assert(!mempool.hasReject(tx.hash()));
}));
it('should not cache a malleated wtx with wit removed', cob(function* () {
it('should not cache a malleated wtx with wit removed', co(function* () {
var w = wallet;
var kp = KeyRing.generate();
var tx, prev, prevHash, err;
@ -326,7 +325,7 @@ describe('Mempool', function() {
assert(!mempool.hasReject(tx.hash()));
}));
it('should cache non-malleated tx without sig', cob(function* () {
it('should cache non-malleated tx without sig', co(function* () {
var w = wallet;
var kp = KeyRing.generate();
var tx, prev, prevHash, err;
@ -354,7 +353,7 @@ describe('Mempool', function() {
cached = tx;
}));
it('should clear reject cache', cob(function* () {
it('should clear reject cache', co(function* () {
var w = wallet;
var tx, input;
@ -368,7 +367,7 @@ describe('Mempool', function() {
assert(!mempool.hasReject(cached.hash()));
}));
it('should destroy mempool', cob(function* () {
it('should destroy mempool', co(function* () {
yield mempool.close();
}));
});

View File

@ -17,7 +17,6 @@ var Outpoint = require('../lib/primitives/outpoint');
var Script = require('../lib/script/script');
var HD = require('../lib/hd');
var scriptTypes = Script.types;
var cob = co.cob;
var KEY1 = 'xprv9s21ZrQH143K3Aj6xQBymM31Zb4BVc7wxqfUhMZrzewdDVCt'
+ 'qUP9iWfcHgJofs25xbaUpCps9GDXj83NiWvQCAkWQhVj5J4CorfnpKX94AZ';
@ -68,12 +67,12 @@ describe('Wallet', function() {
this.timeout(5000);
it('should open walletdb', cob(function* () {
it('should open walletdb', co(function* () {
consensus.COINBASE_MATURITY = 0;
yield walletdb.open();
}));
it('should generate new key and address', cob(function* () {
it('should generate new key and address', co(function* () {
var w = yield walletdb.create();
var addr = w.getAddress('base58');
assert(addr);
@ -90,7 +89,7 @@ describe('Wallet', function() {
});
});
it('should create and get wallet', cob(function* () {
it('should create and get wallet', co(function* () {
var w1, w2;
w1 = yield walletdb.create();
@ -134,19 +133,19 @@ describe('Wallet', function() {
assert(tx.verify(flags));
});
it('should sign/verify pubkeyhash tx', cob(function* () {
it('should sign/verify pubkeyhash tx', co(function* () {
yield testP2PKH(false, false);
}));
it('should sign/verify witnesspubkeyhash tx', cob(function* () {
it('should sign/verify witnesspubkeyhash tx', co(function* () {
yield testP2PKH(true, false);
}));
it('should sign/verify witnesspubkeyhash tx with bullshit nesting', cob(function* () {
it('should sign/verify witnesspubkeyhash tx with bullshit nesting', co(function* () {
yield testP2PKH(true, true);
}));
it('should multisign/verify TX', cob(function* () {
it('should multisign/verify TX', co(function* () {
var w, k, script, src, tx, maxSize;
w = yield walletdb.create({
@ -183,7 +182,7 @@ describe('Wallet', function() {
assert(tx.verify());
}));
it('should handle missed and invalid txs', cob(function* () {
it('should handle missed and invalid txs', co(function* () {
var w = yield walletdb.create();
var f = yield walletdb.create();
var t1, t2, t3, t4, f1, fake, balance, txs;
@ -287,7 +286,7 @@ describe('Wallet', function() {
}));
}));
it('should cleanup spenders after double-spend', cob(function* () {
it('should cleanup spenders after double-spend', co(function* () {
var w = doubleSpendWallet;
var tx, txs, total, balance;
@ -323,7 +322,7 @@ describe('Wallet', function() {
assert.equal(total, 56000);
}));
it('should handle missed txs without resolution', cob(function* () {
it('should handle missed txs without resolution', co(function* () {
var walletdb, w, f, t1, t2, t3, t4, f1, balance, txs;
walletdb = new WalletDB({
@ -448,7 +447,7 @@ describe('Wallet', function() {
assert.equal(balance.unconfirmed, 10000);
}));
it('should fill tx with inputs', cob(function* () {
it('should fill tx with inputs', co(function* () {
var w1 = yield walletdb.create();
var w2 = yield walletdb.create();
var view, t1, t2, t3, err;
@ -493,7 +492,7 @@ describe('Wallet', function() {
assert.equal(err.requiredFunds, 25000);
}));
it('should fill tx with inputs with accurate fee', cob(function* () {
it('should fill tx with inputs with accurate fee', co(function* () {
var w1 = yield walletdb.create({ master: KEY1 });
var w2 = yield walletdb.create({ master: KEY2 });
var view, t1, t2, t3, balance, err;
@ -552,7 +551,7 @@ describe('Wallet', function() {
assert(balance.unconfirmed === 5460);
}));
it('should sign multiple inputs using different keys', cob(function* () {
it('should sign multiple inputs using different keys', co(function* () {
var w1 = yield walletdb.create();
var w2 = yield walletdb.create();
var to = yield walletdb.create();
@ -746,19 +745,19 @@ describe('Wallet', function() {
assert.equal(send.getFee(view), 10000);
});
it('should verify 2-of-3 scripthash tx', cob(function* () {
it('should verify 2-of-3 scripthash tx', co(function* () {
yield testMultisig(false, false);
}));
it('should verify 2-of-3 witnessscripthash tx', cob(function* () {
it('should verify 2-of-3 witnessscripthash tx', co(function* () {
yield testMultisig(true, false);
}));
it('should verify 2-of-3 witnessscripthash tx with bullshit nesting', cob(function* () {
it('should verify 2-of-3 witnessscripthash tx with bullshit nesting', co(function* () {
yield testMultisig(true, true);
}));
it('should fill tx with account 1', cob(function* () {
it('should fill tx with account 1', co(function* () {
var w1 = yield walletdb.create();
var w2 = yield walletdb.create();
var account, accounts, rec, t1, t2, t3, err;
@ -813,7 +812,7 @@ describe('Wallet', function() {
assert.deepEqual(accounts, ['default', 'foo']);
}));
it('should fail to fill tx with account 1', cob(function* () {
it('should fail to fill tx with account 1', co(function* () {
var w = yield walletdb.create();
var acc, account, t1, t2, err;
@ -879,7 +878,7 @@ describe('Wallet', function() {
yield w.fund(t2, { rate: 10000, round: true, account: 'foo' });
}));
it('should create two accounts (multiple encryption)', cob(function* () {
it('should create two accounts (multiple encryption)', co(function* () {
var w = yield walletdb.create({ id: 'foobar', passphrase: 'foo' });
var account;
@ -893,7 +892,7 @@ describe('Wallet', function() {
yield w.lock();
}));
it('should fill tx with inputs when encrypted', cob(function* () {
it('should fill tx with inputs when encrypted', co(function* () {
var w = yield walletdb.create({ passphrase: 'foo' });
var t1, t2, err;
@ -931,7 +930,7 @@ describe('Wallet', function() {
assert(t2.verify());
}));
it('should fill tx with inputs with subtract fee', cob(function* () {
it('should fill tx with inputs with subtract fee', co(function* () {
var w1 = yield walletdb.create();
var w2 = yield walletdb.create();
var t1, t2;
@ -960,7 +959,7 @@ describe('Wallet', function() {
assert.equal(t2.getFee(), 10000);
}));
it('should fill tx with inputs with subtract fee', cob(function* () {
it('should fill tx with inputs with subtract fee', co(function* () {
var w1 = yield walletdb.create();
var w2 = yield walletdb.create();
var options, t1, t2;
@ -994,19 +993,19 @@ describe('Wallet', function() {
assert.equal(t2.getFee(), 10000);
}));
it('should get range of txs', cob(function* () {
it('should get range of txs', co(function* () {
var w = wallet;
var txs = yield w.getRange({ start: util.now() - 1000 });
assert.equal(txs.length, 2);
}));
it('should get range of txs from account', cob(function* () {
it('should get range of txs from account', co(function* () {
var w = wallet;
var txs = yield w.getRange('foo', { start: util.now() - 1000 });
assert.equal(txs.length, 2);
}));
it('should not get range of txs from non-existent account', cob(function* () {
it('should not get range of txs from non-existent account', co(function* () {
var w = wallet;
var txs, err;
@ -1020,13 +1019,13 @@ describe('Wallet', function() {
assert.equal(err.message, 'Account not found.');
}));
it('should get account balance', cob(function* () {
it('should get account balance', co(function* () {
var w = wallet;
var balance = yield w.getBalance('foo');
assert.equal(balance.unconfirmed, 21840);
}));
it('should import privkey', cob(function* () {
it('should import privkey', co(function* () {
var key = KeyRing.generate();
var w = yield walletdb.create({ passphrase: 'test' });
var options, k, t1, t2, wtx;
@ -1069,7 +1068,7 @@ describe('Wallet', function() {
ekey = key;
}));
it('should import pubkey', cob(function* () {
it('should import pubkey', co(function* () {
var priv = KeyRing.generate();
var key = new KeyRing(priv.publicKey);
var w = yield walletdb.create({ watchOnly: true });
@ -1085,7 +1084,7 @@ describe('Wallet', function() {
assert(k);
}));
it('should import address', cob(function* () {
it('should import address', co(function* () {
var key = KeyRing.generate();
var w = yield walletdb.create({ watchOnly: true });
var k;
@ -1100,7 +1099,7 @@ describe('Wallet', function() {
assert(!k);
}));
it('should get details', cob(function* () {
it('should get details', co(function* () {
var w = wallet;
var txs = yield w.getRange('foo', { start: util.now() - 1000 });
var details = yield w.toDetails(txs);
@ -1109,7 +1108,7 @@ describe('Wallet', function() {
}));
}));
it('should rename wallet', cob(function* () {
it('should rename wallet', co(function* () {
var w = wallet;
yield wallet.rename('test');
var txs = yield w.getRange('foo', { start: util.now() - 1000 });
@ -1117,7 +1116,7 @@ describe('Wallet', function() {
assert.equal(details[0].toJSON().id, 'test');
}));
it('should change passphrase with encrypted imports', cob(function* () {
it('should change passphrase with encrypted imports', co(function* () {
var w = ewallet;
var addr = ekey.getAddress();
var path, d1, d2, k;
@ -1156,7 +1155,7 @@ describe('Wallet', function() {
assert.equal(k.getHash('hex'), addr.getHash('hex'));
}));
it('should recover from a missed tx', cob(function* () {
it('should recover from a missed tx', co(function* () {
var walletdb, alice, addr, bob, t1, t2, t3;
walletdb = new WalletDB({
@ -1220,7 +1219,7 @@ describe('Wallet', function() {
assert.equal((yield bob.getBalance()).unconfirmed, 30000);
}));
it('should recover from a missed tx and double spend', cob(function* () {
it('should recover from a missed tx and double spend', co(function* () {
var walletdb, alice, addr, bob, t1, t2, t3, t2a;
walletdb = new WalletDB({