tx/wallet: misc fixes.

This commit is contained in:
Christopher Jeffrey 2016-12-11 06:14:32 -08:00
parent 59645ac3ec
commit 48fc7549ce
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
14 changed files with 90 additions and 71 deletions

View File

@ -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.

View File

@ -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).
*/

View File

@ -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.

View File

@ -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)

View File

@ -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
*/

View File

@ -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';
};
/*

View File

@ -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`.

View File

@ -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);
};
/**

View File

@ -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;
};

View File

@ -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))

View File

@ -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)

View File

@ -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);
}),

View File

@ -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)

View File

@ -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* () {