diff --git a/lib/hd/hd.js b/lib/hd/hd.js index 31d7be93..ce200a51 100644 --- a/lib/hd/hd.js +++ b/lib/hd/hd.js @@ -20,13 +20,14 @@ var HD = exports; /** * Instantiate an HD key (public or private) from an base58 string. * @param {Base58String} xkey + * @param {Network?} network * @returns {HDPrivateKey|HDPublicKey} */ -HD.fromBase58 = function fromBase58(xkey) { +HD.fromBase58 = function fromBase58(xkey, network) { if (HDPrivateKey.isBase58(xkey)) - return HDPrivateKey.fromBase58(xkey); - return HDPublicKey.fromBase58(xkey); + return HDPrivateKey.fromBase58(xkey, network); + return HDPublicKey.fromBase58(xkey, network); }; /** @@ -68,13 +69,14 @@ HD.fromMnemonic = function fromMnemonic(options, network) { /** * Instantiate an HD key from a jsonified key object. * @param {Object} json - The jsonified transaction object. + * @param {Network?} network * @returns {HDPrivateKey|HDPublicKey} */ -HD.fromJSON = function fromJSON(json) { +HD.fromJSON = function fromJSON(json, network) { if (json.xprivkey) - return HDPrivateKey.fromJSON(json); - return HDPublicKey.fromJSON(json); + return HDPrivateKey.fromJSON(json, network); + return HDPublicKey.fromJSON(json, network); }; /** @@ -116,7 +118,7 @@ HD.from = function from(options, network) { return options; if (HD.isBase58(options)) - return HD.fromBase58(options); + return HD.fromBase58(options, network); if (HD.isRaw(options)) return HD.fromRaw(options); diff --git a/lib/hd/private.js b/lib/hd/private.js index e8c6f5d1..16a70cb6 100644 --- a/lib/hd/private.js +++ b/lib/hd/private.js @@ -615,11 +615,14 @@ HDPrivateKey.generate = function generate(network) { * Inject properties from base58 key. * @private * @param {Base58String} xkey + * @param {Network?} network */ -HDPrivateKey.prototype.fromBase58 = function fromBase58(xkey) { +HDPrivateKey.prototype.fromBase58 = function fromBase58(xkey, network) { this.fromRaw(base58.decode(xkey)); this._xprivkey = xkey; + if (network && !this.verifyNetwork(network)) + throw new Error('Network mismatch for HD private key.'); return this; }; @@ -813,11 +816,12 @@ HDPrivateKey.fromExtended = function fromExtended(data) { /** * Instantiate an HD private key from a base58 string. * @param {Base58String} xkey + * @param {Network?} network * @returns {HDPrivateKey} */ -HDPrivateKey.fromBase58 = function fromBase58(xkey) { - return new HDPrivateKey().fromBase58(xkey); +HDPrivateKey.fromBase58 = function fromBase58(xkey, network) { + return new HDPrivateKey().fromBase58(xkey, network); }; /** @@ -856,12 +860,13 @@ HDPrivateKey.prototype.toJSON = function toJSON() { * Inject properties from json object. * @private * @param {Object} json + * @param {Network?} network */ -HDPrivateKey.prototype.fromJSON = function fromJSON(json) { +HDPrivateKey.prototype.fromJSON = function fromJSON(json, network) { assert(json.xprivkey, 'Could not handle key JSON.'); - this.fromBase58(json.xprivkey); + this.fromBase58(json.xprivkey, network); if (json.mnemonic) this.mnemonic = Mnemonic.fromJSON(json.mnemonic); @@ -872,11 +877,12 @@ HDPrivateKey.prototype.fromJSON = function fromJSON(json) { /** * Instantiate an HDPrivateKey from a jsonified key object. * @param {Object} json - The jsonified key object. + * @param {Network?} network * @returns {HDPrivateKey} */ -HDPrivateKey.fromJSON = function fromJSON(json) { - return new HDPrivateKey().fromJSON(json); +HDPrivateKey.fromJSON = function fromJSON(json, network) { + return new HDPrivateKey().fromJSON(json, network); }; /** diff --git a/lib/hd/public.js b/lib/hd/public.js index 4746b4a5..f6141c1d 100644 --- a/lib/hd/public.js +++ b/lib/hd/public.js @@ -409,22 +409,24 @@ HDPublicKey.prototype.toJSON = function toJSON() { * Inject properties from json object. * @private * @param {Object} json + * @param {Network?} network */ -HDPublicKey.prototype.fromJSON = function fromJSON(json) { +HDPublicKey.prototype.fromJSON = function fromJSON(json, network) { assert(json.xpubkey, 'Could not handle HD key JSON.'); - this.fromBase58(json.xpubkey); + this.fromBase58(json.xpubkey, network); return this; }; /** - * Instantiate an HDPrivateKey from a jsonified key object. + * Instantiate an HDPublicKey from a jsonified key object. * @param {Object} json - The jsonified transaction object. + * @param {Network?} network * @returns {HDPrivateKey} */ -HDPublicKey.fromJSON = function fromJSON(json) { - return new HDPublicKey().fromJSON(json); +HDPublicKey.fromJSON = function fromJSON(json, network) { + return new HDPublicKey().fromJSON(json, network); }; /** @@ -477,11 +479,14 @@ HDPublicKey.isRaw = function isRaw(data) { * Inject properties from a base58 key. * @private * @param {Base58String} xkey + * @param {Network?} network */ -HDPublicKey.prototype.fromBase58 = function fromBase58(xkey) { +HDPublicKey.prototype.fromBase58 = function fromBase58(xkey, network) { this.fromRaw(base58.decode(xkey)); this._xpubkey = xkey; + if (network && !this.verifyNetwork(network)) + throw new Error('Network mismatch for HD public key.'); return this; }; @@ -581,11 +586,12 @@ HDPublicKey.prototype.toRaw = function toRaw(network) { /** * Instantiate an HD public key from a base58 string. * @param {Base58String} xkey + * @param {Network?} network * @returns {HDPublicKey} */ -HDPublicKey.fromBase58 = function fromBase58(xkey) { - return new HDPublicKey().fromBase58(xkey); +HDPublicKey.fromBase58 = function fromBase58(xkey, network) { + return new HDPublicKey().fromBase58(xkey, network); }; /** diff --git a/lib/http/rpc.js b/lib/http/rpc.js index 844f5f89..a2927ce7 100644 --- a/lib/http/rpc.js +++ b/lib/http/rpc.js @@ -2055,7 +2055,7 @@ RPC.prototype._generatetoaddress = co(function* generatetoaddress(args, help) { throw new RPCError('generatetoaddress numblocks address ( maxtries )'); numblocks = toNumber(args[0], 1); - address = Address.fromBase58(toString(args[1])); + address = Address.fromBase58(toString(args[1]), this.network); return yield this._generateBlocks(numblocks, address); }); @@ -2137,7 +2137,7 @@ RPC.prototype.createrawtransaction = co(function* createrawtransaction(args, hel continue; } - address = Address.fromBase58(key); + address = Address.fromBase58(key, this.network); b58 = address.toBase58(this.network); if (addrs[b58]) @@ -2270,7 +2270,7 @@ RPC.prototype._signrawtransaction = co(function* signrawtransaction(wallet, tx, if (typeof secret !== 'string') throw new RPCError('Invalid parameter'); - key = KeyRing.fromSecret(secret); + key = KeyRing.fromSecret(secret, this.network); keyMap[key.getPublicKey('hex')] = key; keys.push(key); } @@ -2375,7 +2375,7 @@ RPC.prototype.fundrawtransaction = co(function* fundrawtransaction(args, help) { changeAddress = toString(options.changeAddress); if (changeAddress) - changeAddress = Address.fromBase58(changeAddress); + changeAddress = Address.fromBase58(changeAddress, this.network); feeRate = options.feeRate; @@ -2494,7 +2494,7 @@ RPC.prototype.validateaddress = co(function* validateaddress(args, help) { b58 = toString(args[0]); try { - address = Address.fromBase58(b58); + address = Address.fromBase58(b58, this.network); } catch (e) { return { isvalid: false @@ -2561,7 +2561,7 @@ RPC.prototype.signmessagewithprivkey = co(function* signmessagewithprivkey(args, key = toString(args[0]); msg = toString(args[1]); - key = KeyRing.fromSecret(key); + key = KeyRing.fromSecret(key, this.network); msg = new Buffer(RPC.magic + msg, 'utf8'); msg = crypto.hash256(msg); @@ -3242,7 +3242,7 @@ RPC.prototype.importprivkey = co(function* importprivkey(args, help) { if (rescan && this.chain.options.prune) throw new RPCError('Cannot rescan when pruned.'); - key = KeyRing.fromSecret(secret); + key = KeyRing.fromSecret(secret, this.network); yield wallet.importKey(0, key); @@ -3291,7 +3291,7 @@ RPC.prototype.importwallet = co(function* importwallet(args, help) { if (parts.length < 4) throw new RPCError('Malformed wallet.'); - secret = KeyRing.fromSecret(parts[0]); + secret = KeyRing.fromSecret(parts[0], this.network); time = +parts[1]; label = parts[2]; @@ -3332,7 +3332,7 @@ RPC.prototype.importaddress = co(function* importaddress(args, help) { if (rescan && this.chain.options.prune) throw new RPCError('Cannot rescan when pruned.'); - addr = Address.fromBase58(addr); + addr = Address.fromBase58(addr, this.network); yield wallet.importAddress(0, addr); @@ -3888,7 +3888,7 @@ RPC.prototype.sendfrom = co(function* sendfrom(args, help) { } account = toString(args[0]); - address = Address.fromBase58(toString(args[1])); + address = Address.fromBase58(toString(args[1]), this.network); amount = toSatoshi(args[2]); if (!account) @@ -3940,7 +3940,7 @@ RPC.prototype.sendmany = co(function* sendmany(args, help) { for (i = 0; i < keys.length; i++) { key = keys[i]; value = toSatoshi(sendTo[key]); - address = Address.fromBase58(key); + address = Address.fromBase58(key, this.network); hash = address.getHash('hex'); if (uniq[hash]) @@ -3976,7 +3976,7 @@ RPC.prototype.sendtoaddress = co(function* sendtoaddress(args, help) { + ' subtractfeefromamount )'); } - address = Address.fromBase58(toString(args[0])); + address = Address.fromBase58(toString(args[0]), this.network); amount = toSatoshi(args[1]); subtractFee = toBool(args[4]); diff --git a/lib/http/server.js b/lib/http/server.js index d1d8ee0f..e2950df4 100644 --- a/lib/http/server.js +++ b/lib/http/server.js @@ -345,7 +345,7 @@ HTTPServer.prototype._init = function _init() { if (params.accountKey) { enforce(typeof params.accountKey === 'string', 'accountKey must be a string.'); - options.accountKey = HD.fromBase58(params.accountKey); + options.accountKey = HD.fromBase58(params.accountKey, this.network); } if (params.timeout != null) { @@ -371,9 +371,7 @@ HTTPServer.prototype._init = function _init() { if (output.address) { enforce(typeof output.address === 'string', 'Address must be a string.'); - output.address = Address.fromBase58(output.address); - enforce(output.address.verifyNetwork(this.network), - 'Wrong network for address.'); + output.address = Address.fromBase58(output.address, this.network); } else if (output.script) { enforce(typeof output.script === 'string', 'Script must be a string.'); @@ -396,13 +394,13 @@ HTTPServer.prototype._init = function _init() { for (i = 0; i < params.address.length; i++) { address = params.address[i]; enforce(typeof address === 'string', 'Address must be a string.'); - address = Address.fromBase58(address); + address = Address.fromBase58(address, this.network); options.address.push(address); } } else { enforce(typeof params.address === 'string', 'Address must be a string.'); - options.address = Address.fromBase58(params.address); + options.address = Address.fromBase58(params.address, this.network); } } @@ -439,7 +437,7 @@ HTTPServer.prototype._init = function _init() { if (params.privateKey) { enforce(typeof params.privateKey === 'string', 'Key must be a string.'); - options.privateKey = KeyRing.fromSecret(params.privateKey); + options.privateKey = KeyRing.fromSecret(params.privateKey, this.network); } if (params.publicKey) { @@ -450,7 +448,7 @@ HTTPServer.prototype._init = function _init() { if (params.master) { enforce(typeof params.master === 'string', 'Key must be a string.'); - options.master = HD.fromBase58(params.master); + options.master = HD.fromBase58(params.master, this.network); } if (params.mnemonic) { diff --git a/lib/primitives/address.js b/lib/primitives/address.js index 4f046cda..d5251cd5 100644 --- a/lib/primitives/address.js +++ b/lib/primitives/address.js @@ -284,23 +284,31 @@ Address.fromRaw = function fromRaw(data) { * Inject properties from base58 address. * @private * @param {Base58Address} data + * @param {Network?} network * @throws Parse error */ -Address.prototype.fromBase58 = function fromBase58(data) { +Address.prototype.fromBase58 = function fromBase58(data, network) { assert(typeof data === 'string'); - return this.fromRaw(base58.decode(data)); + + this.fromRaw(base58.decode(data)); + + if (network && !this.verifyNetwork(network)) + throw new Error('Network mismatch for address.'); + + return this; }; /** * Create an address object from a base58 address. * @param {Base58Address} address + * @param {Network?} network * @returns {Address} * @throws Parse error. */ -Address.fromBase58 = function fromBase58(address) { - return new Address().fromBase58(address); +Address.fromBase58 = function fromBase58(address, network) { + return new Address().fromBase58(address, network); }; /** diff --git a/lib/primitives/keyring.js b/lib/primitives/keyring.js index d9bba9d5..c78e1a11 100644 --- a/lib/primitives/keyring.js +++ b/lib/primitives/keyring.js @@ -323,9 +323,10 @@ KeyRing.prototype.toSecret = function toSecret() { * Inject properties from serialized CBitcoinSecret. * @private * @param {Base58String} secret + * @param {Network?} network */ -KeyRing.prototype.fromSecret = function fromSecret(data) { +KeyRing.prototype.fromSecret = function fromSecret(data, network) { var br = new BufferReader(base58.decode(data), true); var i, prefix, version, type, key, compressed; @@ -351,17 +352,23 @@ KeyRing.prototype.fromSecret = function fromSecret(data) { br.verifyChecksum(); - return this.fromPrivate(key, compressed, type); + this.fromPrivate(key, compressed, type); + + if (network && !this.verifyNetwork(network)) + throw new Error('Network mismatch for WIF.'); + + return this; }; /** * Instantiate a keyring from a serialized CBitcoinSecret. * @param {Base58String} secret + * @param {Network?} network * @returns {KeyRing} */ -KeyRing.fromSecret = function fromSecret(data) { - return new KeyRing().fromSecret(data); +KeyRing.fromSecret = function fromSecret(data, network) { + return new KeyRing().fromSecret(data, network); }; /** diff --git a/lib/wallet/account.js b/lib/wallet/account.js index cba6c54f..10c20724 100644 --- a/lib/wallet/account.js +++ b/lib/wallet/account.js @@ -280,7 +280,7 @@ Account.prototype.pushKey = function pushKey(key) { var index; if (HD.isBase58(key)) - key = HD.fromBase58(key); + key = HD.fromBase58(key, this.network); assert(key.verifyNetwork(this.network), 'Network mismatch for account key.'); @@ -320,7 +320,7 @@ Account.prototype.pushKey = function pushKey(key) { Account.prototype.spliceKey = function spliceKey(key) { if (HD.isBase58(key)) - key = HD.fromBase58(key); + key = HD.fromBase58(key, this.network); assert(key.verifyNetwork(this.network), 'Network mismatch for account key.'); diff --git a/lib/wallet/wallet.js b/lib/wallet/wallet.js index df8a97ac..979be82e 100644 --- a/lib/wallet/wallet.js +++ b/lib/wallet/wallet.js @@ -111,7 +111,7 @@ Wallet.prototype.fromOptions = function fromOptions(options) { key = HD.fromMnemonic(null, this.network); if (HD.isBase58(key)) - key = HD.fromBase58(key); + key = HD.fromBase58(key, this.network); assert(HD.isPrivate(key), 'Must create wallet with hd private key.'); @@ -697,7 +697,7 @@ Wallet.prototype._createAccount = co(function* createAccount(options, passphrase key = options.accountKey; if (HD.isBase58(key)) - key = HD.fromBase58(key); + key = HD.fromBase58(key, this.network); if (!HD.isPublic(key)) throw new Error('Must add HD public keys to watch only wallet.'); diff --git a/lib/wallet/walletkey.js b/lib/wallet/walletkey.js index 24ee2b94..e94685eb 100644 --- a/lib/wallet/walletkey.js +++ b/lib/wallet/walletkey.js @@ -106,11 +106,12 @@ WalletKey.fromScript = function fromScript(key, script, compressed, network) { /** * Instantiate a wallet key from a serialized CBitcoinSecret. * @param {Base58String} secret + * @param {Network?} network * @returns {WalletKey} */ -WalletKey.fromSecret = function fromSecret(data) { - return new WalletKey().fromSecret(data); +WalletKey.fromSecret = function fromSecret(data, network) { + return new WalletKey().fromSecret(data, network); }; /**