hd testing methods.
This commit is contained in:
parent
9ac406aa2d
commit
48f8edbe80
124
lib/bcoin/hd.js
124
lib/bcoin/hd.js
@ -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);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user