Browse Source

implemented method fromExtendedKey()

master
JP Richardson 11 years ago
parent
commit
5e592afeee
  1. 35
      lib/hdkey.js
  2. 41
      test/hdkey.test.js

35
lib/hdkey.js

@ -23,10 +23,13 @@ function HDKey(versions) {
this._privateKeyInteger = BigInteger.ZERO
this._publicKey = null
this.chainCode = null
this._fingerprint = 0
this.parentFingerprint = 0
}
Object.defineProperty(HDKey.prototype, 'fingerprint', {get: function() { return this.identifier.slice(0, 4) } })
Object.defineProperty(HDKey.prototype, 'fingerprint', { get: function() { return this._fingerprint } })
Object.defineProperty(HDKey.prototype, 'identifier', {get: function() { return this._identifier } })
Object.defineProperty(HDKey.prototype, 'pubKeyHash', {get: function() { return this.identifier }})
Object.defineProperty(HDKey.prototype, 'privateKey', {
get: function() {
@ -38,6 +41,7 @@ Object.defineProperty(HDKey.prototype, 'privateKey', {
this._privateKeyInteger = BigInteger.fromBuffer(this._privateKey)
this._publicKey = ecparams.params.G.multiply(this._privateKeyInteger).getEncoded(true) //force compressed point
this._identifier = hash160(this.publicKey)
this._fingerprint = this._identifier.slice(0, 4).readUInt32BE(0)
}
})
@ -49,6 +53,8 @@ Object.defineProperty(HDKey.prototype, 'publicKey', {
assert(value.length === 33 || value.length === 65, 'Public key must be 33 or 65 bytes.')
var pt = Point.decodeFrom(ecparams, value)
this._publicKey = pt.getEncoded(true) //force compressed point
this._identifier = hash160(this.publicKey)
this._fingerprint = this._identifier.slice(0, 4).readUInt32BE(0)
this._privateKey = null
this._privateKeyInteger = null
}
@ -147,7 +153,7 @@ HDKey.prototype.deriveChild = function(index) {
hd.chainCode = IR
hd.depth = this.depth + 1
hd.parentFingerprint = this.fingerprint.readUInt32BE(0)
hd.parentFingerprint = this.fingerprint//.readUInt32BE(0)
hd.index = index
return hd
@ -165,6 +171,31 @@ HDKey.fromMasterSeed = function(seedBuffer, versions) {
return hdkey
}
HDKey.fromExtendedKey = function(keyBuffer, versions) {
// => version(4) || depth(1) || fingerprint(4) || index(4) || chain(32) || key(33)
versions = versions || BITCOIN_VERSIONS
var hdkey = new HDKey(versions)
var version = keyBuffer.readUInt32BE(0)
assert(version === versions.private || version === versions.public, 'Version mismatch: does not match private or public')
hdkey.depth = keyBuffer.readUInt8(4)
hdkey.parentFingerprint = keyBuffer.readUInt32BE(5)
hdkey.index = keyBuffer.readUInt32BE(9)
hdkey.chainCode = keyBuffer.slice(13, 45)
var key = keyBuffer.slice(45)
if (key.readUInt8(0) === 0) { //private
assert(version === versions.private, 'Version mismatch: version does not match private')
hdkey.privateKey = key.slice(1) //cut off first 0x0 byte
} else {
assert(version === versions.public, 'Version mismatch: version does not match public')
hdkey.publicKey = key
}
return hdkey
}
function serialize(hdkey, version, key) {
// => version(4) || depth(1) || fingerprint(4) || index(4) || chain(32) || key(33)
var buffer = new Buffer(LEN)

41
test/hdkey.test.js

@ -23,6 +23,9 @@ describe('hdkey', function() {
var hdkey = HDKey.fromMasterSeed(new Buffer(f.seed, 'hex'))
var childkey = hdkey.derive(f.path)
if (encode(childkey.privateExtendedKey) == "xprvA2nrNbFZABcdryreWet9Ea4LvTJcGsqrMzxHx98MMrotbir7yrKCEXw7nadnHM8Dq38EGfSh6dqA9QWTyefMLEcBYJUuekgW4BYPJcr9E7j")
console.log(childkey.fingerprint.toString('16'))
assert.equal(encode(childkey.privateExtendedKey), f.private)
assert.equal(encode(childkey.publicExtendedKey), f.public)
})
@ -62,4 +65,42 @@ describe('hdkey', function() {
hdkey.publicKey = pub
})
})
describe('+ fromExtendedKey()', function() {
describe('> when private', function() {
it('should parse it', function() {
//m/0/2147483647'/1/2147483646'/2
var key = "xprvA2nrNbFZABcdryreWet9Ea4LvTJcGsqrMzxHx98MMrotbir7yrKCEXw7nadnHM8Dq38EGfSh6dqA9QWTyefMLEcBYJUuekgW4BYPJcr9E7j"
var keyBuffer = bs58.decode(key).slice(0, 78)
var hdkey = HDKey.fromExtendedKey(keyBuffer)
assert.equal(hdkey.versions.private, 0x0488ade4)
assert.equal(hdkey.versions.public, 0x0488b21e)
assert.equal(hdkey.depth, 5)
assert.equal(hdkey.parentFingerprint, 0x31a507b8)
assert.equal(hdkey.index, 2)
assert.equal(hdkey.chainCode.toString('hex'), '9452b549be8cea3ecb7a84bec10dcfd94afe4d129ebfd3b3cb58eedf394ed271')
assert.equal(hdkey.privateKey.toString('hex'), 'bb7d39bdb83ecf58f2fd82b6d918341cbef428661ef01ab97c28a4842125ac23')
assert.equal(hdkey.publicKey.toString('hex'), '024d902e1a2fc7a8755ab5b694c575fce742c48d9ff192e63df5193e4c7afe1f9c')
assert.equal(hdkey.identifier.toString('hex'), '26132fdbe7bf89cbc64cf8dafa3f9f88b8666220')
})
})
describe('> when public', function() {
it('should parse it', function() {
//m/0/2147483647'/1/2147483646'/2
var key = "xpub6FnCn6nSzZAw5Tw7cgR9bi15UV96gLZhjDstkXXxvCLsUXBGXPdSnLFbdpq8p9HmGsApME5hQTZ3emM2rnY5agb9rXpVGyy3bdW6EEgAtqt"
var keyBuffer = bs58.decode(key).slice(0, 78)
var hdkey = HDKey.fromExtendedKey(keyBuffer)
assert.equal(hdkey.versions.private, 0x0488ade4)
assert.equal(hdkey.versions.public, 0x0488b21e)
assert.equal(hdkey.depth, 5)
assert.equal(hdkey.parentFingerprint, 0x31a507b8)
assert.equal(hdkey.index, 2)
assert.equal(hdkey.chainCode.toString('hex'), '9452b549be8cea3ecb7a84bec10dcfd94afe4d129ebfd3b3cb58eedf394ed271')
assert.equal(hdkey.privateKey, null)
assert.equal(hdkey.publicKey.toString('hex'), '024d902e1a2fc7a8755ab5b694c575fce742c48d9ff192e63df5193e4c7afe1f9c')
assert.equal(hdkey.identifier.toString('hex'), '26132fdbe7bf89cbc64cf8dafa3f9f88b8666220')
})
})
})
})

Loading…
Cancel
Save