Skip to content

Commit

Permalink
mempool: sanitize after reorg.
Browse files Browse the repository at this point in the history
  • Loading branch information
chjj committed Sep 27, 2017
1 parent 459a9f2 commit 1aa78e2
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 8 deletions.
4 changes: 2 additions & 2 deletions lib/blockchain/chain.js
Expand Up @@ -905,7 +905,7 @@ Chain.prototype.reorganize = async function reorganize(competitor) {
competitor.height
);

this.emit('reorganize', tip, competitor);
await this.fire('reorganize', tip, competitor);
};

/**
Expand Down Expand Up @@ -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);
};

/**
Expand Down
53 changes: 52 additions & 1 deletion lib/mempool/mempool.js
Expand Up @@ -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');
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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
Expand Down
17 changes: 13 additions & 4 deletions lib/mempool/mempoolentry.js
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
};

/**
Expand All @@ -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();
};
Expand All @@ -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;
Expand Down
9 changes: 9 additions & 0 deletions lib/node/fullnode.js
Expand Up @@ -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();
Expand Down
6 changes: 5 additions & 1 deletion lib/node/spvnode.js
Expand Up @@ -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) => {
Expand Down

0 comments on commit 1aa78e2

Please sign in to comment.