From 882b18e188cd221b340fa44a9d9a9faa3a90c6eb Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Sat, 25 Jun 2016 04:42:42 -0700 Subject: [PATCH] keypair refactor. --- lib/bcoin/hd.js | 335 ++++++++++++++++++++++++++++++------------- lib/bcoin/keypair.js | 211 ++++++++++++++++----------- lib/bcoin/keyring.js | 8 +- lib/bcoin/wallet.js | 94 ++++-------- 4 files changed, 387 insertions(+), 261 deletions(-) diff --git a/lib/bcoin/hd.js b/lib/bcoin/hd.js index 64dd63a4..bcbe41f1 100644 --- a/lib/bcoin/hd.js +++ b/lib/bcoin/hd.js @@ -129,6 +129,12 @@ function Mnemonic(options) { this.fromOptions(options); } +/** + * Inject properties from options object. + * @private + * @param {Object} options + */ + Mnemonic.prototype.fromOptions = function fromOptions(options) { if (!options) options = {}; @@ -147,65 +153,16 @@ Mnemonic.prototype.fromOptions = function fromOptions(options) { assert(this.bits % 32 === 0); }; +/** + * Instantiate mnemonic from options. + * @param {Object} options + * @returns {Mnemonic} + */ + Mnemonic.fromOptions = function fromOptions(options) { return new Mnemonic().fromOptions(options); }; -Mnemonic.prototype.toJSON = function toJSON() { - return { - bits: this.bits, - entropy: this.entropy ? this.entropy.toString('hex') : null, - phrase: this.phrase, - passphrase: this.passphrase, - language: this.language, - seed: this.seed ? this.seed.toString('hex') : null - }; -}; - -Mnemonic.prototype.fromJSON = function fromJSON(json) { - this.bits = json.bits; - if (json.entropy) - this.entropy = new Buffer(json.entropy, 'hex'); - this.phrase = json.phrase; - this.passphrase = json.passphrase; - this.language = json.language; - if (json.seed) - this.seed = new Buffer(json.seed, 'hex'); - return this; -}; - -Mnemonic.fromJSON = function fromJSON(json) { - return new Mnemonic().fromJSON(json); -}; - -Mnemonic.prototype.toRaw = function toRaw(writer) { - var p = new BufferWriter(writer); - p.writeU16(this.bits); - p.writeBytes(this.entropy); - p.writeVarString(this.phrase, 'utf8'); - p.writeVarString(this.passphrase, 'utf8'); - p.writeVarString(this.language, 'utf8'); - p.writeBytes(this.seed); - if (!writer) - p = p.render(); - return p; -}; - -Mnemonic.prototype.fromRaw = function fromRaw(data) { - var p = new BufferReader(data); - this.bits = p.readU16(); - this.entropy = p.readBytes(this.bits / 8); - this.phrase = p.readVarString('utf8'); - this.passphrase = p.readVarString('utf8'); - this.language = p.readVarString('utf8'); - this.seed = p.readBytes(64); - return this; -}; - -Mnemonic.fromRaw = function fromRaw(data) { - return new Mnemonic().fromRaw(data); -}; - /** * Generate the seed. * @returns {Buffer} pbkdf2 seed. @@ -300,6 +257,96 @@ Mnemonic.getWordlist = function getWordlist(language) { } }; +/** + * Convert mnemonic to a json-friendly object. + * @returns {Object} + */ + +Mnemonic.prototype.toJSON = function toJSON() { + return { + bits: this.bits, + entropy: this.entropy ? this.entropy.toString('hex') : null, + phrase: this.phrase, + passphrase: this.passphrase, + language: this.language, + seed: this.seed ? this.seed.toString('hex') : null + }; +}; + +/** + * Inject properties from json object. + * @private + * @param {Object} json + */ + +Mnemonic.prototype.fromJSON = function fromJSON(json) { + this.bits = json.bits; + this.entropy = new Buffer(json.entropy, 'hex'); + this.phrase = json.phrase; + this.passphrase = json.passphrase; + this.language = json.language; + this.seed = new Buffer(json.seed, 'hex'); + return this; +}; + +/** + * Instantiate mnemonic from json object. + * @param {Object} json + * @returns {Mnemonic} + */ + +Mnemonic.fromJSON = function fromJSON(json) { + return new Mnemonic().fromJSON(json); +}; + +/** + * Serialize mnemonic. + * @returns {Buffer} + */ + +Mnemonic.prototype.toRaw = function toRaw(writer) { + var p = new BufferWriter(writer); + + p.writeU16(this.bits); + p.writeBytes(this.entropy); + p.writeVarString(this.phrase, 'utf8'); + p.writeVarString(this.passphrase, 'utf8'); + p.writeVarString(this.language, 'utf8'); + p.writeBytes(this.seed); + + if (!writer) + p = p.render(); + + return p; +}; + +/** + * Inject properties from serialized data. + * @private + * @param {Buffer} data + */ + +Mnemonic.prototype.fromRaw = function fromRaw(data) { + var p = new BufferReader(data); + this.bits = p.readU16(); + this.entropy = p.readBytes(this.bits / 8); + this.phrase = p.readVarString('utf8'); + this.passphrase = p.readVarString('utf8'); + this.language = p.readVarString('utf8'); + this.seed = p.readBytes(64); + return this; +}; + +/** + * Instantiate mnemonic from serialized data. + * @param {Buffer} data + * @returns {Mnemonic} + */ + +Mnemonic.fromRaw = function fromRaw(data) { + return new Mnemonic().fromRaw(data); +}; + /** * Test whether an object is a Mnemonic. * @param {Object} obj @@ -401,6 +448,18 @@ HD.fromRaw = function fromRaw(data) { return HDPublicKey.fromRaw(data); }; +/** + * Instantiate HD key from extended serialized data. + * @param {Buffer} data + * @returns {HDPrivateKey|HDPublicKey} + */ + +HD.fromExtended = function fromExtended(data) { + if (HDPrivateKey.hasPrefix(data)) + return HDPrivateKey.fromExtended(data); + return HDPublicKey.fromRaw(data); +}; + /** * Generate an hdkey from any number of options. * @param {Object|Mnemonic|Buffer} options - mnemonic, mnemonic @@ -571,6 +630,12 @@ function HDPrivateKey(options) { utils.inherits(HDPrivateKey, HD); +/** + * Inject properties from options object. + * @private + * @param {Object} options + */ + HDPrivateKey.prototype.fromOptions = function fromOptions(options) { assert(options, 'No options for HD private key.'); assert(options.depth <= 0xff, 'Depth is too high.'); @@ -590,6 +655,12 @@ HDPrivateKey.prototype.fromOptions = function fromOptions(options) { return this; }; +/** + * Instantiate HD private key from options object. + * @param {Object} options + * @returns {HDPrivateKey} + */ + HDPrivateKey.fromOptions = function fromOptions(options) { return new HDPrivateKey().fromOptions(options); }; @@ -846,13 +917,10 @@ HDPrivateKey.prototype.equal = function equal(obj) { }; /** - * Create an hd private key from a seed. - * @param {Buffer|Mnemonic|Object} options - A seed, - * mnemonic, or mnemonic options. - * @param {String?} network - * @returns {Object} A "naked" key (a - * plain javascript object which is suitable - * for passing to the HDPrivateKey constructor). + * Inject properties from seed. + * @private + * @param {Buffer} seed + * @param {(Network|NetworkType)?} network */ HDPrivateKey.prototype.fromSeed = function fromSeed(seed, network) { @@ -885,10 +953,9 @@ HDPrivateKey.prototype.fromSeed = function fromSeed(seed, network) { }; /** - * Instantiate an hd private key from a seed. - * @param {Buffer|Mnemonic|Object} seed - A - * seed, mnemonic, or mnemonic options. - * @param {String?} network + * Instantiate an hd private key from a 512 bit seed. + * @param {Buffer} seed + * @param {(Network|NetworkType)?} network * @returns {HDPrivateKey} */ @@ -897,10 +964,10 @@ HDPrivateKey.fromSeed = function fromSeed(seed, network) { }; /** - * Instantiate an hd private key from a mnemonic. + * Inject properties from a mnemonic. + * @private * @param {Mnemonic|Object} mnemonic - * @param {String?} network - * @returns {HDPrivateKey} + * @param {(Network|NetworkType)?} network */ HDPrivateKey.prototype.fromMnemonic = function fromMnemonic(mnemonic, network) { @@ -936,19 +1003,22 @@ HDPrivateKey.prototype.fromMnemonic = function fromMnemonic(mnemonic, network) { return this; }; +/** + * Instantiate an hd private key from a mnemonic. + * @param {Mnemonic|Object} mnemonic + * @param {(Network|NetworkType)?} network + * @returns {HDPrivateKey} + */ + HDPrivateKey.fromMnemonic = function fromMnemonic(mnemonic, network) { return new HDPrivateKey().fromMnemonic(mnemonic, network); }; /** - * Generate an hd private key from a key and/or entropy bytes. - * @param {Object?} options - * @param {Buffer?} options.privateKey - * @param {Buffer?} options.entropy - * @param {String?} network - * @returns {Object} A "naked" key (a - * plain javascript object which is suitable - * for passing to the HDPrivateKey constructor). + * Inject properties from privateKey and entropy. + * @private + * @param {Object} options + * @param {(Network|NetworkType)?} network */ HDPrivateKey.prototype.generate = function _generate(options, network) { @@ -985,7 +1055,7 @@ HDPrivateKey.prototype.generate = function _generate(options, network) { * @param {Object?} options * @param {Buffer?} options.privateKey * @param {Buffer?} options.entropy - * @param {String?} network + * @param {(Network|NetworkType)?} network * @returns {HDPrivateKey} */ @@ -994,9 +1064,9 @@ HDPrivateKey.generate = function generate(options, network) { }; /** - * Parse a base58 extended private key. + * Inject properties from base58 key. + * @private * @param {Base58String} xkey - * @returns {Object} */ HDPrivateKey.prototype.fromBase58 = function fromBase58(xkey) { @@ -1006,9 +1076,9 @@ HDPrivateKey.prototype.fromBase58 = function fromBase58(xkey) { }; /** - * Parse a raw serialized key. + * Inject properties from serialized data. + * @private * @param {Buffer} raw - * @returns {Object} */ HDPrivateKey.prototype.fromRaw = function fromRaw(raw) { @@ -1041,7 +1111,7 @@ HDPrivateKey.prototype.fromRaw = function fromRaw(raw) { /** * Serialize key to a base58 string. - * @param {Network|String} network + * @param {(Network|NetworkType)?} network * @returns {Base58String} */ @@ -1051,7 +1121,7 @@ HDPrivateKey.prototype.toBase58 = function toBase58(network) { /** * Serialize the key. - * @param {Network|NetworkType} network + * @param {(Network|NetworkType)?} network * @returns {Buffer} */ @@ -1079,7 +1149,56 @@ HDPrivateKey.prototype.toRaw = function toRaw(network, writer) { }; /** - * Instantiate a transaction from a base58 string. + * Serialize the key in "extended" + * format (includes the mnemonic). + * @param {(Network|NetworkType)?} network + * @returns {Buffer} + */ + +HDPrivateKey.prototype.toExtended = function toExtended(network, writer) { + var p = new BufferWriter(writer); + + this.toRaw(network, p); + + if (this.mnemonic) { + p.writeU8(1); + this.mnemonic.toRaw(p); + } else { + p.writeU8(0); + } + + if (!writer) + p = p.render(); + + return p; +}; + +/** + * Inject properties from extended serialized data. + * @private + * @param {Buffer} data + */ + +HDPrivateKey.prototype.fromExtended = function fromExtended(data) { + var p = new BufferReader(data); + this.fromRaw(p); + if (p.readU8() === 1) + this.mnemonic = Mnemonic.fromRaw(p); + return this; +}; + +/** + * Instantiate key from "extended" serialized data. + * @param {Buffer} data + * @returns {HDPrivateKey} + */ + +HDPrivateKey.fromExtended = function fromExtended(data) { + return new HDPrivateKey().fromExtended(data); +}; + +/** + * Instantiate an HD private key from a base58 string. * @param {Base58String} xkey * @returns {HDPrivateKey} */ @@ -1111,9 +1230,9 @@ HDPrivateKey.prototype.toJSON = function toJSON() { }; /** - * Handle a deserialized JSON HDPrivateKey object. + * Inject properties from json object. + * @private * @param {Object} json - * @returns {Object} A "naked" HDPrivateKey. */ HDPrivateKey.prototype.fromJSON = function fromJSON(json) { @@ -1129,7 +1248,7 @@ HDPrivateKey.prototype.fromJSON = function fromJSON(json) { /** * Instantiate an HDPrivateKey from a jsonified key object. - * @param {Object} json - The jsonified transaction object. + * @param {Object} json - The jsonified key object. * @returns {HDPrivateKey} */ @@ -1145,9 +1264,9 @@ HDPrivateKey.fromJSON = function fromJSON(json) { HDPrivateKey.isHDPrivateKey = function isHDPrivateKey(obj) { return obj - && obj.privateKey - && Buffer.isBuffer(obj.chainCode) - && typeof obj.derive === 'function'; + && typeof obj.derive === 'function' + && typeof obj.toExtended === 'function' + && obj.chainCode !== undefined; }; /** @@ -1195,6 +1314,12 @@ function HDPublicKey(options) { utils.inherits(HDPublicKey, HD); +/** + * Inject properties from options object. + * @private + * @param {Object} options + */ + HDPublicKey.prototype.fromOptions = function fromOptions(options) { assert(options, 'No options for HDPublicKey'); assert(options.depth <= 0xff, 'Depth is too high.'); @@ -1211,6 +1336,12 @@ HDPublicKey.prototype.fromOptions = function fromOptions(options) { return this; }; +/** + * Instantiate HD public key from options object. + * @param {Object} options + * @returns {HDPublicKey} + */ + HDPublicKey.fromOptions = function fromOptions(options) { return new HDPublicKey().fromOptions(options); }; @@ -1388,7 +1519,6 @@ HDPublicKey.prototype.equal = function equal(obj) { /** * Convert key to a more json-friendly object. - * @method * @returns {Object} */ @@ -1399,9 +1529,9 @@ HDPublicKey.prototype.toJSON = function toJSON() { }; /** - * Handle a deserialized JSON HDPublicKey object. + * Inject properties from json object. + * @private * @param {Object} json - * @returns {Object} A "naked" HDPublicKey. */ HDPublicKey.prototype.fromJSON = function fromJSON(json) { @@ -1412,7 +1542,6 @@ HDPublicKey.prototype.fromJSON = function fromJSON(json) { /** * Instantiate an HDPrivateKey from a jsonified key object. - * @method * @param {Object} json - The jsonified transaction object. * @returns {HDPrivateKey} */ @@ -1468,9 +1597,9 @@ HDPublicKey.hasPrefix = function hasPrefix(data) { }; /** - * Parse a base58 extended public key. + * Inject properties from a base58 key. + * @private * @param {Base58String} xkey - * @returns {Object} */ HDPublicKey.prototype.fromBase58 = function fromBase58(xkey) { @@ -1480,9 +1609,9 @@ HDPublicKey.prototype.fromBase58 = function fromBase58(xkey) { }; /** - * Parse a raw serialized key. + * Inject properties from serialized data. + * @private * @param {Buffer} raw - * @returns {Object} */ HDPublicKey.prototype.fromRaw = function fromRaw(raw) { @@ -1550,7 +1679,7 @@ HDPublicKey.prototype.toRaw = function toRaw(network, writer) { }; /** - * Instantiate a transaction from a base58 string. + * Instantiate an HD public key from a base58 string. * @param {Base58String} xkey * @returns {HDPublicKey} */ @@ -1577,9 +1706,9 @@ HDPublicKey.fromRaw = function fromRaw(data) { HDPublicKey.isHDPublicKey = function isHDPublicKey(obj) { return obj - && !obj.privateKey - && Buffer.isBuffer(obj.chainCode) - && typeof obj.derive === 'function'; + && typeof obj.derive === 'function' + && typeof obj.toExtended !== 'function' + && obj.chainCode !== undefined; }; [HDPrivateKey, HDPublicKey].forEach(function(HD) { diff --git a/lib/bcoin/keypair.js b/lib/bcoin/keypair.js index d4b94098..fb23d154 100644 --- a/lib/bcoin/keypair.js +++ b/lib/bcoin/keypair.js @@ -29,11 +29,25 @@ function KeyPair(options) { if (!(this instanceof KeyPair)) return new KeyPair(options); + this.network = null; + this.compressed = true; + this.privateKey = null; + this._publicKey = null; + + if (options) + this.fromOptions(options); +} + +/** + * Inject properties from options object. + * @private + * @param {Object} options + */ + +KeyPair.prototype.fromOptions = function fromOptions(options) { if (!options) options = {}; - this.options = options; - this.key = null; this.compressed = options.compressed !== false; this.network = bcoin.network.get(options.network); @@ -45,15 +59,31 @@ function KeyPair(options) { this.privateKey = options.privateKey; this._publicKey = options.publicKey; -} + + return this; +}; /** - * Generate a keypair. + * Instantiate key pair from options object. + * @param {Object} options * @returns {KeyPair} */ -KeyPair.generate = function() { - return new KeyPair({ privateKey: bcoin.ec.generatePrivateKey() }); +KeyPair.fromOptions = function fromOptions(options) { + return new KeyPair().fromOptions(options); +}; + +/** + * Generate a keypair. + * @param {(Network|NetworkType)?} network + * @returns {KeyPair} + */ + +KeyPair.generate = function(network) { + var key = new KeyPair(); + key.network = bcoin.network.get(network); + key.privateKey = bcoin.ec.generatePrivateKey(); + return key; }; /** @@ -127,85 +157,105 @@ KeyPair.prototype.getPublicKey = function getPublicKey(enc) { /** * Convert key to a CBitcoinSecret. - * @returns {Base58String} + * @param {(Network|NetworkType)?} network + * @returns {Buffer} */ -KeyPair.prototype.toSecret = function toSecret(network) { +KeyPair.prototype.toRaw = function toRaw(network, writer) { + var p = new BufferWriter(writer); + if (!network) network = this.network; - return KeyPair.toSecret(this.getPrivateKey(), this.compressed, network); -}; - -/** - * Convert key to a CBitcoinSecret. - * @param {Buffer} privateKey - * @param {Boolean?} compressed - * @returns {Base58String} - */ - -KeyPair.toSecret = function toSecret(privateKey, compressed, network) { - var p = new BufferWriter(); - network = bcoin.network.get(network); - p.writeU8(network.prefixes.privkey); - p.writeBytes(privateKey); - if (compressed !== false) + p.writeU8(network.prefixes.privkey); + p.writeBytes(this.getPrivateKey()); + + if (this.compressed) p.writeU8(1); p.writeChecksum(); - return utils.toBase58(p.render()); + if (!writer) + p = p.render(); + + return p; }; /** - * Parse a serialized CBitcoinSecret. - * @param {Base58String} secret - * @returns {Object} A "naked" keypair object. + * Convert key to a CBitcoinSecret. + * @param {(Network|NetworkType)?} network + * @returns {Base58String} */ -KeyPair.parseSecret = function parseSecret(secret) { - var data = utils.fromBase58(secret); +KeyPair.prototype.toSecret = function toSecret(network) { + return utils.toBase58(this.toRaw(network)); +}; + +/** + * Inject properties from serialized CBitcoinSecret. + * @private + * @param {Buffer} data + */ + +KeyPair.prototype.fromRaw = function fromRaw(data) { var p = new BufferReader(data, true); var compressed = false; - var i, prefix, type, privateKey; + var i, prefix, version, type, privateKey; - prefix = p.readU8(); + version = p.readU8(); for (i = 0; i < network.types.length; i++) { type = network.types[i]; prefix = network[type].prefixes.privkey; - if (data.version === prefix) + if (version === prefix) break; } assert(i < network.types.length, 'Network not found.'); - privateKey = p.readBytes(32); + this.network = bcoin.network.get(type); + this.privateKey = p.readBytes(32); if (p.left() > 4) { assert(p.readU8() === 1, 'Bad compression flag.'); - compressed = true; + this.compressed = true; } p.verifyChecksum(); - return { - network: type, - privateKey: privateKey, - compressed: compressed - }; + return this; }; /** - * Instantiate a transaction from a serialized CBitcoinSecret. + * Inject properties from serialized CBitcoinSecret. + * @private * @param {Base58String} secret - * @returns {Keypair} + */ + +KeyPair.prototype.fromSecret = function fromSecret(secret) { + return this.fromRaw(utils.fromBase58(secret)); +}; + +/** + * Instantiate a key pair from a serialized CBitcoinSecret. + * @param {Buffer} data + * @returns {KeyPair} + */ + +KeyPair.fromRaw = function fromRaw(data) { + return new KeyPair().fromRaw(data); +}; + +/** + * Instantiate a key pair from a serialized CBitcoinSecret. + * @param {Base58String} secret + * @returns {KeyPair} */ KeyPair.fromSecret = function fromSecret(secret) { - return new KeyPair(KeyPair.parseSecret(secret)); + return new KeyPair().fromSecret(secret); }; /** @@ -214,68 +264,57 @@ KeyPair.fromSecret = function fromSecret(secret) { * @returns {Object} */ -KeyPair.prototype.toJSON = function toJSON(passphrase) { - var json = { - v: 1, - name: 'keypair', - encrypted: passphrase ? true : false +KeyPair.prototype.toJSON = function toJSON() { + return { + network: this.network.type, + compressed: this.compressed, + privateKey: this.privateKey ? this.toSecret() : null, + publicKey: this.getPublicKey('base58') }; - - if (this.key.privateKey) { - json.privateKey = passphrase - ? utils.encrypt(this.toSecret(), passphrase).toString('hex') - : this.toSecret(); - return json; - } - - json.publicKey = this.getPublicKey('base58'); - - return json; }; /** - * Handle a deserialized JSON keypair object. + * Inject properties from json object. + * @private * @param {Object} json - * @returns {Object} A "naked" keypair (a - * plain javascript object which is suitable - * for passing to the KeyPair constructor). */ -KeyPair.parseJSON = function parseJSON(json, passphrase) { - var privateKey, publicKey; +KeyPair.prototype.fromJSON = function fromJSON(json) { + this.network = bcoin.network.get(json.network); + this.compressed = json.compressed; - assert.equal(json.v, 1); - assert.equal(json.name, 'keypair'); - - if (json.encrypted && !passphrase) - throw new Error('Cannot decrypt key.'); - - if (json.privateKey) { - privateKey = json.privateKey; - if (json.encrypted) - privateKey = utils.decrypt(privateKey, passphrase).toString('utf8'); - return KeyPair.parseSecret(privateKey); - } + if (json.privateKey) + return this.fromSecret(json.privateKey); if (json.publicKey) { - publicKey = utils.fromBase58(json.publicKey); - return { - publicKey: publicKey, - compressed: publicKey[0] !== 0x04 - }; + this.publicKey = utils.fromBase58(json.publicKey); + this.compressed = this.publicKey[0] !== 0x04; + return this; } assert(false, 'Could not parse KeyPair JSON.'); }; /** - * Instantiate a transaction from a jsonified keypair object. - * @param {Object} json - The jsonified transaction object. + * Instantiate a key pair from a jsonified object. + * @param {Object} json - The jsonified key pair object. * @returns {KeyPair} */ -KeyPair.fromJSON = function fromJSON(json, passphrase) { - return new KeyPair(KeyPair.parseJSON(json, passphrase)); +KeyPair.fromJSON = function fromJSON(passphrase) { + return new KeyPair().fromJSON(json); +}; + +/** + * Test whether an object is a key pair. + * @param {Object?} obj + * @returns {Boolean} + */ + +KeyPair.isKeyPair = function isKeyPair(obj) { + return obj + && obj._privateKey !== undefined + && typeof obj.fromSecret === 'function'; }; /* diff --git a/lib/bcoin/keyring.js b/lib/bcoin/keyring.js index 772b9107..419befc9 100644 --- a/lib/bcoin/keyring.js +++ b/lib/bcoin/keyring.js @@ -597,6 +597,8 @@ KeyRing.prototype.toJSON = function toJSON() { */ KeyRing.prototype.fromJSON = function fromJSON(json) { + var i; + this.nework = bcoin.network.get(json.network); this.type = json.type; this.m = json.m; @@ -607,7 +609,10 @@ KeyRing.prototype.fromJSON = function fromJSON(json) { this.change = json.change; this.index = json.index; this.key = utils.fromBase58(json.key); - this.keys = json.keys.map(utils.fromBase58); + + for (i = 0; i < json.keys.length; i++) + this.keys.push(utils.fromBase58(json.keys[i])); + return this; }; @@ -671,7 +676,6 @@ KeyRing.prototype.fromRaw = function fromRaw(data) { this.change = p.readU32(); this.index = p.readU32(); this.key = p.readVarBytes(); - this.keys = []; count = p.readU8(); diff --git a/lib/bcoin/wallet.js b/lib/bcoin/wallet.js index e69b77bd..94ce3ae3 100644 --- a/lib/bcoin/wallet.js +++ b/lib/bcoin/wallet.js @@ -1402,7 +1402,7 @@ Wallet.prototype.inspect = function inspect() { network: this.network.type, initialized: this.initialized, accountDepth: this.accountDepth, - master: this.master.toJSON(), + master: this.master, account: this.account }; }; @@ -2192,7 +2192,6 @@ Account.prototype.fromJSON = function fromJSON(json) { this.receiveDepth = json.receiveDepth; this.changeDepth = json.changeDepth; this.accountKey = bcoin.hd.fromBase58(json.accountKey); - this.keys = []; for (i = 0; i < json.keys.length; i++) this.keys.push(bcoin.hd.fromBase58(key)); @@ -2255,7 +2254,6 @@ Account.prototype.fromRaw = function fromRaw(data) { this.receiveDepth = p.readU32(); this.changeDepth = p.readU32(); this.accountKey = bcoin.hd.fromRaw(p.readBytes(82)); - this.keys = []; count = p.readU8(); @@ -2313,12 +2311,10 @@ function MasterKey(options) { return new MasterKey(options); this.encrypted = false; - this.xprivkey = null; - this.phrase = null; - this.passphrase = null; - this.key = null; this.iv = null; this.ciphertext = null; + this.key = null; + this.timer = null; this._destroy = this.destroy.bind(this); this.locker = new bcoin.locker(this); @@ -2332,9 +2328,6 @@ function MasterKey(options) { MasterKey.prototype.fromOptions = function fromOptions(options) { this.encrypted = !!options.encrypted; - this.xprivkey = options.xprivkey; - this.phrase = options.phrase; - this.passphrase = options.passphrase; this.iv = options.iv; this.ciphertext = options.ciphertext; this.key = options.key || null; @@ -2362,7 +2355,7 @@ MasterKey.fromOptions = function fromOptions(options) { MasterKey.prototype.toKey = function toKey(passphrase, timeout, callback) { var self = this; - var unlock, data; + var unlock; unlock = this.locker.lock(toKey, [passphrase, timeout, callback]); @@ -2384,16 +2377,13 @@ MasterKey.prototype.toKey = function toKey(passphrase, timeout, callback) { return callback(err); try { - data = MasterKey.fromRaw(data); + self.key = bcoin.hd.fromExtended(data); } catch (e) { return callback(e); } - self.key = data.key; self.start(timeout); - data.destroy(); - return callback(null, self.key); }); }; @@ -2481,12 +2471,16 @@ MasterKey.prototype.decrypt = function decrypt(passphrase, callback) { if (err) return callback(err); + try { + self.key = bcoin.hd.fromExtended(data); + } catch (e) { + return callback(e); + } + self.encrypted = false; self.iv = null; self.ciphertext = null; - self.fromRaw(data); - return callback(); }); }; @@ -2514,7 +2508,8 @@ MasterKey.prototype.encrypt = function encrypt(passphrase, callback) { return callback(); iv = bcoin.ec.random(16); - data = this.toRaw(); + data = this.key.toExtended(); + this.stop(); utils.encrypt(data, passphrase, iv, function(err, data) { if (err) @@ -2525,23 +2520,13 @@ MasterKey.prototype.encrypt = function encrypt(passphrase, callback) { self.iv = iv; self.ciphertext = data; - self.xprivkey.fill(0); - self.xprivkey = null; - - if (self.phrase) { - self.phrase.fill(0); - self.phrase = null; - self.passphrase.fill(0); - self.passphrase = null; - } - return callback(); }); }; /** * Serialize the key in the form of: - * `[enc-flag][iv?][ciphertext?][phrase-marker][phrase?][passphrase?][xprivkey]` + * `[enc-flag][iv?][ciphertext?][extended-key?]` * @returns {Buffer} */ @@ -2560,16 +2545,7 @@ MasterKey.prototype.toRaw = function toRaw(writer) { } p.writeU8(0); - - if (this.phrase) { - p.writeU8(1); - p.writeVarBytes(this.phrase); - p.writeVarBytes(this.passphrase); - } else { - p.writeU8(0); - } - - p.writeBytes(this.xprivkey); + p.writeVarBytes(this.key.toExtended()); if (!writer) p = p.render(); @@ -2594,13 +2570,7 @@ MasterKey.prototype.fromRaw = function fromRaw(raw) { return this; } - if (p.readU8() === 1) { - this.phrase = p.readVarBytes(); - this.passphrase = p.readVarBytes(); - } - - this.xprivkey = p.readBytes(82); - this.key = bcoin.hd.fromRaw(this.xprivkey); + this.key = bcoin.hd.fromExtended(p.readVarBytes()); return this; }; @@ -2624,15 +2594,7 @@ MasterKey.prototype.fromKey = function fromKey(key) { this.encrypted = false; this.iv = null; this.ciphertext = null; - - if (key.mnemonic) { - this.phrase = new Buffer(key.mnemonic.phrase, 'utf8'); - this.passphrase = new Buffer(key.mnemonic.passphrase, 'utf8'); - } - - this.xprivkey = key.toRaw(); this.key = key; - return this; }; @@ -2652,26 +2614,20 @@ MasterKey.fromKey = function fromKey(key) { */ MasterKey.prototype.toJSON = function toJSON() { - var phrase, passphrase, xprivkey, iv, ciphertext; + var iv, ciphertext, key; if (this.encrypted) { iv = this.iv.toString('hex'); ciphertext = this.ciphertext.toString('hex'); } else { - if (this.phrase) { - phrase = this.phrase.toString('utf8'); - passphrase = this.passphrase.toString('utf8'); - } - xprivkey = utils.toBase58(this.xprivkey); + key = this.key.toJSON(); } return { encrypted: this.encrypted, iv: iv, ciphertext: ciphertext, - phrase: phrase, - passphrase: passphrase, - xprivkey: xprivkey + key: key }; }; @@ -2688,12 +2644,7 @@ MasterKey.prototype.fromJSON = function fromJSON(json) { this.iv = new Buffer(json.iv, 'hex'); this.ciphertext = new Buffer(json.ciphertext, 'hex'); } else { - if (json.phrase) { - this.phrase = new Buffer(json.phrase, 'utf8'); - this.passphrase = new Buffer(json.passphrase, 'utf8'); - } - this.xprivkey = utils.fromBase58(json.xprivkey); - this.key = bcoin.hd.fromRaw(this.xprivkey); + this.key = bcoin.hd.fromJSON(json.key); } return this; @@ -2715,7 +2666,10 @@ MasterKey.fromJSON = function fromJSON(json) { */ MasterKey.prototype.inspect = function inspect() { - return this.toJSON(); + var json = this.toJSON(); + if (this.key) + json.key = this.key.toJSON(); + return json; }; /**