From fa22c79dbe799bdbc8ab0f74e8faaeaf8cb07c3d Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Thu, 4 Feb 2016 02:44:16 -0800 Subject: [PATCH] hd and wallet work. --- lib/bcoin.js | 5 +- lib/bcoin/address.js | 10 +- lib/bcoin/hd.js | 211 +++++++++++++++---------------------------- lib/bcoin/keypair.js | 136 ++++++++-------------------- lib/bcoin/script.js | 2 +- lib/bcoin/tx-pool.js | 17 ++++ lib/bcoin/utils.js | 2 +- lib/bcoin/wallet.js | 152 ++++++++++++++++--------------- 8 files changed, 219 insertions(+), 316 deletions(-) diff --git a/lib/bcoin.js b/lib/bcoin.js index b3301b1c..ef6f8010 100644 --- a/lib/bcoin.js +++ b/lib/bcoin.js @@ -39,6 +39,9 @@ bcoin.protocol.network.set(process.env.BCOIN_NETWORK || 'main'); bcoin.bn = bn; bcoin.elliptic = elliptic; -bcoin.signature = require('elliptic/lib/elliptic/ec/signature'); +bcoin.utils.assert(!bcoin.ecdsa.signature); +bcoin.ecdsa.signature = require('elliptic/lib/elliptic/ec/signature'); +bcoin.utils.assert(!bcoin.ecdsa.keypair); +bcoin.ecdsa.keypair = require('elliptic/lib/elliptic/ec/key'); bcoin.hash = hash; bcoin.async = async; diff --git a/lib/bcoin/address.js b/lib/bcoin/address.js index 398f54f7..c917e9b3 100644 --- a/lib/bcoin/address.js +++ b/lib/bcoin/address.js @@ -34,15 +34,9 @@ function Address(options) { this.storage = options.storage; this.label = options.label || ''; this.change = !!options.change; + this.derived = !!options.derived; - this.key = bcoin.keypair({ - priv: options.priv, - pub: options.pub, - key: options.key, - personalization: options.personalization, - entropy: options.entropy, - compressed: options.compressed - }); + this.key = bcoin.keypair(options); this.type = options.type || 'pubkeyhash'; this.subtype = options.subtype; diff --git a/lib/bcoin/hd.js b/lib/bcoin/hd.js index 22c7f25f..02a9ce5c 100644 --- a/lib/bcoin/hd.js +++ b/lib/bcoin/hd.js @@ -538,7 +538,7 @@ HDPrivateKey.prototype._normalize = function _normalize(data, version) { }; HDPrivateKey.prototype._seed = function _seed(seed) { - if (seed instanceof bcoin.hd.seed) + if (seed instanceof HDSeed) seed = seed.seed; if (utils.isHex(seed)) @@ -592,27 +592,20 @@ HDPrivateKey.prototype._unbuild = function _unbuild(xkey) { }; HDPrivateKey.prototype._build = function _build(data) { - var sequence = []; + var sequence = new Array(82); var off = 0; var checksum, xprivkey, pair, privateKey, publicKey, size, fingerPrint; - utils.copy(data.version, sequence, off, true); - off += data.version.length; - utils.copy(data.depth, sequence, off, true); - off += data.depth.length; - utils.copy(data.parentFingerPrint, sequence, off, true); - off += data.parentFingerPrint.length; - utils.copy(data.childIndex, sequence, off, true); - off += data.childIndex.length; - utils.copy(data.chainCode, sequence, off, true); - off += data.chainCode.length; - utils.copy([0], sequence, off, true); - off += [0].length; - utils.copy(data.privateKey, sequence, off, true); - off += data.privateKey.length; - checksum = utils.dsha256(sequence).slice(0, 4); - utils.copy(checksum, sequence, off, true); - off += checksum.length; + off += utils.copy(data.version, sequence, off); + off += utils.copy(data.depth, sequence, off); + off += utils.copy(data.parentFingerPrint, sequence, off); + off += utils.copy(data.childIndex, sequence, off); + off += utils.copy(data.chainCode, sequence, off); + off += utils.copy([0], sequence, off); + off += utils.copy(data.privateKey, sequence, off); + checksum = utils.dsha256(sequence.slice(0, off)).slice(0, 4); + off += utils.copy(checksum, sequence, off); + assert(off === 82); xprivkey = utils.toBase58(sequence); @@ -635,7 +628,18 @@ HDPrivateKey.prototype._build = function _build(data) { this.fingerPrint = fingerPrint; this.publicKey = publicKey; - this.hdpub = bcoin.hd.pub(this); + this.hdpub = new HDPublicKey({ + version: this.version, + depth: this.depth, + parentFingerPrint: this.parentFingerPrint, + childIndex: this.childIndex, + chainCode: this.chainCode, + privateKey: this.privateKey, + checksum: this.checksum, + publicKey: this.publicKey, + master: this.master + }); + this.xpubkey = this.hdpub.xpubkey; this.pair = bcoin.ecdsa.keyPair({ priv: this.privateKey }); }; @@ -697,18 +701,6 @@ HDPrivateKey._getIndexes = function _getIndexes(path) { index = +step; - if (i === 0) { - indexes.purpose = index; - } else if (i === 1) { - indexes.coinType = index; - } else if (i === 2) { - indexes.accountIndex = index; - } else if (i === 3) { - indexes.isChange = index === 1; - } else if (i === 4) { - indexes.addressIndex = index; - } - if (hardened) index += constants.hd.hardened; @@ -743,130 +735,76 @@ HDPrivateKey.prototype.deriveString = function deriveString(path) { indexes = HDPrivateKey._getIndexes(path); - child = indexes.reduce(function(prev, index, i) { + return indexes.reduce(function(prev, index, i) { return prev.derive(index); }, this); - - child.purpose = indexes.purpose; - child.coinType = indexes.coinType; - child.accountIndex = indexes.accountIndex; - child.isChange = indexes.isChange; - child.addressIndex = indexes.addressIndex; - - return child; }; HDPrivateKey.prototype.toJSON = function toJSON(encrypt) { var json = { v: 1, - name: 'keypair', + name: 'hdkey', encrypted: encrypt ? true : false }; - if (this.hd) { - if (this.hd.xprivkey) { - if (this.hd.seed) { - json.mnemonic = encrypt - ? encrypt(this.hd.seed.mnemonic) - : this.hd.seed.mnemonic; - json.passphrase = encrypt - ? encrypt(this.hd.seed.passphrase) - : this.hd.seed.passphrase; - return json; - } - json.xpriv = encrypt - ? encrypt(this.hd.xprivkey) - : this.hd.xprivkey; + if (this instanceof HDPrivateKey) { + if (this.seed) { + json.mnemonic = encrypt + ? encrypt(this.seed.mnemonic) + : this.seed.mnemonic; + json.passphrase = encrypt + ? encrypt(this.seed.passphrase) + : this.seed.passphrase; return json; } - - json.xpub = this.hd.xpubkey; - + json.xprivkey = encrypt + ? encrypt(this.xprivkey) + : this.xprivkey; return json; } - if (this._key.priv) { - json.priv = encrypt - ? encrypt(this.getPrivate('base58')) - : this.getPrivate('base58'); - return json; - } + json.xpubkey = this.hd.xpubkey; - json.pub = this.getPublic('hex'); return json; }; HDPrivateKey.fromJSON = function fromJSON(json, decrypt) { - var key, priv, pub, compressed, xprivkey; - var path = {}; - assert.equal(json.v, 1); - assert.equal(json.name, 'keypair'); + assert.equal(json.name, 'hdkey'); if (json.encrypted && !decrypt) throw new Error('Cannot decrypt address'); if (json.mnemonic) { - return new KeyPair({ - key: bcoin.hd.priv({ - seed: bcoin.hd.seed({ - mnemonic: json.encrypted - ? decrypt(json.mnemonic) - : json.mnemonic, - passphrase: json.encrypted - ? decrypt(json.passphrase) - : json.passphrase - }) + return new HDPrivateKey({ + seed: new HDSeed({ + mnemonic: json.encrypted + ? decrypt(json.mnemonic) + : json.mnemonic, + passphrase: json.encrypted + ? decrypt(json.passphrase) + : json.passphrase }) }); } - if (json.xpriv) { - xprivkey = json.xpriv; - if (json.encrypted) - xprivkey = decrypt(xprivkey); - return new KeyPair({ - key: bcoin.hd.priv({ - xkey: xprivkey - }) + if (json.xprivkey) { + return new HDPrivateKey({ + xkey: json.encrypted + ? decrypt(json.xprivkey) + : json.xprivkey }); } - if (json.xpub) { - return new KeyPair({ - key: bcoin.hd.pub({ - xkey: json.xpub - }) - }); - } - - if (json.priv) { - priv = json.priv; - if (json.encrypted) - priv = decrypt(priv); - - key = KeyPair.fromSecret(json.priv); - priv = key.priv; - compressed = key.compressed; - return new KeyPair({ - priv: priv, - compressed: compressed - }); - } - - if (json.pub) { - pub = bcoin.utils.toArray(json.pub, 'hex'); - compressed = pub[0] !== 0x04; - return new KeyPair({ - pub: pub, - compressed: compressed + if (json.xpubkey) { + return new HDPublicKey({ + xkey: json.xpubkey }); } assert(false); }; - /** * HD Public Key */ @@ -917,6 +855,8 @@ HDPublicKey.prototype.deriveCosignerAddress = HDPrivateKey.prototype.deriveCosig HDPublicKey.prototype.isPurpose45 = HDPrivateKey.prototype.isPurpose45; HDPublicKey.prototype.isAccount44 = HDPrivateKey.prototype.isAccount44; +HDPublicKey.prototype.toJSON = HDPrivateKey.prototype.toJSON; +HDPublicKey.fromJSON = HDPrivateKey.fromJSON; HDPublicKey.isExtended = function isExtended(data) { if (typeof data !== 'string') @@ -956,25 +896,19 @@ HDPublicKey.prototype._unbuild = function _unbuild(xkey) { }; HDPublicKey.prototype._build = function _build(data) { - var sequence = []; + var sequence = new Array(82); var off = 0; var checksum, xpubkey, publicKey, size, fingerPrint; - utils.copy(data.version, sequence, off, true); - off += data.version.length; - utils.copy(data.depth, sequence, off, true); - off += data.depth.length; - utils.copy(data.parentFingerPrint, sequence, off, true); - off += data.parentFingerPrint.length; - utils.copy(data.childIndex, sequence, off, true); - off += data.childIndex.length; - utils.copy(data.chainCode, sequence, off, true); - off += data.chainCode.length; - utils.copy(data.publicKey, sequence, off, true); - off += data.publicKey.length; - checksum = utils.dsha256(sequence).slice(0, 4); - utils.copy(checksum, sequence, off, true); - off += checksum.length; + off += utils.copy(data.version, sequence, off); + off += utils.copy(data.depth, sequence, off); + off += utils.copy(data.parentFingerPrint, sequence, off); + off += utils.copy(data.childIndex, sequence, off); + off += utils.copy(data.chainCode, sequence, off); + off += utils.copy(data.publicKey, sequence, off); + checksum = utils.dsha256(sequence.slice(0, off)).slice(0, 4); + off += utils.copy(checksum, sequence, off); + assert(off === 82); if (!data.checksum || !data.checksum.length) data.checksum = checksum; @@ -1156,10 +1090,10 @@ function pbkdf2(key, salt, iterations, dkLen) { if (typeof salt === 'string') salt = utils.toArray(salt, null); - var DK = new Array(dkLen); - var U = new Array(hLen); - var T = new Array(hLen); - var block1 = new Array(salt.length + 4); + var DK = new Buffer(dkLen); + var U = new Buffer(hLen); + var T = new Buffer(hLen); + var block1 = new Buffer(salt.length + 4); var l = Math.ceil(dkLen / hLen); var r = dkLen - (l - 1) * hLen; @@ -1200,4 +1134,7 @@ function pbkdf2(key, salt, iterations, dkLen) { hd.seed = HDSeed; hd.priv = HDPrivateKey; hd.pub = HDPublicKey; +hd.privateKey = HDPrivateKey; +hd.publicKey = HDPublicKey; hd.pbkdf2 = pbkdf2; +hd.fromJSON = HDPrivateKey.fromJSON; diff --git a/lib/bcoin/keypair.js b/lib/bcoin/keypair.js index 7049e69e..f38281d2 100644 --- a/lib/bcoin/keypair.js +++ b/lib/bcoin/keypair.js @@ -29,59 +29,59 @@ function KeyPair(options) { return options.key; this.options = options; - this._key = options.key || null; - this.hd = options.hd || null; + this.pair = null; this.compressed = options.compressed !== false; - if (options.privateKey) - options.priv = options.privateKey; + if (options.key) + options.pair = options.key; - if (options.publicKey) - options.pub = options.publicKey; + if (options.priv) + options.privateKey = options.priv; - if (options.priv instanceof bcoin.hd.priv) { - this.hd = options.priv; - this._key = options.priv.pair; - } else if (options.pub instanceof bcoin.hd.pub) { - this.hd = options.pub; - this._key = options.pub.pair; - } else if (options.hd) { - this.hd = typeof options.hd === 'object' - ? bcoin.hd.priv(options.hd) - : bcoin.hd.priv(); - this._key = this.hd.pair; - } else if (options.key) { - if ((options.key instanceof bcoin.hd.priv) - || (options.key instanceof bcoin.hd.pub)) { - this.hd = options.key; - this._key = options.key.pair; - } else { - this._key = options.key; - } - } else if (options.priv || options.pub) { - this._key = bcoin.ecdsa.keyPair({ - priv: options.priv, - pub: options.pub + if (options.pub) + options.publicKey = options.pub; + + if (options.passphrase) + options.entropy = utils.sha256(options.passphrase); + + if (options.privateKey instanceof bcoin.hd.privateKey) { + this.pair = options.privateKey.pair; + } else if (options.publicKey instanceof bcoin.hd.publicKey) { + this.pair = options.publicKey.pair; + } else if (options.pair) { + assert(options.pair instanceof bcoin.ecdsa.keypair); + this.pair = options.pair; + } else if (options.privateKey || options.publicKey) { + this.pair = bcoin.ecdsa.keyPair({ + priv: options.privateKey, + pub: options.publicKey }); } else { - this._key = bcoin.ecdsa.genKeyPair({ + this.pair = bcoin.ecdsa.genKeyPair({ pers: options.personalization, entropy: options.entropy - || (options.passphrase ? utils.sha256(options.passphrase) : null) }); } } KeyPair.prototype.__defineGetter__('priv', function() { - return this._key.getPrivate(); + return this.pair.getPrivate(); }); KeyPair.prototype.__defineGetter__('pub', function() { - return this._key.getPublic(); + return this.pair.getPublic(); +}); + +KeyPair.prototype.__defineGetter__('privateKey', function() { + return this.pair.getPrivate(); +}); + +KeyPair.prototype.__defineGetter__('publicKey', function() { + return this.pair.getPublic(); }); KeyPair.prototype.getPrivate = function getPrivate(enc) { - var priv = this._key.getPrivate(); + var priv = this.pair.getPrivate(); if (!priv) return; @@ -98,7 +98,7 @@ KeyPair.prototype.getPrivate = function getPrivate(enc) { }; KeyPair.prototype.getPublic = function getPublic(enc) { - var pub = this._key.getPublic(this.compressed, 'array'); + var pub = this.pair.getPublic(this.compressed, 'array'); if (enc === 'base58') return utils.toBase58(pub); @@ -125,7 +125,7 @@ KeyPair.toSecret = function toSecret(priv, compressed) { arr = arr.concat(priv); - if (compressed) + if (compressed !== false) arr.push(1); chk = utils.checksum(arr); @@ -151,7 +151,7 @@ KeyPair.fromSecret = function fromSecret(priv) { } return new KeyPair({ - priv: priv, + privateKey: priv, compressed: compressed }); }; @@ -163,29 +163,7 @@ KeyPair.prototype.toJSON = function toJSON(encrypt) { encrypted: encrypt ? true : false }; - if (this.hd) { - if (this.hd.xprivkey) { - if (this.hd.seed) { - json.mnemonic = encrypt - ? encrypt(this.hd.seed.mnemonic) - : this.hd.seed.mnemonic; - json.passphrase = encrypt - ? encrypt(this.hd.seed.passphrase) - : this.hd.seed.passphrase; - return json; - } - json.xpriv = encrypt - ? encrypt(this.hd.xprivkey) - : this.hd.xprivkey; - return json; - } - - json.xpub = this.hd.xpubkey; - - return json; - } - - if (this._key.priv) { + if (this.pair.priv) { json.priv = encrypt ? encrypt(this.getPrivate('base58')) : this.getPrivate('base58'); @@ -206,40 +184,6 @@ KeyPair.fromJSON = function fromJSON(json, decrypt) { if (json.encrypted && !decrypt) throw new Error('Cannot decrypt address'); - if (json.mnemonic) { - return new KeyPair({ - key: bcoin.hd.priv({ - seed: bcoin.hd.seed({ - mnemonic: json.encrypted - ? decrypt(json.mnemonic) - : json.mnemonic, - passphrase: json.encrypted - ? decrypt(json.passphrase) - : json.passphrase - }) - }) - }); - } - - if (json.xpriv) { - xprivkey = json.xpriv; - if (json.encrypted) - xprivkey = decrypt(xprivkey); - return new KeyPair({ - key: bcoin.hd.priv({ - xkey: xprivkey - }) - }); - } - - if (json.xpub) { - return new KeyPair({ - key: bcoin.hd.pub({ - xkey: json.xpub - }) - }); - } - if (json.priv) { priv = json.priv; if (json.encrypted) @@ -249,7 +193,7 @@ KeyPair.fromJSON = function fromJSON(json, decrypt) { priv = key.priv; compressed = key.compressed; return new KeyPair({ - priv: priv, + privateKey: priv, compressed: compressed }); } @@ -258,7 +202,7 @@ KeyPair.fromJSON = function fromJSON(json, decrypt) { pub = bcoin.utils.toArray(json.pub, 'hex'); compressed = pub[0] !== 0x04; return new KeyPair({ - pub: pub, + publicKey: pub, compressed: compressed }); } diff --git a/lib/bcoin/script.js b/lib/bcoin/script.js index e7249652..75b7a670 100644 --- a/lib/bcoin/script.js +++ b/lib/bcoin/script.js @@ -2061,7 +2061,7 @@ script.isLowDER = function isLowDER(sig) { return false; try { - sig = new bcoin.signature(sig.slice(0, -1)); + sig = new bcoin.ecdsa.signature(sig.slice(0, -1)); } catch (e) { return false; } diff --git a/lib/bcoin/tx-pool.js b/lib/bcoin/tx-pool.js index e511bac8..8f2e8548 100644 --- a/lib/bcoin/tx-pool.js +++ b/lib/bcoin/tx-pool.js @@ -307,6 +307,23 @@ TXPool.prototype.fromJSON = function fromJSON(json) { }, this); }; +TXPool.fromJSON = function fromJSON(wallet, json) { + var txPool; + + assert.equal(json.v, 1); + assert.equal(json.type, 'tx-pool'); + + txPool = new TXPool(wallet); + + utils.nextTick(function() { + json.txs.forEach(function(tx) { + txPool.add(bcoin.tx.fromJSON(tx)); + }); + }); + + return tx; +}; + /** * Expose */ diff --git a/lib/bcoin/utils.js b/lib/bcoin/utils.js index 10cc3735..18646121 100644 --- a/lib/bcoin/utils.js +++ b/lib/bcoin/utils.js @@ -240,7 +240,7 @@ utils.array2utf8 = function array2utf8(arr) { utils.copy = function copy(src, dst, off, force) { if (Buffer.isBuffer(src) && Buffer.isBuffer(dst)) { - assert(!force); + utils.assert(!force); return src.copy(dst, off, 0, src.length); } diff --git a/lib/bcoin/wallet.js b/lib/bcoin/wallet.js index 2fef1fd2..c2a180f4 100644 --- a/lib/bcoin/wallet.js +++ b/lib/bcoin/wallet.js @@ -38,32 +38,38 @@ function Wallet(options) { delete options.hd; } - if (options.priv - || options.pub - || options.key + if (options.key) + options.pair = options.key; + + if (options.priv) + options.privateKey = options.priv; + + if (options.pub) + options.publicKey = options.pub; + + if (options.privateKey + || options.publicKey + || options.pair || options.personalization || options.entropy + || options.passphrase || options.compressed) { - if ((options.key instanceof bcoin.hd.priv) - || options.key instanceof bcoin.hd.pub) { - options.master = options.key; - delete options.key; - } else if (options.priv instanceof bcoin.hd.priv) { - options.master = options.priv; - delete options.priv; - } else if (options.pub instanceof bcoin.hd.pub) { - options.master = options.pub; - delete options.pub; + if ((options.pair instanceof bcoin.hd.privateKey) + || options.pair instanceof bcoin.hd.publicKey) { + options.master = options.pair; + delete options.pair; + } else if (options.privateKey instanceof bcoin.hd.privateKey) { + options.master = options.privateKey; + delete options.privateKey; + } else if (options.publicKey instanceof bcoin.hd.publicKey) { + options.master = options.publicKey; + delete options.publicKey; } } this.options = options; this.addresses = []; this.master = options.master || null; - - if (this.master && !(this.master instanceof bcoin.keypair)) - this.master = bcoin.keypair({ hd: this.master }); - this._addressTable = {}; this._labelMap = {}; @@ -119,28 +125,29 @@ function Wallet(options) { throw new Error('n ranges between 1 and ' + this.nmax); if (this.bip45) { - this.purposeKey = this.master.hd.isPurpose45() - ? this.master.hd - : this.master.hd.derivePurpose45(); - } else if (this.hd) { - this.accountKey = this.master.hd.isAccount44() - ? this.master.hd - : this.master.hd.deriveAccount44(this.accountIndex); + this.purposeKey = this.master.isPurpose45() + ? this.master + : this.master.derivePurpose45(); + } else if (this.bip44) { + this.accountKey = this.master.isAccount44() + ? this.master + : this.master.deriveAccount44(this.accountIndex); } if (!options.addresses) options.addresses = []; - if (options.priv - || options.pub - || options.key + if (options.privateKey + || options.publicKey + || options.pair || options.personalization || options.entropy + || options.passphrase || options.compressed) { options.addresses.push({ - priv: options.priv, - pub: options.pub, - key: options.key, + privateKey: options.privateKey, + publicKey: options.publicKey, + pair: options.pair, personalization: options.personalization, entropy: options.entropy, compressed: options.compressed, @@ -168,10 +175,33 @@ function Wallet(options) { // generate the last receiving address. However, since "normal" wallets // cannot deterministically generate keys, we have to buffer the generated // key for later. - if (!this.bip45) { - if (this.hd) { - // Generate the last known receiving address - key = this.createKey(false, Math.max(0, this.addressDepth - 1)); + if (this.bip44) { + // Generate the last known receiving address + key = this.createKey(false, Math.max(0, this.addressDepth - 1)); + this.current = bcoin.address({ + priv: key.priv, + type: this.type, + subtype: this.subtype, + m: this.m, + n: this.n, + keys: options.keys, + derived: true + }); + } else if (this.normal) { + // Try to find the last receiving address if there is one. + receiving = options.addresses.filter(function(address) { + return !address.change + && ((address.priv || address.privateKey) + || (address.pub || address.publicKey) + || (address.key || address.pair)); + }).pop(); + if (receiving) { + this.current = bcoin.address(receiving); + } else { + // No receiving address is in this wallet yet, generate + // it and save it so createKey can recreate it later. + key = this.createKey(); + this._firstKey = key; this.current = bcoin.address({ priv: key.priv, type: this.type, @@ -180,27 +210,6 @@ function Wallet(options) { n: this.n, keys: options.keys }); - } else { - // Try to find the last receiving address if there is one. - receiving = options.addresses.filter(function(address) { - return !address.change && (address.priv || address.pub || address.key); - }).pop(); - if (receiving) { - this.current = bcoin.address(receiving); - } else { - // No receiving address is in this wallet yet, generate - // it and save it so createKey can recreate it later. - key = this.createKey(); - this._firstKey = key; - this.current = bcoin.address({ - priv: key.priv, - type: this.type, - subtype: this.subtype, - m: this.m, - n: this.n, - keys: options.keys - }); - } } } @@ -218,13 +227,13 @@ inherits(Wallet, EventEmitter); // Wallet ID: // bip45: Purpose key address -// HD: Account key address -// Normal: Address of first key in wallet +// bip44: Account key address +// normal: Address of first key in wallet Wallet.prototype.getID = function() { if (this.bip45) return bcoin.address.key2addr(this.purposeKey.publicKey); - if (this.hd) + if (this.bip44) return bcoin.address.key2addr(this.accountKey.publicKey); if (this.addresses.length) @@ -274,7 +283,7 @@ Wallet.prototype._initAddresses = function() { this.prefix = 'bt/wallet/' + this.getID() + '/'; - this.tx = new bcoin.txPool(this); + this.tx = options.tx || bcoin.txPool(this); this._init(); }; @@ -513,7 +522,8 @@ Wallet.prototype.createAddress = function createAddress(change, index) { m: this.m, n: this.n, keys: [], - change: change + change: change, + derived: !!this.hd }; if (index == null) { @@ -652,7 +662,7 @@ Wallet.prototype.getPublicKey = function getPublicKey(enc) { }; Wallet.prototype.createKey = function createKey(change, index) { - var key, pub, priv; + var key; if (!this.hd) { if (this._firstKey) { @@ -931,6 +941,12 @@ Wallet.prototype.toJSON = function toJSON(encrypt) { addressDepth: this.addressDepth, changeDepth: this.changeDepth, cosignerIndex: this.cosignerIndex, + master: this.master ? this.master.toJSON(encrypt) : null, + addresses: this.addresses.filter(function(address) { + return !address.derived; + }, this).map(function(address) { + return address.toJSON(encrypt); + }), keys: this.bip45 ? this.purposeKeys.map(function(key) { return key.xpubkey; @@ -938,14 +954,6 @@ Wallet.prototype.toJSON = function toJSON(encrypt) { : this.keys.map(function(key) { return utils.toBase58(key); }), - master: this.master ? this.master.toJSON(encrypt) : null, - addresses: this.addresses.filter(function(address) { - if (this.hd) - return false; - return true; - }, this).map(function(address) { - return address.toJSON(encrypt); - }), balance: utils.toBTC(this.getBalance()), tx: this.tx.toJSON() }; @@ -970,12 +978,12 @@ Wallet.fromJSON = function fromJSON(json, decrypt) { changeDepth: json.changeDepth, cosignerIndex: json.cosignerIndex, master: json.master - ? bcoin.address.fromJSON(json.master, decrypt) + ? bcoin.hd.fromJSON(json.master, decrypt) : null, - keys: json.keys, addresses: json.addresses.map(function(address) { return bcoin.address.fromJSON(address, decrypt); - }) + }), + keys: json.keys }); w.tx.fromJSON(json.tx);