mempool: refactor addr index.

This commit is contained in:
Christopher Jeffrey 2016-12-18 16:26:07 -08:00
parent 37770aa6df
commit 42f0b2aa19
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD

View File

@ -89,8 +89,8 @@ function Mempool(options) {
this.tx = {}; this.tx = {};
this.spents = {}; this.spents = {};
this.currentTX = null; this.currentTX = null;
this.coinIndex = new AddressIndex(this); this.coinIndex = new CoinIndex(this);
this.txIndex = new AddressIndex(this); this.txIndex = new TXIndex(this);
this.rejects = new Bloom.Rolling(120000, 0.000001); this.rejects = new Bloom.Rolling(120000, 0.000001);
@ -381,7 +381,6 @@ Mempool.prototype.limitOrphans = function limitOrphans() {
/** /**
* Retrieve a transaction from the mempool. * Retrieve a transaction from the mempool.
* Note that this will not be filled with coins.
* @param {Hash} hash * @param {Hash} hash
* @returns {TX} * @returns {TX}
*/ */
@ -422,7 +421,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, entry.height); return Coin.fromTX(entry.tx, index, -1);
}; };
/** /**
@ -488,7 +487,7 @@ Mempool.prototype.getCoinsByAddress = function getCoinsByAddress(addresses) {
if (!hash) if (!hash)
continue; continue;
coin = this.coinIndex.getCoins(hash); coin = this.coinIndex.get(hash);
for (j = 0; j < coin.length; j++) for (j = 0; j < coin.length; j++)
coins.push(coin[j]); coins.push(coin[j]);
@ -516,7 +515,7 @@ Mempool.prototype.getTXByAddress = function getTXByAddress(addresses) {
if (!hash) if (!hash)
continue; continue;
tx = this.txIndex.getTX(hash); tx = this.txIndex.get(hash);
for (j = 0; j < tx.length; j++) for (j = 0; j < tx.length; j++)
txs.push(tx[j]); txs.push(tx[j]);
@ -555,7 +554,6 @@ Mempool.prototype.getMetaByAddress = function getMetaByAddress(addresses) {
/** /**
* Retrieve a transaction from the mempool. * Retrieve a transaction from the mempool.
* Note that this will not be filled with coins.
* @param {Hash} hash * @param {Hash} hash
* @returns {TXMeta} * @returns {TXMeta}
*/ */
@ -1636,10 +1634,11 @@ Mempool.prototype.trackEntry = function trackEntry(entry, view) {
var hash = tx.hash('hex'); var hash = tx.hash('hex');
var i, input, output, key, coin; var i, input, output, key, coin;
assert(!this.tx[hash]);
this.tx[hash] = entry; this.tx[hash] = entry;
if (this.options.indexAddress) if (this.options.indexAddress)
this.txIndex.addTX(tx, view); this.txIndex.insert(tx, view);
assert(!tx.isCoinbase()); assert(!tx.isCoinbase());
@ -1648,7 +1647,7 @@ Mempool.prototype.trackEntry = function trackEntry(entry, view) {
key = input.prevout.toKey(); key = input.prevout.toKey();
if (this.options.indexAddress) if (this.options.indexAddress)
this.coinIndex.removeCoin(input.prevout); this.coinIndex.remove(input.prevout);
this.spents[key] = entry; this.spents[key] = entry;
} }
@ -1660,9 +1659,7 @@ Mempool.prototype.trackEntry = function trackEntry(entry, view) {
if (output.script.isUnspendable()) if (output.script.isUnspendable())
continue; continue;
coin = Coin.fromTX(tx, i, entry.height); this.coinIndex.insert(tx, i);
this.coinIndex.addCoin(coin);
} }
} }
@ -1679,12 +1676,13 @@ Mempool.prototype.trackEntry = function trackEntry(entry, view) {
Mempool.prototype.untrackEntry = function untrackEntry(entry) { Mempool.prototype.untrackEntry = function untrackEntry(entry) {
var tx = entry.tx; var tx = entry.tx;
var hash = tx.hash('hex'); var hash = tx.hash('hex');
var i, input, output, key, coin; var i, input, output, outpoint, key;
assert(this.tx[hash]);
delete this.tx[hash]; delete this.tx[hash];
if (this.options.indexAddress) if (this.options.indexAddress)
this.txIndex.removeTX(tx); this.txIndex.remove(tx);
assert(!tx.isCoinbase()); assert(!tx.isCoinbase());
@ -1693,7 +1691,7 @@ Mempool.prototype.untrackEntry = function untrackEntry(entry) {
key = input.prevout.toKey(); key = input.prevout.toKey();
if (this.options.indexAddress) if (this.options.indexAddress)
this.coinIndex.removeCoin(input.prevout); this.coinIndex.remove(input.prevout);
delete this.spents[key]; delete this.spents[key];
} }
@ -1705,9 +1703,9 @@ Mempool.prototype.untrackEntry = function untrackEntry(entry) {
if (output.script.isUnspendable()) if (output.script.isUnspendable())
continue; continue;
coin = Coin.fromTX(tx, i, entry.height); outpoint = Outpoint.fromTX(tx, i);
this.coinIndex.removeCoin(coin); this.coinIndex.remove(outpoint);
} }
} }
@ -1848,22 +1846,26 @@ Mempool.prototype.getSize = function getSize() {
}; };
/** /**
* Address Index * TX Address Index
*/ */
function AddressIndex(mempool) { function TXIndex(mempool) {
this.mempool = mempool; this.mempool = mempool;
// Map of addr->txids.
this.index = {}; this.index = {};
// Map of txid->addrs.
this.map = {}; this.map = {};
} }
AddressIndex.prototype.reset = function reset() { TXIndex.prototype.reset = function reset() {
this.index = {}; this.index = {};
this.map = {}; this.map = {};
}; };
AddressIndex.prototype.getTX = function getTX(address) { TXIndex.prototype.get = function get(addr) {
var items = this.index[address]; var items = this.index[addr];
var out = []; var out = [];
var i, hash, tx; var i, hash, tx;
@ -1880,8 +1882,8 @@ AddressIndex.prototype.getTX = function getTX(address) {
return out; return out;
}; };
AddressIndex.prototype.getMeta = function getMeta(address) { TXIndex.prototype.getMeta = function getMeta(addr) {
var items = this.index[address]; var items = this.index[addr];
var out = []; var out = [];
var i, hash, tx; var i, hash, tx;
@ -1898,37 +1900,37 @@ AddressIndex.prototype.getMeta = function getMeta(address) {
return out; return out;
}; };
AddressIndex.prototype.addTX = function addTX(tx, view) { TXIndex.prototype.insert = function insert(tx, view) {
var key = tx.hash('hex'); var key = tx.hash('hex');
var hashes = tx.getHashes(view, 'hex'); var addrs = tx.getHashes(view, 'hex');
var i, hash, items; var i, addr, items;
for (i = 0; i < hashes.length; i++) { for (i = 0; i < addrs.length; i++) {
hash = hashes[i]; addr = addrs[i];
items = this.index[hash]; items = this.index[addr];
if (!items) { if (!items) {
items = []; items = [];
this.index[hash] = items; this.index[addr] = items;
} }
util.binaryInsert(items, tx.hash(), util.cmp); util.binaryInsert(items, tx.hash(), util.cmp);
} }
this.map[key] = hashes; this.map[key] = addrs;
}; };
AddressIndex.prototype.removeTX = function removeTX(tx) { TXIndex.prototype.remove = function remove(tx) {
var key = tx.hash('hex'); var key = tx.hash('hex');
var hashes = this.map[key]; var addrs = this.map[key];
var i, hash, items; var i, addr, items;
if (!hashes) if (!addrs)
return; return;
for (i = 0; i < hashes.length; i++) { for (i = 0; i < addrs.length; i++) {
hash = hashes[i]; addr = addrs[i];
items = this.index[hash]; items = this.index[addr];
if (!items) if (!items)
continue; continue;
@ -1936,14 +1938,33 @@ AddressIndex.prototype.removeTX = function removeTX(tx) {
util.binaryRemove(items, tx.hash(), util.cmp); util.binaryRemove(items, tx.hash(), util.cmp);
if (items.length === 0) if (items.length === 0)
delete this.index[hash]; delete this.index[addr];
} }
delete this.map[key]; delete this.map[key];
}; };
AddressIndex.prototype.getCoins = function getCoins(address) { /**
var items = this.index[address]; * Coin Address Index
*/
function CoinIndex(mempool) {
this.mempool = mempool;
// Map of addr->outpoints.
this.index = {};
// Map of outpoint->addr.
this.map = {};
}
CoinIndex.prototype.reset = function reset() {
this.index = {};
this.map = {};
};
CoinIndex.prototype.get = function get(addr) {
var items = this.index[addr];
var out = []; var out = [];
var i, item, outpoint, coin; var i, item, outpoint, coin;
@ -1961,49 +1982,51 @@ AddressIndex.prototype.getCoins = function getCoins(address) {
return out; return out;
}; };
AddressIndex.prototype.addCoin = function addCoin(coin) { CoinIndex.prototype.insert = function insert(tx, i) {
var key = coin.toKey(); var output = tx.outputs[i];
var hash = coin.getHash('hex'); var addr = output.getHash('hex');
var outpoint, items; var items, outpoint, key;
if (!hash) if (!addr)
return; return;
items = this.index[hash]; items = this.index[addr];
if (!items) { if (!items) {
items = []; items = [];
this.index[hash] = items; this.index[addr] = items;
} }
outpoint = Outpoint(coin.hash, coin.index).toRaw(); outpoint = Outpoint.fromTX(tx, i);
util.binaryInsert(items, outpoint, util.cmp); key = outpoint.toKey();
this.map[key] = hash; util.binaryInsert(items, outpoint.toRaw(), util.cmp);
this.map[key] = addr;
}; };
AddressIndex.prototype.removeCoin = function removeCoin(coin) { CoinIndex.prototype.remove = function remove(outpoint) {
var key = coin.toKey(); var key = outpoint.toKey();
var hash = this.map[key]; var addr = this.map[key];
var outpoint, items; var items;
if (!hash) if (!addr)
return; return;
items = this.index[hash]; items = this.index[addr];
if (!items) if (!items)
return; return;
outpoint = Outpoint(coin.hash, coin.index).toRaw(); util.binaryRemove(items, outpoint.toRaw(), util.cmp);
util.binaryRemove(items, outpoint, util.cmp);
if (items.length === 0) if (items.length === 0)
delete this.index[hash]; delete this.index[addr];
delete this.map[key]; delete this.map[key];
}; };
/* /*
* Helpers * Helpers
*/ */