mempool. remove spenders.
This commit is contained in:
parent
67dc96ff5d
commit
f4f4658390
@ -91,6 +91,7 @@ function Mempool(options) {
|
||||
: network.requireStandard;
|
||||
this.rejectAbsurdFees = this.options.rejectAbsurdFees !== false;
|
||||
this.prematureWitness = !!this.options.prematureWitness;
|
||||
this.accurateMemory = !!this.options.accurateMemory;
|
||||
|
||||
this.maxSize = options.maxSize || constants.mempool.MAX_MEMPOOL_SIZE;
|
||||
this.minFeeRate = 0;
|
||||
@ -258,7 +259,7 @@ Mempool.prototype.addBlock = function addBlock(block, callback, force) {
|
||||
copy = tx.clone();
|
||||
copy.unsetBlock();
|
||||
|
||||
self.addUnchecked(tx, next);
|
||||
self.addUnchecked(tx, next, true);
|
||||
});
|
||||
});
|
||||
}, function(err) {
|
||||
@ -285,14 +286,14 @@ Mempool.prototype.addBlock = function addBlock(block, callback, force) {
|
||||
copy.height = existing.height;
|
||||
copy.ps = existing.ps;
|
||||
|
||||
self.removeUnchecked(copy, function(err) {
|
||||
self.removeUnchecked(copy, false, function(err) {
|
||||
if (err)
|
||||
return next(err);
|
||||
|
||||
self.emit('confirmed', tx, block);
|
||||
|
||||
return next();
|
||||
});
|
||||
}, true);
|
||||
});
|
||||
}, function(err) {
|
||||
if (err)
|
||||
@ -348,7 +349,7 @@ Mempool.prototype.removeBlock = function removeBlock(block, callback, force) {
|
||||
self.emit('unconfirmed', tx, block);
|
||||
|
||||
return next();
|
||||
});
|
||||
}, true);
|
||||
});
|
||||
}, callback);
|
||||
};
|
||||
@ -376,7 +377,7 @@ Mempool.prototype.limitMempoolSize = function limitMempoolSize(callback) {
|
||||
if (self.getSize() <= self.maxSize)
|
||||
return next();
|
||||
|
||||
self.removeUnchecked(tx, function(err) {
|
||||
self.removeUnchecked(tx, true, function(err) {
|
||||
if (err)
|
||||
return next(err);
|
||||
|
||||
@ -389,7 +390,7 @@ Mempool.prototype.limitMempoolSize = function limitMempoolSize(callback) {
|
||||
}
|
||||
|
||||
next();
|
||||
});
|
||||
}, true);
|
||||
}, function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
@ -406,12 +407,9 @@ Mempool.prototype.limitMempoolSize = function limitMempoolSize(callback) {
|
||||
|
||||
Mempool.prototype.pruneOrphans = function pruneOrphans(callback) {
|
||||
var self = this;
|
||||
|
||||
callback = utils.ensure(callback);
|
||||
|
||||
utils.forEachSerial(Object.keys(this.orphans), function(hash, next) {
|
||||
if (self.totalOrphans <= constants.mempool.MAX_ORPHAN_TX)
|
||||
return next();
|
||||
return callback();
|
||||
self.removeOrphan(hash, next);
|
||||
}, callback);
|
||||
};
|
||||
@ -656,7 +654,7 @@ Mempool.prototype.addTX = function addTX(tx, callback, force) {
|
||||
0));
|
||||
}
|
||||
|
||||
self.addUnchecked(tx, callback);
|
||||
self.addUnchecked(tx, callback, true);
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -676,8 +674,15 @@ Mempool.prototype.addTX = function addTX(tx, callback, force) {
|
||||
* @param {Function} callback - Returns [{@link VerifyError}].
|
||||
*/
|
||||
|
||||
Mempool.prototype.addUnchecked = function addUnchecked(tx, callback) {
|
||||
Mempool.prototype.addUnchecked = function addUnchecked(tx, callback, force) {
|
||||
var self = this;
|
||||
|
||||
var unlock = this._lock(addUnchecked, [tx, callback], force);
|
||||
if (!unlock)
|
||||
return;
|
||||
|
||||
callback = utils.wrap(callback, unlock);
|
||||
|
||||
this._addUnchecked(tx, function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
@ -713,7 +718,7 @@ Mempool.prototype.addUnchecked = function addUnchecked(tx, callback) {
|
||||
}
|
||||
bcoin.debug('Resolved orphan %s in mempool.', tx.rhash);
|
||||
next();
|
||||
});
|
||||
}, true);
|
||||
});
|
||||
}, callback);
|
||||
});
|
||||
@ -727,10 +732,16 @@ Mempool.prototype.addUnchecked = function addUnchecked(tx, callback) {
|
||||
* @param {Function} callback
|
||||
*/
|
||||
|
||||
Mempool.prototype.removeUnchecked = function removeUnchecked(tx, callback, limit) {
|
||||
Mempool.prototype.removeUnchecked = function removeUnchecked(tx, limit, callback, force) {
|
||||
var self = this;
|
||||
var rate;
|
||||
|
||||
var unlock = this._lock(removeUnchecked, [tx, limit, callback], force);
|
||||
if (!unlock)
|
||||
return;
|
||||
|
||||
callback = utils.wrap(callback, unlock);
|
||||
|
||||
this.fillAllHistory(tx, function(err, tx) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
@ -739,7 +750,7 @@ Mempool.prototype.removeUnchecked = function removeUnchecked(tx, callback, limit
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
self._removeUnchecked(tx, function(err) {
|
||||
self._removeUnchecked(tx, limit, function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
@ -1016,13 +1027,8 @@ Mempool.prototype.storeOrphan = function storeOrphan(tx, callback, force) {
|
||||
this.orphans[hash] = tx.toExtended(true);
|
||||
this.totalOrphans++;
|
||||
|
||||
if (self.totalOrphans > constants.mempool.MAX_ORPHAN_TX) {
|
||||
return self.pruneOrphans(function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
callback();
|
||||
});
|
||||
}
|
||||
if (this.totalOrphans > constants.mempool.MAX_ORPHAN_TX)
|
||||
return this.pruneOrphans(callback);
|
||||
|
||||
return callback();
|
||||
};
|
||||
@ -1144,7 +1150,7 @@ Mempool.prototype.resolveOrphans = function resolveOrphans(tx, callback, force)
|
||||
|
||||
Mempool.prototype.removeOrphan = function removeOrphan(tx, callback) {
|
||||
var self = this;
|
||||
var prevout, hash;
|
||||
var i, prevout, hash;
|
||||
|
||||
function getOrphan(tx, callback) {
|
||||
if (typeof tx === 'string')
|
||||
@ -1163,7 +1169,6 @@ Mempool.prototype.removeOrphan = function removeOrphan(tx, callback) {
|
||||
prevout = tx.getPrevout();
|
||||
|
||||
utils.forEachSerial(prevout, function(prev, next) {
|
||||
var i, p;
|
||||
self.getWaiting(prev, function(err, hashes) {
|
||||
if (err)
|
||||
return next(err);
|
||||
@ -1317,53 +1322,46 @@ Mempool.prototype.isDoubleSpend = function isDoubleSpend(tx, callback) {
|
||||
|
||||
Mempool.prototype.getConfidence = function getConfidence(hash, callback) {
|
||||
var self = this;
|
||||
var tx;
|
||||
|
||||
callback = utils.asyncify(callback);
|
||||
|
||||
function isDoubleSpend(callback) {
|
||||
function getTX(callback) {
|
||||
if (hash instanceof bcoin.tx)
|
||||
return callback(null, hash, hash.hash('hex'));
|
||||
|
||||
return this.getTX(hash, function(err, tx) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
return callback(null, tx, hash);
|
||||
});
|
||||
}
|
||||
|
||||
function isDoubleSpend(tx, callback) {
|
||||
if (tx)
|
||||
return self.isDoubleSpend(tx, callback);
|
||||
return callback(null, false);
|
||||
}
|
||||
|
||||
function done(tx, hash) {
|
||||
return isDoubleSpend(function(err, result) {
|
||||
return getTX(function(err, tx, hash) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
return self.hasTX(hash, function(err, result) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
if (result)
|
||||
return callback(null, constants.confidence.INCONFLICT);
|
||||
return callback(null, constants.confidence.PENDING);
|
||||
|
||||
return self.hasTX(hash, function(err, result) {
|
||||
return isDoubleSpend(tx, function(err, result) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
if (result)
|
||||
return callback(null, constants.confidence.PENDING);
|
||||
return callback(null, constants.confidence.INCONFLICT);
|
||||
|
||||
function getBlock(callback) {
|
||||
if (tx && tx.block)
|
||||
return callback(null, tx.block);
|
||||
return self.chain.db.getTX(hash, function(err, existing) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
if (!existing)
|
||||
return callback();
|
||||
|
||||
return callback(null, existing.block);
|
||||
});
|
||||
}
|
||||
|
||||
return getBlock(function(err, block) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
if (!block)
|
||||
return callback(null, constants.confidence.UNKNOWN);
|
||||
|
||||
self.chain.db.isMainChain(block, function(err, result) {
|
||||
if (tx && tx.block) {
|
||||
return self.chain.db.isMainChain(tx.block, function(err, result) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
@ -1372,18 +1370,19 @@ Mempool.prototype.getConfidence = function getConfidence(hash, callback) {
|
||||
|
||||
return callback(null, constants.confidence.DEAD);
|
||||
});
|
||||
}
|
||||
|
||||
return self.chain.db.isUnspentTX(hash, function(err, existing) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
if (existing)
|
||||
return callback(null, constants.confidence.BUILDING);
|
||||
|
||||
return callback(null, constants.confidence.UNKNOWN);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (hash instanceof bcoin.tx)
|
||||
return done(hash, hash.hash('hex'));
|
||||
|
||||
return this.getTX(hash, function(err, tx) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
done(tx, hash);
|
||||
});
|
||||
};
|
||||
|
||||
@ -1394,17 +1393,11 @@ Mempool.prototype.getConfidence = function getConfidence(hash, callback) {
|
||||
* @param {Function} callback
|
||||
*/
|
||||
|
||||
Mempool.prototype._addUnchecked = function addUnchecked(tx, callback, force) {
|
||||
Mempool.prototype._addUnchecked = function _addUnchecked(tx, callback) {
|
||||
var self = this;
|
||||
var hash = tx.hash('hex');
|
||||
var i, addresses, address, input, output, key, coin, batch;
|
||||
|
||||
var unlock = this.writeLock.lock(addUnchecked, [tx, callback], force);
|
||||
if (!unlock)
|
||||
return;
|
||||
|
||||
callback = utils.wrap(callback, unlock);
|
||||
|
||||
batch = this.db.batch();
|
||||
|
||||
batch.put('t/' + hash, tx.toExtended());
|
||||
@ -1464,16 +1457,10 @@ Mempool.prototype._addUnchecked = function addUnchecked(tx, callback, force) {
|
||||
* @param {Function} callback
|
||||
*/
|
||||
|
||||
Mempool.prototype._removeUnchecked = function removeUnchecked(hash, callback, force) {
|
||||
Mempool.prototype._removeUnchecked = function _removeUnchecked(hash, limit, callback) {
|
||||
var self = this;
|
||||
var batch, i, addresses, output;
|
||||
|
||||
var unlock = this.writeLock.lock(removeUnchecked, [hash, callback], force);
|
||||
if (!unlock)
|
||||
return;
|
||||
|
||||
callback = utils.wrap(callback, unlock);
|
||||
|
||||
if (hash.hash)
|
||||
hash = hash.hash('hex');
|
||||
|
||||
@ -1533,12 +1520,11 @@ Mempool.prototype._removeUnchecked = function removeUnchecked(hash, callback, fo
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
for (i = 0; i < tx.outputs.length; i++) {
|
||||
output = tx.outputs[i];
|
||||
utils.forEachSerial(tx.outputs, function(output, next, i) {
|
||||
key = hash + '/' + i;
|
||||
|
||||
if (output.script.isUnspendable())
|
||||
continue;
|
||||
return next();
|
||||
|
||||
batch.del('c/' + key);
|
||||
|
||||
@ -1547,9 +1533,25 @@ Mempool.prototype._removeUnchecked = function removeUnchecked(hash, callback, fo
|
||||
if (address)
|
||||
batch.del('C/' + address + '/' + key);
|
||||
}
|
||||
}
|
||||
|
||||
return batch.write(callback);
|
||||
if (!limit)
|
||||
return next();
|
||||
|
||||
self.isSpent(hash, i, function(err, spender) {
|
||||
if (err)
|
||||
return next(err);
|
||||
|
||||
if (!spender)
|
||||
return next();
|
||||
|
||||
self._removeUnchecked(spender, limit, next);
|
||||
});
|
||||
}, function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
return batch.write(callback);
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
@ -1577,7 +1579,7 @@ Mempool.prototype.memUsageBitcoind = function memUsage(tx) {
|
||||
mem += mallocUsage(tx.outputs.length);
|
||||
|
||||
for (i = 0; i < tx.inputs.length; i++)
|
||||
mem += mallocUsage(tx.inputs[i].script.getSize()) + 0;
|
||||
mem += mallocUsage(tx.inputs[i].script.getSize());
|
||||
|
||||
for (i = 0; i < tx.outputs.length; i++)
|
||||
mem += mallocUsage(tx.outputs[i].script.getSize());
|
||||
@ -1586,9 +1588,9 @@ Mempool.prototype.memUsageBitcoind = function memUsage(tx) {
|
||||
|
||||
for (i = 0; i < tx.inputs.length; i++) {
|
||||
input = tx.inputs[i];
|
||||
mem += mallocUsage(input.witness.length);
|
||||
for (j = 0; j < input.witness.length; j++)
|
||||
mem += mallocUsage(input.witness[j].length);
|
||||
mem += mallocUsage(input.witness.items.length);
|
||||
for (j = 0; j < input.witness.items.length; j++)
|
||||
mem += mallocUsage(input.witness[j].items.length);
|
||||
}
|
||||
|
||||
return mem;
|
||||
@ -1686,11 +1688,11 @@ var ptrSize = (process.platform == null
|
||||
|| process.platform === 'arm') ? 8 : 4;
|
||||
|
||||
function mallocUsage(alloc) {
|
||||
if (alloc == 0)
|
||||
if (alloc === 0)
|
||||
return 0;
|
||||
if (ptrSize === 8)
|
||||
return ((alloc + 31) >> 4) << 4;
|
||||
return ((alloc + 15) >> 3) << 3;
|
||||
return ((alloc + 31) >>> 4) << 4;
|
||||
return ((alloc + 15) >>> 3) << 3;
|
||||
}
|
||||
|
||||
return Mempool;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user