diff --git a/lib/wallet/account.js b/lib/wallet/account.js index 888404a2..ea64d616 100644 --- a/lib/wallet/account.js +++ b/lib/wallet/account.js @@ -58,18 +58,18 @@ function Account(db, options) { this.wid = 0; this.id = null; this.name = null; + this.initialized = false; this.witness = this.db.options.witness; - this.accountKey = null; + this.watchOnly = false; + this.type = Account.types.PUBKEYHASH; + this.m = 1; + this.n = 1; this.accountIndex = 0; this.receiveDepth = 0; this.changeDepth = 0; this.nestedDepth = 0; - this.type = Account.types.PUBKEYHASH; - this.m = 1; - this.n = 1; + this.accountKey = null; this.keys = []; - this.initialized = false; - this.watchOnly = false; if (options) this.fromOptions(options); @@ -119,31 +119,19 @@ Account.prototype.fromOptions = function fromOptions(options) { this.name = options.name; } + if (options.initialized != null) { + assert(typeof options.initialized === 'boolean'); + this.initialized = options.initialized; + } + if (options.witness != null) { assert(typeof options.witness === 'boolean'); this.witness = options.witness; } - this.accountKey = options.accountKey; - - if (options.accountIndex != null) { - assert(utils.isNumber(options.accountIndex)); - this.accountIndex = options.accountIndex; - } - - if (options.receiveDepth != null) { - assert(utils.isNumber(options.receiveDepth)); - this.receiveDepth = options.receiveDepth; - } - - if (options.changeDepth != null) { - assert(utils.isNumber(options.changeDepth)); - this.changeDepth = options.changeDepth; - } - - if (options.nestedDepth != null) { - assert(utils.isNumber(options.nestedDepth)); - this.nestedDepth = options.nestedDepth; + if (options.watchOnly != null) { + assert(typeof options.watchOnly === 'boolean'); + this.watchOnly = options.watchOnly; } if (options.type != null) { @@ -167,16 +155,28 @@ Account.prototype.fromOptions = function fromOptions(options) { this.n = options.n; } - if (options.initialized != null) { - assert(typeof options.initialized === 'boolean'); - this.initialized = options.initialized; + if (options.accountIndex != null) { + assert(utils.isNumber(options.accountIndex)); + this.accountIndex = options.accountIndex; } - if (options.watchOnly != null) { - assert(typeof options.watchOnly === 'boolean'); - this.watchOnly = options.watchOnly; + if (options.receiveDepth != null) { + assert(utils.isNumber(options.receiveDepth)); + this.receiveDepth = options.receiveDepth; } + if (options.changeDepth != null) { + assert(utils.isNumber(options.changeDepth)); + this.changeDepth = options.changeDepth; + } + + if (options.nestedDepth != null) { + assert(utils.isNumber(options.nestedDepth)); + this.nestedDepth = options.nestedDepth; + } + + this.accountKey = options.accountKey; + if (this.n > 1) this.type = Account.types.MULTISIG; @@ -674,21 +674,21 @@ Account.prototype.inspect = function inspect() { name: this.name, network: this.network, initialized: this.initialized, + witness: this.witness, watchOnly: this.watchOnly, type: Account.typesByVal[this.type].toLowerCase(), m: this.m, n: this.n, + accountIndex: this.accountIndex, + receiveDepth: this.receiveDepth, + changeDepth: this.changeDepth, + nestedDepth: this.nestedDepth, address: this.initialized ? this.receive.getAddress() : null, nestedAddress: this.initialized && this.nested ? this.nested.getAddress() : null, - witness: this.witness, - accountIndex: this.accountIndex, - receiveDepth: this.receiveDepth, - changeDepth: this.changeDepth, - nestedDepth: this.nestedDepth, accountKey: this.accountKey.xpubkey, keys: this.keys.map(function(key) { return key.xpubkey; @@ -704,15 +704,14 @@ Account.prototype.inspect = function inspect() { Account.prototype.toJSON = function toJSON() { return { - network: this.network.type, wid: this.wid, name: this.name, initialized: this.initialized, + witness: this.witness, watchOnly: this.watchOnly, type: Account.typesByVal[this.type].toLowerCase(), m: this.m, n: this.n, - witness: this.witness, accountIndex: this.accountIndex, receiveDepth: this.receiveDepth, changeDepth: this.changeDepth, @@ -742,7 +741,6 @@ Account.prototype.toJSON = function toJSON() { Account.prototype.fromJSON = function fromJSON(json) { var i, key; - assert.equal(json.network, this.network.type); assert(utils.isNumber(json.wid)); assert(utils.isName(json.id), 'Bad wallet ID.'); assert(utils.isName(json.name), 'Bad account name.'); @@ -761,11 +759,11 @@ Account.prototype.fromJSON = function fromJSON(json) { this.wid = json.wid; this.name = json.name; this.initialized = json.initialized; + this.witness = json.witness; this.watchOnly = json.watchOnly; this.type = Account.types[json.type.toUpperCase()]; this.m = json.m; this.n = json.n; - this.witness = json.witness; this.accountIndex = json.accountIndex; this.receiveDepth = json.receiveDepth; this.changeDepth = json.changeDepth; @@ -791,13 +789,12 @@ Account.prototype.toRaw = function toRaw(writer) { var p = new BufferWriter(writer); var i, key; - p.writeU32(this.network.magic); p.writeVarString(this.name, 'ascii'); p.writeU8(this.initialized ? 1 : 0); + p.writeU8(this.witness ? 1 : 0); p.writeU8(this.type); p.writeU8(this.m); p.writeU8(this.n); - p.writeU8(this.witness ? 1 : 0); p.writeU32(this.accountIndex); p.writeU32(this.receiveDepth); p.writeU32(this.changeDepth); @@ -827,13 +824,12 @@ Account.prototype.fromRaw = function fromRaw(data) { var p = new BufferReader(data); var i, count, key; - this.network = Network.fromMagic(p.readU32()); this.name = p.readVarString('ascii'); this.initialized = p.readU8() === 1; + this.witness = p.readU8() === 1; this.type = p.readU8(); this.m = p.readU8(); this.n = p.readU8(); - this.witness = p.readU8() === 1; this.accountIndex = p.readU32(); this.receiveDepth = p.readU32(); this.changeDepth = p.readU32(); diff --git a/lib/wallet/wallet.js b/lib/wallet/wallet.js index a8d6d975..d65cc256 100644 --- a/lib/wallet/wallet.js +++ b/lib/wallet/wallet.js @@ -69,12 +69,12 @@ function Wallet(db, options) { this.wid = 0; this.id = null; - this.master = null; this.initialized = false; this.watchOnly = false; this.accountDepth = 0; this.token = constants.ZERO_HASH; this.tokenDepth = 0; + this.master = null; this.txdb = new TXDB(this); this.account = null; @@ -107,6 +107,16 @@ Wallet.prototype.fromOptions = function fromOptions(options) { this.master = master; + if (options.wid != null) { + assert(utils.isNumber(options.wid)); + this.wid = options.wid; + } + + if (options.id) { + assert(utils.isName(options.id), 'Bad wallet ID.'); + id = options.id; + } + if (options.initialized != null) { assert(typeof options.initialized === 'boolean'); this.initialized = options.initialized; @@ -122,16 +132,6 @@ Wallet.prototype.fromOptions = function fromOptions(options) { this.accountDepth = options.accountDepth; } - if (options.wid != null) { - assert(utils.isNumber(options.wid)); - this.wid = options.wid; - } - - if (options.id) { - assert(utils.isName(options.id), 'Bad wallet ID.'); - id = options.id; - } - if (!id) id = this.getID(); @@ -651,8 +651,12 @@ Wallet.prototype._createAccount = co(function* createAccount(options) { if (this.watchOnly && options.accountKey) { key = options.accountKey; + if (!HD.isHD(key)) key = HD.from(key, this.network); + + if (HD.isPrivate(key)) + throw new Error('Cannot add xprivkey to watch-only wallet.'); } else { key = master.deriveAccount44(this.accountDepth); } @@ -2106,6 +2110,8 @@ Wallet.prototype.toJSON = function toJSON() { */ Wallet.prototype.fromJSON = function fromJSON(json) { + var network; + assert(utils.isNumber(json.wid)); assert(typeof json.initialized === 'boolean'); assert(typeof json.watchOnly === 'boolean'); @@ -2115,7 +2121,8 @@ Wallet.prototype.fromJSON = function fromJSON(json) { assert(json.token.length === 64); assert(utils.isNumber(json.tokenDepth)); - this.network = Network.get(json.network); + network = Network.get(json.network); + this.wid = json.wid; this.id = json.id; this.initialized = json.initialized; @@ -2124,6 +2131,8 @@ Wallet.prototype.fromJSON = function fromJSON(json) { this.token = new Buffer(json.token, 'hex'); this.master = MasterKey.fromJSON(json.master); + assert(network === this.db.network, 'Wallet network mismatch.'); + return this; }; @@ -2159,7 +2168,10 @@ Wallet.prototype.toRaw = function toRaw(writer) { Wallet.prototype.fromRaw = function fromRaw(data) { var p = new BufferReader(data); - this.network = Network.fromMagic(p.readU32()); + var network; + + network = Network.fromMagic(p.readU32()); + this.wid = p.readU32(); this.id = p.readVarString('ascii'); this.initialized = p.readU8() === 1; @@ -2168,6 +2180,9 @@ Wallet.prototype.fromRaw = function fromRaw(data) { this.token = p.readBytes(32); this.tokenDepth = p.readU32(); this.master = MasterKey.fromRaw(p.readVarBytes()); + + assert(network === this.db.network, 'Wallet network mismatch.'); + return this; };