diff --git a/lib/hd/private.js b/lib/hd/private.js index b9632209..c1898b47 100644 --- a/lib/hd/private.js +++ b/lib/hd/private.js @@ -7,6 +7,7 @@ 'use strict'; var utils = require('../utils/utils'); +var LRU = require('../utils/lru'); var crypto = require('../crypto/crypto'); var ec = require('../crypto/ec'); var assert = require('assert'); @@ -187,11 +188,19 @@ HDPrivateKey.prototype.destroy = function destroy(pub) { * @returns {HDPrivateKey} */ -HDPrivateKey.prototype.derive = function derive(index, hardened) { +HDPrivateKey.prototype.derive = function derive(index, hardened, cache) { var p, id, data, hash, left, right, key, child; + if (hardened instanceof LRU) { + cache = hardened; + hardened = false; + } + + if (!cache) + cache = HD.cache; + if (typeof index === 'string') - return this.derivePath(index); + return this.derivePath(index, cache); hardened = index >= constants.hd.HARDENED ? true : hardened; @@ -204,11 +213,12 @@ HDPrivateKey.prototype.derive = function derive(index, hardened) { if (this.depth >= 0xff) throw new Error('Depth too high.'); - id = this.getID(index); - child = HD.cache.get(id); - - if (child) - return child; + if (cache) { + id = this.getID(index); + child = cache.get(id); + if (child) + return child; + } p = new BufferWriter(); @@ -245,7 +255,8 @@ HDPrivateKey.prototype.derive = function derive(index, hardened) { child.privateKey = key; child.publicKey = ec.publicKeyCreate(key, true); - HD.cache.set(id, child); + if (cache) + cache.set(id, child); return child; }; @@ -270,13 +281,13 @@ HDPrivateKey.prototype.getID = function getID(index) { * @throws Error if key is not a master key. */ -HDPrivateKey.prototype.deriveAccount44 = function deriveAccount44(accountIndex) { +HDPrivateKey.prototype.deriveAccount44 = function deriveAccount44(accountIndex, cache) { assert(utils.isNumber(accountIndex), 'Account index must be a number.'); assert(this.isMaster(), 'Cannot derive account index.'); return this - .derive(44, true) - .derive(this.network.keyPrefix.coinType, true) - .derive(accountIndex, true); + .derive(44, true, cache) + .derive(this.network.keyPrefix.coinType, true, cache) + .derive(accountIndex, true, cache); }; /** @@ -284,9 +295,9 @@ HDPrivateKey.prototype.deriveAccount44 = function deriveAccount44(accountIndex) * @returns {HDPrivateKey} */ -HDPrivateKey.prototype.derivePurpose45 = function derivePurpose45() { +HDPrivateKey.prototype.derivePurpose45 = function derivePurpose45(cache) { assert(this.isMaster(), 'Cannot derive purpose 45.'); - return this.derive(45, true); + return this.derive(45, true, cache); }; /** @@ -395,13 +406,13 @@ HDPrivateKey.isValidPath = function isValidPath(path) { * @throws Error if `path` is not a valid path. */ -HDPrivateKey.prototype.derivePath = function derivePath(path) { +HDPrivateKey.prototype.derivePath = function derivePath(path, cache) { var indexes = HD.parsePath(path, constants.hd.MAX_INDEX); var key = this; var i; for (i = 0; i < indexes.length; i++) - key = key.derive(indexes[i]); + key = key.derive(indexes[i], cache); return key; }; diff --git a/lib/hd/public.js b/lib/hd/public.js index 171adadb..f722f9e2 100644 --- a/lib/hd/public.js +++ b/lib/hd/public.js @@ -7,6 +7,7 @@ 'use strict'; var utils = require('../utils/utils'); +var LRU = require('../utils/lru'); var crypto = require('../crypto/crypto'); var ec = require('../crypto/ec'); var assert = require('assert'); @@ -140,11 +141,19 @@ HDPublicKey.prototype.destroy = function destroy() { * @throws on `hardened` */ -HDPublicKey.prototype.derive = function derive(index, hardened) { +HDPublicKey.prototype.derive = function derive(index, hardened, cache) { var p, id, data, hash, left, right, key, child; + if (hardened instanceof LRU) { + cache = hardened; + hardened = false; + } + + if (!cache) + cache = HD.cache; + if (typeof index === 'string') - return this.derivePath(index); + return this.derivePath(index, cache); if (index >= constants.hd.HARDENED || hardened) throw new Error('Index out of range.'); @@ -155,11 +164,12 @@ HDPublicKey.prototype.derive = function derive(index, hardened) { if (this.depth >= 0xff) throw new Error('Depth too high.'); - id = this.getID(index); - child = HD.cache.get(id); - - if (child) - return child; + if (cache) { + id = this.getID(index); + child = cache.get(id); + if (child) + return child; + } p = new BufferWriter(); p.writeBytes(this.publicKey); @@ -187,7 +197,8 @@ HDPublicKey.prototype.derive = function derive(index, hardened) { child.chainCode = right; child.publicKey = key; - HD.cache.set(id, child); + if (cache) + cache.set(id, child); return child; }; @@ -288,13 +299,13 @@ HDPublicKey.isValidPath = function isValidPath(path) { * @throws Error if hardened. */ -HDPublicKey.prototype.derivePath = function derivePath(path) { +HDPublicKey.prototype.derivePath = function derivePath(path, cache) { var indexes = HD.parsePath(path, constants.hd.HARDENED); var key = this; var i; for (i = 0; i < indexes.length; i++) - key = key.derive(indexes[i]); + key = key.derive(indexes[i], cache); return key; };