diff --git a/lib/hd/private.js b/lib/hd/private.js index f184e073..f66c783d 100644 --- a/lib/hd/private.js +++ b/lib/hd/private.js @@ -162,6 +162,18 @@ HDPrivateKey.prototype.xpubkey = function xpubkey() { return this.toPublic().xpubkey(); }; +/** + * Verify network. + * @param {(NetworkType|Network)} network + * @returns {Boolean} + */ + +HDPrivateKey.prototype.verifyNetwork = function verifyNetwork(network) { + network = Network.get(network); + return this.network.keyPrefix.xprivkey === network.keyPrefix.xprivkey + && this.network.keyPrefix.coinType === network.keyPrefix.coinType; +}; + /** * Destroy the key (zeroes chain code, privkey, and pubkey). * @param {Boolean} pub - Destroy hd public key as well. diff --git a/lib/hd/public.js b/lib/hd/public.js index 2c9fe5ca..e276f4aa 100644 --- a/lib/hd/public.js +++ b/lib/hd/public.js @@ -132,6 +132,18 @@ HDPublicKey.prototype.xpubkey = function() { return this._xpubkey; }; +/** + * Verify network. + * @param {(NetworkType|Network)} network + * @returns {Boolean} + */ + +HDPublicKey.prototype.verifyNetwork = function verifyNetwork(network) { + network = Network.get(network); + return this.network.keyPrefix.xpubkey === network.keyPrefix.xpubkey + && this.network.keyPrefix.coinType === network.keyPrefix.coinType; +}; + /** * Destroy the key (zeroes chain code and pubkey). */ diff --git a/lib/http/client.js b/lib/http/client.js index 230d761c..06dce9a1 100644 --- a/lib/http/client.js +++ b/lib/http/client.js @@ -702,17 +702,6 @@ HTTPClient.prototype.sign = function sign(id, tx, options) { return this._post('/wallet/' + id + '/sign', body); }; -/** - * Fill a transaction with coins. - * @param {TX} tx - * @returns {Promise} - */ - -HTTPClient.prototype.fillCoins = function fillCoins(id, tx) { - var body = { tx: toHex(tx) }; - return this._post('/wallet/' + id + '/fill', body); -}; - /** * @param {WalletID} id * @param {Number} now - Current time. diff --git a/lib/http/rpc.js b/lib/http/rpc.js index 4c55633c..4e19767b 100644 --- a/lib/http/rpc.js +++ b/lib/http/rpc.js @@ -765,6 +765,12 @@ RPC.prototype.getblock = co(function* getblock(args) { RPC.prototype._txToJSON = function _txToJSON(tx, entry) { var self = this; + var height = entry ? entry.height : -1; + var conf = 0; + + if (height >= this.chain.height) + conf = height + 1 - this.chain.height; + return { txid: tx.txid(), hash: tx.wtxid(), @@ -800,7 +806,7 @@ RPC.prototype._txToJSON = function _txToJSON(tx, entry) { }; }), blockhash: entry ? entry.rhash() : null, - confirmations: tx.getConfirmations(this.chain.height), + confirmations: conf, time: entry ? entry.ts : 0, blocktime: entry ? entry.ts : 0 }; @@ -1170,7 +1176,7 @@ RPC.prototype.gettxout = co(function* gettxout(args) { return { bestblock: this.chain.tip.rhash(), - confirmations: coin.getConfirmations(this.chain.height), + confirmations: coin.getDepth(this.chain.height), value: Amount.btc(coin.value, true), scriptPubKey: this._scriptToJSON(coin.script, true), version: coin.version, @@ -2920,7 +2926,7 @@ RPC.prototype.getreceivedbyaccount = co(function* getreceivedbyaccount(args) { for (i = 0; i < txs.length; i++) { wtx = txs[i]; - conf = wtx.getConfirmations(this.chain.height); + conf = wtx.getDepth(this.chain.height); if (conf < minconf) continue; @@ -2961,7 +2967,7 @@ RPC.prototype.getreceivedbyaddress = co(function* getreceivedbyaddress(args) { for (i = 0; i < txs.length; i++) { wtx = txs[i]; - if (wtx.getConfirmations(this.chain.height) < minconf) + if (wtx.getDepth(this.chain.height) < minconf) continue; for (j = 0; j < wtx.tx.outputs.length; j++) { @@ -3389,7 +3395,7 @@ RPC.prototype._listReceived = co(function* _listReceived(minconf, empty, account for (i = 0; i < txs.length; i++) { wtx = txs[i]; - conf = wtx.getConfirmations(this.chain.height); + conf = wtx.getDepth(this.chain.height); if (conf < minconf) continue; @@ -3495,7 +3501,7 @@ RPC.prototype.listsinceblock = co(function* listsinceblock(args) { if (wtx.height < height) continue; - if (wtx.getConfirmations(this.chain.height) < minconf) + if (wtx.getDepth(this.chain.height) < minconf) continue; if (!highest || wtx.height > highest) diff --git a/lib/http/wallet.js b/lib/http/wallet.js index 88a89e8b..bdd43452 100644 --- a/lib/http/wallet.js +++ b/lib/http/wallet.js @@ -272,14 +272,6 @@ HTTPWallet.prototype.sign = function sign(tx, options) { return this.client.sign(this.id, tx, options); }; -/** - * @see Wallet#fillCoins - */ - -HTTPWallet.prototype.fillCoins = function fillCoins(tx) { - return this.client.fillCoins(tx); -}; - /** * @see HTTPClient#getWallet */ diff --git a/lib/primitives/coin.js b/lib/primitives/coin.js index 9cf4688c..41a7031d 100644 --- a/lib/primitives/coin.js +++ b/lib/primitives/coin.js @@ -98,7 +98,7 @@ Coin.fromOptions = function fromOptions(options) { * @return {Number} */ -Coin.prototype.getConfirmations = function getConfirmations(height) { +Coin.prototype.getDepth = function getDepth(height) { assert(typeof height === 'number', 'Must pass a height.'); if (this.height === -1) @@ -363,7 +363,7 @@ Coin.isCoin = function isCoin(obj) { return obj && obj.version !== undefined && obj.script !== undefined - && typeof obj.getConfirmations === 'function'; + && typeof obj.getDepth === 'function'; }; /* diff --git a/lib/primitives/keyring.js b/lib/primitives/keyring.js index 7390847d..6ca26d1d 100644 --- a/lib/primitives/keyring.js +++ b/lib/primitives/keyring.js @@ -329,6 +329,17 @@ KeyRing.fromSecret = function fromSecret(data) { return new KeyRing().fromSecret(data); }; +/** + * Verify network. + * @param {(NetworkType|Network)} network + * @returns {Boolean} + */ + +KeyRing.prototype.verifyNetwork = function verifyNetwork(network) { + network = Network.get(network); + return this.network.keyPrefix.privkey === network.keyPrefix.privkey; +}; + /** * Get private key. * @param {String?} enc - Can be `"hex"`, `"base58"`, or `null`. diff --git a/lib/primitives/mtx.js b/lib/primitives/mtx.js index 799e7781..46753421 100644 --- a/lib/primitives/mtx.js +++ b/lib/primitives/mtx.js @@ -154,10 +154,11 @@ MTX.prototype.addInput = function addInput(coin, index) { if (coin instanceof Outpoint) { input.prevout.fromOptions(coin); - } else { - input.fromOptions(coin); + this.inputs.push(input); + return this; } + input.fromOptions(coin); this.inputs.push(input); return this; @@ -306,8 +307,8 @@ MTX.prototype.getSigops = function getSigops(flags) { * @returns {Boolean} */ -MTX.prototype.checkInputs = function checkInputs(spendHeight, ret) { - return TX.prototype.checkInputs.call(this, this.view, spendHeight, ret); +MTX.prototype.checkInputs = function checkInputs(height, ret) { + return TX.prototype.checkInputs.call(this, this.view, height, ret); }; /** @@ -1294,10 +1295,14 @@ MTX.prototype.setSequence = function setSequence(index, locktime, seconds) { * @private */ -MTX.prototype._mutable = function _mutable() { - var i; - for (i = 0; i < this.outputs.length; i++) - this.outputs[i].mutable = true; +MTX.prototype._mutable = function _mutable(value) { + var i, output; + + for (i = 0; i < this.outputs.length; i++) { + output = this.outputs[i]; + output.mutable = value; + } + return this; }; @@ -1343,7 +1348,7 @@ MTX.prototype.getJSON = function getJSON(network) { */ MTX.fromJSON = function fromJSON(json) { - return new MTX().fromJSON(JSON)._mutable(); + return new MTX().fromJSON(JSON)._mutable(true); }; /** @@ -1351,7 +1356,7 @@ MTX.fromJSON = function fromJSON(json) { */ MTX.fromReader = function fromReader(br) { - return new MTX().fromReader(br)._mutable(); + return new MTX().fromReader(br)._mutable(true); }; /** @@ -1361,23 +1366,7 @@ MTX.fromReader = function fromReader(br) { MTX.fromRaw = function fromRaw(data, enc) { if (typeof data === 'string') data = new Buffer(data, enc); - return new MTX().fromRaw(data)._mutable(); -}; - -/** - * @see TX.fromExtended - */ - -MTX.fromExtended = function fromExtended(data, saveCoins, enc) { - if (typeof saveCoins === 'string') { - enc = saveCoins; - saveCoins = false; - } - - if (typeof data === 'string') - data = new Buffer(data, enc); - - return new MTX().fromExtended(data, saveCoins)._mutable(); + return new MTX().fromRaw(data)._mutable(true); }; /** diff --git a/lib/primitives/tx.js b/lib/primitives/tx.js index 9f6fa809..1a4832c1 100644 --- a/lib/primitives/tx.js +++ b/lib/primitives/tx.js @@ -1242,6 +1242,9 @@ TX.prototype.isSane = function isSane(ret) { } } + if (!this.mutable) + this._outputValue = total; + return true; }; @@ -1381,13 +1384,11 @@ TX.prototype.hasStandardInputs = function hasStandardInputs(view) { */ TX.prototype.hasStandardWitness = function hasStandardWitness(view, ret) { - var result; + var result = this.getWitnessStandard(view); if (!ret) ret = new VerifyResult(); - result = this.getWitnessStandard(view); - switch (result) { case BAD_WITNESS: ret.reason = 'bad-witness'; @@ -1543,7 +1544,7 @@ TX.prototype.getWitnessStandard = function getWitnessStandard(view) { * after they're created). Note that this function is * consensus critical. * @param {CoinView} view - * @param {Number} spendHeight - Height at which the + * @param {Number} height - Height at which the * transaction is being spent. In the mempool this is * the chain height plus one at the time it entered the pool. * @param {Object?} ret - Return object, may be @@ -1551,13 +1552,15 @@ TX.prototype.getWitnessStandard = function getWitnessStandard(view) { * @returns {Boolean} */ -TX.prototype.checkInputs = function checkInputs(view, spendHeight, ret) { +TX.prototype.checkInputs = function checkInputs(view, height, ret) { var total = 0; var i, input, coins, coin, fee, value; if (!ret) ret = new VerifyResult(); + assert(typeof height === 'number'); + for (i = 0; i < this.inputs.length; i++) { input = this.inputs[i]; coins = view.get(input.prevout.hash); @@ -1569,8 +1572,8 @@ TX.prototype.checkInputs = function checkInputs(view, spendHeight, ret) { return false; } - if (coins.coinbase && spendHeight != null) { - if (spendHeight - coins.height < constants.tx.COINBASE_MATURITY) { + if (coins.coinbase) { + if (height - coins.height < constants.tx.COINBASE_MATURITY) { ret.reason = 'bad-txns-premature-spend-of-coinbase'; ret.score = 0; return false; @@ -1617,6 +1620,9 @@ TX.prototype.checkInputs = function checkInputs(view, spendHeight, ret) { return false; } + if (!this.mutable) + this._inputValue = total; + return true; }; diff --git a/lib/wallet/account.js b/lib/wallet/account.js index 8bc49e4a..a9d4dbc7 100644 --- a/lib/wallet/account.js +++ b/lib/wallet/account.js @@ -281,7 +281,7 @@ Account.prototype.pushKey = function pushKey(key) { if (HD.isBase58(key)) key = HD.fromBase58(key); - assert(key.network === this.network, + assert(key.verifyNetwork(this.network), 'Network mismatch for account key.'); if (!HD.isPublic(key)) @@ -321,7 +321,7 @@ Account.prototype.spliceKey = function spliceKey(key) { if (HD.isBase58(key)) key = HD.fromBase58(key); - assert(key.network === this.network, + assert(key.verifyNetwork(this.network), 'Network mismatch for account key.'); if (!HD.isHDPublicKey(key)) diff --git a/lib/wallet/records.js b/lib/wallet/records.js index 06285270..ca18753e 100644 --- a/lib/wallet/records.js +++ b/lib/wallet/records.js @@ -531,7 +531,7 @@ TXRecord.prototype.getBlock = function getBlock() { * @returns {Number} confirmations */ -TXRecord.prototype.getConfirmations = function getConfirmations(height) { +TXRecord.prototype.getDepth = function getDepth(height) { assert(typeof height === 'number', 'Must pass in height.'); if (this.height === -1) diff --git a/lib/wallet/txdb.js b/lib/wallet/txdb.js index 069b161e..e1f554af 100644 --- a/lib/wallet/txdb.js +++ b/lib/wallet/txdb.js @@ -3154,7 +3154,7 @@ Details.prototype.setOutput = function setOutput(i, path) { * @returns {Number} */ -Details.prototype.getConfirmations = function getConfirmations() { +Details.prototype.getDepth = function getDepth() { var depth; if (this.height === -1) @@ -3235,7 +3235,7 @@ Details.prototype.toJSON = function toJSON() { virtualSize: this.vsize, fee: Amount.btc(fee), rate: Amount.btc(rate), - confirmations: this.getConfirmations(), + confirmations: this.getDepth(), inputs: this.inputs.map(function(input) { return input.getJSON(self.network); }), diff --git a/lib/wallet/wallet.js b/lib/wallet/wallet.js index 7487d493..5e7937a1 100644 --- a/lib/wallet/wallet.js +++ b/lib/wallet/wallet.js @@ -116,7 +116,7 @@ Wallet.prototype.fromOptions = function fromOptions(options) { assert(HD.isPrivate(key), 'Must create wallet with hd private key.'); - assert(key.network === this.network, + assert(key.verifyNetwork(this.network), 'Network mismatch for master key.'); this.master.fromKey(key); @@ -702,7 +702,7 @@ Wallet.prototype._createAccount = co(function* createAccount(options, passphrase if (!HD.isPublic(key)) throw new Error('Must add HD public keys to watch only wallet.'); - assert(key.network === this.network, + assert(key.verifyNetwork(this.network), 'Network mismatch for watch only key.'); } else { assert(this.master.key); @@ -1240,7 +1240,7 @@ Wallet.prototype._importKey = co(function* importKey(acct, ring, passphrase) { if (acct == null) acct = 0; - assert(ring.network === this.network, + assert(ring.verifyNetwork(this.network), 'Network mismatch for key.'); if (!this.watchOnly) { @@ -1325,7 +1325,7 @@ Wallet.prototype._importAddress = co(function* importAddress(acct, address) { if (acct == null) acct = 0; - assert(address.network === this.network, + assert(address.verifyNetwork(this.network), 'Network mismatch for address.'); if (!this.watchOnly) diff --git a/test/wallet-test.js b/test/wallet-test.js index c3993e89..02283b5b 100644 --- a/test/wallet-test.js +++ b/test/wallet-test.js @@ -1151,7 +1151,9 @@ describe('Wallet', function() { var w = wallet; var txs = yield w.getRange('foo', { start: util.now() - 1000 }); var details = yield w.toDetails(txs); - assert.equal(details[1].toJSON().outputs[0].path.name, 'foo'); + assert(details.some(function(tx) { + return tx.toJSON().outputs[0].path.name === 'foo'; + })); })); it('should rename wallet', cob(function* () {