tx/wallet: misc fixes.
This commit is contained in:
parent
59645ac3ec
commit
48fc7549ce
@ -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.
|
||||
|
||||
@ -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).
|
||||
*/
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
*/
|
||||
|
||||
@ -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';
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@ -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`.
|
||||
|
||||
@ -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);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -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;
|
||||
};
|
||||
|
||||
|
||||
@ -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))
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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);
|
||||
}),
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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* () {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user