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