coins: undo coins fixes.

This commit is contained in:
Christopher Jeffrey 2016-12-09 16:31:52 -08:00
parent 12b3274d33
commit 092c1a90df
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
13 changed files with 68 additions and 36 deletions

View File

@ -213,8 +213,6 @@ Coins.prototype.spend = function spend(index) {
if (!entry || entry.spent) if (!entry || entry.spent)
return; return;
// this.outputs[index] = null;
// this.cleanup();
entry.spent = true; entry.spent = true;
return entry; return entry;
@ -587,6 +585,7 @@ CoinEntry.prototype.reader = function reader() {
CoinEntry.prototype.toCoin = function toCoin(coins, index) { CoinEntry.prototype.toCoin = function toCoin(coins, index) {
var coin = new Coin(); var coin = new Coin();
var output = this.toOutput();
// Load in all necessary properties // Load in all necessary properties
// from the parent Coins object. // from the parent Coins object.
@ -595,13 +594,8 @@ CoinEntry.prototype.toCoin = function toCoin(coins, index) {
coin.height = coins.height; coin.height = coins.height;
coin.hash = coins.hash; coin.hash = coins.hash;
coin.index = index; coin.index = index;
coin.script = output.script;
if (this.output) { coin.value = output.value;
coin.script = this.output.script;
coin.value = this.output.value;
} else {
decompress.coin(coin, this.reader());
}
return coin; return coin;
}; };

View File

@ -6,6 +6,7 @@
'use strict'; 'use strict';
var assert = require('assert');
var co = require('../utils/co'); var co = require('../utils/co');
var Coins = require('./coins'); var Coins = require('./coins');
var UndoCoins = require('./undocoins'); var UndoCoins = require('./undocoins');
@ -144,6 +145,7 @@ CoinView.prototype.spendFrom = function spendFrom(coins, index) {
undo.height = coins.height; undo.height = coins.height;
undo.coinbase = coins.coinbase; undo.coinbase = coins.coinbase;
undo.version = coins.version; undo.version = coins.version;
assert(undo.height !== -1);
} }
return true; return true;

View File

@ -140,6 +140,7 @@ UndoCoins.prototype.apply = function apply(view, outpoint) {
assert(!view.unspent[hash]); assert(!view.unspent[hash]);
view.unspent[hash] = coins; view.unspent[hash] = coins;
coins.hash = hash;
coins.coinbase = undo.coinbase; coins.coinbase = undo.coinbase;
coins.height = undo.height; coins.height = undo.height;
coins.version = undo.version; coins.version = undo.version;
@ -151,8 +152,6 @@ UndoCoins.prototype.apply = function apply(view, outpoint) {
coins.addOutput(index, undo.toOutput()); coins.addOutput(index, undo.toOutput());
assert(coins.has(index)); assert(coins.has(index));
return coins.getCoin(index);
}; };
/** /**

View File

@ -406,7 +406,7 @@ Mempool.prototype.getCoin = function getCoin(hash, index) {
if (index >= entry.tx.outputs.length) if (index >= entry.tx.outputs.length)
return; return;
return Coin.fromTX(entry.tx, index); return Coin.fromTX(entry.tx, index, entry.height);
}; };
/** /**
@ -1565,7 +1565,7 @@ Mempool.prototype.trackEntry = function trackEntry(entry, view) {
if (output.script.isUnspendable()) if (output.script.isUnspendable())
continue; continue;
coin = Coin.fromTX(tx, i); coin = Coin.fromTX(tx, i, entry.height);
this.coinIndex.addCoin(coin); this.coinIndex.addCoin(coin);
} }
@ -1610,7 +1610,7 @@ Mempool.prototype.untrackEntry = function untrackEntry(entry) {
if (output.script.isUnspendable()) if (output.script.isUnspendable())
continue; continue;
coin = Coin.fromTX(tx, i); coin = Coin.fromTX(tx, i, entry.height);
this.coinIndex.removeCoin(coin); this.coinIndex.removeCoin(coin);
} }

View File

@ -606,7 +606,17 @@ Block.prototype.getPrevout = function getPrevout() {
* @returns {Object} * @returns {Object}
*/ */
Block.prototype.inspect = function inspect(view) { Block.prototype.inspect = function inspect() {
return this.show();
};
/**
* Inspect the block and return a more
* user-friendly representation of the data.
* @returns {Object}
*/
Block.prototype.show = function show(view) {
var commitmentHash = this.getCommitmentHash('hex'); var commitmentHash = this.getCommitmentHash('hex');
return { return {
hash: this.rhash(), hash: this.rhash(),

View File

@ -282,11 +282,12 @@ Coin.fromRaw = function fromRaw(data, enc) {
* @param {Number} index * @param {Number} index
*/ */
Coin.prototype.fromTX = function fromTX(tx, index) { Coin.prototype.fromTX = function fromTX(tx, index, height) {
assert(util.isNumber(index)); assert(util.isNumber(index));
assert(index < tx.outputs.length); assert(index < tx.outputs.length);
assert(typeof height === 'number');
this.version = tx.version; this.version = tx.version;
this.height = tx.height; this.height = height;
this.value = tx.outputs[index].value; this.value = tx.outputs[index].value;
this.script = tx.outputs[index].script; this.script = tx.outputs[index].script;
this.coinbase = tx.isCoinbase(); this.coinbase = tx.isCoinbase();
@ -302,8 +303,8 @@ Coin.prototype.fromTX = function fromTX(tx, index) {
* @returns {Coin} * @returns {Coin}
*/ */
Coin.fromTX = function fromTX(tx, index) { Coin.fromTX = function fromTX(tx, index, height) {
return new Coin().fromTX(tx, index); return new Coin().fromTX(tx, index, height);
}; };
/** /**

View File

@ -224,7 +224,16 @@ Input.prototype.isCoinbase = function isCoinbase() {
* @returns {Object} * @returns {Object}
*/ */
Input.prototype.inspect = function inspect(coin) { Input.prototype.inspect = function inspect() {
return this.show();
};
/**
* Convert the input to a more user-friendly object.
* @returns {Object}
*/
Input.prototype.show = function show(coin) {
return { return {
type: this.getType(coin), type: this.getType(coin),
subtype: this.getSubtype(coin), subtype: this.getSubtype(coin),

View File

@ -164,7 +164,7 @@ MTX.prototype.addInput = function addInput(coin, index) {
if (coin instanceof TX) { if (coin instanceof TX) {
input.fromTX(coin, index); input.fromTX(coin, index);
coin = Coin.fromTX(coin, index); coin = Coin.fromTX(coin, index, -1);
} }
if (coin instanceof Coin) { if (coin instanceof Coin) {
@ -1329,6 +1329,15 @@ MTX.prototype._mutable = function _mutable() {
*/ */
MTX.prototype.inspect = function inspect() { MTX.prototype.inspect = function inspect() {
return this.show();
};
/**
* Inspect the transaction.
* @returns {Object}
*/
MTX.prototype.show = function show() {
return TX.prototype.inspect.call(this, this.view); return TX.prototype.inspect.call(this, this.view);
}; };

View File

@ -2001,7 +2001,17 @@ TX.prototype.toInv = function toInv() {
* @returns {Object} * @returns {Object}
*/ */
TX.prototype.inspect = function inspect(view) { TX.prototype.inspect = function inspect() {
return this.show();
};
/**
* Inspect the transaction and return a more
* user-friendly representation of the data.
* @returns {Object}
*/
TX.prototype.show = function show(view) {
var rate = 0; var rate = 0;
var fee = 0; var fee = 0;

View File

@ -439,7 +439,7 @@ TXDB.prototype.resolveOutputs = co(function* resolveOutputs(tx, block, resolved)
var flags = constants.flags.MANDATORY_VERIFY_FLAGS; var flags = constants.flags.MANDATORY_VERIFY_FLAGS;
var hash = tx.hash('hex'); var hash = tx.hash('hex');
var i, j, input, output, key; var i, j, input, output, key;
var orphans, orphan, coin, valid; var orphans, orphan, valid;
if (!resolved) if (!resolved)
resolved = []; resolved = [];
@ -460,8 +460,6 @@ TXDB.prototype.resolveOutputs = co(function* resolveOutputs(tx, block, resolved)
delete this.orphans[key]; delete this.orphans[key];
coin = Coin.fromTX(tx, i);
// Note that their might be multiple // Note that their might be multiple
// orphans per input, either due to // orphans per input, either due to
// double spends or an adversary // double spends or an adversary
@ -479,7 +477,7 @@ TXDB.prototype.resolveOutputs = co(function* resolveOutputs(tx, block, resolved)
// We can finally verify this input. // We can finally verify this input.
if (this.options.verify && orphan.tx.height === -1) if (this.options.verify && orphan.tx.height === -1)
valid = yield orphan.tx.verifyInputAsync(orphan.index, coin, flags); valid = yield orphan.tx.verifyInputAsync(orphan.index, output, flags);
// If it's valid and fully resolved, // If it's valid and fully resolved,
// we can resolve _its_ outputs. // we can resolve _its_ outputs.
@ -613,7 +611,7 @@ TXDB.prototype.resolveInput = co(function* resolveInput(tx, index, path) {
assert(stx); assert(stx);
// Crete the credit and add the undo coin. // Crete the credit and add the undo coin.
credit = Credit.fromTX(tx, index); credit = Credit.fromTX(tx, index, tx.height);
this.spendCredit(credit, stx, spent.index); this.spendCredit(credit, stx, spent.index);
@ -1111,7 +1109,7 @@ TXDB.prototype.insert = co(function* insert(tx, block) {
continue; continue;
} }
credit = Credit.fromTX(tx, i); credit = Credit.fromTX(tx, i, tx.height);
this.pending.coin++; this.pending.coin++;
this.pending.unconfirmed += output.value; this.pending.unconfirmed += output.value;
@ -1426,7 +1424,7 @@ TXDB.prototype.erase = co(function* erase(tx) {
details.setOutput(i, path); details.setOutput(i, path);
credit = Credit.fromTX(tx, i); credit = Credit.fromTX(tx, i, tx.height);
this.pending.coin--; this.pending.coin--;
this.pending.unconfirmed -= output.value; this.pending.unconfirmed -= output.value;
@ -2981,8 +2979,8 @@ Credit.prototype.toRaw = function toRaw() {
* @returns {Credit} * @returns {Credit}
*/ */
Credit.prototype.fromTX = function fromTX(tx, index) { Credit.prototype.fromTX = function fromTX(tx, index, height) {
this.coin.fromTX(tx, index); this.coin.fromTX(tx, index, height);
this.spent = false; this.spent = false;
return this; return this;
}; };
@ -2994,8 +2992,8 @@ Credit.prototype.fromTX = function fromTX(tx, index) {
* @returns {Credit} * @returns {Credit}
*/ */
Credit.fromTX = function fromTX(tx, index) { Credit.fromTX = function fromTX(tx, index, height) {
return new Credit().fromTX(tx, index); return new Credit().fromTX(tx, index, height);
}; };
/** /**

View File

@ -225,7 +225,7 @@ describe('Chain', function() {
yield chain.add(block); yield chain.add(block);
tx = block.txs[1]; tx = block.txs[1];
output = bcoin.coin.fromTX(tx, 1); output = bcoin.coin.fromTX(tx, 1, chain.height);
coin = yield chain.db.getCoin(tx.hash('hex'), 1); coin = yield chain.db.getCoin(tx.hash('hex'), 1);

View File

@ -58,7 +58,7 @@ describe('Mempool', function() {
mempool.trackEntry(entry, funding.view); mempool.trackEntry(entry, funding.view);
return bcoin.coin.fromTX(funding, 0); return bcoin.coin.fromTX(funding, 0, -1);
} }
it('should open mempool', cob(function* () { it('should open mempool', cob(function* () {

View File

@ -216,7 +216,7 @@ describe('Wallet', function() {
.addOutput(w.getAddress(), 24000) .addOutput(w.getAddress(), 24000)
.addOutput(w.getAddress(), 24000); .addOutput(w.getAddress(), 24000);
doubleSpend = bcoin.coin.fromTX(t1, 0); doubleSpend = bcoin.coin.fromTX(t1, 0, -1);
// balance: 49000 // balance: 49000
yield w.sign(t2); yield w.sign(t2);