mempool: sanitize after reorg.
This commit is contained in:
parent
459a9f25f4
commit
1aa78e2248
@ -905,7 +905,7 @@ Chain.prototype.reorganize = async function reorganize(competitor) {
|
||||
competitor.height
|
||||
);
|
||||
|
||||
this.emit('reorganize', tip, competitor);
|
||||
await this.fire('reorganize', tip, competitor);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -957,7 +957,7 @@ Chain.prototype.reorganizeSPV = async function reorganizeSPV(competitor) {
|
||||
'Chain replay from height %d necessary.',
|
||||
fork.height);
|
||||
|
||||
this.emit('reorganize', tip, competitor);
|
||||
await this.fire('reorganize', tip, competitor);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -10,6 +10,7 @@ const assert = require('assert');
|
||||
const path = require('path');
|
||||
const AsyncObject = require('../utils/asyncobject');
|
||||
const common = require('../blockchain/common');
|
||||
const consensus = require('../protocol/consensus');
|
||||
const policy = require('../protocol/policy');
|
||||
const util = require('../utils/util');
|
||||
const random = require('../crypto/random');
|
||||
@ -198,8 +199,9 @@ Mempool.prototype._addBlock = async function _addBlock(block, txs) {
|
||||
|
||||
if (!entry) {
|
||||
this.removeOrphan(hash);
|
||||
this.resolveOrphans(tx);
|
||||
this.removeDoubleSpends(tx);
|
||||
if (this.waiting.has(hash))
|
||||
await this.handleOrphans(tx);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -303,6 +305,55 @@ Mempool.prototype._removeBlock = async function _removeBlock(block, txs) {
|
||||
total, block.height);
|
||||
};
|
||||
|
||||
/**
|
||||
* Sanitize the mempool after a reorg.
|
||||
* @private
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
Mempool.prototype._handleReorg = async function _handleReorg() {
|
||||
const height = this.chain.height + 1;
|
||||
const mtp = await this.chain.getMedianTime(this.chain.tip);
|
||||
const remove = [];
|
||||
|
||||
for (const [hash, entry] of this.map) {
|
||||
const {tx} = entry;
|
||||
|
||||
if (!tx.isFinal(height, mtp)) {
|
||||
remove.push(hash);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (tx.version > 1) {
|
||||
let hasLocks = false;
|
||||
|
||||
for (const {sequence} of tx.inputs) {
|
||||
if (!(sequence & consensus.SEQUENCE_DISABLE_FLAG)) {
|
||||
hasLocks = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasLocks) {
|
||||
remove.push(hash);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (entry.coinbase)
|
||||
remove.push(hash);
|
||||
}
|
||||
|
||||
for (const hash of remove) {
|
||||
const entry = this.getEntry(hash);
|
||||
|
||||
if (!entry)
|
||||
continue;
|
||||
|
||||
this.evictEntry(entry);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Reset the mempool.
|
||||
* @method
|
||||
|
||||
@ -43,6 +43,7 @@ function MempoolEntry(options) {
|
||||
this.deltaFee = 0;
|
||||
this.time = 0;
|
||||
this.value = 0;
|
||||
this.coinbase = false;
|
||||
this.dependencies = false;
|
||||
this.descFee = 0;
|
||||
this.descSize = 0;
|
||||
@ -67,6 +68,7 @@ MempoolEntry.prototype.fromOptions = function fromOptions(options) {
|
||||
this.deltaFee = options.deltaFee;
|
||||
this.time = options.time;
|
||||
this.value = options.value;
|
||||
this.coinbase = options.coinbase;
|
||||
this.dependencies = options.dependencies;
|
||||
this.descFee = options.descFee;
|
||||
this.descSize = options.descSize;
|
||||
@ -99,11 +101,14 @@ MempoolEntry.prototype.fromTX = function fromTX(tx, view, height) {
|
||||
const fee = tx.getFee(view);
|
||||
|
||||
let dependencies = false;
|
||||
let coinbase = false;
|
||||
|
||||
for (const {prevout} of tx.inputs) {
|
||||
if (view.getHeight(prevout) === -1) {
|
||||
if (view.isCoinbase(prevout))
|
||||
coinbase = true;
|
||||
|
||||
if (view.getHeight(prevout) === -1)
|
||||
dependencies = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this.tx = tx;
|
||||
@ -115,6 +120,7 @@ MempoolEntry.prototype.fromTX = function fromTX(tx, view, height) {
|
||||
this.deltaFee = fee;
|
||||
this.time = util.now();
|
||||
this.value = value;
|
||||
this.coinbase = coinbase;
|
||||
this.dependencies = dependencies;
|
||||
this.descFee = fee;
|
||||
this.descSize = size;
|
||||
@ -229,6 +235,7 @@ MempoolEntry.prototype.memUsage = function memUsage() {
|
||||
let total = 0;
|
||||
|
||||
total += 176; // mempool entry
|
||||
total += 48; // coinbase
|
||||
total += 48; // dependencies
|
||||
|
||||
total += 208; // tx
|
||||
@ -297,7 +304,7 @@ MempoolEntry.prototype.isFree = function isFree(height) {
|
||||
*/
|
||||
|
||||
MempoolEntry.prototype.getSize = function getSize() {
|
||||
return this.tx.getSize() + 41;
|
||||
return this.tx.getSize() + 42;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -315,6 +322,7 @@ MempoolEntry.prototype.toRaw = function toRaw() {
|
||||
bw.writeU64(this.fee);
|
||||
bw.writeU32(this.time);
|
||||
bw.writeU64(this.value);
|
||||
bw.writeU8(this.coinbase ? 1 : 0);
|
||||
bw.writeU8(this.dependencies ? 1 : 0);
|
||||
return bw.render();
|
||||
};
|
||||
@ -337,6 +345,7 @@ MempoolEntry.prototype.fromRaw = function fromRaw(data) {
|
||||
this.deltaFee = this.fee;
|
||||
this.time = br.readU32();
|
||||
this.value = br.readU64();
|
||||
this.coinbase = br.readU8() === 1;
|
||||
this.dependencies = br.readU8() === 1;
|
||||
this.descFee = this.fee;
|
||||
this.descSize = this.size;
|
||||
|
||||
@ -197,6 +197,15 @@ FullNode.prototype._init = function _init() {
|
||||
this.emit('disconnect', entry, block);
|
||||
});
|
||||
|
||||
this.chain.hook('reorganize', async (tip, competitor) => {
|
||||
try {
|
||||
await this.mempool._handleReorg();
|
||||
} catch (e) {
|
||||
this.error(e);
|
||||
}
|
||||
this.emit('reorganize', tip, competitor);
|
||||
});
|
||||
|
||||
this.chain.hook('reset', async (tip) => {
|
||||
try {
|
||||
await this.mempool._reset();
|
||||
|
||||
@ -143,7 +143,11 @@ SPVNode.prototype._init = function _init() {
|
||||
});
|
||||
|
||||
this.chain.on('disconnect', (entry, block) => {
|
||||
this.emit('disconnect', entry);
|
||||
this.emit('disconnect', entry, block);
|
||||
});
|
||||
|
||||
this.chain.on('reorganize', (tip, competitor) => {
|
||||
this.emit('reorganize', tip, competitor);
|
||||
});
|
||||
|
||||
this.chain.on('reset', (tip) => {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user