commit
09455a6ad8
2 changed files with 58 additions and 22 deletions
|
@ -31,6 +31,7 @@ function HDNode(K, chainCode, network) {
|
|||
network = network || networks.bitcoin
|
||||
|
||||
assert(Buffer.isBuffer(chainCode), 'Expected Buffer, got ' + chainCode)
|
||||
assert.equal(chainCode.length, 32, 'Expected chainCode length of 32, got ' + chainCode.length)
|
||||
assert(network.bip32, 'Unknown BIP32 constants for network')
|
||||
|
||||
this.chainCode = chainCode
|
||||
|
@ -142,12 +143,27 @@ HDNode.prototype.getAddress = function() {
|
|||
return this.pubKey.getAddress(this.network)
|
||||
}
|
||||
|
||||
HDNode.prototype.neutered = function() {
|
||||
var neutered = new HDNode(this.pubKey.Q, this.chainCode, this.network)
|
||||
neutered.depth = this.depth
|
||||
neutered.index = this.index
|
||||
neutered.parentFingerprint = this.parentFingerprint
|
||||
|
||||
return neutered
|
||||
}
|
||||
|
||||
HDNode.prototype.toBase58 = function(isPrivate) {
|
||||
return base58check.encode(this.toBuffer(isPrivate))
|
||||
}
|
||||
|
||||
HDNode.prototype.toBuffer = function(isPrivate) {
|
||||
if (isPrivate == undefined) isPrivate = !!this.privKey
|
||||
if (isPrivate == undefined) {
|
||||
isPrivate = !!this.privKey
|
||||
|
||||
// FIXME: remove in 2.x.y
|
||||
} else {
|
||||
console.warn('isPrivate flag is deprecated, please use the .neutered() method instead')
|
||||
}
|
||||
|
||||
// Version
|
||||
var version = isPrivate ? this.network.bip32.private : this.network.bip32.public
|
||||
|
@ -173,6 +189,7 @@ HDNode.prototype.toBuffer = function(isPrivate) {
|
|||
|
||||
// 33 bytes: the public key or private key data
|
||||
if (isPrivate) {
|
||||
// FIXME: remove in 2.x.y
|
||||
assert(this.privKey, 'Missing private key')
|
||||
|
||||
// 0x00 + k for private keys
|
||||
|
|
|
@ -49,7 +49,13 @@ describe('HDNode', function() {
|
|||
assert.equal(hd.network, networks.testnet)
|
||||
})
|
||||
|
||||
it('throws an exception when an unknown network is given', function() {
|
||||
it('throws when an invalid length chain code is given', function() {
|
||||
assert.throws(function() {
|
||||
new HDNode(d, chainCode.slice(0, 20), networks.testnet)
|
||||
}, /Expected chainCode length of 32, got 20/)
|
||||
})
|
||||
|
||||
it('throws when an unknown network is given', function() {
|
||||
assert.throws(function() {
|
||||
new HDNode(d, chainCode, {})
|
||||
}, /Unknown BIP32 constants for network/)
|
||||
|
@ -82,9 +88,9 @@ describe('HDNode', function() {
|
|||
describe('toBase58', function() {
|
||||
fixtures.valid.forEach(function(f) {
|
||||
it('exports ' + f.master.base58 + ' (public) correctly', function() {
|
||||
var hd = HDNode.fromSeedHex(f.master.seed)
|
||||
var hd = HDNode.fromSeedHex(f.master.seed).neutered()
|
||||
|
||||
assert.equal(hd.toBase58(false), f.master.base58)
|
||||
assert.equal(hd.toBase58(), f.master.base58)
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -92,10 +98,11 @@ describe('HDNode', function() {
|
|||
it('exports ' + f.master.base58Priv + ' (private) correctly', function() {
|
||||
var hd = HDNode.fromSeedHex(f.master.seed)
|
||||
|
||||
assert.equal(hd.toBase58(true), f.master.base58Priv)
|
||||
assert.equal(hd.toBase58(), f.master.base58Priv)
|
||||
})
|
||||
})
|
||||
|
||||
// FIXME: remove in 2.x.y
|
||||
it('fails when there is no private key', function() {
|
||||
var hd = HDNode.fromBase58(fixtures.valid[0].master.base58)
|
||||
|
||||
|
@ -160,9 +167,9 @@ describe('HDNode', function() {
|
|||
describe('toBuffer/toHex', function() {
|
||||
fixtures.valid.forEach(function(f) {
|
||||
it('exports ' + f.master.hex + ' (public) correctly', function() {
|
||||
var hd = HDNode.fromSeedHex(f.master.seed)
|
||||
var hd = HDNode.fromSeedHex(f.master.seed).neutered()
|
||||
|
||||
assert.equal(hd.toHex(false), f.master.hex)
|
||||
assert.equal(hd.toHex(), f.master.hex)
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -170,10 +177,11 @@ describe('HDNode', function() {
|
|||
it('exports ' + f.master.hexPriv + ' (private) correctly', function() {
|
||||
var hd = HDNode.fromSeedHex(f.master.seed)
|
||||
|
||||
assert.equal(hd.toHex(true), f.master.hexPriv)
|
||||
assert.equal(hd.toHex(), f.master.hexPriv)
|
||||
})
|
||||
})
|
||||
|
||||
// FIXME: remove in 2.x.y
|
||||
it('fails when there is no private key', function() {
|
||||
var hd = HDNode.fromHex(fixtures.valid[0].master.hex)
|
||||
|
||||
|
@ -220,6 +228,21 @@ describe('HDNode', function() {
|
|||
})
|
||||
})
|
||||
|
||||
describe('neutered', function() {
|
||||
var f = fixtures.valid[0]
|
||||
|
||||
it('strips all private information', function() {
|
||||
var hd = HDNode.fromBase58(f.master.base58)
|
||||
var hdn = hd.neutered()
|
||||
|
||||
assert.equal(hdn.privKey, undefined)
|
||||
assert.equal(hdn.pubKey.toHex(), hd.pubKey.toHex())
|
||||
assert.equal(hdn.chainCode, hd.chainCode)
|
||||
assert.equal(hdn.depth, hd.depth)
|
||||
assert.equal(hdn.index, hd.index)
|
||||
})
|
||||
})
|
||||
|
||||
describe('derive', function() {
|
||||
function verifyVector(hd, v, depth) {
|
||||
assert.equal(hd.privKey.toWIF(), v.wif)
|
||||
|
@ -256,32 +279,28 @@ describe('HDNode', function() {
|
|||
var f = fixtures.valid[1]
|
||||
var c = f.children[0]
|
||||
|
||||
var parentNode = HDNode.fromBase58(f.master.base58Priv)
|
||||
var child = parentNode.derive(c.m)
|
||||
var master = HDNode.fromBase58(f.master.base58Priv)
|
||||
var child = master.derive(c.m).neutered()
|
||||
|
||||
// FIXME: N(CKDpriv((kpar, cpar), i)), could be done better...
|
||||
var childNeutered = HDNode.fromBase58(child.toBase58(false)) // neuter
|
||||
assert.equal(childNeutered.toBase58(), c.base58)
|
||||
assert.equal(child.toBase58(), c.base58)
|
||||
})
|
||||
|
||||
it('works for Private -> public (neutered, hardened)', function() {
|
||||
var f = fixtures.valid[0]
|
||||
var c = f.children[0]
|
||||
|
||||
var parentNode = HDNode.fromBase58(f.master.base58Priv)
|
||||
var child = parentNode.deriveHardened(c.m)
|
||||
var master = HDNode.fromBase58(f.master.base58Priv)
|
||||
var child = master.deriveHardened(c.m).neutered()
|
||||
|
||||
// FIXME: N(CKDpriv((kpar, cpar), i)), could be done better...
|
||||
var childNeutered = HDNode.fromBase58(child.toBase58(false)) // neuter
|
||||
assert.equal(childNeutered.toBase58(), c.base58)
|
||||
assert.equal(child.toBase58(), c.base58)
|
||||
})
|
||||
|
||||
it('works for Public -> public', function() {
|
||||
var f = fixtures.valid[1]
|
||||
var c = f.children[0]
|
||||
|
||||
var parentNode = HDNode.fromBase58(f.master.base58)
|
||||
var child = parentNode.derive(c.m)
|
||||
var master = HDNode.fromBase58(f.master.base58)
|
||||
var child = master.derive(c.m)
|
||||
|
||||
assert.equal(child.toBase58(), c.base58)
|
||||
})
|
||||
|
@ -290,10 +309,10 @@ describe('HDNode', function() {
|
|||
var f = fixtures.valid[0]
|
||||
var c = f.children[0]
|
||||
|
||||
var parentNode = HDNode.fromBase58(f.master.base58)
|
||||
var master = HDNode.fromBase58(f.master.base58)
|
||||
|
||||
assert.throws(function() {
|
||||
parentNode.deriveHardened(c.m)
|
||||
master.deriveHardened(c.m)
|
||||
}, /Could not derive hardened child key/)
|
||||
})
|
||||
})
|
||||
|
|
Loading…
Add table
Reference in a new issue