From e8c32735413d616dd39ef832cbe9ef0a756d2c80 Mon Sep 17 00:00:00 2001 From: Mononaut Date: Mon, 30 Jan 2023 16:26:37 -0600 Subject: [PATCH] fix drift in next block viz with mixed template algos --- backend/src/api/mempool-blocks.ts | 39 +++++++++++++++++----------- backend/src/api/websocket-handler.ts | 20 +++++++------- 2 files changed, 35 insertions(+), 24 deletions(-) diff --git a/backend/src/api/mempool-blocks.ts b/backend/src/api/mempool-blocks.ts index d94ed77bd..0df125d55 100644 --- a/backend/src/api/mempool-blocks.ts +++ b/backend/src/api/mempool-blocks.ts @@ -33,7 +33,7 @@ class MempoolBlocks { return this.mempoolBlockDeltas; } - public updateMempoolBlocks(memPool: { [txid: string]: TransactionExtended }): void { + public updateMempoolBlocks(memPool: { [txid: string]: TransactionExtended }, saveResults: boolean = false): MempoolBlockWithTransactions[] { const latestMempool = memPool; const memPoolArray: TransactionExtended[] = []; for (const i in latestMempool) { @@ -75,10 +75,14 @@ class MempoolBlocks { logger.debug('Mempool blocks calculated in ' + time / 1000 + ' seconds'); const blocks = this.calculateMempoolBlocks(memPoolArray, this.mempoolBlocks); - const deltas = this.calculateMempoolDeltas(this.mempoolBlocks, blocks); - this.mempoolBlocks = blocks; - this.mempoolBlockDeltas = deltas; + if (saveResults) { + const deltas = this.calculateMempoolDeltas(this.mempoolBlocks, blocks); + this.mempoolBlocks = blocks; + this.mempoolBlockDeltas = deltas; + } + + return blocks; } private calculateMempoolBlocks(transactionsSorted: TransactionExtended[], prevBlocks: MempoolBlockWithTransactions[]): MempoolBlockWithTransactions[] { @@ -143,7 +147,7 @@ class MempoolBlocks { return mempoolBlockDeltas; } - public async makeBlockTemplates(newMempool: { [txid: string]: TransactionExtended }): Promise { + public async makeBlockTemplates(newMempool: { [txid: string]: TransactionExtended }, saveResults: boolean = false): Promise { // 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 } = {}; @@ -184,19 +188,21 @@ class MempoolBlocks { this.txSelectionWorker.postMessage({ type: 'set', mempool: strippedMempool }); const { blocks, clusters } = await workerResultPromise; - this.processBlockTemplates(newMempool, blocks, clusters); - // clean up thread error listener this.txSelectionWorker?.removeListener('error', threadErrorListener); + + return this.processBlockTemplates(newMempool, blocks, clusters, saveResults); } catch (e) { logger.err('makeBlockTemplates failed. ' + (e instanceof Error ? e.message : e)); } + return this.mempoolBlocks; } - public async updateBlockTemplates(newMempool: { [txid: string]: TransactionExtended }, added: TransactionExtended[], removed: string[]): Promise { + public async updateBlockTemplates(newMempool: { [txid: string]: TransactionExtended }, added: TransactionExtended[], removed: string[], saveResults: boolean = false): Promise { if (!this.txSelectionWorker) { // need to reset the worker - return this.makeBlockTemplates(newMempool); + this.makeBlockTemplates(newMempool, saveResults); + return; } // 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 @@ -224,16 +230,16 @@ class MempoolBlocks { this.txSelectionWorker.postMessage({ type: 'update', added: addedStripped, removed }); const { blocks, clusters } = await workerResultPromise; - this.processBlockTemplates(newMempool, blocks, clusters); - // clean up thread error listener this.txSelectionWorker?.removeListener('error', threadErrorListener); + + this.processBlockTemplates(newMempool, blocks, clusters, saveResults); } catch (e) { logger.err('updateBlockTemplates failed. ' + (e instanceof Error ? e.message : e)); } } - private processBlockTemplates(mempool, blocks, clusters): void { + private processBlockTemplates(mempool, blocks, clusters, saveResults): MempoolBlockWithTransactions[] { // update this thread's mempool with the results blocks.forEach(block => { block.forEach(tx => { @@ -278,10 +284,13 @@ class MempoolBlocks { }).filter(tx => !!tx), undefined, undefined, blockIndex); }); - const deltas = this.calculateMempoolDeltas(this.mempoolBlocks, mempoolBlocks); + if (saveResults) { + const deltas = this.calculateMempoolDeltas(this.mempoolBlocks, mempoolBlocks); + this.mempoolBlocks = mempoolBlocks; + this.mempoolBlockDeltas = deltas; + } - this.mempoolBlocks = mempoolBlocks; - this.mempoolBlockDeltas = deltas; + return mempoolBlocks; } private dataToMempoolBlocks(transactions: TransactionExtended[], diff --git a/backend/src/api/websocket-handler.ts b/backend/src/api/websocket-handler.ts index 3ca49293d..cffbea346 100644 --- a/backend/src/api/websocket-handler.ts +++ b/backend/src/api/websocket-handler.ts @@ -251,9 +251,9 @@ class WebsocketHandler { } if (config.MEMPOOL.ADVANCED_GBT_MEMPOOL) { - await mempoolBlocks.updateBlockTemplates(newMempool, newTransactions, deletedTransactions.map(tx => tx.txid)); + await mempoolBlocks.updateBlockTemplates(newMempool, newTransactions, deletedTransactions.map(tx => tx.txid), true); } else { - mempoolBlocks.updateMempoolBlocks(newMempool); + mempoolBlocks.updateMempoolBlocks(newMempool, true); } const mBlocks = mempoolBlocks.getMempoolBlocks(); @@ -418,16 +418,18 @@ class WebsocketHandler { const _memPool = memPool.getMempool(); + let projectedBlocks; + // template calculation functions have mempool side effects, so calculate audits using + // a cloned copy of the mempool if we're running a different algorithm for mempool updates + const auditMempool = (config.MEMPOOL.ADVANCED_GBT_AUDIT === config.MEMPOOL.ADVANCED_GBT_MEMPOOL) ? _memPool : JSON.parse(JSON.stringify(_memPool)); if (config.MEMPOOL.ADVANCED_GBT_AUDIT) { - await mempoolBlocks.makeBlockTemplates(_memPool); + projectedBlocks = await mempoolBlocks.makeBlockTemplates(auditMempool, false); } else { - mempoolBlocks.updateMempoolBlocks(_memPool); + projectedBlocks = mempoolBlocks.updateMempoolBlocks(auditMempool, false); } if (Common.indexingEnabled() && memPool.isInSync()) { - const projectedBlocks = mempoolBlocks.getMempoolBlocksWithTransactions(); - - const { censored, added, fresh, score } = Audit.auditBlock(transactions, projectedBlocks, _memPool); + const { censored, added, fresh, score } = Audit.auditBlock(transactions, projectedBlocks, auditMempool); const matchRate = Math.round(score * 100 * 100) / 100; const stripped = projectedBlocks[0]?.transactions ? projectedBlocks[0].transactions.map((tx) => { @@ -471,9 +473,9 @@ class WebsocketHandler { } if (config.MEMPOOL.ADVANCED_GBT_MEMPOOL) { - await mempoolBlocks.updateBlockTemplates(_memPool, [], removed); + await mempoolBlocks.updateBlockTemplates(_memPool, [], removed, true); } else { - mempoolBlocks.updateMempoolBlocks(_memPool); + mempoolBlocks.updateMempoolBlocks(_memPool, true); } const mBlocks = mempoolBlocks.getMempoolBlocks(); const mBlockDeltas = mempoolBlocks.getMempoolBlockDeltas();