From 0e31719d134305a533e391b19f3b4d85d337577c Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Fri, 27 May 2016 00:27:09 -0700 Subject: [PATCH] Revert "simple coin views." This reverts commit 5074e3100d0935efa2f43c9873c6699599c84e4d. --- lib/bcoin/chaindb.js | 232 ++++++++++++++++--------------------------- 1 file changed, 87 insertions(+), 145 deletions(-) diff --git a/lib/bcoin/chaindb.js b/lib/bcoin/chaindb.js index f3849430..2621d24f 100644 --- a/lib/bcoin/chaindb.js +++ b/lib/bcoin/chaindb.js @@ -92,8 +92,8 @@ function ChainDB(chain, options) { // Average number of outputs per tx: 2.2 // Average size of outputs per tx: 74b // Average number of txs: 2300 - // Key size: 66b (* 2) - this.coinWindow = ((165 * 1024 + 2300 * 4) + (2300 * 66 * 2)) * 5; + // Key size: 68b (* 2) + this.coinWindow = ((165 * 1024 + 5000 * 9) + (5000 * 68 * 2)) * 5; this.coinCache = new bcoin.lru(this.coinWindow); this.cacheHash = new bcoin.lru(this.cacheWindow, 1); @@ -782,7 +782,7 @@ ChainDB.prototype.removeBlock = function removeBlock(hash, batch, callback) { ChainDB.prototype.connectBlock = function connectBlock(block, batch, callback) { var self = this; var undo = new BufferWriter(); - var i, j, tx, input, output, key, addresses, address, hash, view, coins, raw; + var i, j, tx, input, output, key, addresses, address, hash, coin; if (this.options.spv) { self.emit('add block', block); @@ -830,38 +830,31 @@ ChainDB.prototype.connectBlock = function connectBlock(block, batch, callback) { batch.del('C/' + address + '/' + key); } + batch.del('c/' + key); + Framer.coin(input.coin, false, undo); - block.view.spend(input.prevout.hash, input.prevout.index); + self.coinCache.remove(key); } for (j = 0; j < tx.outputs.length; j++) { output = tx.outputs[j]; + key = hash + '/' + j; if (output.script.isUnspendable()) continue; + coin = bcoin.coin.fromTX(tx, j).toRaw(); + if (self.options.indexAddress) { address = output.getHash(); if (address) batch.put('C/' + address + '/' + key, DUMMY); } - } - block.view.add(tx.toCoins()); - } + batch.put('c/' + key, coin); - view = block.view.toArray(); - - for (i = 0; i < view.length; i++) { - coins = view[i]; - if (coins.count() === 0) { - batch.del('c/' + coins.hash); - self.coinCache.remove(coins.hash); - } else { - raw = coins.toRaw(); - batch.put('c/' + coins.hash, raw); - self.coinCache.set(coins.hash, raw); + self.coinCache.set(key, coin); } } @@ -887,7 +880,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, view, coins, raw; + var i, j, tx, input, output, key, addresses, address, hash, coin; if (this.options.spv) return utils.nextTick(callback); @@ -929,10 +922,12 @@ ChainDB.prototype.disconnectBlock = function disconnectBlock(block, batch, callb batch.put('C/' + address + '/' + key, DUMMY); } - block.view.addCoin(input.coin); - } + coin = input.coin.toRaw(); - block.view.add(tx.toCoins()); + batch.put('c/' + key, coin); + + self.coinCache.set(key, coin); + } for (j = 0; j < tx.outputs.length; j++) { output = tx.outputs[j]; @@ -947,21 +942,9 @@ ChainDB.prototype.disconnectBlock = function disconnectBlock(block, batch, callb batch.del('C/' + address + '/' + key); } - block.view.spend(hash, j); - } - } + batch.del('c/' + key); - view = block.view.toArray(); - - for (i = 0; i < view.length; i++) { - coins = view[i]; - if (coins.count() === 0) { - batch.del('c/' + coins.hash); - self.coinCache.remove(coins.hash); - } else { - raw = coins.toRaw(); - batch.put('c/' + coins.hash, raw); - self.coinCache.set(coins.hash, raw); + self.coinCache.remove(key); } } @@ -1065,62 +1048,29 @@ ChainDB.prototype.fillHistory = function fillHistory(tx, callback) { */ ChainDB.prototype.getCoin = function getCoin(hash, index, callback) { + var self = this; + var key = hash + '/' + index; var coin; - this.getCoins(hash, true, function(err, coins) { - if (err) - return callback(err); - - if (!coins) - return callback(); - - try { - coin = bcoin.coins.parseCoin(coins, hash, index); - } catch (e) { - return callback(e); - } - - return callback(null, coin); - }); -}; - -/** - * Get coins (unspents only). - * @param {Hash} hash - * @param {Function} callback - Returns [Error, {@link Coins}]. - */ - -ChainDB.prototype.getCoins = function getCoins(hash, raw, callback) { - var self = this; - var coins; - - if (!callback) { - callback = raw; - raw = false; - } - - coins = this.coinCache.get(hash); - - if (coins) { + coin = this.coinCache.get(key); + if (coin) { callback = utils.asyncify(callback); - - if (raw) - return callback(null, coins); - try { - coins = bcoin.coins.fromRaw(coins, hash); + coin = bcoin.coin.fromRaw(coin); + coin.hash = hash; + coin.index = index; } catch (e) { return callback(e); } - - return callback(null, coins); + return callback(null, coin); } - this.db.fetch('c/' + hash, function(data) { - self.coinCache.set(hash, data); - if (raw) - return data; - return bcoin.coins.fromRaw(data, hash); + this.db.fetch('c/' + key, function(data) { + var coin = bcoin.coin.fromRaw(data); + coin.hash = hash; + coin.index = index; + self.coinCache.set(key, data); + return coin; }, callback); }; @@ -1178,32 +1128,27 @@ ChainDB.prototype.getCoinsByAddress = function getCoinsByAddress(addresses, call utils.forEachSerial(addresses, function(address, next) { address = bcoin.address.getHash(address); - if (!address) return next(); - - self.db.iterate({ + self.db.lookup({ gte: 'C/' + address, lte: 'C/' + address + '~', transform: function(key) { key = key.split('/'); - return [key[2], +key[3]]; + return 'c/' + key[2] + '/' + key[3]; + }, + parse: function(data, key) { + var coin = bcoin.coin.fromRaw(data); + var hash = key.split('/'); + coin.hash = hash[1]; + coin.index = +hash[2]; + return coin; } - }, function(err, keys) { + }, function(err, coin) { if (err) return next(err); - - utils.forEachSerial(keys, function(key, next) { - self.getCoin(key[0], key[1], function(err, coin) { - if (err) - return callback(err); - - if (coin) - coins.push(coin); - - return next(); - }); - }, next); + coins = coins.concat(coin); + next(); }); }, function(err) { if (err) @@ -1339,21 +1284,9 @@ ChainDB.prototype._ensureHistory = function _ensureHistory(hash, callback) { */ ChainDB.prototype.fillBlock = function fillBlock(block, callback) { - var self = this; - var view = new bcoin.coinview(); var coins, spent, i, tx, hash, j, input, key; - utils.forEachSerial(block.getPrevout(), function(prevout, next) { - self.getCoins(prevout, function(err, coins) { - if (err) - return next(err); - - if (coins) - view.add(coins); - - next(); - }); - }, function(err) { + return this.fillCoins(block.txs, function(err) { if (err) return callback(err); @@ -1364,8 +1297,6 @@ ChainDB.prototype.fillBlock = function fillBlock(block, callback) { tx = block.txs[i]; hash = tx.hash('hex'); - view.fill(tx); - for (j = 0; j < tx.inputs.length; j++) { input = tx.inputs[j]; key = input.prevout.hash + '/' + input.prevout.index; @@ -1387,8 +1318,6 @@ ChainDB.prototype.fillBlock = function fillBlock(block, callback) { coins[hash + '/' + j] = bcoin.coin.fromTX(tx, j); } - block.view = view; - return callback(null, block); }); }; @@ -1421,36 +1350,30 @@ ChainDB.prototype.getUndoCoins = function getUndoCoins(hash, callback) { */ ChainDB.prototype.fillHistoryBlock = function fillHistoryBlock(block, callback) { - var self = this; var i, j, k, tx, input; - return this.fillBlock(block, function(err) { + return this.getUndoCoins(block.hash('hex'), function(err, coins) { if (err) return callback(err); - return self.getUndoCoins(block.hash('hex'), function(err, coins) { - if (err) - return callback(err); - - if (!coins) - return callback(null, block); - - for (i = 0, k = 0; i < block.txs.length; i++) { - tx = block.txs[i]; - - if (tx.isCoinbase()) - continue; - - for (j = 0; j < tx.inputs.length; j++) { - input = tx.inputs[j]; - input.coin = coins[k++]; - input.coin.hash = input.prevout.hash; - input.coin.index = input.prevout.index; - } - } - + if (!coins) return callback(null, block); - }); + + for (i = 0, k = 0; i < block.txs.length; i++) { + tx = block.txs[i]; + + if (tx.isCoinbase()) + continue; + + for (j = 0; j < tx.inputs.length; j++) { + input = tx.inputs[j]; + input.coin = coins[k++]; + input.coin.hash = input.prevout.hash; + input.coin.index = input.prevout.index; + } + } + + return callback(null, block); }); }; @@ -1504,13 +1427,32 @@ ChainDB.prototype.isUnspentTX = function isUnspentTX(hash, callback) { */ ChainDB.prototype.isSpentTX = function isSpentTX(hash, callback) { + var iter; + if (hash.hash) hash = hash.hash('hex'); - this.getCoins(hash, function(err, coins) { - if (err) - return callback(err); - return callback(null, !coins); + iter = this.db.iterator({ + gte: 'c/' + hash, + lte: 'c/' + hash + '~', + keys: true, + values: false, + fillCache: false, + keyAsBuffer: false + }); + + iter.next(function(err, key, value) { + if (err) { + return iter.end(function() { + callback(err); + }); + } + + iter.end(function(err) { + if (err) + return callback(err); + return callback(null, key === undefined); + }); }); };