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