From 809ff1461e9351e9ca83b55c00b3b5a4ee251693 Mon Sep 17 00:00:00 2001 From: Braydon Fuller Date: Fri, 14 Aug 2015 16:05:14 -0400 Subject: [PATCH] Restore error when trying to derive a hardened path with HDPublicKey. - Restores InvalidIndexCantDeriveHardened error in spec - Passes hardened argument in HDPublicKey (in case the feature is attempted to be used similarly to HDPrivateKey) - Fixes undefined error with InvalidLength - Fixes tests to check for the error type - Various formatting cleanup improvements --- lib/errors/spec.js | 3 ++ lib/hdpublickey.js | 28 +++++++------- test/hdpublickey.js | 91 ++++++++++++++++++++++----------------------- 3 files changed, 61 insertions(+), 61 deletions(-) diff --git a/lib/errors/spec.js b/lib/errors/spec.js index ef54ddf4f..9279f81b5 100644 --- a/lib/errors/spec.js +++ b/lib/errors/spec.js @@ -164,6 +164,9 @@ module.exports = [{ }, { name: 'InvalidPath', message: 'Invalid derivation path, it should look like: "m/1/100", got "{0}"' + }, { + name: 'InvalidIndexCantDeriveHardened', + message: 'Invalid argument: creating a hardened path requires an HDPrivateKey' }, { name: 'MustSupplyArgument', message: 'Must supply an argument to create a HDPublicKey' diff --git a/lib/hdpublickey.js b/lib/hdpublickey.js index 923df7d2a..198947d06 100644 --- a/lib/hdpublickey.js +++ b/lib/hdpublickey.js @@ -108,9 +108,9 @@ HDPublicKey.isValidPath = function(arg) { * * @param {string|number} arg */ -HDPublicKey.prototype.derive = function (arg) { +HDPublicKey.prototype.derive = function(arg, hardened) { if (_.isNumber(arg)) { - return this._deriveWithNumber(arg); + return this._deriveWithNumber(arg, hardened); } else if (_.isString(arg)) { return this._deriveFromString(arg); } else { @@ -118,8 +118,8 @@ HDPublicKey.prototype.derive = function (arg) { } }; -HDPublicKey.prototype._deriveWithNumber = function (index) { - if (index >= HDPublicKey.Hardened) { +HDPublicKey.prototype._deriveWithNumber = function(index, hardened) { + if (index >= HDPublicKey.Hardened || hardened) { throw new hdErrors.InvalidIndexCantDeriveHardened(); } if (index < 0) { @@ -150,7 +150,7 @@ HDPublicKey.prototype._deriveWithNumber = function (index) { return derived; }; -HDPublicKey.prototype._deriveFromString = function (path) { +HDPublicKey.prototype._deriveFromString = function(path) { /* jshint maxcomplexity: 8 */ if (_.contains(path, "'")) { throw new hdErrors.InvalidIndexCantDeriveHardened(); @@ -175,7 +175,7 @@ HDPublicKey.prototype._deriveFromString = function (path) { * network provided matches the network serialized. * @return {boolean} */ -HDPublicKey.isValidSerialized = function (data, network) { +HDPublicKey.isValidSerialized = function(data, network) { return _.isNull(HDPublicKey.getSerializedError(data, network)); }; @@ -188,7 +188,7 @@ HDPublicKey.isValidSerialized = function (data, network) { * network provided matches the network serialized. * @return {errors|null} */ -HDPublicKey.getSerializedError = function (data, network) { +HDPublicKey.getSerializedError = function(data, network) { /* jshint maxcomplexity: 10 */ /* jshint maxstatements: 20 */ if (!(_.isString(data) || BufferUtil.isBuffer(data))) { @@ -203,7 +203,7 @@ HDPublicKey.getSerializedError = function (data, network) { return new errors.InvalidB58Checksum(data); } if (data.length !== HDPublicKey.DataSize) { - return new errors.InvalidLength(data); + return new hdErrors.InvalidLength(data); } if (!_.isUndefined(network)) { var error = HDPublicKey._validateNetwork(data, network); @@ -218,7 +218,7 @@ HDPublicKey.getSerializedError = function (data, network) { return null; }; -HDPublicKey._validateNetwork = function (data, networkArg) { +HDPublicKey._validateNetwork = function(data, networkArg) { var network = Network.get(networkArg); if (!network) { return new errors.InvalidNetworkArgument(networkArg); @@ -241,7 +241,7 @@ HDPublicKey.prototype._buildFromPrivate = function (arg) { return this._buildFromBuffers(args); }; -HDPublicKey.prototype._buildFromObject = function (arg) { +HDPublicKey.prototype._buildFromObject = function(arg) { /* jshint maxcomplexity: 10 */ // TODO: Type validation var buffers = { @@ -257,7 +257,7 @@ HDPublicKey.prototype._buildFromObject = function (arg) { return this._buildFromBuffers(buffers); }; -HDPublicKey.prototype._buildFromSerialized = function (arg) { +HDPublicKey.prototype._buildFromSerialized = function(arg) { var decoded = Base58Check.decode(arg); var buffers = { version: decoded.slice(HDPublicKey.VersionStart, HDPublicKey.VersionEnd), @@ -289,7 +289,7 @@ HDPublicKey.prototype._buildFromSerialized = function (arg) { * representation * @return {HDPublicKey} this */ -HDPublicKey.prototype._buildFromBuffers = function (arg) { +HDPublicKey.prototype._buildFromBuffers = function(arg) { /* jshint maxcomplexity: 8 */ /* jshint maxstatements: 20 */ @@ -333,7 +333,7 @@ HDPublicKey.prototype._buildFromBuffers = function (arg) { return this; }; -HDPublicKey._validateBufferArguments = function (arg) { +HDPublicKey._validateBufferArguments = function(arg) { var checkBuffer = function(name, size) { var buff = arg[name]; assert(BufferUtil.isBuffer(buff), name + ' argument is not a buffer, it\'s ' + typeof buff); @@ -367,7 +367,7 @@ HDPublicKey.fromObject = function(arg) { * Returns the base58 checked representation of the public key * @return {string} a string starting with "xpub..." in livenet */ -HDPublicKey.prototype.toString = function () { +HDPublicKey.prototype.toString = function() { return this.xpubkey; }; diff --git a/test/hdpublickey.js b/test/hdpublickey.js index e8a582b73..f006d737b 100644 --- a/test/hdpublickey.js +++ b/test/hdpublickey.js @@ -24,31 +24,22 @@ var derived_0_1_200000 = 'xpub6BqyndF6rkBNTV6LXwiY8Pco8aqctqq7tGEUdA8fmGDTnDJphn describe('HDPublicKey interface', function() { var expectFail = function(func, errorType) { - var got = null; - var error = null; - try { + (function() { func(); - } catch (e) { - error = e; - got = e instanceof errorType; - } - if (!error instanceof errorType) { - console.log('Error', typeof error); - } - // expect(got).to.equal(true); + }).should.throw(errorType); }; var expectDerivationFail = function(argument, error) { - return expectFail(function() { + (function() { var pubkey = new HDPublicKey(xpubkey); - xpubkey.derive(argument); - }, error); + pubkey.derive(argument); + }).should.throw(error); }; var expectFailBuilding = function(argument, error) { - return expectFail(function() { + (function() { return new HDPublicKey(argument); - }, error); + }).should.throw(error); }; describe('creation formats', function() { @@ -225,55 +216,61 @@ describe('HDPublicKey interface', function() { it('doesn\'t allow other parameters like m\' or M\' or "s"', function() { /* jshint quotmark: double */ - expectDerivationFail("m'", hdErrors.InvalidDerivationArgument); - expectDerivationFail("M'", hdErrors.InvalidDerivationArgument); - expectDerivationFail("1", hdErrors.InvalidDerivationArgument); - expectDerivationFail("S", hdErrors.InvalidDerivationArgument); + expectDerivationFail("m'", hdErrors.InvalidIndexCantDeriveHardened); + expectDerivationFail("M'", hdErrors.InvalidIndexCantDeriveHardened); + expectDerivationFail("1", hdErrors.InvalidPath); + expectDerivationFail("S", hdErrors.InvalidPath); }); it('can\'t derive hardened keys', function() { expectFail(function() { return new HDPublicKey(xpubkey).derive(HDPublicKey.Hardened); - }, hdErrors.InvalidDerivationArgument); + }, hdErrors.InvalidIndexCantDeriveHardened); }); - it('validates correct paths', function() { - var valid; + it('can\'t derive hardened keys via second argument', function() { + expectFail(function() { + return new HDPublicKey(xpubkey).derive(5, true); + }, hdErrors.InvalidIndexCantDeriveHardened); + }); - valid = HDPublicKey.isValidPath('m/123/12'); - valid.should.equal(true); + it('validates correct paths', function() { + var valid; - valid = HDPublicKey.isValidPath('m'); - valid.should.equal(true); + valid = HDPublicKey.isValidPath('m/123/12'); + valid.should.equal(true); - valid = HDPublicKey.isValidPath(123); - valid.should.equal(true); - }); + valid = HDPublicKey.isValidPath('m'); + valid.should.equal(true); - it('rejects illegal paths', function() { - var valid; + valid = HDPublicKey.isValidPath(123); + valid.should.equal(true); + }); - valid = HDPublicKey.isValidPath('m/-1/12'); - valid.should.equal(false); + it('rejects illegal paths', function() { + var valid; - valid = HDPublicKey.isValidPath("m/0'/12"); - valid.should.equal(false); + valid = HDPublicKey.isValidPath('m/-1/12'); + valid.should.equal(false); - valid = HDPublicKey.isValidPath("m/8000000000/12"); - valid.should.equal(false); + valid = HDPublicKey.isValidPath("m/0'/12"); + valid.should.equal(false); - valid = HDPublicKey.isValidPath('bad path'); - valid.should.equal(false); + valid = HDPublicKey.isValidPath("m/8000000000/12"); + valid.should.equal(false); - valid = HDPublicKey.isValidPath(-1); - valid.should.equal(false); + valid = HDPublicKey.isValidPath('bad path'); + valid.should.equal(false); - valid = HDPublicKey.isValidPath(8000000000); - valid.should.equal(false); + valid = HDPublicKey.isValidPath(-1); + valid.should.equal(false); - valid = HDPublicKey.isValidPath(HDPublicKey.Hardened); - valid.should.equal(false); - }); + valid = HDPublicKey.isValidPath(8000000000); + valid.should.equal(false); + + valid = HDPublicKey.isValidPath(HDPublicKey.Hardened); + valid.should.equal(false); + }); it('should use the cache', function() { var pubkey = new HDPublicKey(xpubkey);