add testing for key cache
This commit is contained in:
parent
13fd2592fc
commit
865a69f6f2
7
index.js
7
index.js
|
@ -18,11 +18,13 @@ bitcore.encoding.BufferReader = require('./lib/encoding/bufferreader');
|
|||
bitcore.encoding.BufferWriter = require('./lib/encoding/bufferwriter');
|
||||
bitcore.encoding.Varint = require('./lib/encoding/varint');
|
||||
|
||||
// utilities
|
||||
bitcore.util = {};
|
||||
bitcore.util.bitcoin = require('./lib/util/bitcoin');
|
||||
bitcore.util.buffer = require('./lib/util/buffer');
|
||||
bitcore.util.js = require('./lib/util/js');
|
||||
|
||||
// errors thrown by the library
|
||||
bitcore.errors = require('./lib/errors');
|
||||
|
||||
// main bitcoin library
|
||||
|
@ -41,7 +43,7 @@ bitcore.Txin = require('./lib/txin');
|
|||
bitcore.Txout = require('./lib/txout');
|
||||
|
||||
|
||||
//dependencies, subject to change
|
||||
// dependencies, subject to change
|
||||
bitcore.deps = {};
|
||||
bitcore.deps.bnjs = require('bn.js');
|
||||
bitcore.deps.bs58 = require('bs58');
|
||||
|
@ -53,3 +55,6 @@ bitcore.deps.elliptic = require('elliptic');
|
|||
//bitcore.txpartial = require('lib/txpartial');
|
||||
|
||||
//bitcore.bip70 = require('lib/bip70');
|
||||
|
||||
// Internal usage, exposed for testing/advanced tweaking
|
||||
bitcore._HDKeyCache = require('./lib/hdkeycache');
|
||||
|
|
|
@ -1,16 +1,45 @@
|
|||
'use strict';
|
||||
|
||||
var cache = {};
|
||||
|
||||
module.exports = {
|
||||
_cache: {},
|
||||
_count: 0,
|
||||
_eraseIndex: 0,
|
||||
_usedList: {},
|
||||
_usedIndex: {},
|
||||
_CACHE_SIZE: 5000,
|
||||
|
||||
get: function(xkey, number, hardened) {
|
||||
hardened = !!hardened;
|
||||
var key = xkey + '/' + number + '/' + hardened;
|
||||
if (cache[key]) {
|
||||
return cache[key];
|
||||
if (this._cache[key]) {
|
||||
this._cacheHit(key);
|
||||
return this._cache[key];
|
||||
}
|
||||
},
|
||||
set: function(xkey, number, hardened, derived) {
|
||||
hardened = !!hardened;
|
||||
var key = xkey + '/' + number + '/' + hardened;
|
||||
cache[key] = derived;
|
||||
this._cache[key] = derived;
|
||||
this._cacheHit(key);
|
||||
},
|
||||
_cacheHit: function(key) {
|
||||
if (this._usedIndex[key]) {
|
||||
delete this._usedList[this._usedIndex[key]];
|
||||
}
|
||||
this._usedList[this._count] = key;
|
||||
this._usedIndex[key] = this._count;
|
||||
this._count++;
|
||||
this._cacheRemove();
|
||||
},
|
||||
_cacheRemove: function() {
|
||||
while (this._eraseIndex < this._count - this._CACHE_SIZE) {
|
||||
if (this._usedList[this._eraseIndex]) {
|
||||
var removeKey = this._usedList[this._eraseIndex];
|
||||
delete this._usedIndex[removeKey];
|
||||
delete this._cache[removeKey];
|
||||
}
|
||||
delete this._usedList[this._eraseIndex];
|
||||
this._eraseIndex++;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
'use strict';
|
||||
|
||||
var _ = require('lodash');
|
||||
var expect = require('chai').expect;
|
||||
var bitcore = require('..');
|
||||
var HDPrivateKey = bitcore.HDPrivateKey;
|
||||
|
||||
var xprivkey = 'xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi';
|
||||
|
||||
describe('HDKey cache', function() {
|
||||
/* jshint unused: false */
|
||||
var cache = bitcore._HDKeyCache;
|
||||
var master = new HDPrivateKey(xprivkey);
|
||||
|
||||
beforeEach(function() {
|
||||
cache._cache = {};
|
||||
cache._count = 0;
|
||||
cache._eraseIndex = 0;
|
||||
cache._usedIndex = {};
|
||||
cache._usedList = {};
|
||||
cache._CACHE_SIZE = 3; // Reduce for quick testing
|
||||
});
|
||||
|
||||
it('saves a derived key', function() {
|
||||
var child = master.derive(0);
|
||||
expect(cache._cache[master.xprivkey + '/0/false'].xprivkey).to.equal(child.xprivkey);
|
||||
});
|
||||
it('starts erasing unused keys', function() {
|
||||
var child1 = master.derive(0);
|
||||
var child2 = child1.derive(0);
|
||||
var child3 = child2.derive(0);
|
||||
expect(cache._cache[master.xprivkey + '/0/false'].xprivkey).to.equal(child1.xprivkey);
|
||||
var child4 = child3.derive(0);
|
||||
expect(cache._cache[master.xprivkey + '/0/false']).to.equal(undefined);
|
||||
});
|
||||
it('avoids erasing keys that get cache hits ("hot keys")', function() {
|
||||
var child1 = master.derive(0);
|
||||
var child2 = master.derive(0).derive(0);
|
||||
expect(cache._cache[master.xprivkey + '/0/false'].xprivkey).to.equal(child1.xprivkey);
|
||||
var child1_copy = master.derive(0);
|
||||
expect(cache._cache[master.xprivkey + '/0/false'].xprivkey).to.equal(child1.xprivkey);
|
||||
});
|
||||
it('keeps the size of the cache small', function() {
|
||||
var child1 = master.derive(0);
|
||||
var child2 = child1.derive(0);
|
||||
var child3 = child2.derive(0);
|
||||
var child4 = child3.derive(0);
|
||||
expect(_.size(cache._cache)).to.equal(3);
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue