hd testing methods.

This commit is contained in:
Christopher Jeffrey 2016-05-16 12:36:52 -07:00
parent 9ac406aa2d
commit 48f8edbe80
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD

View File

@ -139,7 +139,8 @@ Mnemonic.prototype.toSeed = function toSeed() {
this.seed = utils.pbkdf2( this.seed = utils.pbkdf2(
nfkd(this.phrase), nfkd(this.phrase),
nfkd('mnemonic' + this.passphrase), nfkd('mnemonic' + this.passphrase),
2048, 64); 2048,
64);
return this.seed; return this.seed;
}; };
@ -560,34 +561,24 @@ HDPrivateKey.prototype.derive = function derive(index, hardened) {
* @throws Error if key is not a master key. * @throws Error if key is not a master key.
*/ */
HDPrivateKey.prototype.deriveAccount44 = function deriveAccount44(options) { HDPrivateKey.prototype.deriveAccount44 = function deriveAccount44(accountIndex) {
var coinType, accountIndex, child; var coinType;
if (typeof options === 'number') assert(utils.isNumber(accountIndex), 'accountIndex must be a number.');
options = { accountIndex: options };
coinType = options.coinType;
accountIndex = options.accountIndex;
if (this instanceof HDPublicKey) { if (this instanceof HDPublicKey) {
assert(this.isAccount44()); assert(this.isAccount44(accountIndex), 'Cannot derive account index.');
return this; return this;
} }
if (coinType == null) assert(this.isMaster(), 'Cannot derive account index.');
coinType = this.network === 'main' ? 0 : 1;
assert(utils.isNumber(coinType)); coinType = this.network === 'main' ? 0 : 1;
assert(utils.isNumber(accountIndex));
child = this return this
.derive(44, true) .derive(44, true)
.derive(coinType, true) .derive(coinType, true)
.derive(accountIndex, true); .derive(accountIndex, true);
assert(child.isAccount44());
return child;
}; };
/** /**
@ -599,15 +590,38 @@ HDPrivateKey.prototype.derivePurpose45 = function derivePurpose45() {
var child; var child;
if (this instanceof HDPublicKey) { if (this instanceof HDPublicKey) {
assert(this.isPurpose45()); assert(this.isPurpose45(), 'Cannot derive purpose 45.');
return this; return this;
} }
child = this.derive(45, true); assert(this.isMaster(), 'Cannot derive purpose 45.');
assert(child.isPurpose45()); return this.derive(45, true);
};
return child; /**
* Test whether the key is a master key.
* @returns {Boolean}
*/
HDPrivateKey.prototype.isMaster = function isMaster() {
return this.depth === 0
&& this.childIndex === 0
&& utils.readU32(this.parentFingerPrint, 0) === 0;
};
/**
* Test whether the key is (most likely) a BIP44 account key.
* @param {Number?} accountIndex
* @returns {Boolean}
*/
HDPrivateKey.prototype.isAccount44 = function isAccount44(accountIndex) {
if (accountIndex != null) {
if (this.childIndex !== constants.hd.HARDENED + accountIndex)
return false;
}
return this.depth === 3 && this.childIndex >= constants.hd.HARDENED;
}; };
/** /**
@ -616,20 +630,7 @@ HDPrivateKey.prototype.derivePurpose45 = function derivePurpose45() {
*/ */
HDPrivateKey.prototype.isPurpose45 = function isPurpose45() { HDPrivateKey.prototype.isPurpose45 = function isPurpose45() {
if (this.depth !== 1) return this.depth === 1 && this.childIndex === constants.hd.HARDENED + 45;
return false;
return this.childIndex === constants.hd.HARDENED + 45;
};
/**
* Test whether the key is (most likely) a BIP44 account key.
* @returns {Boolean}
*/
HDPrivateKey.prototype.isAccount44 = function isAccount44() {
if (this.childIndex < constants.hd.HARDENED)
return false;
return this.depth === 3;
}; };
/** /**
@ -662,6 +663,9 @@ HDPrivateKey.isExtended = function isExtended(data) {
*/ */
HDPrivateKey.isValidPath = function isValidPath(path) { HDPrivateKey.isValidPath = function isValidPath(path) {
if (typeof path !== 'string')
return false;
try { try {
HD.parsePath(path, constants.hd.MAX_INDEX); HD.parsePath(path, constants.hd.MAX_INDEX);
return true; return true;
@ -722,8 +726,7 @@ HDPrivateKey.parseSeed = function parseSeed(seed, network) {
parentFingerPrint: new Buffer([0, 0, 0, 0]), parentFingerPrint: new Buffer([0, 0, 0, 0]),
childIndex: 0, childIndex: 0,
chainCode: chainCode, chainCode: chainCode,
privateKey: privateKey, privateKey: privateKey
mnemonic: seed
}; };
}; };
@ -752,14 +755,19 @@ HDPrivateKey.fromMnemonic = function fromMnemonic(mnemonic, network) {
if (!(mnemonic instanceof Mnemonic)) if (!(mnemonic instanceof Mnemonic))
mnemonic = new Mnemonic(mnemonic); mnemonic = new Mnemonic(mnemonic);
if (mnemonic.seed || mnemonic.phrase || mnemonic.entropy) if (mnemonic.seed || mnemonic.phrase || mnemonic.entropy) {
return HDPrivateKey.fromSeed(mnemonic.toSeed(), network); key = HDPrivateKey.parseSeed(mnemonic.toSeed(), network);
key.mnemonic = mnemonic;
return new HDPrivateKey(key);
}
// Very unlikely, but not impossible // Very unlikely, but not impossible
// to get an invalid private key. // to get an invalid private key.
for (;;) { for (;;) {
try { try {
key = HDPrivateKey.fromSeed(mnemonic.toSeed(), network); key = HDPrivateKey.parseSeed(mnemonic.toSeed(), network);
key.mnemonic = mnemonic;
key = new HDPrivateKey(key);
} catch (e) { } catch (e) {
if (e.message === 'Master private key is invalid.') { if (e.message === 'Master private key is invalid.') {
mnemonic.seed = null; mnemonic.seed = null;
@ -896,8 +904,7 @@ HDPrivateKey.prototype.toBase58 = function toBase58(network) {
*/ */
HDPrivateKey.fromBase58 = function fromBase58(xkey) { HDPrivateKey.fromBase58 = function fromBase58(xkey) {
var data = HDPrivateKey.parseBase58(xkey); return new HDPrivateKey(HDPrivateKey.parseBase58(xkey));
return new HDPrivateKey(data);
}; };
/** /**
@ -1149,6 +1156,23 @@ HDPublicKey.prototype.deriveAccount44 = HDPrivateKey.prototype.deriveAccount44;
HDPublicKey.prototype.derivePurpose45 = HDPrivateKey.prototype.derivePurpose45; HDPublicKey.prototype.derivePurpose45 = HDPrivateKey.prototype.derivePurpose45;
/**
* Test whether the key is a master key.
* @method
* @returns {Boolean}
*/
HDPublicKey.prototype.isMaster = HDPrivateKey.prototype.isMaster;
/**
* Test whether the key is (most likely) a BIP44 account key.
* @method
* @param {Number?} accountIndex
* @returns {Boolean}
*/
HDPublicKey.prototype.isAccount44 = HDPrivateKey.prototype.isAccount44;
/** /**
* Test whether the key is a BIP45 purpose key. * Test whether the key is a BIP45 purpose key.
* @method * @method
@ -1157,14 +1181,6 @@ HDPublicKey.prototype.derivePurpose45 = HDPrivateKey.prototype.derivePurpose45;
HDPublicKey.prototype.isPurpose45 = HDPrivateKey.prototype.isPurpose45; HDPublicKey.prototype.isPurpose45 = HDPrivateKey.prototype.isPurpose45;
/**
* Test whether the key is (most likely) a BIP44 account key.
* @method
* @returns {Boolean}
*/
HDPublicKey.prototype.isAccount44 = HDPrivateKey.prototype.isAccount44;
/** /**
* Test whether a string is a valid path. * Test whether a string is a valid path.
* @param {String} path * @param {String} path
@ -1173,6 +1189,9 @@ HDPublicKey.prototype.isAccount44 = HDPrivateKey.prototype.isAccount44;
*/ */
HDPublicKey.isValidPath = function isValidPath(path) { HDPublicKey.isValidPath = function isValidPath(path) {
if (typeof path !== 'string')
return false;
try { try {
HD.parsePath(path, constants.hd.HARDENED); HD.parsePath(path, constants.hd.HARDENED);
return true; return true;
@ -1314,8 +1333,7 @@ HDPublicKey.prototype.toBase58 = function toBase58(network) {
*/ */
HDPublicKey.fromBase58 = function fromBase58(xkey) { HDPublicKey.fromBase58 = function fromBase58(xkey) {
var data = HDPublicKey.parseBase58(xkey); return new HDPublicKey(HDPublicKey.parseBase58(xkey));
return new HDPublicKey(data);
}; };
/** /**