mempool: refactor addr indexing.

This commit is contained in:
Christopher Jeffrey 2017-02-28 21:41:20 -08:00
parent d92d6487b5
commit 8cb2c4a1a0
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD

View File

@ -28,6 +28,7 @@ var encoding = require('../utils/encoding');
var layout = require('./layout');
var LDB = require('../db/ldb');
var Fees = require('./fees');
var Map = require('../utils/map');
var VerifyError = errors.VerifyError;
var VerifyResult = errors.VerifyResult;
@ -92,8 +93,8 @@ function Mempool(options) {
this.spents = {};
this.rejects = new Bloom.Rolling(120000, 0.000001);
this.coinIndex = new CoinIndex(this);
this.txIndex = new TXIndex(this);
this.coinIndex = new CoinIndex();
this.txIndex = new TXIndex();
}
util.inherits(Mempool, AsyncObject);
@ -107,7 +108,7 @@ util.inherits(Mempool, AsyncObject);
Mempool.prototype._open = co(function* open() {
var size = (this.options.maxSize / 1024).toFixed(2);
var i, entries, entry, fees;
var i, entries, entry, view, fees;
yield this.chain.open();
yield this.cache.open();
@ -122,7 +123,13 @@ Mempool.prototype._open = co(function* open() {
for (i = 0; i < entries.length; i++) {
entry = entries[i];
this.updateAncestors(entry);
if (this.options.indexAddress) {
view = yield this.getCoinView(entry.tx);
this.indexEntry(entry, view);
}
}
this.logger.info(
@ -1704,10 +1711,8 @@ Mempool.prototype.trackEntry = function trackEntry(entry, view) {
this.spents[key] = entry;
}
if (this.options.indexAddress) {
assert(view, 'No view passed to trackEntry.');
if (this.options.indexAddress && view)
this.indexEntry(entry, view);
}
this.size += entry.memUsage();
this.totalTX++;
@ -1751,13 +1756,14 @@ Mempool.prototype.untrackEntry = function untrackEntry(entry) {
Mempool.prototype.indexEntry = function indexEntry(entry, view) {
var tx = entry.tx;
var i, input;
var i, input, prev;
this.txIndex.insert(tx, view);
this.txIndex.insert(entry, view);
for (i = 0; i < tx.inputs.length; i++) {
input = tx.inputs[i];
this.coinIndex.remove(input.prevout);
prev = input.prevout;
this.coinIndex.remove(prev.hash, prev.index);
}
for (i = 0; i < tx.outputs.length; i++)
@ -1772,9 +1778,10 @@ Mempool.prototype.indexEntry = function indexEntry(entry, view) {
Mempool.prototype.unindexEntry = function unindexEntry(entry) {
var tx = entry.tx;
var hash = tx.hash('hex');
var i, input, prevout, prev;
this.txIndex.remove(tx);
this.txIndex.remove(hash);
for (i = 0; i < tx.inputs.length; i++) {
input = tx.inputs[i];
@ -1787,10 +1794,8 @@ Mempool.prototype.unindexEntry = function unindexEntry(entry) {
this.coinIndex.insert(prev, prevout.index);
}
for (i = 0; i < tx.outputs.length; i++) {
prevout = Outpoint.fromTX(tx, i);
this.coinIndex.remove(prevout);
}
for (i = 0; i < tx.outputs.length; i++)
this.coinIndex.remove(hash, i);
};
/**
@ -2015,8 +2020,6 @@ MempoolOptions.prototype.fromOptions = function fromOptions(options) {
if (options.persistent != null) {
assert(typeof options.persistent === 'boolean');
this.persistent = options.persistent;
assert(this.persistent !== this.indexAddress,
'Cannot have persistent mempool with address indexing.');
}
return this;
@ -2036,13 +2039,10 @@ MempoolOptions.fromOptions = function fromOptions(options) {
* TX Address Index
* @constructor
* @ignore
* @param {Mempool} mempool
*/
function TXIndex(mempool) {
this.mempool = mempool;
// Map of addr->txids.
function TXIndex() {
// Map of addr->entries.
this.index = {};
// Map of txid->addrs.
@ -2057,16 +2057,16 @@ TXIndex.prototype.reset = function reset() {
TXIndex.prototype.get = function get(addr) {
var items = this.index[addr];
var out = [];
var i, hash, tx;
var i, keys, entry;
if (!items)
return out;
for (i = 0; i < items.length; i++) {
hash = items[i].toString('hex');
tx = this.mempool.getTX(hash);
assert(tx);
out.push(tx);
keys = items.keys();
for (i = 0; i < keys.length; i++) {
entry = items.get(keys[i]);
out.push(entry.tx);
}
return out;
@ -2075,44 +2075,50 @@ TXIndex.prototype.get = function get(addr) {
TXIndex.prototype.getMeta = function getMeta(addr) {
var items = this.index[addr];
var out = [];
var i, hash, tx;
var i, entry, keys, meta;
if (!items)
return out;
for (i = 0; i < items.length; i++) {
hash = items[i].toString('hex');
tx = this.mempool.getMeta(hash);
assert(tx);
out.push(tx);
keys = items.keys();
for (i = 0; i < keys.length; i++) {
entry = items.get(keys[i]);
meta = TXMeta.fromTX(entry.tx);
meta.ps = entry.ts;
out.push(meta);
}
return out;
};
TXIndex.prototype.insert = function insert(tx, view) {
var key = tx.hash('hex');
TXIndex.prototype.insert = function insert(entry, view) {
var tx = entry.tx;
var hash = tx.hash('hex');
var addrs = tx.getHashes(view, 'hex');
var i, addr, items;
if (addrs.length === 0)
return;
for (i = 0; i < addrs.length; i++) {
addr = addrs[i];
items = this.index[addr];
if (!items) {
items = [];
items = new Map();
this.index[addr] = items;
}
util.binaryInsert(items, tx.hash(), util.cmp);
assert(!items.has(hash));
items.set(hash, entry);
}
this.map[key] = addrs;
this.map[hash] = addrs;
};
TXIndex.prototype.remove = function remove(tx) {
var key = tx.hash('hex');
var addrs = this.map[key];
TXIndex.prototype.remove = function remove(hash) {
var addrs = this.map[hash];
var i, addr, items;
if (!addrs)
@ -2122,29 +2128,26 @@ TXIndex.prototype.remove = function remove(tx) {
addr = addrs[i];
items = this.index[addr];
if (!items)
continue;
assert(items);
assert(items.has(hash));
util.binaryRemove(items, tx.hash(), util.cmp);
items.remove(hash);
if (items.length === 0)
if (items.size === 0)
delete this.index[addr];
}
delete this.map[key];
delete this.map[hash];
};
/**
* Coin Address Index
* @constructor
* @ignore
* @param {Mempool} mempool
*/
function CoinIndex(mempool) {
this.mempool = mempool;
// Map of addr->outpoints.
function CoinIndex() {
// Map of addr->coins.
this.index = {};
// Map of outpoint->addr.
@ -2159,26 +2162,27 @@ CoinIndex.prototype.reset = function reset() {
CoinIndex.prototype.get = function get(addr) {
var items = this.index[addr];
var out = [];
var i, item, outpoint, coin;
var i, keys, coin;
if (!items)
return out;
for (i = 0; i < items.length; i++) {
item = items[i];
outpoint = Outpoint.fromRaw(item);
coin = this.mempool.getCoin(outpoint.hash, outpoint.index);
keys = items.keys();
for (i = 0; i < keys.length; i++) {
coin = items.get(keys[i]);
assert(coin);
out.push(coin);
out.push(coin.toCoin());
}
return out;
};
CoinIndex.prototype.insert = function insert(tx, i) {
var output = tx.outputs[i];
CoinIndex.prototype.insert = function insert(tx, index) {
var output = tx.outputs[index];
var hash = tx.hash('hex');
var addr = output.getHash('hex');
var items, outpoint, key;
var items, key;
if (!addr)
return;
@ -2186,20 +2190,20 @@ CoinIndex.prototype.insert = function insert(tx, i) {
items = this.index[addr];
if (!items) {
items = [];
items = new Map();
this.index[addr] = items;
}
outpoint = Outpoint.fromTX(tx, i);
key = outpoint.toKey();
key = Outpoint.toKey(hash, index);
util.binaryInsert(items, outpoint.toRaw(), util.cmp);
assert(!items.has(key));
items.set(key, new IndexedCoin(tx, index));
this.map[key] = addr;
};
CoinIndex.prototype.remove = function remove(outpoint) {
var key = outpoint.toKey();
CoinIndex.prototype.remove = function remove(hash, index) {
var key = Outpoint.toKey(hash, index);
var addr = this.map[key];
var items;
@ -2208,17 +2212,33 @@ CoinIndex.prototype.remove = function remove(outpoint) {
items = this.index[addr];
if (!items)
return;
assert(items);
assert(items.has(key));
items.remove(key);
util.binaryRemove(items, outpoint.toRaw(), util.cmp);
if (items.length === 0)
if (items.size === 0)
delete this.index[addr];
delete this.map[key];
};
/**
* IndexedCoin
* @constructor
* @ignore
* @param {TX} tx
* @param {Number} index
*/
function IndexedCoin(tx, index) {
this.tx = tx;
this.index = index;
}
IndexedCoin.prototype.toCoin = function toCoin() {
return Coin.fromTX(this.tx, this.index, -1);
};
/**
* Orphan
* @constructor