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
|
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.',
|
'Chain replay from height %d necessary.',
|
||||||
fork.height);
|
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 path = require('path');
|
||||||
const AsyncObject = require('../utils/asyncobject');
|
const AsyncObject = require('../utils/asyncobject');
|
||||||
const common = require('../blockchain/common');
|
const common = require('../blockchain/common');
|
||||||
|
const consensus = require('../protocol/consensus');
|
||||||
const policy = require('../protocol/policy');
|
const policy = require('../protocol/policy');
|
||||||
const util = require('../utils/util');
|
const util = require('../utils/util');
|
||||||
const random = require('../crypto/random');
|
const random = require('../crypto/random');
|
||||||
@ -198,8 +199,9 @@ Mempool.prototype._addBlock = async function _addBlock(block, txs) {
|
|||||||
|
|
||||||
if (!entry) {
|
if (!entry) {
|
||||||
this.removeOrphan(hash);
|
this.removeOrphan(hash);
|
||||||
this.resolveOrphans(tx);
|
|
||||||
this.removeDoubleSpends(tx);
|
this.removeDoubleSpends(tx);
|
||||||
|
if (this.waiting.has(hash))
|
||||||
|
await this.handleOrphans(tx);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -303,6 +305,55 @@ Mempool.prototype._removeBlock = async function _removeBlock(block, txs) {
|
|||||||
total, block.height);
|
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.
|
* Reset the mempool.
|
||||||
* @method
|
* @method
|
||||||
|
|||||||
@ -43,6 +43,7 @@ function MempoolEntry(options) {
|
|||||||
this.deltaFee = 0;
|
this.deltaFee = 0;
|
||||||
this.time = 0;
|
this.time = 0;
|
||||||
this.value = 0;
|
this.value = 0;
|
||||||
|
this.coinbase = false;
|
||||||
this.dependencies = false;
|
this.dependencies = false;
|
||||||
this.descFee = 0;
|
this.descFee = 0;
|
||||||
this.descSize = 0;
|
this.descSize = 0;
|
||||||
@ -67,6 +68,7 @@ MempoolEntry.prototype.fromOptions = function fromOptions(options) {
|
|||||||
this.deltaFee = options.deltaFee;
|
this.deltaFee = options.deltaFee;
|
||||||
this.time = options.time;
|
this.time = options.time;
|
||||||
this.value = options.value;
|
this.value = options.value;
|
||||||
|
this.coinbase = options.coinbase;
|
||||||
this.dependencies = options.dependencies;
|
this.dependencies = options.dependencies;
|
||||||
this.descFee = options.descFee;
|
this.descFee = options.descFee;
|
||||||
this.descSize = options.descSize;
|
this.descSize = options.descSize;
|
||||||
@ -99,11 +101,14 @@ MempoolEntry.prototype.fromTX = function fromTX(tx, view, height) {
|
|||||||
const fee = tx.getFee(view);
|
const fee = tx.getFee(view);
|
||||||
|
|
||||||
let dependencies = false;
|
let dependencies = false;
|
||||||
|
let coinbase = false;
|
||||||
|
|
||||||
for (const {prevout} of tx.inputs) {
|
for (const {prevout} of tx.inputs) {
|
||||||
if (view.getHeight(prevout) === -1) {
|
if (view.isCoinbase(prevout))
|
||||||
|
coinbase = true;
|
||||||
|
|
||||||
|
if (view.getHeight(prevout) === -1)
|
||||||
dependencies = true;
|
dependencies = true;
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.tx = tx;
|
this.tx = tx;
|
||||||
@ -115,6 +120,7 @@ MempoolEntry.prototype.fromTX = function fromTX(tx, view, height) {
|
|||||||
this.deltaFee = fee;
|
this.deltaFee = fee;
|
||||||
this.time = util.now();
|
this.time = util.now();
|
||||||
this.value = value;
|
this.value = value;
|
||||||
|
this.coinbase = coinbase;
|
||||||
this.dependencies = dependencies;
|
this.dependencies = dependencies;
|
||||||
this.descFee = fee;
|
this.descFee = fee;
|
||||||
this.descSize = size;
|
this.descSize = size;
|
||||||
@ -229,6 +235,7 @@ MempoolEntry.prototype.memUsage = function memUsage() {
|
|||||||
let total = 0;
|
let total = 0;
|
||||||
|
|
||||||
total += 176; // mempool entry
|
total += 176; // mempool entry
|
||||||
|
total += 48; // coinbase
|
||||||
total += 48; // dependencies
|
total += 48; // dependencies
|
||||||
|
|
||||||
total += 208; // tx
|
total += 208; // tx
|
||||||
@ -297,7 +304,7 @@ MempoolEntry.prototype.isFree = function isFree(height) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
MempoolEntry.prototype.getSize = function getSize() {
|
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.writeU64(this.fee);
|
||||||
bw.writeU32(this.time);
|
bw.writeU32(this.time);
|
||||||
bw.writeU64(this.value);
|
bw.writeU64(this.value);
|
||||||
|
bw.writeU8(this.coinbase ? 1 : 0);
|
||||||
bw.writeU8(this.dependencies ? 1 : 0);
|
bw.writeU8(this.dependencies ? 1 : 0);
|
||||||
return bw.render();
|
return bw.render();
|
||||||
};
|
};
|
||||||
@ -337,6 +345,7 @@ MempoolEntry.prototype.fromRaw = function fromRaw(data) {
|
|||||||
this.deltaFee = this.fee;
|
this.deltaFee = this.fee;
|
||||||
this.time = br.readU32();
|
this.time = br.readU32();
|
||||||
this.value = br.readU64();
|
this.value = br.readU64();
|
||||||
|
this.coinbase = br.readU8() === 1;
|
||||||
this.dependencies = br.readU8() === 1;
|
this.dependencies = br.readU8() === 1;
|
||||||
this.descFee = this.fee;
|
this.descFee = this.fee;
|
||||||
this.descSize = this.size;
|
this.descSize = this.size;
|
||||||
|
|||||||
@ -197,6 +197,15 @@ FullNode.prototype._init = function _init() {
|
|||||||
this.emit('disconnect', entry, block);
|
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) => {
|
this.chain.hook('reset', async (tip) => {
|
||||||
try {
|
try {
|
||||||
await this.mempool._reset();
|
await this.mempool._reset();
|
||||||
|
|||||||
@ -143,7 +143,11 @@ SPVNode.prototype._init = function _init() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.chain.on('disconnect', (entry, block) => {
|
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) => {
|
this.chain.on('reset', (tip) => {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user