Browse Source

Change name of derive to deriveChild

This is to avoid any accidental upgrades to a bugfixed version without awareness of the change.
patch-2
Braydon Fuller 8 years ago
parent
commit
d32ae41adc
  1. 14
      docs/hierarchical.md
  2. 15
      lib/hdprivatekey.js
  3. 11
      lib/hdpublickey.js
  4. 24
      test/hdkeycache.js
  5. 83
      test/hdkeys.js
  6. 12
      test/hdprivatekey.js
  7. 20
      test/hdpublickey.js

14
docs/hierarchical.md

@ -15,9 +15,9 @@ var HDPrivateKey = bitcore.HDPrivateKey;
var hdPrivateKey = new HDPrivateKey(); var hdPrivateKey = new HDPrivateKey();
var retrieved = new HDPrivateKey('xpriv...'); var retrieved = new HDPrivateKey('xpriv...');
var derived = hdPrivateKey.derive("m/0'"); var derived = hdPrivateKey.deriveChild("m/0'");
var derivedByNumber = hdPrivateKey.derive(1).derive(2, true); var derivedByNumber = hdPrivateKey.deriveChild(1).deriveChild(2, true);
var derivedByArgument = hdPrivateKey.derive("m/1/2'"); var derivedByArgument = hdPrivateKey.deriveChild("m/1/2'");
assert(derivedByNumber.xprivkey === derivedByArgument.xprivkey); assert(derivedByNumber.xprivkey === derivedByArgument.xprivkey);
var address = derived.privateKey.toAddress(); var address = derived.privateKey.toAddress();
@ -39,5 +39,11 @@ try {
} }
var address = new Address(hdPublicKey.publicKey, Networks.livenet); var address = new Address(hdPublicKey.publicKey, Networks.livenet);
var derivedAddress = new Address(hdPublicKey.derive(100).publicKey, Networks.testnet); var derivedAddress = new Address(hdPublicKey.deriveChild(100).publicKey, Networks.testnet);
``` ```
## Upgrading from v0.13.x and previous to v1.0.0
There was a bug that was discovered with derivation that would incorrectly calculate the child key against the [BIP32 specification](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki). The method `derive` has been deprecated and replaced with `deriveChild` and `deriveNonCompliantChild`. As the names indicate `deriveNonCompliantChild` will derive using the non-BIP32 derivation and is the equivalent of `derive` in v0.13 and previous versions. The `deriveNonCompliantChild` method should not be used unless you're upgrading and need to maintain compatibility with the old derivation.
The bug only affected hardened derivations using an extended private key, and did not affect public key derivation. It also did not affect every derivation and would happen 1 in 256 times where where the private key for the extended private key had a leading zero *(e.g. any private key less than or equal to '0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff')*. The leading zero was not included in serialization before hashing to derive a child key, as it should have been.

15
lib/hdprivatekey.js

