Merge pull request #86 from maraoz/feature/cache-BIP32
Feature/cache bip32
This commit is contained in:
commit
ae8f50793f
9 changed files with 160 additions and 74 deletions
|
|
@ -10,45 +10,57 @@ var util = bitcore.util;
|
||||||
var PublicKeyRing = require('./PublicKeyRing');
|
var PublicKeyRing = require('./PublicKeyRing');
|
||||||
|
|
||||||
function PrivateKey(opts) {
|
function PrivateKey(opts) {
|
||||||
|
opts = opts || {};
|
||||||
this.network = opts.networkName === 'testnet' ?
|
this.network = opts.networkName === 'testnet' ?
|
||||||
networks.testnet : networks.livenet;
|
networks.testnet : networks.livenet;
|
||||||
var init = opts.extendedPrivateKeyString || this.network.name;
|
var init = opts.extendedPrivateKeyString || this.network.name;
|
||||||
this.BIP32 = opts.BIP32 || new BIP32(init);
|
this.bip = opts.BIP32 || new BIP32(init);
|
||||||
|
this.privateKeyCache = opts.privateKeyCache || {};
|
||||||
this._calcId();
|
this._calcId();
|
||||||
};
|
};
|
||||||
|
|
||||||
PrivateKey.prototype._calcId = function() {
|
PrivateKey.prototype._calcId = function() {
|
||||||
this.id = util.ripe160(this.BIP32.extendedPublicKey).toString('hex');
|
this.id = util.ripe160(this.bip.extendedPublicKey).toString('hex');
|
||||||
};
|
};
|
||||||
|
|
||||||
PrivateKey.prototype.getBIP32 = function(index,isChange) {
|
PrivateKey.fromObj = function(obj) {
|
||||||
if (typeof index === 'undefined') {
|
return new PrivateKey(obj);
|
||||||
return this.BIP32;
|
|
||||||
}
|
|
||||||
return this.BIP32.derive( isChange ?
|
|
||||||
PublicKeyRing.ChangeBranch(index):PublicKeyRing.PublicBranch(index) );
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
PrivateKey.fromObj = function(o) {
|
|
||||||
return new PrivateKey({
|
|
||||||
extendedPrivateKeyString: o.extendedPrivateKeyString,
|
|
||||||
networkName: o.networkName,
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
PrivateKey.prototype.toObj = function() {
|
PrivateKey.prototype.toObj = function() {
|
||||||
return {
|
return {
|
||||||
extendedPrivateKeyString: this.BIP32.extendedPrivateKeyString(),
|
extendedPrivateKeyString: this.getExtendedPrivateKeyString(),
|
||||||
networkName: this.network.name,
|
networkName: this.network.name,
|
||||||
|
privateKeyCache: this.privateKeyCache
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
PrivateKey.prototype.getExtendedPublicKeyString = function() {
|
||||||
|
return this.bip.extendedPublicKeyString();
|
||||||
|
};
|
||||||
|
|
||||||
|
PrivateKey.prototype.getExtendedPrivateKeyString = function() {
|
||||||
|
return this.bip.extendedPrivateKeyString();
|
||||||
|
};
|
||||||
|
|
||||||
|
PrivateKey.prototype._getBIP32 = function(path) {
|
||||||
|
if (typeof path === 'undefined') {
|
||||||
|
return this.bip;
|
||||||
|
}
|
||||||
|
return this.bip.derive(path);
|
||||||
|
};
|
||||||
|
|
||||||
PrivateKey.prototype.get = function(index,isChange) {
|
PrivateKey.prototype.get = function(index,isChange) {
|
||||||
var derivedBIP32 = this.getBIP32(index,isChange);
|
var path = PublicKeyRing.Branch(index, isChange);
|
||||||
|
var pk = this.privateKeyCache[path];
|
||||||
|
if (!pk) {
|
||||||
|
var derivedBIP32 = this._getBIP32(path);
|
||||||
|
pk = this.privateKeyCache[path] = derivedBIP32.eckey.private.toString('hex');
|
||||||
|
} else {
|
||||||
|
//console.log('cache hit!');
|
||||||
|
}
|
||||||
var wk = new WalletKey({network: this.network});
|
var wk = new WalletKey({network: this.network});
|
||||||
var p = derivedBIP32.eckey.private.toString('hex');
|
wk.fromObj({priv: pk});
|
||||||
wk.fromObj({priv: p});
|
|
||||||
return wk;
|
return wk;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,10 +25,12 @@ function PublicKeyRing(opts) {
|
||||||
this.requiredCopayers = opts.requiredCopayers || 3;
|
this.requiredCopayers = opts.requiredCopayers || 3;
|
||||||
this.totalCopayers = opts.totalCopayers || 5;
|
this.totalCopayers = opts.totalCopayers || 5;
|
||||||
|
|
||||||
this.copayersBIP32 = [];
|
this.copayersBIP32 = opts.copayersBIP32 || [];
|
||||||
|
|
||||||
this.changeAddressIndex=0;
|
this.changeAddressIndex= opts.changeAddressIndex || 0;
|
||||||
this.addressIndex=0;
|
this.addressIndex= opts.addressIndex || 0;
|
||||||
|
|
||||||
|
this.publicKeysCache = opts.publicKeysCache || {};
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -40,33 +42,18 @@ function PublicKeyRing(opts) {
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
PublicKeyRing.PublicBranch = function (index) {
|
PublicKeyRing.Branch = function (index, isChange) {
|
||||||
return 'm/0/'+index;
|
return 'm/'+(isChange?1:0)+'/'+index;
|
||||||
};
|
|
||||||
|
|
||||||
PublicKeyRing.ChangeBranch = function (index) {
|
|
||||||
return 'm/1/'+index;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
PublicKeyRing.fromObj = function (data) {
|
PublicKeyRing.fromObj = function (data) {
|
||||||
if (!data.ts) {
|
if (data instanceof PublicKeyRing) {
|
||||||
throw new Error('bad data format: Did you use .toObj()?');
|
throw new Error('bad data format: Did you use .toObj()?');
|
||||||
}
|
}
|
||||||
var config = { networkName: data.networkName || 'livenet' };
|
data.copayersBIP32 = data.copayersExtPubKeys.map(function(pk) {
|
||||||
|
|
||||||
var w = new PublicKeyRing(config);
|
|
||||||
|
|
||||||
w.walletId = data.walletId;
|
|
||||||
w.requiredCopayers = data.requiredCopayers;
|
|
||||||
w.totalCopayers = data.totalCopayers;
|
|
||||||
w.addressIndex = data.addressIndex;
|
|
||||||
w.changeAddressIndex = data.changeAddressIndex;
|
|
||||||
w.copayersBIP32 = data.copayersExtPubKeys.map( function (pk) {
|
|
||||||
return new BIP32(pk);
|
return new BIP32(pk);
|
||||||
});
|
});
|
||||||
|
return new PublicKeyRing(data);
|
||||||
w.ts = data.ts;
|
|
||||||
return w;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
PublicKeyRing.prototype.toObj = function() {
|
PublicKeyRing.prototype.toObj = function() {
|
||||||
|
|
@ -81,7 +68,7 @@ PublicKeyRing.prototype.toObj = function() {
|
||||||
copayersExtPubKeys: this.copayersBIP32.map( function (b) {
|
copayersExtPubKeys: this.copayersBIP32.map( function (b) {
|
||||||
return b.extendedPublicKeyString();
|
return b.extendedPublicKeyString();
|
||||||
}),
|
}),
|
||||||
ts: parseInt(Date.now() / 1000),
|
publicKeysCache: this.publicKeysCache
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -95,7 +82,6 @@ PublicKeyRing.prototype.registeredCopayers = function () {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
PublicKeyRing.prototype.isComplete = function () {
|
PublicKeyRing.prototype.isComplete = function () {
|
||||||
return this.registeredCopayers() >= this.totalCopayers;
|
return this.registeredCopayers() >= this.totalCopayers;
|
||||||
};
|
};
|
||||||
|
|
@ -134,12 +120,19 @@ PublicKeyRing.prototype.addCopayer = function (newEpk) {
|
||||||
PublicKeyRing.prototype.getPubKeys = function (index, isChange) {
|
PublicKeyRing.prototype.getPubKeys = function (index, isChange) {
|
||||||
this._checkKeys();
|
this._checkKeys();
|
||||||
|
|
||||||
var pubKeys = [];
|
var path = PublicKeyRing.Branch(index, isChange);
|
||||||
var l = this.copayersBIP32.length;
|
var pubKeys = this.publicKeysCache[path];
|
||||||
for(var i=0; i<l; i++) {
|
if (!pubKeys) {
|
||||||
var path = isChange ? PublicKeyRing.ChangeBranch(index) : PublicKeyRing.PublicBranch(index);
|
pubKeys = [];
|
||||||
var bip32 = this.copayersBIP32[i].derive(path);
|
var l = this.copayersBIP32.length;
|
||||||
pubKeys[i] = bip32.eckey.public;
|
for(var i=0; i<l; i++) {
|
||||||
|
var bip32 = this.copayersBIP32[i].derive(path);
|
||||||
|
pubKeys[i] = bip32.eckey.public;
|
||||||
|
}
|
||||||
|
this.publicKeysCache[path] = pubKeys;
|
||||||
|
//console.log('cache fill['+path+']='+pubKeys.length);
|
||||||
|
} else {
|
||||||
|
//console.log('cache hit!');
|
||||||
}
|
}
|
||||||
|
|
||||||
return pubKeys;
|
return pubKeys;
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,7 @@ WalletFactory.prototype.read = function(walletId) {
|
||||||
// JIC: Add our key
|
// JIC: Add our key
|
||||||
try {
|
try {
|
||||||
w.publicKeyRing.addCopayer(
|
w.publicKeyRing.addCopayer(
|
||||||
w.privateKey.getBIP32().extendedPublicKeyString()
|
w.privateKey.getExtendedPublicKeyString()
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.log('NOT NECCESARY AN ERROR:', e); //TODO
|
this.log('NOT NECCESARY AN ERROR:', e); //TODO
|
||||||
|
|
@ -94,7 +94,7 @@ WalletFactory.prototype.create = function(opts) {
|
||||||
requiredCopayers: requiredCopayers,
|
requiredCopayers: requiredCopayers,
|
||||||
totalCopayers: totalCopayers,
|
totalCopayers: totalCopayers,
|
||||||
});
|
});
|
||||||
opts.publicKeyRing.addCopayer(opts.privateKey.getBIP32().extendedPublicKeyString());
|
opts.publicKeyRing.addCopayer(opts.privateKey.getExtendedPublicKeyString());
|
||||||
this.log('\t### PublicKeyRing Initialized');
|
this.log('\t### PublicKeyRing Initialized');
|
||||||
|
|
||||||
opts.txProposals = opts.txProposals || new TxProposals({
|
opts.txProposals = opts.txProposals || new TxProposals({
|
||||||
|
|
@ -110,7 +110,7 @@ WalletFactory.prototype.create = function(opts) {
|
||||||
opts.spendUnconfirmed = opts.spendUnconfirmed || this.walletDefaults.spendUnconfirmed;
|
opts.spendUnconfirmed = opts.spendUnconfirmed || this.walletDefaults.spendUnconfirmed;
|
||||||
opts.requiredCopayers = requiredCopayers;
|
opts.requiredCopayers = requiredCopayers;
|
||||||
opts.totalCopayers = totalCopayers;
|
opts.totalCopayers = totalCopayers;
|
||||||
var w = new Wallet(opts);
|
var w = new Wallet(opts);
|
||||||
w.store();
|
w.store();
|
||||||
return w;
|
return w;
|
||||||
};
|
};
|
||||||
|
|
@ -139,7 +139,7 @@ WalletFactory.prototype.openRemote = function(peedId) {
|
||||||
requiredCopayers: requiredCopayers,
|
requiredCopayers: requiredCopayers,
|
||||||
totalCopayers: totalCopayers,
|
totalCopayers: totalCopayers,
|
||||||
});
|
});
|
||||||
opts.publicKeyRing.addCopayer(opts.privateKey.getBIP32().extendedPublicKeyString());
|
opts.publicKeyRing.addCopayer(opts.privateKey.getExtendedPublicKeyString());
|
||||||
this.log('\t### PublicKeyRing Initialized');
|
this.log('\t### PublicKeyRing Initialized');
|
||||||
|
|
||||||
opts.txProposals = opts.txProposals || new TxProposals({
|
opts.txProposals = opts.txProposals || new TxProposals({
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
</script>
|
</script>
|
||||||
<script src="test.API.js"></script>
|
<script src="test.API.js"></script>
|
||||||
<script src="test.blockchain.Insight.js"></script>
|
<script src="test.blockchain.Insight.js"></script>
|
||||||
|
<script src="test.performance.js"></script>
|
||||||
<script src="test.PrivateKey.js"></script>
|
<script src="test.PrivateKey.js"></script>
|
||||||
<script src="test.PublicKeyRing.js"></script>
|
<script src="test.PublicKeyRing.js"></script>
|
||||||
<script src="test.storage.LocalPlain.js"></script>
|
<script src="test.storage.LocalPlain.js"></script>
|
||||||
|
|
|
||||||
|
|
@ -24,8 +24,8 @@ describe('PrivateKey model', function() {
|
||||||
it('should create an instance', function () {
|
it('should create an instance', function () {
|
||||||
var w = new PrivateKey(config);
|
var w = new PrivateKey(config);
|
||||||
should.exist(w);
|
should.exist(w);
|
||||||
should.exist(w.BIP32);
|
should.exist(w.bip);
|
||||||
should.exist(w.BIP32.derive);
|
should.exist(w.bip.derive);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should derive priv keys', function () {
|
it('should derive priv keys', function () {
|
||||||
|
|
@ -76,15 +76,14 @@ describe('PrivateKey model', function() {
|
||||||
var w1 = new PrivateKey(config);
|
var w1 = new PrivateKey(config);
|
||||||
var w2 = PrivateKey.fromObj(w1.toObj());
|
var w2 = PrivateKey.fromObj(w1.toObj());
|
||||||
|
|
||||||
w2.getBIP32().extendedPrivateKeyString().should.equal(w1.getBIP32().extendedPrivateKeyString());
|
w2.toObj().extendedPrivateKeyString.should.equal(w1.toObj().extendedPrivateKeyString);
|
||||||
w2.getBIP32().extendedPublicKeyString().should.equal(w1.getBIP32().extendedPublicKeyString());
|
|
||||||
w2.id.should.equal(w1.id);
|
w2.id.should.equal(w1.id);
|
||||||
|
|
||||||
|
|
||||||
w2.getBIP32(1,1).extendedPrivateKeyString().should
|
JSON.stringify(w2.get(1,1).storeObj()).should
|
||||||
.equal(w1.getBIP32(1,1).extendedPrivateKeyString());
|
.equal(JSON.stringify(w1.get(1,1).storeObj()));
|
||||||
w2.getBIP32(1,0).extendedPrivateKeyString().should
|
JSON.stringify(w2.get(1,0).storeObj()).should
|
||||||
.equal(w1.getBIP32(1,0).extendedPrivateKeyString());
|
.equal(JSON.stringify(w1.get(1,0).storeObj()));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ var createPKR = function (bip32s) {
|
||||||
for(var i=0; i<5; i++) {
|
for(var i=0; i<5; i++) {
|
||||||
if (bip32s) {
|
if (bip32s) {
|
||||||
var b=bip32s[i];
|
var b=bip32s[i];
|
||||||
w.addCopayer(b?b.extendedPublicKeyString():null);
|
w.addCopayer(b?b.getExtendedPublicKeyString():null);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
w.addCopayer();
|
w.addCopayer();
|
||||||
|
|
@ -110,7 +110,7 @@ describe('TxProposals model', function() {
|
||||||
networkName: config.networkName,
|
networkName: config.networkName,
|
||||||
});
|
});
|
||||||
var start = new Date().getTime();
|
var start = new Date().getTime();
|
||||||
var pkr=createPKR([priv.getBIP32()]);
|
var pkr=createPKR([priv]);
|
||||||
var ts = Date.now();
|
var ts = Date.now();
|
||||||
var isChange=0;
|
var isChange=0;
|
||||||
var index=0;
|
var index=0;
|
||||||
|
|
@ -150,7 +150,7 @@ describe('TxProposals model', function() {
|
||||||
var ts = Date.now();
|
var ts = Date.now();
|
||||||
var isChange=0;
|
var isChange=0;
|
||||||
var index=0;
|
var index=0;
|
||||||
var pkr = createPKR([priv.getBIP32()]);
|
var pkr = createPKR([priv]);
|
||||||
var opts = {remainderOut: { address: pkr.generateAddress(true).toString() }};
|
var opts = {remainderOut: { address: pkr.generateAddress(true).toString() }};
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -225,7 +225,7 @@ var _dumpChunks = function (scriptSig, label) {
|
||||||
var ts = Date.now();
|
var ts = Date.now();
|
||||||
var isChange=0;
|
var isChange=0;
|
||||||
var index=0;
|
var index=0;
|
||||||
var pkr = createPKR([priv.getBIP32(), priv2.getBIP32()]);
|
var pkr = createPKR([priv, priv2]);
|
||||||
var opts = {remainderOut: { address: pkr.generateAddress(true).toString() }};
|
var opts = {remainderOut: { address: pkr.generateAddress(true).toString() }};
|
||||||
|
|
||||||
var w = new TxProposals({
|
var w = new TxProposals({
|
||||||
|
|
@ -325,7 +325,7 @@ var _dumpChunks = function (scriptSig, label) {
|
||||||
var ts = Date.now();
|
var ts = Date.now();
|
||||||
var isChange=0;
|
var isChange=0;
|
||||||
var index=0;
|
var index=0;
|
||||||
var pkr = createPKR([priv.getBIP32(), priv2.getBIP32(), priv3.getBIP32() ]);
|
var pkr = createPKR([priv, priv2, priv3]);
|
||||||
var opts = {remainderOut: { address: pkr.generateAddress(true).toString() }};
|
var opts = {remainderOut: { address: pkr.generateAddress(true).toString() }};
|
||||||
|
|
||||||
var w = new TxProposals({
|
var w = new TxProposals({
|
||||||
|
|
@ -416,7 +416,7 @@ var _dumpChunks = function (scriptSig, label) {
|
||||||
it('#toObj #fromObj roundtrip', function () {
|
it('#toObj #fromObj roundtrip', function () {
|
||||||
|
|
||||||
var priv = new PrivateKey(config);
|
var priv = new PrivateKey(config);
|
||||||
var pkr = createPKR([priv.getBIP32()]);
|
var pkr = createPKR([priv]);
|
||||||
var w = new TxProposals({
|
var w = new TxProposals({
|
||||||
walletId: 'qwerty',
|
walletId: 'qwerty',
|
||||||
networkName: config.networkName,
|
networkName: config.networkName,
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ describe('Wallet model', function() {
|
||||||
requiredCopayers: c.requiredCopayers,
|
requiredCopayers: c.requiredCopayers,
|
||||||
totalCopayers: c.totalCopayers,
|
totalCopayers: c.totalCopayers,
|
||||||
});
|
});
|
||||||
c.publicKeyRing.addCopayer(c.privateKey.getBIP32().extendedPublicKeyString());
|
c.publicKeyRing.addCopayer(c.privateKey.getExtendedPublicKeyString());
|
||||||
|
|
||||||
c.txProposals = new copay.TxProposals({
|
c.txProposals = new copay.TxProposals({
|
||||||
networkName: c.networkName,
|
networkName: c.networkName,
|
||||||
|
|
@ -87,16 +87,16 @@ describe('Wallet model', function() {
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
var createW2 = function (bip32s) {
|
var createW2 = function (privateKeys) {
|
||||||
var w = createW();
|
var w = createW();
|
||||||
should.exist(w);
|
should.exist(w);
|
||||||
|
|
||||||
var pkr = w.publicKeyRing;
|
var pkr = w.publicKeyRing;
|
||||||
|
|
||||||
for(var i=0; i<4; i++) {
|
for(var i=0; i<4; i++) {
|
||||||
if (bip32s) {
|
if (privateKeys) {
|
||||||
var b=bip32s[i];
|
var k=privateKeys[i];
|
||||||
pkr.addCopayer(b?b.extendedPublicKeyString():null);
|
pkr.addCopayer(k?k.getExtendedPublicKeyString():null);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
pkr.addCopayer();
|
pkr.addCopayer();
|
||||||
|
|
|
||||||
69
test/test.performance.js
Normal file
69
test/test.performance.js
Normal file
|
|
@ -0,0 +1,69 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var chai = chai || require('chai');
|
||||||
|
var should = chai.should();
|
||||||
|
var PrivateKey = require('../js/models/core/PrivateKey');
|
||||||
|
var PublicKeyRing = require('../js/models/core/PublicKeyRing');
|
||||||
|
|
||||||
|
describe('Performance tests', function() {
|
||||||
|
describe('PrivateKey', function() {
|
||||||
|
it('should optimize BIP32 private key gen time with cache', function() {
|
||||||
|
var k1 = new PrivateKey();
|
||||||
|
var generateN = 25;
|
||||||
|
var generated = [];
|
||||||
|
var start1 = new Date().getTime();
|
||||||
|
for (var i = 0; i < generateN; i++) {
|
||||||
|
var k = JSON.stringify(k1.get(i, false).storeObj());
|
||||||
|
generated.push(k);
|
||||||
|
}
|
||||||
|
var delta1 = new Date().getTime() - start1;
|
||||||
|
var backup = k1.toObj();
|
||||||
|
var k2 = PrivateKey.fromObj(backup);
|
||||||
|
var start2 = new Date().getTime();
|
||||||
|
for (var i = 0; i < generateN; i++) {
|
||||||
|
var k = JSON.stringify(k2.get(i, false).storeObj());
|
||||||
|
generated[i].should.equal(k);
|
||||||
|
}
|
||||||
|
var delta2 = new Date().getTime() - start2;
|
||||||
|
delta2.should.be.below(delta1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe('PublicKeyRing', function() {
|
||||||
|
var maxN = 7;
|
||||||
|
for (var n = 1; n < maxN; n++) {
|
||||||
|
for (var m = 1; m <= n; m++) {
|
||||||
|
var M = m;
|
||||||
|
var N = n;
|
||||||
|
(function(M, N) {
|
||||||
|
it('should optimize BIP32 publickey gen time with cache for ' + M + '-of-' + N, function() {
|
||||||
|
var pkr1 = new PublicKeyRing({
|
||||||
|
totalCopayers: N,
|
||||||
|
requiredCopayers: M
|
||||||
|
});
|
||||||
|
for (var i = 0; i < N; i++) {
|
||||||
|
pkr1.addCopayer(); // add new random ext public key
|
||||||
|
}
|
||||||
|
var generateN = 5;
|
||||||
|
var generated = [];
|
||||||
|
var start1 = new Date().getTime();
|
||||||
|
for (var i = 0; i < generateN; i++) {
|
||||||
|
var pubKeys = JSON.stringify(pkr1.getPubKeys(i, false));
|
||||||
|
generated.push(pubKeys);
|
||||||
|
}
|
||||||
|
var delta1 = new Date().getTime() - start1;
|
||||||
|
var backup = pkr1.toObj();
|
||||||
|
var pkr2 = PublicKeyRing.fromObj(backup);
|
||||||
|
var start2 = new Date().getTime();
|
||||||
|
for (var i = 0; i < generateN; i++) {
|
||||||
|
var pubKeys = JSON.stringify(pkr2.getPubKeys(i, false));
|
||||||
|
generated[i].should.equal(pubKeys);
|
||||||
|
}
|
||||||
|
var delta2 = new Date().getTime() - start2;
|
||||||
|
delta2.should.be.below(delta1);
|
||||||
|
});
|
||||||
|
})(M, N);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
@ -50,6 +50,18 @@ var createBundle = function(opts) {
|
||||||
b.require('./test/mocks/FakeStorage', {
|
b.require('./test/mocks/FakeStorage', {
|
||||||
expose: './mocks/FakeStorage'
|
expose: './mocks/FakeStorage'
|
||||||
});
|
});
|
||||||
|
b.require('./js/models/network/WebRTC', {
|
||||||
|
expose: '../js/models/network/WebRTC'
|
||||||
|
});
|
||||||
|
b.require('./js/models/blockchain/Insight', {
|
||||||
|
expose: '../js/models/blockchain/Insight'
|
||||||
|
});
|
||||||
|
b.require('./js/models/core/PrivateKey', {
|
||||||
|
expose: '../js/models/core/PrivateKey'
|
||||||
|
});
|
||||||
|
b.require('./js/models/core/PublicKeyRing', {
|
||||||
|
expose: '../js/models/core/PublicKeyRing'
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
if (!opts.dontminify) {
|
if (!opts.dontminify) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue