From 1fd85b729d8928b84b9624b1c811372b426515ac Mon Sep 17 00:00:00 2001 From: Mononaut Date: Fri, 24 Mar 2023 09:47:08 +0900 Subject: [PATCH] handle stale transactions in block templates --- backend/src/api/disk-cache.ts | 4 +++- backend/src/api/mempool-blocks.ts | 15 +++++++++++---- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/backend/src/api/disk-cache.ts b/backend/src/api/disk-cache.ts index 7180c6f51..0ec502c08 100644 --- a/backend/src/api/disk-cache.ts +++ b/backend/src/api/disk-cache.ts @@ -43,7 +43,9 @@ class DiskCache { const mempool = memPool.getMempool(); const mempoolArray: TransactionExtended[] = []; for (const tx in mempool) { - mempoolArray.push(mempool[tx]); + if (mempool[tx] && !mempool[tx].deleteAfter) { + mempoolArray.push(mempool[tx]); + } } Common.shuffleArray(mempoolArray); diff --git a/backend/src/api/mempool-blocks.ts b/backend/src/api/mempool-blocks.ts index 3c2feb0e2..ff502be24 100644 --- a/backend/src/api/mempool-blocks.ts +++ b/backend/src/api/mempool-blocks.ts @@ -151,7 +151,7 @@ class MempoolBlocks { // prepare a stripped down version of the mempool with only the minimum necessary data // to reduce the overhead of passing this data to the worker thread const strippedMempool: { [txid: string]: ThreadTransaction } = {}; - Object.values(newMempool).forEach(entry => { + Object.values(newMempool).filter(tx => !tx.deleteAfter).forEach(entry => { strippedMempool[entry.txid] = { txid: entry.txid, fee: entry.fee, @@ -186,7 +186,9 @@ class MempoolBlocks { this.txSelectionWorker?.once('error', reject); }); this.txSelectionWorker.postMessage({ type: 'set', mempool: strippedMempool }); - const { blocks, clusters } = await workerResultPromise; + let { blocks, clusters } = await workerResultPromise; + // filter out stale transactions + blocks = blocks.map(block => block.filter(tx => (tx.txid && tx.txid in newMempool))); // clean up thread error listener this.txSelectionWorker?.removeListener('error', threadErrorListener); @@ -228,7 +230,9 @@ class MempoolBlocks { this.txSelectionWorker?.once('error', reject); }); this.txSelectionWorker.postMessage({ type: 'update', added: addedStripped, removed }); - const { blocks, clusters } = await workerResultPromise; + let { blocks, clusters } = await workerResultPromise; + // filter out stale transactions + blocks = blocks.map(block => block.filter(tx => (tx.txid && tx.txid in newMempool))); // clean up thread error listener this.txSelectionWorker?.removeListener('error', threadErrorListener); @@ -243,7 +247,7 @@ class MempoolBlocks { // update this thread's mempool with the results blocks.forEach(block => { block.forEach(tx => { - if (tx.txid in mempool) { + if (tx.txid && tx.txid in mempool) { if (tx.effectiveFeePerVsize != null) { mempool[tx.txid].effectiveFeePerVsize = tx.effectiveFeePerVsize; } @@ -253,6 +257,9 @@ class MempoolBlocks { const cluster = clusters[tx.cpfpRoot]; let matched = false; cluster.forEach(txid => { + if (!txid || !mempool[txid]) { + return; + } if (txid === tx.txid) { matched = true; } else {