switch back to leveldown mempool.

This commit is contained in:
Christopher Jeffrey 2016-04-02 23:12:01 -07:00
parent eda31da3ea
commit a58b566c69
7 changed files with 1128 additions and 237 deletions

View File

@ -113,7 +113,7 @@ bcoin.fullnode = require('./bcoin/fullnode');
bcoin.chainblock = require('./bcoin/chainblock');
bcoin.chaindb = require('./bcoin/chaindb');
bcoin.chain = require('./bcoin/chain');
bcoin.mempool = require('./bcoin/mempool');
bcoin.mempool = require('./bcoin/mempool2');
bcoin.keypair = require('./bcoin/keypair');
bcoin.address = require('./bcoin/address');
bcoin.walletdb = require('./bcoin/walletdb');

View File

@ -330,7 +330,16 @@ BST.prototype.rangeCompare = function rangeCompare(key, gteKey, lteKey) {
*/
BST.prototype.open = function open(options, callback) {
if (!callback) {
callback = options;
options = null;
}
if (!options)
options = {};
this.options = options;
return utils.nextTick(callback);
};
@ -434,7 +443,7 @@ BST.destroy = function destroy(location, callback) {
};
BST.repair = function repair(location, callback) {
return utils.asyncify(callback)(new Error('Cannot repair.'));
return utils.nextTick(callback);
};
/**

View File

@ -54,9 +54,6 @@ function getLocation(name) {
}
function getBackend(backend) {
if (backend === 'bst')
return require('./bst');
if (bcoin.isBrowser)
return require('level-js');
@ -70,10 +67,12 @@ function getBackend(backend) {
else if (backend === 'lmdb')
backend = 'lmdb';
else if (backend === 'memory')
backend = 'memdown';
backend = 'bst';
if (backend !== 'memdown')
bcoin.ensurePrefix();
if (backend === 'bst')
return require('./bst');
bcoin.ensurePrefix();
return require(backend);
}

View File

@ -138,223 +138,33 @@ Mempool.prototype.removeBlock = function removeBlock(block, callback, force) {
Mempool.prototype.limitMempoolSize = function limitMempoolSize(callback) {
var self = this;
var txs;
if (this.totalSize <= Mempool.MAX_MEMPOOL_SIZE)
return utils.asyncify(callback)(null, true);
if (this.size <= Mempool.MAX_MEMPOOL_SIZE)
return callback(null, true);
try {
txs = this.getRangeSync({
start: 0,
end: utils.now() - Mempool.MEMPOOL_EXPIRY
});
} catch (e) {
return utils.asyncify(callback)(e);
}
utils.forEachSerial(function(tx, next) {
self.removeUnchecked(tx, next);
}, function(err) {
this.db.getRange({
start: 0,
end: utils.now() - Mempool.MEMPOOL_EXPIRY
}, function(err, txs) {
if (err)
return callback(err);
try {
self.purgeOrphansSync();
} catch (e) {
return callback(e);
}
utils.forEachSerial(function(tx, next) {
self.removeUnchecked(tx, next);
}, function(err) {
if (err)
return callback(err);
return callback(null, self.totalSize <= Mempool.MAX_MEMPOOL_SIZE);
self.purgeOrphans(function(err) {
if (err)
return callback(err);
return callback(null, self.size <= Mempool.MAX_MEMPOOL_SIZE);
});
});
});
};
Mempool.prototype.getRangeSync = function getRangeSync(options) {
var hashes = this.psIndex.range(options.start, options.end);
var txs = [];
var i, tx;
for (i = 0; i < hashes.length; i++) {
tx = this.getTXSync(hashes[i]);
if (tx)
txs.push(tx);
}
return txs;
};
Mempool.prototype.purgeOrphansSync = function purgeOrphansSync() {
var keys = Object.keys(this.orphans);
var key, i;
this.waiting = {};
this.totalOrphans = 0;
for (i = 0; i < keys.length; i++) {
key = keys[i];
this.totalSize -= this.orphans[key].length;
delete this.orphans[key];
}
};
Mempool.prototype.getSync =
Mempool.prototype.getTXSync = function getTXSync(hash) {
var tx;
if (hash instanceof bcoin.tx)
hash = hash.hash('hex');
tx = this.txs[hash];
if (!tx)
return;
return bcoin.tx.fromExtended(tx);
};
Mempool.prototype.getCoinSync = function getCoinSync(hash, index) {
var key = hash + '/' + index;
var coin;
coin = this.coins[key];
if (!coin)
return;
coin = bcoin.coin.fromRaw(coin);
coin.hash = hash;
coin.index = index;
return coin;
};
Mempool.prototype.isSpentSync = function isSpentSync(hash, index) {
var key = hash + '/' + index;
return this.spent[key] != null;
};
Mempool.prototype.isDoubleSpendSync = function isDoubleSpendSync(tx) {
var i, input;
for (i = 0; i < tx.inputs.length; i++) {
input = tx.inputs[i];
if (this.isSpentSync(input.prevout.hash, input.prevout.index))
return true;
}
return false;
};
Mempool.prototype.getCoinsByAddressSync = function getCoinsByAddressSync(addresses) {
var coins = [];
var i, j, address, keys, key, coin;
if (!Array.isArray(addresses))
addresses = [addresses];
addresses = utils.uniqs(addresses);
for (i = 0; i < addresses.length; i++) {
address = addresses[i];
keys = this.addressMap.getCoins(address);
for (j = 0; j < keys.length; j++) {
key = keys[j];
coin = this.getCoinSync(key[0], key[1]);
if (coin)
coins.push(coin);
}
}
return coins;
};
Mempool.prototype.getByAddressSync =
Mempool.prototype.getTXByAddressSync = function getTXByAddressSync(addresses, callback) {
var uniq = {};
var txs = [];
var i, j, address, hashes, hash, tx;
if (!Array.isArray(addresses))
addresses = [addresses];
addresses = utils.uniqs(addresses);
for (i = 0; i < addresses.length; i++) {
address = addresses[i];
hashes = this.addressMap.getTX(address);
for (j = 0; j < hashes.length; j++) {
hash = hashes[j];
if (uniq[hash])
continue;
tx = this.getTXSync(hash);
if (!tx)
continue;
uniq[hash] = true;
txs.push(tx);
}
}
return txs;
};
Mempool.prototype.fillTXSync = function fillTXSync(tx) {
var i, input, prev;
if (tx.isCoinbase())
return tx;
for (i = 0; i < tx.inputs.length; i++) {
input = tx.inputs[i];
if (input.coin)
continue;
prev = this.getTXSync(input.prevout.hash);
if (!prev)
continue;
input.coin = bcoin.coin(prev, input.prevout.index);
}
return tx;
};
Mempool.prototype.fillCoinsSync = function fillCoinsSync(tx) {
var i, input;
if (tx.isCoinbase())
return tx;
for (i = 0; i < tx.inputs.length; i++) {
input = tx.inputs[i];
if (input.coin)
continue;
try {
input.coin = this.getCoinSync(input.prevout.hash, input.prevout.index);
} catch (e) {
return callback(e);
}
}
return tx;
};
Mempool.prototype.hasSync =
Mempool.prototype.hasTXSync = function hasTXSync(hash) {
if (hash instanceof bcoin.tx)
hash = hash.hash('hex');
return this.txs[hash] != null;
};
Mempool.prototype.add =
Mempool.prototype.addTX = function addTX(tx, callback, force) {
var self = this;

1040
lib/bcoin/mempool2.js Normal file

File diff suppressed because it is too large Load Diff

View File

@ -130,7 +130,7 @@ Miner.prototype.start = function start() {
if (err)
return next(err);
self.node.fillCoins(tx, function(err) {
self.mempool.fillAllCoins(tx, function(err) {
if (err)
return next(err);

View File

@ -1536,6 +1536,15 @@ TXPool.prototype.getTX = function getTX(hash, callback) {
});
};
TXPool.prototype.hasTX = function hasTX(hash, callback) {
return this.getTX(hash, function(err, tx) {
if (err)
return callback(err);
return callback(null, tx != null);
});
};
TXPool.prototype.getCoin = function getCoin(hash, index, callback) {
var prefix = this.prefix + '/';
var key = prefix + 'u/t/' + hash + '/' + index;
@ -1559,6 +1568,15 @@ TXPool.prototype.getCoin = function getCoin(hash, index, callback) {
});
};
TXPool.prototype.hasCoin = function hasCoin(hash, index, callback) {
return this.getCoin(hash, index, function(err, coin) {
if (err)
return callback(err);
return callback(null, coin != null);
});
};
TXPool.prototype.getBalance = function getBalance(address, callback) {
var confirmed = new bn(0);
var unconfirmed = new bn(0);
@ -1684,46 +1702,61 @@ TXPool.prototype.removeUnchecked = function removeUnchecked(hash, callback, forc
batch.del(prefix + 't/t/' + hash);
batch.del(prefix + 't/s/s/' + pad32(tx.ps) + '/' + hash);
batch.del(prefix + 'D/' + hash);
tx.getAddresses().forEach(function(address) {
batch.del(prefix + 't/a/' + address + '/' + hash);
});
tx.inputs.forEach(function(input) {
utils.forEachSerial(tx.inputs, function(input, next) {
var key = input.prevout.hash + '/' + input.prevout.index;
var address;
if (tx.isCoinbase())
return;
return next();
if (!input.coin)
return;
return next();
address = input.getAddress();
batch.del(prefix + 'u/t/' + key);
batch.del(prefix + 's/t/' + key);
if (address)
batch.del(prefix + 'u/a/' + address + '/' + key);
});
self.hasTX(input.prevout.hash, function(err, result) {
if (err)
return next(err);
tx.outputs.forEach(function(output, i) {
var key = hash + '/' + i;
var address = output.getAddress();
if (result) {
batch.put(prefix + 'u/t/' + key, input.coin.toRaw());
if (address)
batch.put(prefix + 'u/a/' + address + '/' + key, DUMMY);
} else {
batch.del(prefix + 'u/t/' + key);
if (address)
batch.del(prefix + 'u/a/' + address + '/' + key);
}
batch.del(prefix + 'u/t/' + key);
if (address)
batch.del(prefix + 'u/a/' + address + '/' + key);
});
batch.write(function(err) {
next();
});
}, function(err) {
if (err)
return callback(err);
self.emit('remove tx', tx);
return callback();
tx.outputs.forEach(function(output, i) {
var key = hash + '/' + i;
var address = output.getAddress();
batch.del(prefix + 'u/t/' + key);
if (address)
batch.del(prefix + 'u/a/' + address + '/' + key);
});
batch.write(function(err) {
if (err)
return callback(err);
self.emit('remove tx', tx);
return callback();
});
});
});
};