diff --git a/lib/blockchain/chaindb.js b/lib/blockchain/chaindb.js index b74fa448..cdfd56ca 100644 --- a/lib/blockchain/chaindb.js +++ b/lib/blockchain/chaindb.js @@ -1700,14 +1700,35 @@ ChainDB.prototype.connectBlock = co(function* connectBlock(block, view) { if (this.options.spv) return; - this.pending.connect(block, view); + this.pending.connect(block); // Genesis block's coinbase is unspendable. if (this.chain.isGenesis(block)) return; - // Index transactions if enabled. - this.indexBlock(block.txs); + for (i = 0; i < block.txs.length; i++) { + tx = block.txs[i]; + + if (i > 0) { + for (j = 0; j < tx.inputs.length; j++) { + input = tx.inputs[j]; + assert(input.coin); + this.pending.spend(input.coin); + } + } + + for (j = 0; j < tx.outputs.length; j++) { + output = tx.outputs[j]; + + if (output.script.isUnspendable()) + continue; + + this.pending.add(output); + } + + // Index the transaction if enabled. + this.indexTX(tx); + } // Commit new coin state. this.saveView(view); @@ -1733,14 +1754,24 @@ ChainDB.prototype.disconnectBlock = co(function* disconnectBlock(block) { view = yield this.getUndoView(block); + this.pending.disconnect(block); + for (i = block.txs.length - 1; i >= 0; i--) { tx = block.txs[i]; hash = tx.hash('hex'); + if (i > 0) { + for (j = 0; j < tx.inputs.length; j++) { + input = tx.inputs[j]; + assert(input.coin); + this.pending.add(input.coin); + } + } + // Add all of the coins we are about to // remove. This is to ensure they appear // in the view array below. - view.add(Coins.fromTX(tx)); + view.addTX(tx); for (j = 0; j < tx.outputs.length; j++) { output = tx.outputs[j]; @@ -1750,14 +1781,14 @@ ChainDB.prototype.disconnectBlock = co(function* disconnectBlock(block) { // Spend added coin. view.spend(hash, j); + + this.pending.spend(output); } // Remove from transaction index. this.unindexTX(tx); } - this.pending.disconnect(block, view); - // Commit new coin state. this.saveView(view); @@ -1805,24 +1836,6 @@ ChainDB.prototype.saveOptions = function saveOptions() { return this.db.put(layout.O, this.options.toRaw()); }; -/** - * Index transactions by txid and address. - * @private - * @param {TX[]} txs - */ - -ChainDB.prototype.indexBlock = function indexBlock(txs) { - var i, tx; - - if (!this.options.indexTX && !this.options.indexAddress) - return; - - for (i = 0; i < block.txs.length; i++) { - tx = block.txs[i]; - this.indexTX(tx); - } -}; - /** * Index a transaction by txid and address. * @private @@ -2101,16 +2114,22 @@ ChainState.prototype.clone = function clone() { return state; }; -ChainState.prototype.connect = function connect(block, view) { +ChainState.prototype.connect = function connect(block) { this.tx += block.txs.length; - this.coin += view.coinDelta; - this.value += view.valueDelta; }; -ChainState.prototype.disconnect = function connect(block, view) { +ChainState.prototype.disconnect = function connect(block) { this.tx -= block.txs.length; - this.coin += view.coinDelta; - this.value += view.valueDelta; +}; + +ChainState.prototype.add = function add(coin) { + this.coin++; + this.value += coin.value; +}; + +ChainState.prototype.spend = function spend(coin) { + this.coin--; + this.value -= coin.value; }; ChainState.prototype.commit = function commit(hash) { diff --git a/lib/blockchain/coinview.js b/lib/blockchain/coinview.js index c736f2d7..b2a6540e 100644 --- a/lib/blockchain/coinview.js +++ b/lib/blockchain/coinview.js @@ -23,8 +23,6 @@ function CoinView(coins) { this.coins = coins || {}; this.undo = new UndoCoins(); - this.coinDelta = 0; - this.valueDelta = 0; } /** @@ -42,21 +40,7 @@ CoinView.prototype.add = function add(coins) { */ CoinView.prototype.addTX = function addTX(tx) { - var coins = Coins.fromTX(tx); - var i, entry; - - this.coinDelta += coins.outputs.length; - - for (i = 0; i < coins.outputs.length; i++) { - entry = coins.outputs[i]; - - if (!entry) - continue; - - this.valueDelta += entry.output.value; - } - - this.add(coins); + this.add(Coins.fromTX(tx)); }; /** @@ -106,7 +90,7 @@ CoinView.prototype.has = function has(hash, index) { CoinView.prototype.spend = function spend(hash, index) { var coins = this.coins[hash]; - var entry, undo, coin; + var entry, undo; if (!coins) return; @@ -125,12 +109,7 @@ CoinView.prototype.spend = function spend(hash, index) { undo.version = coins.version; } - coin = entry.toCoin(coins, index); - - this.coinDelta -= 1; - this.valueDelta -= coin.value; - - return coin; + return entry.toCoin(coins, index); }; /** diff --git a/lib/blockchain/undocoins.js b/lib/blockchain/undocoins.js index ea795a89..1a5c1b76 100644 --- a/lib/blockchain/undocoins.js +++ b/lib/blockchain/undocoins.js @@ -117,7 +117,7 @@ UndoCoins.prototype.apply = function apply(i, view, outpoint) { var undo = this.items[i]; var hash = outpoint.hash; var index = outpoint.index; - var coins, coin; + var coins; assert(undo); @@ -137,13 +137,7 @@ UndoCoins.prototype.apply = function apply(i, view, outpoint) { coins.add(index, undo.toOutput()); - coin = coins.getCoin(index); - assert(coin); - - view.coinDelta += 1; - view.valueDelta += coin.value; - - return coin; + return coins.getCoin(index); }; /**