@ -127,6 +127,11 @@ HDPrivateKey._getDerivationIndexes = function(path) {
return _.any(indexes, isNaN) ? null : indexes; return _.any(indexes, isNaN) ? null : indexes;
}; };
HDPrivateKey.prototype.derive = function() {
throw new Error('Method has been deprecated, please use deriveChild or deriveNonCompliantChild' +
'and see documentation for more information');
};
/** /**
* Get a derived child based on a string or number. * Get a derived child based on a string or number.
* *
@ -145,8 +150,8 @@ HDPrivateKey._getDerivationIndexes = function(path) {
* @example * @example
* ```javascript * ```javascript
* var parent = new HDPrivateKey('xprv...'); * var parent = new HDPrivateKey('xprv...');
* var child_0_1_2h = parent.derive(0).derive(1).derive(2, true); * var child_0_1_2h = parent.deriveChild(0).deriveChild(1).deriveChild(2, true);
* var copy_of_child_0_1_2h = parent.derive("m/0/1/2'"); * var copy_of_child_0_1_2h = parent.deriveChild("m/0/1/2'");
* assert(child_0_1_2h.xprivkey === copy_of_child_0_1_2h); * assert(child_0_1_2h.xprivkey === copy_of_child_0_1_2h);
* ``` * ```
* *
@ -155,7 +160,7 @@ HDPrivateKey._getDerivationIndexes = function(path) {
* @param {boolean?} nonCompliant - This should not be used and only for backwards compatibility * @param {boolean?} nonCompliant - This should not be used and only for backwards compatibility
* *
*/ */
HDPrivateKey.prototype.derive = function(arg, hardened, nonCompliant) { HDPrivateKey.prototype.deriveChild = function(arg, hardened, nonCompliant) {
if (_.isNumber(arg)) { if (_.isNumber(arg)) {
return this._deriveWithNumber(arg, hardened, nonCompliant); return this._deriveWithNumber(arg, hardened, nonCompliant);
} else if (_.isString(arg)) { } else if (_.isString(arg)) {
@ -178,8 +183,8 @@ HDPrivateKey.prototype.derive = function(arg, hardened, nonCompliant) {
* @param {string|number} arg * @param {string|number} arg
* @param {boolean?} hardened * @param {boolean?} hardened
*/ */
HDPrivateKey.prototype.deriveNonCompliant = function(arg, hardened) { HDPrivateKey.prototype.deriveNonCompliantChild = function(arg, hardened) {
var derived = this.derive(arg, hardened, true); var derived = this.deriveChild(arg, hardened, true);
return derived; return derived;
}; };

11
lib/hdpublickey.js

@ -86,6 +86,11 @@ HDPublicKey.isValidPath = function(arg) {
return false; return false;
}; };
HDPublicKey.prototype.derive = function() {
throw new Error('Method has been deprecated, please use deriveChild instead' +
'and see documentation for more information');
};
/** /**
* Get a derivated child based on a string or number. * Get a derivated child based on a string or number.
* *
@ -101,14 +106,14 @@ HDPublicKey.isValidPath = function(arg) {
* @example * @example
* ```javascript * ```javascript
* var parent = new HDPublicKey('xpub...'); * var parent = new HDPublicKey('xpub...');
* var child_0_1_2 = parent.derive(0).derive(1).derive(2); * var child_0_1_2 = parent.deriveChild(0).deriveChild(1).deriveChild(2);
* var copy_of_child_0_1_2 = parent.derive("m/0/1/2"); * var copy_of_child_0_1_2 = parent.deriveChild("m/0/1/2");
* assert(child_0_1_2.xprivkey === copy_of_child_0_1_2); * assert(child_0_1_2.xprivkey === copy_of_child_0_1_2);
* ``` * ```
* *
* @param {string|number} arg * @param {string|number} arg
*/ */
HDPublicKey.prototype.derive = function(arg, hardened) { HDPublicKey.prototype.deriveChild = function(arg, hardened) {
if (_.isNumber(arg)) { if (_.isNumber(arg)) {
return this._deriveWithNumber(arg, hardened); return this._deriveWithNumber(arg, hardened);
} else if (_.isString(arg)) { } else if (_.isString(arg)) {

24
test/hdkeycache.js

@ -24,29 +24,29 @@ describe('HDKey cache', function() {
}); });
it('saves a derived key', function() { it('saves a derived key', function() {
var child = master.derive(0); var child = master.deriveChild(0);
expect(cache._cache['0' + master.xprivkey + '/0/false'].xprivkey).to.equal(child.xprivkey); expect(cache._cache['0' + master.xprivkey + '/0/false'].xprivkey).to.equal(child.xprivkey);
}); });
it('starts erasing unused keys', function() { it('starts erasing unused keys', function() {
var child1 = master.derive(0); var child1 = master.deriveChild(0);
var child2 = child1.derive(0); var child2 = child1.deriveChild(0);
var child3 = child2.derive(0); var child3 = child2.deriveChild(0);
expect(cache._cache['0' + master.xprivkey + '/0/false'].xprivkey).to.equal(child1.xprivkey); expect(cache._cache['0' + master.xprivkey + '/0/false'].xprivkey).to.equal(child1.xprivkey);
var child4 = child3.derive(0); var child4 = child3.deriveChild(0);
expect(cache._cache['0' + master.xprivkey + '/0/false']).to.equal(undefined); expect(cache._cache['0' + master.xprivkey + '/0/false']).to.equal(undefined);
}); });
it('avoids erasing keys that get cache hits ("hot keys")', function() { it('avoids erasing keys that get cache hits ("hot keys")', function() {
var child1 = master.derive(0); var child1 = master.deriveChild(0);
var child2 = master.derive(0).derive(0); var child2 = master.deriveChild(0).deriveChild(0);
expect(cache._cache['0' + master.xprivkey + '/0/false'].xprivkey).to.equal(child1.xprivkey); expect(cache._cache['0' + master.xprivkey + '/0/false'].xprivkey).to.equal(child1.xprivkey);
var child1_copy = master.derive(0); var child1_copy = master.deriveChild(0);
expect(cache._cache['0' + master.xprivkey + '/0/false'].xprivkey).to.equal(child1.xprivkey); expect(cache._cache['0' + master.xprivkey + '/0/false'].xprivkey).to.equal(child1.xprivkey);
}); });
it('keeps the size of the cache small', function() { it('keeps the size of the cache small', function() {
var child1 = master.derive(0); var child1 = master.deriveChild(0);
var child2 = child1.derive(0); var child2 = child1.deriveChild(0);
var child3 = child2.derive(0); var child3 = child2.deriveChild(0);
var child4 = child3.derive(0); var child4 = child3.deriveChild(0);
expect(_.size(cache._cache)).to.equal(3); expect(_.size(cache._cache)).to.equal(3);
}); });
}); });

83
test/hdkeys.js

@ -81,69 +81,69 @@ describe('BIP32 compliance', function() {
}); });
it("should get m/0' ext. private key from test vector 1", function() { it("should get m/0' ext. private key from test vector 1", function() {
var privateKey = new HDPrivateKey(vector1_m_private).derive("m/0'"); var privateKey = new HDPrivateKey(vector1_m_private).deriveChild("m/0'");
privateKey.xprivkey.should.equal(vector1_m0h_private); privateKey.xprivkey.should.equal(vector1_m0h_private);
}); });
it("should get m/0' ext. public key from test vector 1", function() { it("should get m/0' ext. public key from test vector 1", function() {
HDPrivateKey(vector1_m_private).derive("m/0'") HDPrivateKey(vector1_m_private).deriveChild("m/0'")
.xpubkey.should.equal(vector1_m0h_public); .xpubkey.should.equal(vector1_m0h_public);
}); });
it("should get m/0'/1 ext. private key from test vector 1", function() { it("should get m/0'/1 ext. private key from test vector 1", function() {
HDPrivateKey(vector1_m_private).derive("m/0'/1") HDPrivateKey(vector1_m_private).deriveChild("m/0'/1")
.xprivkey.should.equal(vector1_m0h1_private); .xprivkey.should.equal(vector1_m0h1_private);
}); });
it("should get m/0'/1 ext. public key from test vector 1", function() { it("should get m/0'/1 ext. public key from test vector 1", function() {
HDPrivateKey(vector1_m_private).derive("m/0'/1") HDPrivateKey(vector1_m_private).deriveChild("m/0'/1")
.xpubkey.should.equal(vector1_m0h1_public); .xpubkey.should.equal(vector1_m0h1_public);
}); });
it("should get m/0'/1 ext. public key from m/0' public key from test vector 1", function() { it("should get m/0'/1 ext. public key from m/0' public key from test vector 1", function() {
var derivedPublic = HDPrivateKey(vector1_m_private).derive("m/0'").hdPublicKey.derive("m/1"); var derivedPublic = HDPrivateKey(vector1_m_private).deriveChild("m/0'").hdPublicKey.deriveChild("m/1");
derivedPublic.xpubkey.should.equal(vector1_m0h1_public); derivedPublic.xpubkey.should.equal(vector1_m0h1_public);
}); });
it("should get m/0'/1/2' ext. private key from test vector 1", function() { it("should get m/0'/1/2' ext. private key from test vector 1", function() {
var privateKey = new HDPrivateKey(vector1_m_private); var privateKey = new HDPrivateKey(vector1_m_private);
var derived = privateKey.derive("m/0'/1/2'"); var derived = privateKey.deriveChild("m/0'/1/2'");
derived.xprivkey.should.equal(vector1_m0h12h_private); derived.xprivkey.should.equal(vector1_m0h12h_private);
}); });
it("should get m/0'/1/2' ext. public key from test vector 1", function() { it("should get m/0'/1/2' ext. public key from test vector 1", function() {
HDPrivateKey(vector1_m_private).derive("m/0'/1/2'") HDPrivateKey(vector1_m_private).deriveChild("m/0'/1/2'")
.xpubkey.should.equal(vector1_m0h12h_public); .xpubkey.should.equal(vector1_m0h12h_public);
}); });
it("should get m/0'/1/2'/2 ext. private key from test vector 1", function() { it("should get m/0'/1/2'/2 ext. private key from test vector 1", function() {
HDPrivateKey(vector1_m_private).derive("m/0'/1/2'/2") HDPrivateKey(vector1_m_private).deriveChild("m/0'/1/2'/2")
.xprivkey.should.equal(vector1_m0h12h2_private); .xprivkey.should.equal(vector1_m0h12h2_private);
}); });
it("should get m/0'/1/2'/2 ext. public key from m/0'/1/2' public key from test vector 1", function() { it("should get m/0'/1/2'/2 ext. public key from m/0'/1/2' public key from test vector 1", function() {
var derived = HDPrivateKey(vector1_m_private).derive("m/0'/1/2'").hdPublicKey; var derived = HDPrivateKey(vector1_m_private).deriveChild("m/0'/1/2'").hdPublicKey;
derived.derive("m/2").xpubkey.should.equal(vector1_m0h12h2_public); derived.deriveChild("m/2").xpubkey.should.equal(vector1_m0h12h2_public);
}); });
it("should get m/0'/1/2h/2 ext. public key from test vector 1", function() { it("should get m/0'/1/2h/2 ext. public key from test vector 1", function() {
HDPrivateKey(vector1_m_private).derive("m/0'/1/2'/2") HDPrivateKey(vector1_m_private).deriveChild("m/0'/1/2'/2")
.xpubkey.should.equal(vector1_m0h12h2_public); .xpubkey.should.equal(vector1_m0h12h2_public);
}); });
it("should get m/0'/1/2h/2/1000000000 ext. private key from test vector 1", function() { it("should get m/0'/1/2h/2/1000000000 ext. private key from test vector 1", function() {
HDPrivateKey(vector1_m_private).derive("m/0'/1/2'/2/1000000000") HDPrivateKey(vector1_m_private).deriveChild("m/0'/1/2'/2/1000000000")
.xprivkey.should.equal(vector1_m0h12h21000000000_private); .xprivkey.should.equal(vector1_m0h12h21000000000_private);
}); });
it("should get m/0'/1/2h/2/1000000000 ext. public key from test vector 1", function() { it("should get m/0'/1/2h/2/1000000000 ext. public key from test vector 1", function() {
HDPrivateKey(vector1_m_private).derive("m/0'/1/2'/2/1000000000") HDPrivateKey(vector1_m_private).deriveChild("m/0'/1/2'/2/1000000000")
.xpubkey.should.equal(vector1_m0h12h21000000000_public); .xpubkey.should.equal(vector1_m0h12h21000000000_public);
}); });
it("should get m/0'/1/2'/2/1000000000 ext. public key from m/0'/1/2'/2 public key from test vector 1", function() { it("should get m/0'/1/2'/2/1000000000 ext. public key from m/0'/1/2'/2 public key from test vector 1", function() {
var derived = HDPrivateKey(vector1_m_private).derive("m/0'/1/2'/2").hdPublicKey; var derived = HDPrivateKey(vector1_m_private).deriveChild("m/0'/1/2'/2").hdPublicKey;
derived.derive("m/1000000000").xpubkey.should.equal(vector1_m0h12h21000000000_public); derived.deriveChild("m/1000000000").xpubkey.should.equal(vector1_m0h12h21000000000_public);
}); });
it('should initialize test vector 2 from the extended public key', function() { it('should initialize test vector 2 from the extended public key', function() {
@ -159,66 +159,66 @@ describe('BIP32 compliance', function() {
}); });
it("should get m/0 ext. private key from test vector 2", function() { it("should get m/0 ext. private key from test vector 2", function() {
HDPrivateKey(vector2_m_private).derive(0).xprivkey.should.equal(vector2_m0_private); HDPrivateKey(vector2_m_private).deriveChild(0).xprivkey.should.equal(vector2_m0_private);
}); });
it("should get m/0 ext. public key from test vector 2", function() { it("should get m/0 ext. public key from test vector 2", function() {
HDPrivateKey(vector2_m_private).derive(0).xpubkey.should.equal(vector2_m0_public); HDPrivateKey(vector2_m_private).deriveChild(0).xpubkey.should.equal(vector2_m0_public);
}); });
it("should get m/0 ext. public key from m public key from test vector 2", function() { it("should get m/0 ext. public key from m public key from test vector 2", function() {
HDPrivateKey(vector2_m_private).hdPublicKey.derive(0).xpubkey.should.equal(vector2_m0_public); HDPrivateKey(vector2_m_private).hdPublicKey.deriveChild(0).xpubkey.should.equal(vector2_m0_public);
}); });
it("should get m/0/2147483647h ext. private key from test vector 2", function() { it("should get m/0/2147483647h ext. private key from test vector 2", function() {
HDPrivateKey(vector2_m_private).derive("m/0/2147483647'") HDPrivateKey(vector2_m_private).deriveChild("m/0/2147483647'")
.xprivkey.should.equal(vector2_m02147483647h_private); .xprivkey.should.equal(vector2_m02147483647h_private);
}); });
it("should get m/0/2147483647h ext. public key from test vector 2", function() { it("should get m/0/2147483647h ext. public key from test vector 2", function() {
HDPrivateKey(vector2_m_private).derive("m/0/2147483647'") HDPrivateKey(vector2_m_private).deriveChild("m/0/2147483647'")
.xpubkey.should.equal(vector2_m02147483647h_public); .xpubkey.should.equal(vector2_m02147483647h_public);
}); });
it("should get m/0/2147483647h/1 ext. private key from test vector 2", function() { it("should get m/0/2147483647h/1 ext. private key from test vector 2", function() {
HDPrivateKey(vector2_m_private).derive("m/0/2147483647'/1") HDPrivateKey(vector2_m_private).deriveChild("m/0/2147483647'/1")
.xprivkey.should.equal(vector2_m02147483647h1_private); .xprivkey.should.equal(vector2_m02147483647h1_private);
}); });
it("should get m/0/2147483647h/1 ext. public key from test vector 2", function() { it("should get m/0/2147483647h/1 ext. public key from test vector 2", function() {
HDPrivateKey(vector2_m_private).derive("m/0/2147483647'/1") HDPrivateKey(vector2_m_private).deriveChild("m/0/2147483647'/1")
.xpubkey.should.equal(vector2_m02147483647h1_public); .xpubkey.should.equal(vector2_m02147483647h1_public);
}); });
it("should get m/0/2147483647h/1 ext. public key from m/0/2147483647h public key from test vector 2", function() { it("should get m/0/2147483647h/1 ext. public key from m/0/2147483647h public key from test vector 2", function() {
var derived = HDPrivateKey(vector2_m_private).derive("m/0/2147483647'").hdPublicKey; var derived = HDPrivateKey(vector2_m_private).deriveChild("m/0/2147483647'").hdPublicKey;
derived.derive(1).xpubkey.should.equal(vector2_m02147483647h1_public); derived.deriveChild(1).xpubkey.should.equal(vector2_m02147483647h1_public);
}); });
it("should get m/0/2147483647h/1/2147483646h ext. private key from test vector 2", function() { it("should get m/0/2147483647h/1/2147483646h ext. private key from test vector 2", function() {
HDPrivateKey(vector2_m_private).derive("m/0/2147483647'/1/2147483646'") HDPrivateKey(vector2_m_private).deriveChild("m/0/2147483647'/1/2147483646'")
.xprivkey.should.equal(vector2_m02147483647h12147483646h_private); .xprivkey.should.equal(vector2_m02147483647h12147483646h_private);
}); });
it("should get m/0/2147483647h/1/2147483646h ext. public key from test vector 2", function() { it("should get m/0/2147483647h/1/2147483646h ext. public key from test vector 2", function() {
HDPrivateKey(vector2_m_private).derive("m/0/2147483647'/1/2147483646'") HDPrivateKey(vector2_m_private).deriveChild("m/0/2147483647'/1/2147483646'")
.xpubkey.should.equal(vector2_m02147483647h12147483646h_public); .xpubkey.should.equal(vector2_m02147483647h12147483646h_public);
}); });
it("should get m/0/2147483647h/1/2147483646h/2 ext. private key from test vector 2", function() { it("should get m/0/2147483647h/1/2147483646h/2 ext. private key from test vector 2", function() {
HDPrivateKey(vector2_m_private).derive("m/0/2147483647'/1/2147483646'/2") HDPrivateKey(vector2_m_private).deriveChild("m/0/2147483647'/1/2147483646'/2")
.xprivkey.should.equal(vector2_m02147483647h12147483646h2_private); .xprivkey.should.equal(vector2_m02147483647h12147483646h2_private);
}); });
it("should get m/0/2147483647h/1/2147483646h/2 ext. public key from test vector 2", function() { it("should get m/0/2147483647h/1/2147483646h/2 ext. public key from test vector 2", function() {
HDPrivateKey(vector2_m_private).derive("m/0/2147483647'/1/2147483646'/2") HDPrivateKey(vector2_m_private).deriveChild("m/0/2147483647'/1/2147483646'/2")
.xpubkey.should.equal(vector2_m02147483647h12147483646h2_public); .xpubkey.should.equal(vector2_m02147483647h12147483646h2_public);
}); });
it("should get m/0/2147483647h/1/2147483646h/2 ext. public key from m/0/2147483647h/2147483646h public key from test vector 2", function() { it("should get m/0/2147483647h/1/2147483646h/2 ext. public key from m/0/2147483647h/2147483646h public key from test vector 2", function() {
var derivedPublic = HDPrivateKey(vector2_m_private) var derivedPublic = HDPrivateKey(vector2_m_private)
.derive("m/0/2147483647'/1/2147483646'").hdPublicKey; .deriveChild("m/0/2147483647'/1/2147483646'").hdPublicKey;
derivedPublic.derive("m/2") derivedPublic.deriveChild("m/2")
.xpubkey.should.equal(vector2_m02147483647h12147483646h2_public); .xpubkey.should.equal(vector2_m02147483647h12147483646h2_public);
}); });
@ -234,7 +234,7 @@ describe('BIP32 compliance', function() {
privateKey: privateKeyBuffer, privateKey: privateKeyBuffer,
chainCode: chainCodeBuffer chainCode: chainCodeBuffer
}); });
var derived = key.derive("m/44'/0'/0'/0/0'"); var derived = key.deriveChild("m/44'/0'/0'/0/0'");
derived.privateKey.toString().should.equal('3348069561d2a0fb925e74bf198762acc47dce7db27372257d2d959a9e6f8aeb'); derived.privateKey.toString().should.equal('3348069561d2a0fb925e74bf198762acc47dce7db27372257d2d959a9e6f8aeb');
}); });
@ -250,10 +250,25 @@ describe('BIP32 compliance', function() {
privateKey: privateKeyBuffer, privateKey: privateKeyBuffer,
chainCode: chainCodeBuffer chainCode: chainCodeBuffer
}); });
var derived = key.deriveNonCompliant("m/44'/0'/0'/0/0'"); var derived = key.deriveNonCompliantChild("m/44'/0'/0'/0/0'");
derived.privateKey.toString().should.equal('4811a079bab267bfdca855b3bddff20231ff7044e648514fa099158472df2836'); derived.privateKey.toString().should.equal('4811a079bab267bfdca855b3bddff20231ff7044e648514fa099158472df2836');
}); });
it('hdprivatekey will throw deprecation message', function() {
expect(function() {
var key = new HDPrivateKey();
key.derive();
}).to.throw('Method has been deprecated');
});
it('hdpublickey will throw deprecation message', function() {
expect(function() {
var key = new HDPrivateKey();
var pubkey = key.hdPublicKey;
pubkey.derive();
}).to.throw('Method has been deprecated');
});
describe('edge cases', function() { describe('edge cases', function() {
var sandbox = sinon.sandbox.create(); var sandbox = sinon.sandbox.create();
afterEach(function() { afterEach(function() {
@ -284,7 +299,7 @@ describe('BIP32 compliance', function() {
privateKey: privateKeyBuffer, privateKey: privateKeyBuffer,
chainCode: chainCodeBuffer chainCode: chainCodeBuffer
}); });
var derived = key.derive("m/44'"); var derived = key.deriveChild("m/44'");
derived.privateKey.toString().should.equal('b15bce3608d607ee3a49069197732c656bca942ee59f3e29b4d56914c1de6825'); derived.privateKey.toString().should.equal('b15bce3608d607ee3a49069197732c656bca942ee59f3e29b4d56914c1de6825');
bitcore.PrivateKey.isValid.callCount.should.equal(2); bitcore.PrivateKey.isValid.callCount.should.equal(2);
}); });
@ -305,7 +320,7 @@ describe('BIP32 compliance', function() {
throw new Error('Point cannot be equal to Infinity'); throw new Error('Point cannot be equal to Infinity');
}; };
sandbox.spy(key, '_deriveWithNumber'); sandbox.spy(key, '_deriveWithNumber');
var derived = key.derive("m/44"); var derived = key.deriveChild("m/44");
key._deriveWithNumber.callCount.should.equal(2); key._deriveWithNumber.callCount.should.equal(2);
key.publicKey.toString().should.equal('029e58b241790284ef56502667b15157b3fc58c567f044ddc35653860f9455d099'); key.publicKey.toString().should.equal('029e58b241790284ef56502667b15157b3fc58c567f044ddc35653860f9455d099');
}); });

