http tests. caches.
This commit is contained in:
parent
a60a48da9a
commit
682596fb05
@ -209,7 +209,7 @@ function ChainDB(chain, options) {
|
||||
// Key size: 66b (* 2)
|
||||
this.coinWindow = ((165 * 1024 + 2300 * 4) + (2300 * 66 * 2)) * 5;
|
||||
|
||||
this.coinCache = new NullCache(this.coinWindow);
|
||||
this.coinCache = new bcoin.lru.nil(this.coinWindow);
|
||||
this.cacheHash = new bcoin.lru(this.cacheWindow, 1);
|
||||
this.cacheHeight = new bcoin.lru(this.cacheWindow, 1);
|
||||
}
|
||||
@ -1482,20 +1482,6 @@ ChainDB.prototype._pruneBlock = function _pruneBlock(block, batch, callback) {
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* A null cache. Every method is a NOP.
|
||||
* @constructor
|
||||
* @param {Number} size
|
||||
*/
|
||||
|
||||
function NullCache(size) {}
|
||||
|
||||
NullCache.prototype.set = function set(key, value) {};
|
||||
NullCache.prototype.remove = function remove(key) {};
|
||||
NullCache.prototype.get = function get(key) {};
|
||||
NullCache.prototype.has = function has(key) {};
|
||||
NullCache.prototype.reset = function reset() {};
|
||||
|
||||
/*
|
||||
* Helpers
|
||||
*/
|
||||
|
||||
@ -194,7 +194,9 @@ HTTPBase.prototype._initIO = function _initIO() {
|
||||
if (!IOServer)
|
||||
return;
|
||||
|
||||
this.io = new IOServer();
|
||||
this.io = new IOServer({
|
||||
transports: ['websocket']
|
||||
});
|
||||
|
||||
this.io.attach(this.server);
|
||||
|
||||
|
||||
@ -75,7 +75,10 @@ HTTPClient.prototype._open = function _open(callback) {
|
||||
if (!IOClient)
|
||||
return callback();
|
||||
|
||||
this.socket = new IOClient(this.uri);
|
||||
this.socket = new IOClient(this.uri, {
|
||||
transports: ['websocket'],
|
||||
forceNew: true
|
||||
});
|
||||
|
||||
this.socket.on('error', function(err) {
|
||||
self.emit('error', err);
|
||||
|
||||
@ -353,8 +353,23 @@ function LRUItem(key, value) {
|
||||
this.prev = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* A null cache. Every method is a NOP.
|
||||
* @constructor
|
||||
* @param {Number} size
|
||||
*/
|
||||
|
||||
function NullCache(size) {}
|
||||
|
||||
NullCache.prototype.set = function set(key, value) {};
|
||||
NullCache.prototype.remove = function remove(key) {};
|
||||
NullCache.prototype.get = function get(key) {};
|
||||
NullCache.prototype.has = function has(key) {};
|
||||
NullCache.prototype.reset = function reset() {};
|
||||
|
||||
/*
|
||||
* Expose
|
||||
*/
|
||||
|
||||
LRU.nil = NullCache;
|
||||
module.exports = LRU;
|
||||
|
||||
@ -1868,7 +1868,7 @@ TX.prototype.inspect = function inspect() {
|
||||
value: utils.btc(this.getOutputValue()),
|
||||
fee: utils.btc(this.getFee()),
|
||||
minFee: utils.btc(this.getMinFee()),
|
||||
rate: utils.btc(this.getRate()),
|
||||
rate: this.getRate(), // Rate can sometimes exceed 53 bits in testing
|
||||
confirmations: this.getConfirmations(),
|
||||
priority: this.getPriority(),
|
||||
date: utils.date(this.ts || this.ps),
|
||||
|
||||
@ -1720,12 +1720,15 @@ Account.prototype.fromOptions = function fromOptions(options) {
|
||||
|
||||
assert(options, 'Options are required.');
|
||||
assert(utils.isAlpha(options.id), 'Wallet ID must be alphanumeric.');
|
||||
assert(utils.isAlpha(options.name), 'Account name must be alphanumeric.');
|
||||
assert(bcoin.hd.isHD(options.accountKey), 'Account key is required.');
|
||||
assert(utils.isNumber(options.accountIndex), 'Account index is required.');
|
||||
|
||||
this.id = options.id;
|
||||
this.name = options.name;
|
||||
|
||||
if (options.name != null) {
|
||||
assert(utils.isAlpha(options.name), 'Account name must be alphanumeric.');
|
||||
this.name = options.name;
|
||||
}
|
||||
|
||||
if (options.witness != null) {
|
||||
assert(typeof options.witness === 'boolean');
|
||||
|
||||
@ -54,6 +54,9 @@ function WalletDB(options) {
|
||||
// We need one read lock for `get` and `create`.
|
||||
// It will hold locks specific to wallet ids.
|
||||
this.readLock = new ReadLock(this);
|
||||
this.accountCache = new bcoin.lru(100000, 1);
|
||||
this.walletCache = new bcoin.lru(100000, 1);
|
||||
this.pathCache = new bcoin.lru(100000, 1);
|
||||
|
||||
this.db = bcoin.ldb({
|
||||
location: this.options.location,
|
||||
@ -425,19 +428,13 @@ WalletDB.prototype.get = function get(id, callback) {
|
||||
return callback(null, watcher.object);
|
||||
}
|
||||
|
||||
this.db.get('w/' + id, function(err, data) {
|
||||
this._get(id, function(err, wallet) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
if (!data)
|
||||
if (!wallet)
|
||||
return callback();
|
||||
|
||||
try {
|
||||
wallet = bcoin.wallet.fromRaw(self, data);
|
||||
} catch (e) {
|
||||
return callback(e);
|
||||
}
|
||||
|
||||
try {
|
||||
self.register(wallet);
|
||||
} catch (e) {
|
||||
@ -453,6 +450,37 @@ WalletDB.prototype.get = function get(id, callback) {
|
||||
});
|
||||
};
|
||||
|
||||
WalletDB.prototype._get = function get(id, callback) {
|
||||
var self = this;
|
||||
var wallet;
|
||||
|
||||
if (!id)
|
||||
return callback();
|
||||
|
||||
wallet = this.walletCache.get(id);
|
||||
|
||||
if (wallet)
|
||||
return callback(null, wallet);
|
||||
|
||||
this.db.get('w/' + id, function(err, data) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
if (!data)
|
||||
return callback();
|
||||
|
||||
try {
|
||||
wallet = bcoin.wallet.fromRaw(self, data);
|
||||
} catch (e) {
|
||||
return callback(e);
|
||||
}
|
||||
|
||||
self.walletCache.set(id, wallet);
|
||||
|
||||
return callback(null, wallet);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Save a wallet to the database.
|
||||
* @param {Wallet} wallet
|
||||
@ -463,6 +491,8 @@ WalletDB.prototype.save = function save(wallet, callback) {
|
||||
if (!utils.isAlpha(wallet.id))
|
||||
return callback(new Error('Wallet IDs must be alphanumeric.'));
|
||||
|
||||
this.walletCache.set(wallet.id, wallet);
|
||||
|
||||
this.db.put('w/' + wallet.id, wallet.toRaw(), callback);
|
||||
};
|
||||
|
||||
@ -480,19 +510,13 @@ WalletDB.prototype.auth = function auth(id, token, callback) {
|
||||
if (!id)
|
||||
return callback(new Error('Wallet not found.'));
|
||||
|
||||
this.db.get('w/' + id, function(err, data) {
|
||||
this._get(id, function(err, wallet) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
if (!data)
|
||||
if (!wallet)
|
||||
return callback(new Error('Wallet not found.'));
|
||||
|
||||
try {
|
||||
wallet = bcoin.wallet.fromRaw(self, data);
|
||||
} catch (e) {
|
||||
return callback(e);
|
||||
}
|
||||
|
||||
if (typeof token === 'string') {
|
||||
if (!utils.isHex(token))
|
||||
return callback(new Error('Authentication error.'));
|
||||
@ -614,19 +638,13 @@ WalletDB.prototype.getAccount = function getAccount(id, name, callback) {
|
||||
if (index === -1)
|
||||
return callback();
|
||||
|
||||
self.db.get('a/' + id + '/' + index, function(err, data) {
|
||||
self._getAccount(id, index, function(err, account) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
if (!data)
|
||||
if (!account)
|
||||
return callback();
|
||||
|
||||
try {
|
||||
account = bcoin.account.fromRaw(self, data);
|
||||
} catch (e) {
|
||||
return callback(e);
|
||||
}
|
||||
|
||||
account.open(function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
@ -637,6 +655,33 @@ WalletDB.prototype.getAccount = function getAccount(id, name, callback) {
|
||||
});
|
||||
};
|
||||
|
||||
WalletDB.prototype._getAccount = function getAccount(id, index, callback) {
|
||||
var self = this;
|
||||
var key = id + '/' + index;
|
||||
var account = this.accountCache.get(key);
|
||||
|
||||
if (account)
|
||||
return callback(null, account);
|
||||
|
||||
this.db.get('a/' + key, function(err, data) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
if (!data)
|
||||
return callback();
|
||||
|
||||
try {
|
||||
account = bcoin.account.fromRaw(self, data);
|
||||
} catch (e) {
|
||||
return callback(e);
|
||||
}
|
||||
|
||||
self.accountCache.set(key, account);
|
||||
|
||||
return callback(null, account);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* List account names and indexes from the db.
|
||||
* @param {WalletID} id
|
||||
@ -675,6 +720,9 @@ WalletDB.prototype.getAccounts = function getAccounts(id, callback) {
|
||||
*/
|
||||
|
||||
WalletDB.prototype.getAccountIndex = function getAccountIndex(id, name, callback) {
|
||||
if (!id)
|
||||
return callback(null, -1);
|
||||
|
||||
if (name == null)
|
||||
return callback(null, -1);
|
||||
|
||||
@ -699,7 +747,7 @@ WalletDB.prototype.getAccountIndex = function getAccountIndex(id, name, callback
|
||||
*/
|
||||
|
||||
WalletDB.prototype.saveAccount = function saveAccount(account, callback) {
|
||||
var index, batch;
|
||||
var index, key, batch;
|
||||
|
||||
if (!utils.isAlpha(account.name))
|
||||
return callback(new Error('Account names must be alphanumeric.'));
|
||||
@ -709,9 +757,13 @@ WalletDB.prototype.saveAccount = function saveAccount(account, callback) {
|
||||
index = new Buffer(4);
|
||||
index.writeUInt32LE(account.accountIndex, 0, true);
|
||||
|
||||
batch.put('a/' + account.id + '/' + account.accountIndex, account.toRaw());
|
||||
key = account.id + '/' + account.accountIndex;
|
||||
|
||||
batch.put('a/' + key, account.toRaw());
|
||||
batch.put('i/' + account.id + '/' + account.name, index);
|
||||
|
||||
this.accountCache.set(key, account);
|
||||
|
||||
batch.write(callback);
|
||||
};
|
||||
|
||||
@ -816,7 +868,7 @@ WalletDB.prototype.saveAddress = function saveAddress(id, addresses, callback) {
|
||||
|
||||
self.emit('save address', address, path);
|
||||
|
||||
self.db.fetch('W/' + hash, parsePaths, function(err, paths) {
|
||||
self._getPaths(hash, function(err, paths) {
|
||||
if (err)
|
||||
return next(err);
|
||||
|
||||
@ -828,6 +880,8 @@ WalletDB.prototype.saveAddress = function saveAddress(id, addresses, callback) {
|
||||
|
||||
paths[id] = path;
|
||||
|
||||
self.pathCache.set(hash, paths);
|
||||
|
||||
batch.put('W/' + hash, serializePaths(paths));
|
||||
|
||||
next();
|
||||
@ -840,6 +894,31 @@ WalletDB.prototype.saveAddress = function saveAddress(id, addresses, callback) {
|
||||
});
|
||||
};
|
||||
|
||||
WalletDB.prototype._getPaths = function _getPaths(hash, callback) {
|
||||
var self = this;
|
||||
var paths;
|
||||
|
||||
if (!hash)
|
||||
return callback();
|
||||
|
||||
paths = this.pathCache.get(hash);
|
||||
|
||||
if (paths)
|
||||
return callback(null, paths);
|
||||
|
||||
this.db.fetch('W/' + hash, parsePaths, function(err, paths) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
if (!paths)
|
||||
return callback();
|
||||
|
||||
self.pathCache.set(hash, paths);
|
||||
|
||||
return callback(null, paths);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Test whether an address hash exists in the
|
||||
* path map and is relevant to the wallet id.
|
||||
@ -867,10 +946,7 @@ WalletDB.prototype.hasAddress = function hasAddress(id, address, callback) {
|
||||
*/
|
||||
|
||||
WalletDB.prototype.getAddress = function getAddress(address, callback) {
|
||||
if (!address)
|
||||
return callback();
|
||||
|
||||
this.db.fetch('W/' + address, parsePaths, callback);
|
||||
this._getPaths(address, callback);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -93,7 +93,7 @@ describe('HTTP', function() {
|
||||
*/
|
||||
|
||||
it('should fill with funds', function(cb) {
|
||||
var balance, receive;
|
||||
var balance, receive, tx;
|
||||
|
||||
// Coinbase
|
||||
var t1 = bcoin.mtx()
|
||||
@ -112,10 +112,13 @@ describe('HTTP', function() {
|
||||
receive = r[0];
|
||||
});
|
||||
|
||||
wallet.once('tx', function(t, map) {
|
||||
tx = t;
|
||||
});
|
||||
|
||||
node.walletdb.addTX(t1, function(err) {
|
||||
assert.ifError(err);
|
||||
setTimeout(function() {
|
||||
return cb();
|
||||
assert(receive);
|
||||
assert.equal(receive.id, 'test');
|
||||
assert.equal(receive.type, 'pubkeyhash');
|
||||
@ -124,8 +127,10 @@ describe('HTTP', function() {
|
||||
assert.equal(balance.confirmed, 0);
|
||||
assert.equal(balance.unconfirmed, 201840);
|
||||
assert.equal(balance.total, 201840);
|
||||
assert(tx);
|
||||
assert.equal(tx.hash('hex'), t1.hash('hex'));
|
||||
cb();
|
||||
}, 2000);
|
||||
}, 300);
|
||||
});
|
||||
});
|
||||
|
||||
@ -171,6 +176,24 @@ describe('HTTP', function() {
|
||||
});
|
||||
});
|
||||
|
||||
it('should generate new api key', function(cb) {
|
||||
var t = wallet.token.toString('hex');
|
||||
wallet.retoken(null, function(err, token) {
|
||||
assert.ifError(err);
|
||||
assert(token.length === 64);
|
||||
assert.notEqual(token, t);
|
||||
cb();
|
||||
});
|
||||
});
|
||||
|
||||
it('should get balance', function(cb) {
|
||||
wallet.getBalance(function(err, balance) {
|
||||
assert.ifError(err);
|
||||
assert.equal(balance.total, 199570);
|
||||
cb();
|
||||
});
|
||||
});
|
||||
|
||||
it('should cleanup', function(cb) {
|
||||
constants.tx.COINBASE_MATURITY = 100;
|
||||
node.close(cb);
|
||||
|
||||
@ -86,10 +86,10 @@ describe('Wallet', function() {
|
||||
w1.destroy();
|
||||
walletdb.get(w1.id, function(err, w1_) {
|
||||
assert.ifError(err);
|
||||
assert(w1 !== w1_);
|
||||
assert(w1.master !== w1_.master);
|
||||
// assert(w1 !== w1_);
|
||||
// assert(w1.master !== w1_.master);
|
||||
assert.equal(w1.master.key.xprivkey, w1.master.key.xprivkey);
|
||||
assert(w1.account !== w1_.account);
|
||||
// assert(w1.account !== w1_.account);
|
||||
assert.equal(w1.account.accountKey.xpubkey, w1.account.accountKey.xpubkey);
|
||||
cb();
|
||||
});
|
||||
@ -819,8 +819,8 @@ describe('Wallet', function() {
|
||||
assert.ifError(err);
|
||||
assert.equal(account.name, 'foo');
|
||||
assert.equal(account.accountIndex, 1);
|
||||
assert(account !== w1.account);
|
||||
assert(account !== acc);
|
||||
// assert(account !== w1.account);
|
||||
// assert(account !== acc);
|
||||
assert(account.accountKey.xpubkey === acc.accountKey.xpubkey);
|
||||
assert(w1.account.accountIndex === 0);
|
||||
assert(account.receiveAddress.getAddress('base58') !== w1.account.receiveAddress.getAddress('base58'));
|
||||
|
||||
Loading…
Reference in New Issue
Block a user