100% test coverage on hdpublickey
This commit is contained in:
parent
edc5b24d69
commit
4c0769fa09
|
@ -9,16 +9,11 @@ var HDPrivateKey = require('./hdprivatekey');
|
||||||
var Network = require('./networks');
|
var Network = require('./networks');
|
||||||
var Point = require('./crypto/point');
|
var Point = require('./crypto/point');
|
||||||
var PublicKey = require('./publickey');
|
var PublicKey = require('./publickey');
|
||||||
var Random = require('./crypto/random');
|
|
||||||
|
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
var buffer = require('buffer');
|
var buffer = require('buffer');
|
||||||
var util = require('./util');
|
var util = require('./util');
|
||||||
|
|
||||||
var MINIMUM_ENTROPY_BITS = 128;
|
|
||||||
var BITS_TO_BYTES = 1/8;
|
|
||||||
var MAXIMUM_ENTROPY_BITS = 512;
|
|
||||||
|
|
||||||
|
|
||||||
function HDPublicKey(arg) {
|
function HDPublicKey(arg) {
|
||||||
/* jshint maxcomplexity: 12 */
|
/* jshint maxcomplexity: 12 */
|
||||||
|
@ -32,7 +27,9 @@ function HDPublicKey(arg) {
|
||||||
if (arg) {
|
if (arg) {
|
||||||
if (_.isString(arg) || buffer.Buffer.isBuffer(arg)) {
|
if (_.isString(arg) || buffer.Buffer.isBuffer(arg)) {
|
||||||
if (HDPublicKey.isValidSerialized(arg)) {
|
if (HDPublicKey.isValidSerialized(arg)) {
|
||||||
this._buildFromSerialized(arg);
|
return this._buildFromSerialized(arg);
|
||||||
|
} else if (util.isValidJson(arg)) {
|
||||||
|
return this._buildFromJson(arg);
|
||||||
} else {
|
} else {
|
||||||
var error = HDPublicKey.getSerializedError(arg);
|
var error = HDPublicKey.getSerializedError(arg);
|
||||||
if (error === HDPublicKey.Errors.ArgumentIsPrivateExtended) {
|
if (error === HDPublicKey.Errors.ArgumentIsPrivateExtended) {
|
||||||
|
@ -43,18 +40,16 @@ function HDPublicKey(arg) {
|
||||||
} else {
|
} else {
|
||||||
if (_.isObject(arg)) {
|
if (_.isObject(arg)) {
|
||||||
if (arg instanceof HDPrivateKey) {
|
if (arg instanceof HDPrivateKey) {
|
||||||
this._buildFromPrivate(arg);
|
return this._buildFromPrivate(arg);
|
||||||
} else {
|
} else {
|
||||||
this._buildFromObject(arg);
|
return this._buildFromObject(arg);
|
||||||
}
|
}
|
||||||
} else if (util.isValidJson(arg)) {
|
|
||||||
this._buildFromJson(arg);
|
|
||||||
} else {
|
} else {
|
||||||
throw new Error(HDPublicKey.Errors.UnrecognizedArgument);
|
throw new Error(HDPublicKey.Errors.UnrecognizedArgument);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this._generateRandomly();
|
throw new Error(HDPublicKey.Errors.MustSupplyArgument);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,7 +132,7 @@ HDPublicKey.isValidSerialized = function (data, network) {
|
||||||
*/
|
*/
|
||||||
HDPublicKey.getSerializedError = function (data, network) {
|
HDPublicKey.getSerializedError = function (data, network) {
|
||||||
/* jshint maxcomplexity: 10 */
|
/* jshint maxcomplexity: 10 */
|
||||||
network = Network.get(network) || Network.defaultNetwork;
|
/* jshint maxstatements: 20 */
|
||||||
if (!(_.isString(data) || buffer.Buffer.isBuffer(data))) {
|
if (!(_.isString(data) || buffer.Buffer.isBuffer(data))) {
|
||||||
return HDPublicKey.Errors.InvalidArgument;
|
return HDPublicKey.Errors.InvalidArgument;
|
||||||
}
|
}
|
||||||
|
@ -152,15 +147,16 @@ HDPublicKey.getSerializedError = function (data, network) {
|
||||||
if (data.length !== 78) {
|
if (data.length !== 78) {
|
||||||
return HDPublicKey.Errors.InvalidLength;
|
return HDPublicKey.Errors.InvalidLength;
|
||||||
}
|
}
|
||||||
if (util.integerFromBuffer(data.slice(0, 4)) === network.xprivkey) {
|
|
||||||
return HDPublicKey.Errors.ArgumentIsPrivateExtended;
|
|
||||||
}
|
|
||||||
if (!_.isUndefined(network)) {
|
if (!_.isUndefined(network)) {
|
||||||
var error = HDPublicKey._validateNetwork(data, network);
|
var error = HDPublicKey._validateNetwork(data, network);
|
||||||
if (error) {
|
if (error) {
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
network = Network.get(network) || Network.defaultNetwork;
|
||||||
|
if (util.integerFromBuffer(data.slice(0, 4)) === network.xprivkey) {
|
||||||
|
return HDPublicKey.Errors.ArgumentIsPrivateExtended;
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -192,17 +188,17 @@ HDPublicKey.prototype._buildFromPrivate = function (arg) {
|
||||||
};
|
};
|
||||||
|
|
||||||
HDPublicKey.prototype._buildFromObject = function (arg) {
|
HDPublicKey.prototype._buildFromObject = function (arg) {
|
||||||
/* jshint maxcomplexity: 8 */
|
/* jshint maxcomplexity: 10 */
|
||||||
// TODO: Type validation
|
// TODO: Type validation
|
||||||
var buffers = {
|
var buffers = {
|
||||||
version: util.integerAsBuffer(Network.get(arg.network).xpubkey),
|
version: arg.network ? util.integerAsBuffer(Network.get(arg.network).xpubkey) : arg.version,
|
||||||
depth: util.integerAsSingleByteBuffer(arg.depth),
|
depth: util.integerAsSingleByteBuffer(arg.depth),
|
||||||
parentFingerPrint: _.isNumber(arg.parentFingerPrint) ? util.integerAsBuffer(arg.parentFingerPrint) : arg.parentFingerPrint,
|
parentFingerPrint: _.isNumber(arg.parentFingerPrint) ? util.integerAsBuffer(arg.parentFingerPrint) : arg.parentFingerPrint,
|
||||||
childIndex: util.integerAsBuffer(arg.childIndex),
|
childIndex: util.integerAsBuffer(arg.childIndex),
|
||||||
chainCode: _.isString(arg.chainCode) ? util.hexToBuffer(arg.chainCode) : arg.chainCode,
|
chainCode: _.isString(arg.chainCode) ? util.hexToBuffer(arg.chainCode) : arg.chainCode,
|
||||||
publicKey: _.isString(arg.publicKey) ? util.hexToBuffer(arg.publicKey) :
|
publicKey: _.isString(arg.publicKey) ? util.hexToBuffer(arg.publicKey) :
|
||||||
buffer.Buffer.isBuffer(arg.publicKey) ? arg.publicKey : arg.publicKey.toBuffer(),
|
buffer.Buffer.isBuffer(arg.publicKey) ? arg.publicKey : arg.publicKey.toBuffer(),
|
||||||
checksum: arg.checksum && arg.checksum.length ? util.integerAsBuffer(arg.checksum) : undefined
|
checksum: _.isNumber(arg.checksum) ? util.integerAsBuffer(arg.checksum) : arg.checksum
|
||||||
};
|
};
|
||||||
return this._buildFromBuffers(buffers);
|
return this._buildFromBuffers(buffers);
|
||||||
};
|
};
|
||||||
|
@ -223,37 +219,6 @@ HDPublicKey.prototype._buildFromSerialized = function (arg) {
|
||||||
return this._buildFromBuffers(buffers);
|
return this._buildFromBuffers(buffers);
|
||||||
};
|
};
|
||||||
|
|
||||||
HDPublicKey.prototype._generateRandomly = function (network) {
|
|
||||||
return HDPublicKey.fromSeed(Random.getRandomBytes(64), network);
|
|
||||||
};
|
|
||||||
|
|
||||||
HDPublicKey.fromSeed = function (hexa, network) {
|
|
||||||
/* jshint maxcomplexity: 8 */
|
|
||||||
|
|
||||||
if (util.isHexaString(hexa)) {
|
|
||||||
hexa = util.hexToBuffer(hexa);
|
|
||||||
}
|
|
||||||
if (!Buffer.isBuffer(hexa)) {
|
|
||||||
throw new Error(HDPublicKey.InvalidEntropyArg);
|
|
||||||
}
|
|
||||||
if (hexa.length < MINIMUM_ENTROPY_BITS * BITS_TO_BYTES) {
|
|
||||||
throw new Error(HDPublicKey.NotEnoughEntropy);
|
|
||||||
}
|
|
||||||
if (hexa.length > MAXIMUM_ENTROPY_BITS * BITS_TO_BYTES) {
|
|
||||||
throw new Error('More than 512 bytes of entropy is nonstandard');
|
|
||||||
}
|
|
||||||
var hash = Hash.sha512hmac(hexa, new buffer.Buffer('Bitcoin seed'));
|
|
||||||
|
|
||||||
return new HDPublicKey({
|
|
||||||
network: Network.get(network) || Network.livenet,
|
|
||||||
depth: 0,
|
|
||||||
parentFingerPrint: 0,
|
|
||||||
childIndex: 0,
|
|
||||||
publicKey: hash.slice(0, 32),
|
|
||||||
chainCode: hash.slice(32, 64)
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Receives a object with buffers in all the properties and populates the
|
* Receives a object with buffers in all the properties and populates the
|
||||||
* internal structure
|
* internal structure
|
||||||
|
@ -272,6 +237,7 @@ HDPublicKey.fromSeed = function (hexa, network) {
|
||||||
*/
|
*/
|
||||||
HDPublicKey.prototype._buildFromBuffers = function (arg) {
|
HDPublicKey.prototype._buildFromBuffers = function (arg) {
|
||||||
/* jshint maxcomplexity: 8 */
|
/* jshint maxcomplexity: 8 */
|
||||||
|
/* jshint maxstatements: 20 */
|
||||||
|
|
||||||
HDPublicKey._validateBufferArguments(arg);
|
HDPublicKey._validateBufferArguments(arg);
|
||||||
this._buffers = arg;
|
this._buffers = arg;
|
||||||
|
@ -280,10 +246,12 @@ HDPublicKey.prototype._buildFromBuffers = function (arg) {
|
||||||
arg.version, arg.depth, arg.parentFingerPrint, arg.childIndex, arg.chainCode,
|
arg.version, arg.depth, arg.parentFingerPrint, arg.childIndex, arg.chainCode,
|
||||||
arg.publicKey
|
arg.publicKey
|
||||||
];
|
];
|
||||||
|
var concat = buffer.Buffer.concat(sequence);
|
||||||
|
var checksum = Base58Check.checksum(concat);
|
||||||
if (!arg.checksum || !arg.checksum.length) {
|
if (!arg.checksum || !arg.checksum.length) {
|
||||||
arg.checksum = Base58Check.checksum(buffer.Buffer.concat(sequence));
|
arg.checksum = checksum;
|
||||||
} else {
|
} else {
|
||||||
if (arg.checksum.toString() !== sequence.toString()) {
|
if (arg.checksum.toString('hex') !== checksum.toString('hex')) {
|
||||||
throw new Error(HDPublicKey.Errors.InvalidB58Checksum);
|
throw new Error(HDPublicKey.Errors.InvalidB58Checksum);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -328,7 +296,7 @@ HDPublicKey.prototype.toString = function () {
|
||||||
|
|
||||||
HDPublicKey.prototype.toObject = function () {
|
HDPublicKey.prototype.toObject = function () {
|
||||||
return {
|
return {
|
||||||
network: Network.get(util.integerFromBuffer(this._buffers.version)),
|
network: Network.get(util.integerFromBuffer(this._buffers.version)).name,
|
||||||
depth: util.integerFromSingleByteBuffer(this._buffers.depth),
|
depth: util.integerFromSingleByteBuffer(this._buffers.depth),
|
||||||
fingerPrint: util.integerFromBuffer(this.fingerPrint),
|
fingerPrint: util.integerFromBuffer(this.fingerPrint),
|
||||||
parentFingerPrint: util.integerFromBuffer(this._buffers.parentFingerPrint),
|
parentFingerPrint: util.integerFromBuffer(this._buffers.parentFingerPrint),
|
||||||
|
@ -344,12 +312,8 @@ HDPublicKey.prototype.toJson = function () {
|
||||||
return JSON.stringify(this.toObject());
|
return JSON.stringify(this.toObject());
|
||||||
};
|
};
|
||||||
|
|
||||||
HDPublicKey.DefaultDepth = 0;
|
|
||||||
HDPublicKey.DefaultFingerprint = 0;
|
|
||||||
HDPublicKey.DefaultChildIndex = 0;
|
|
||||||
HDPublicKey.DefaultNetwork = Network.livenet;
|
|
||||||
HDPublicKey.Hardened = 0x80000000;
|
HDPublicKey.Hardened = 0x80000000;
|
||||||
HDPublicKey.RootElementAlias = ['m', 'M', 'm\'', 'M\''];
|
HDPublicKey.RootElementAlias = ['m', 'M'];
|
||||||
|
|
||||||
HDPublicKey.VersionSize = 4;
|
HDPublicKey.VersionSize = 4;
|
||||||
HDPublicKey.DepthSize = 1;
|
HDPublicKey.DepthSize = 1;
|
||||||
|
@ -393,6 +357,7 @@ HDPublicKey.Errors.InvalidNetwork = 'Unexpected version for network';
|
||||||
HDPublicKey.Errors.InvalidNetworkArgument = 'Network argument must be \'livenet\' or \'testnet\'';
|
HDPublicKey.Errors.InvalidNetworkArgument = 'Network argument must be \'livenet\' or \'testnet\'';
|
||||||
HDPublicKey.Errors.InvalidParentFingerPrint = 'Invalid Parent Fingerprint - must be a number';
|
HDPublicKey.Errors.InvalidParentFingerPrint = 'Invalid Parent Fingerprint - must be a number';
|
||||||
HDPublicKey.Errors.InvalidPath = 'Invalid path for derivation: must start with "m"';
|
HDPublicKey.Errors.InvalidPath = 'Invalid path for derivation: must start with "m"';
|
||||||
|
HDPublicKey.Errors.MustSupplyArgument = 'Must supply an argument for the constructor';
|
||||||
HDPublicKey.Errors.UnrecognizedArgument = 'Creating a HDPublicKey requires a string, a buffer, a json, or an object';
|
HDPublicKey.Errors.UnrecognizedArgument = 'Creating a HDPublicKey requires a string, a buffer, a json, or an object';
|
||||||
|
|
||||||
module.exports = HDPublicKey;
|
module.exports = HDPublicKey;
|
||||||
|
|
|
@ -40,7 +40,7 @@ describe('HDPrivate key interface', function() {
|
||||||
regenerate.xprivkey.should.equal(xprivkey);
|
regenerate.xprivkey.should.equal(xprivkey);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('builds a json keeping the same interface than previous versions', function() {
|
it('builds a json keeping the structure and same members', function() {
|
||||||
assert(util.shallowEquals(
|
assert(util.shallowEquals(
|
||||||
JSON.parse(new HDPrivateKey(json).toJson()),
|
JSON.parse(new HDPrivateKey(json).toJson()),
|
||||||
JSON.parse(new HDPrivateKey(xprivkey).toJson())
|
JSON.parse(new HDPrivateKey(xprivkey).toJson())
|
||||||
|
|
|
@ -0,0 +1,153 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
/* jshint unused: false */
|
||||||
|
var _ = require('lodash');
|
||||||
|
var assert = require('assert');
|
||||||
|
var should = require('chai').should();
|
||||||
|
var expect = require('chai').expect;
|
||||||
|
var bitcore = require('..');
|
||||||
|
var buffer = require('buffer');
|
||||||
|
var util = bitcore.util;
|
||||||
|
var HDPrivateKey = bitcore.HDPrivateKey;
|
||||||
|
var HDPublicKey = bitcore.HDPublicKey;
|
||||||
|
var Base58Check = bitcore.encoding.Base58Check;
|
||||||
|
|
||||||
|
var xprivkey = 'xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi';
|
||||||
|
var xpubkey = 'xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8';
|
||||||
|
var json = '{"network":"livenet","depth":0,"fingerPrint":876747070,"parentFingerPrint":0,"childIndex":0,"chainCode":"873dff81c02f525623fd1fe5167eac3a55a049de3d314bb42ee227ffed37d508","publicKey":"0339a36013301597daef41fbe593a02cc513d0b55527ec2df1050e2e8ff49c85c2","checksum":-1421395167,"xpubkey":"xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8"}';
|
||||||
|
var derived_0_1_200000 = 'xpub6BqyndF6rkBNTV6LXwiY8Pco8aqctqq7tGEUdA8fmGDTnDJphn2fmxr3eM8Lm3m8TrNUsLbEjHvpa3adBU18YpEx4tp2Zp6nqax3mQkudhX';
|
||||||
|
|
||||||
|
describe('HDPublicKey interface', function() {
|
||||||
|
|
||||||
|
var expectFail = function(argument, error) {
|
||||||
|
return function() {
|
||||||
|
expect(function() {
|
||||||
|
return new HDPublicKey(argument);
|
||||||
|
}).to.throw(error);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
describe('creation formats', function() {
|
||||||
|
|
||||||
|
it('returns same argument if already an instance of HDPublicKey', function() {
|
||||||
|
var publicKey = new HDPublicKey(xpubkey);
|
||||||
|
publicKey.should.equal(new HDPublicKey(publicKey));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns the correct xpubkey for a xprivkey', function() {
|
||||||
|
var publicKey = new HDPublicKey(xprivkey);
|
||||||
|
publicKey.xpubkey.should.equal(xpubkey);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('allows to call the argument with no "new" keyword', function() {
|
||||||
|
HDPublicKey(xpubkey).xpubkey.should.equal(new HDPublicKey(xpubkey).xpubkey);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('fails when user doesn\'t supply an argument', function() {
|
||||||
|
expect(function() { return new HDPublicKey(); }).to.throw(HDPublicKey.Errors.MustSupplyArgument);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('doesn\'t recognize an invalid argument', function() {
|
||||||
|
var expectCreationFail = function(argument) {
|
||||||
|
expect(function() { return new HDPublicKey(argument); }).to.throw(HDPublicKey.Errors.UnrecognizedArgument);
|
||||||
|
};
|
||||||
|
expectCreationFail(1);
|
||||||
|
expectCreationFail(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
describe('xpubkey string serialization errors', function() {
|
||||||
|
it('fails on invalid length', expectFail(
|
||||||
|
Base58Check.encode(new buffer.Buffer([1, 2, 3])),
|
||||||
|
HDPublicKey.Errors.InvalidLength
|
||||||
|
));
|
||||||
|
it('fails on invalid base58 encoding', expectFail(
|
||||||
|
xpubkey + '1',
|
||||||
|
HDPublicKey.Errors.InvalidB58Checksum
|
||||||
|
));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can be generated from a json', function() {
|
||||||
|
expect(new HDPublicKey(json).xpubkey).to.equal(xpubkey);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can generate a json that has a particular structure', function() {
|
||||||
|
assert(util.shallowEquals(
|
||||||
|
JSON.parse(new HDPublicKey(json).toJson()),
|
||||||
|
JSON.parse(new HDPublicKey(xpubkey).toJson())
|
||||||
|
));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('builds from a buffer object', function() {
|
||||||
|
(new HDPublicKey(new HDPublicKey(xpubkey)._buffers)).xpubkey.should.equal(xpubkey);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('checks the checksum', function() {
|
||||||
|
var buffers = new HDPublicKey(xpubkey)._buffers;
|
||||||
|
buffers.checksum = util.integerAsBuffer(1);
|
||||||
|
expectFail(buffers, HDPublicKey.Errors.InvalidB58Checksum)();
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('error checking on serialization', function() {
|
||||||
|
it('throws invalid argument when argument is not a string or buffer', function() {
|
||||||
|
HDPublicKey.getSerializedError(1).should.equal(HDPublicKey.Errors.InvalidArgument);
|
||||||
|
});
|
||||||
|
it('if a network is provided, validates that data corresponds to it', function() {
|
||||||
|
HDPublicKey.getSerializedError(xpubkey, 'testnet').should.equal(HDPublicKey.Errors.InvalidNetwork);
|
||||||
|
});
|
||||||
|
it('recognizes invalid network arguments', function() {
|
||||||
|
HDPublicKey.getSerializedError(xpubkey, 'invalid').should.equal(HDPublicKey.Errors.InvalidNetworkArgument);
|
||||||
|
});
|
||||||
|
it('recognizes a valid network', function() {
|
||||||
|
expect(HDPublicKey.getSerializedError(xpubkey, 'livenet')).to.equal(null);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('toString() returns the same value as .xpubkey', function() {
|
||||||
|
var pubKey = new HDPublicKey(xpubkey);
|
||||||
|
pubKey.toString().should.equal(pubKey.xpubkey);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('derivation', function() {
|
||||||
|
it('derivation is the same whether deriving with number or string', function() {
|
||||||
|
var pubkey = new HDPublicKey(xpubkey);
|
||||||
|
var derived1 = pubkey.derive(0).derive(1).derive(200000);
|
||||||
|
var derived2 = pubkey.derive('m/0/1/200000');
|
||||||
|
derived1.xpubkey.should.equal(derived_0_1_200000);
|
||||||
|
derived2.xpubkey.should.equal(derived_0_1_200000);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('allows special parameters m, M', function() {
|
||||||
|
var expectDerivationSuccess = function(argument) {
|
||||||
|
new HDPublicKey(xpubkey).derive(argument).xpubkey.should.equal(xpubkey);
|
||||||
|
};
|
||||||
|
expectDerivationSuccess('m');
|
||||||
|
expectDerivationSuccess('M');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('doesn\'t allow object arguments for derivation', function() {
|
||||||
|
expect(function() {
|
||||||
|
return new HDPublicKey(xpubkey).derive({});
|
||||||
|
}).to.throw(HDPublicKey.Errors.InvalidDerivationArgument);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('doesn\'t allow other parameters like m\' or M\' or "s"', function() {
|
||||||
|
var expectDerivationFail = function(argument) {
|
||||||
|
expect(function() {
|
||||||
|
return new HDPublicKey(xpubkey).derive(argument);
|
||||||
|
}).to.throw(HDPublicKey.Errors.InvalidPath);
|
||||||
|
};
|
||||||
|
/* jshint quotmark: double */
|
||||||
|
expectDerivationFail("m'");
|
||||||
|
expectDerivationFail("M'");
|
||||||
|
expectDerivationFail("1");
|
||||||
|
expectDerivationFail("S");
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can\'t derive hardened keys', function() {
|
||||||
|
expect(function() { return new HDPublicKey(xpubkey).derive(HDPublicKey.Hardened + 1); })
|
||||||
|
.to.throw(HDPublicKey.Errors.InvalidIndexCantDeriveHardened);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in New Issue