Add cache to derivation

This commit is contained in:
Esteban Ordano 2014-11-28 12:24:32 -03:00
parent 4c0769fa09
commit 53900f3196
4 changed files with 42 additions and 2 deletions

16
lib/hdkeycache.js Normal file
View File

@ -0,0 +1,16 @@
'use strict';
var cache = {};
module.exports = {
get: function(xkey, number, hardened) {
var key = xkey + '/' + number + '/' + hardened;
if (cache[key]) {
return cache[key];
}
},
set: function(xkey, number, hardened, derived) {
var key = xkey + '/' + number + '/' + hardened;
cache[key] = derived;
}
};

View File

@ -6,6 +6,7 @@ var Base58 = require('./encoding/base58');
var Base58Check = require('./encoding/base58check');
var Hash = require('./crypto/hash');
var Network = require('./networks');
var HDKeyCache = require('./hdkeycache');
var Point = require('./crypto/point');
var PrivateKey = require('./privatekey');
var Random = require('./crypto/random');
@ -59,12 +60,18 @@ HDPrivateKey.prototype.derive = function(arg, hardened) {
};
HDPrivateKey.prototype._deriveWithNumber = function(index, hardened) {
/* jshint maxstatements: 20 */
/* jshint maxcomplexity: 10 */
if (index >= HDPrivateKey.Hardened) {
hardened = true;
}
if (index < HDPrivateKey.Hardened && hardened) {
index += HDPrivateKey.Hardened;
}
var cached = HDKeyCache.get(this.xprivkey, index, hardened);
if (cached) {
return cached;
}
var indexBuffer = util.integerAsBuffer(index);
var data;
@ -79,7 +86,7 @@ HDPrivateKey.prototype._deriveWithNumber = function(index, hardened) {
var privateKey = leftPart.add(this.privateKey.toBigNumber()).mod(Point.getN()).toBuffer({size: 32});
return new HDPrivateKey({
var derived = new HDPrivateKey({
network: this.network,
depth: this.depth + 1,
parentFingerPrint: this.fingerPrint,
@ -87,6 +94,8 @@ HDPrivateKey.prototype._deriveWithNumber = function(index, hardened) {
chainCode: chainCode,
privateKey: privateKey
});
HDKeyCache.set(this.xprivkey, index, hardened, derived);
return derived;
};
HDPrivateKey.prototype._deriveFromString = function(path) {
@ -174,6 +183,7 @@ HDPrivateKey.prototype._buildFromJson = function(arg) {
};
HDPrivateKey.prototype._buildFromObject = function(arg) {
/* jshint maxcomplexity: 12 */
// TODO: Type validation
var buffers = {
version: arg.network ? util.integerAsBuffer(Network.get(arg.network).xprivkey) : arg.version,

View File

@ -6,6 +6,7 @@ var Base58 = require('./encoding/base58');
var Base58Check = require('./encoding/base58check');
var Hash = require('./crypto/hash');
var HDPrivateKey = require('./hdprivatekey');
var HDKeyCache = require('./hdkeycache');
var Network = require('./networks');
var Point = require('./crypto/point');
var PublicKey = require('./publickey');
@ -67,6 +68,10 @@ HDPublicKey.prototype._deriveWithNumber = function (index, hardened) {
if (hardened || index >= HDPublicKey.Hardened) {
throw new Error(HDPublicKey.Errors.InvalidIndexCantDeriveHardened);
}
var cached = HDKeyCache.get(this.xpubkey, index, hardened);
if (cached) {
return cached;
}
var indexBuffer = util.integerAsBuffer(index);
var data = buffer.Buffer.concat([this.publicKey.toBuffer(), indexBuffer]);
@ -76,7 +81,7 @@ HDPublicKey.prototype._deriveWithNumber = function (index, hardened) {
var publicKey = PublicKey.fromPoint(Point.getG().mul(leftPart).add(this.publicKey.point));
return new HDPublicKey({
var derived = new HDPublicKey({
network: this.network,
depth: this.depth + 1,
parentFingerPrint: this.fingerPrint,
@ -84,6 +89,8 @@ HDPublicKey.prototype._deriveWithNumber = function (index, hardened) {
chainCode: chainCode,
publicKey: publicKey
});
HDKeyCache.set(this.xpubkey, index, hardened, derived);
return derived;
};
HDPublicKey.prototype._deriveFromString = function (path) {

View File

@ -149,5 +149,12 @@ describe('HDPublicKey interface', function() {
expect(function() { return new HDPublicKey(xpubkey).derive(HDPublicKey.Hardened + 1); })
.to.throw(HDPublicKey.Errors.InvalidIndexCantDeriveHardened);
});
it('should use the cache', function() {
var pubkey = new HDPublicKey(xpubkey);
var derived1 = pubkey.derive(0);
var derived2 = pubkey.derive(0);
derived1.xpubkey.should.equal(derived2.xpubkey);
});
});
});