diff --git a/lib/bcoin/chaindb.js b/lib/bcoin/chaindb.js index e43a4d92..15faed92 100644 --- a/lib/bcoin/chaindb.js +++ b/lib/bcoin/chaindb.js @@ -84,7 +84,7 @@ function ChainDB(chain, options) { // check. this.cacheWindow = (this.network.pow.retargetInterval + 1) * 2 + 100; - this.coinCache = new NullCache(100000); + this.coinCache = new bcoin.lru(100000); this.cacheHash = new bcoin.lru(this.cacheWindow); this.cacheHeight = new bcoin.lru(this.cacheWindow); @@ -833,7 +833,7 @@ ChainDB.prototype.connectBlock = function connectBlock(block, batch, callback) { if (output.script.isUnspendable()) continue; - coin = bcoin.coin.fromTX(tx, j); + coin = bcoin.coin.fromTX(tx, j).toRaw(); if (self.options.indexAddress) { address = output.getHash(); @@ -841,7 +841,7 @@ ChainDB.prototype.connectBlock = function connectBlock(block, batch, callback) { batch.put('C/' + address + '/' + key, DUMMY); } - batch.put('c/' + key, coin.toRaw()); + batch.put('c/' + key, coin); self.coinCache.set(key, coin); } @@ -869,7 +869,7 @@ ChainDB.prototype.connectBlock = function connectBlock(block, batch, callback) { ChainDB.prototype.disconnectBlock = function disconnectBlock(block, batch, callback) { var self = this; - var i, j, tx, input, output, key, addresses, address, hash; + var i, j, tx, input, output, key, addresses, address, hash, coin; if (this.options.spv) return utils.nextTick(callback); @@ -911,9 +911,11 @@ ChainDB.prototype.disconnectBlock = function disconnectBlock(block, batch, callb batch.put('C/' + address + '/' + key, DUMMY); } - batch.put('c/' + key, input.coin.toRaw()); + coin = input.coin.toRaw(); - self.coinCache.set(key, input.coin); + batch.put('c/' + key, coin); + + self.coinCache.set(key, coint); } for (j = 0; j < tx.outputs.length; j++) { @@ -1040,14 +1042,23 @@ ChainDB.prototype.getCoin = function getCoin(hash, index, callback) { var coin; coin = this.coinCache.get(key); - if (coin) - return utils.asyncify(callback)(null, coin); + if (coin) { + callback = utils.asyncify(callback); + try { + coin = bcoin.coin.fromRaw(coin); + coin.hash = hash; + coin.index = index; + } catch (e) { + return callback(e); + } + return callback(null, coin); + } this.db.fetch('c/' + key, function(data) { var coin = bcoin.coin.fromRaw(data); coin.hash = hash; coin.index = index; - self.coinCache.set(key, coin); + self.coinCache.set(key, data); return coin; }, callback); }; @@ -1262,13 +1273,14 @@ ChainDB.prototype._ensureHistory = function _ensureHistory(hash, callback) { */ ChainDB.prototype.fillBlock = function fillBlock(block, callback) { - return this.fillCoins(block.txs, function(err) { - var coins, i, tx, hash, j, input, key; + var coins, spent, i, tx, hash, j, input, key; + return this.fillCoins(block.txs, function(err) { if (err) return callback(err); coins = {}; + spent = {}; for (i = 0; i < block.txs.length; i++) { tx = block.txs[i]; @@ -1277,6 +1289,14 @@ ChainDB.prototype.fillBlock = function fillBlock(block, callback) { for (j = 0; j < tx.inputs.length; j++) { input = tx.inputs[j]; key = input.prevout.hash + '/' + input.prevout.index; + + if (spent[key]) { + delete input.coin; + continue; + } + + spent[key] = true; + if (!input.coin && coins[key]) { input.coin = coins[key]; delete coins[key];