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