12
test/hdprivatekey.js

@ -30,7 +30,7 @@ describe('HDPrivate key interface', function() {
var expectDerivationFail = function(argument, error) { var expectDerivationFail = function(argument, error) {
return expectFail(function() { return expectFail(function() {
var privateKey = new HDPrivateKey(xprivkey); var privateKey = new HDPrivateKey(xprivkey);
privateKey.derive(argument); privateKey.deriveChild(argument);
}, error); }, error);
}; };
@ -123,14 +123,14 @@ describe('HDPrivate key interface', function() {
it('allows derivation of hardened keys by passing a very big number', function() { it('allows derivation of hardened keys by passing a very big number', function() {
var privateKey = new HDPrivateKey(xprivkey); var privateKey = new HDPrivateKey(xprivkey);
var derivedByNumber = privateKey.derive(0x80000000); var derivedByNumber = privateKey.deriveChild(0x80000000);
var derivedByArgument = privateKey.derive(0, true); var derivedByArgument = privateKey.deriveChild(0, true);
derivedByNumber.xprivkey.should.equal(derivedByArgument.xprivkey); derivedByNumber.xprivkey.should.equal(derivedByArgument.xprivkey);
}); });
it('returns itself with \'m\' parameter', function() { it('returns itself with \'m\' parameter', function() {
var privateKey = new HDPrivateKey(xprivkey); var privateKey = new HDPrivateKey(xprivkey);
privateKey.should.equal(privateKey.derive('m')); privateKey.should.equal(privateKey.deriveChild('m'));
}); });
it('returns InvalidArgument if invalid data is given to getSerializedError', function() { it('returns InvalidArgument if invalid data is given to getSerializedError', function() {
@ -203,8 +203,8 @@ describe('HDPrivate key interface', function() {
it('shouldn\'t matter if derivations are made with strings or numbers', function() { it('shouldn\'t matter if derivations are made with strings or numbers', function() {
var privateKey = new HDPrivateKey(xprivkey); var privateKey = new HDPrivateKey(xprivkey);
var derivedByString = privateKey.derive('m/0\'/1/2\''); var derivedByString = privateKey.deriveChild('m/0\'/1/2\'');
var derivedByNumber = privateKey.derive(0, true).derive(1).derive(2, true); var derivedByNumber = privateKey.deriveChild(0, true).deriveChild(1).deriveChild(2, true);
derivedByNumber.xprivkey.should.equal(derivedByString.xprivkey); derivedByNumber.xprivkey.should.equal(derivedByString.xprivkey);
}); });

20
test/hdpublickey.js

@ -32,7 +32,7 @@ describe('HDPublicKey interface', function() {
var expectDerivationFail = function(argument, error) { var expectDerivationFail = function(argument, error) {
(function() { (function() {
var pubkey = new HDPublicKey(xpubkey); var pubkey = new HDPublicKey(xpubkey);
pubkey.derive(argument); pubkey.deriveChild(argument);
}).should.throw(error); }).should.throw(error);
}; };
@ -188,15 +188,15 @@ describe('HDPublicKey interface', function() {
describe('derivation', function() { describe('derivation', function() {
it('derivation is the same whether deriving with number or string', function() { it('derivation is the same whether deriving with number or string', function() {
var pubkey = new HDPublicKey(xpubkey); var pubkey = new HDPublicKey(xpubkey);
var derived1 = pubkey.derive(0).derive(1).derive(200000); var derived1 = pubkey.deriveChild(0).deriveChild(1).deriveChild(200000);
var derived2 = pubkey.derive('m/0/1/200000'); var derived2 = pubkey.deriveChild('m/0/1/200000');
derived1.xpubkey.should.equal(derived_0_1_200000); derived1.xpubkey.should.equal(derived_0_1_200000);
derived2.xpubkey.should.equal(derived_0_1_200000); derived2.xpubkey.should.equal(derived_0_1_200000);
}); });
it('allows special parameters m, M', function() { it('allows special parameters m, M', function() {
var expectDerivationSuccess = function(argument) { var expectDerivationSuccess = function(argument) {
new HDPublicKey(xpubkey).derive(argument).xpubkey.should.equal(xpubkey); new HDPublicKey(xpubkey).deriveChild(argument).xpubkey.should.equal(xpubkey);
}; };
expectDerivationSuccess('m'); expectDerivationSuccess('m');
expectDerivationSuccess('M'); expectDerivationSuccess('M');
@ -204,13 +204,13 @@ describe('HDPublicKey interface', function() {
it('doesn\'t allow object arguments for derivation', function() { it('doesn\'t allow object arguments for derivation', function() {
expectFail(function() { expectFail(function() {
return new HDPublicKey(xpubkey).derive({}); return new HDPublicKey(xpubkey).deriveChild({});
}, hdErrors.InvalidDerivationArgument); }, hdErrors.InvalidDerivationArgument);
}); });
it('needs first argument for derivation', function() { it('needs first argument for derivation', function() {
expectFail(function() { expectFail(function() {
return new HDPublicKey(xpubkey).derive('s'); return new HDPublicKey(xpubkey).deriveChild('s');
}, hdErrors.InvalidPath); }, hdErrors.InvalidPath);
}); });
@ -224,13 +224,13 @@ describe('HDPublicKey interface', function() {
it('can\'t derive hardened keys', function() { it('can\'t derive hardened keys', function() {
expectFail(function() { expectFail(function() {
return new HDPublicKey(xpubkey).derive(HDPublicKey.Hardened); return new HDPublicKey(xpubkey).deriveChild(HDPublicKey.Hardened);
}, hdErrors.InvalidIndexCantDeriveHardened); }, hdErrors.InvalidIndexCantDeriveHardened);
}); });
it('can\'t derive hardened keys via second argument', function() { it('can\'t derive hardened keys via second argument', function() {
expectFail(function() { expectFail(function() {
return new HDPublicKey(xpubkey).derive(5, true); return new HDPublicKey(xpubkey).deriveChild(5, true);
}, hdErrors.InvalidIndexCantDeriveHardened); }, hdErrors.InvalidIndexCantDeriveHardened);
}); });
@ -274,8 +274,8 @@ describe('HDPublicKey interface', function() {
it('should use the cache', function() { it('should use the cache', function() {
var pubkey = new HDPublicKey(xpubkey); var pubkey = new HDPublicKey(xpubkey);
var derived1 = pubkey.derive(0); var derived1 = pubkey.deriveChild(0);
var derived2 = pubkey.derive(0); var derived2 = pubkey.deriveChild(0);
derived1.should.equal(derived2); derived1.should.equal(derived2);
}); });
}); });

Loading…
Cancel
Save