mempool: refactor addr indexing.
This commit is contained in:
parent
d92d6487b5
commit
8cb2c4a1a0
@ -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
|
||||
|
||||
Loading…
Reference in New Issue
Block a user