From ada66c227a154a45542d4654704f56c810c8ff54 Mon Sep 17 00:00:00 2001 From: shitikyan Date: Wed, 26 Aug 2026 14:55:31 +0400 Subject: [PATCH] fix(consensus): return own mempool on empty-incoming pull Mempool.receive([]) returned { mempool: [] }, so an idle validator (empty mempool) pulling a peer via the push-pull 'mempool' exchange got nothing back. The proposer's txs never reached the shard, its candidate block's tx-set diverged (broadcastBlockHash missingFromThem>0), and a tx submitted to a single node was never included. Return our own pool, mirroring the unseenTransactions===0 path. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01GaYywCQ3f4SZD78cn1MaXA --- src/libs/blockchain/mempool.ts | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/libs/blockchain/mempool.ts b/src/libs/blockchain/mempool.ts index 1628b730..335f2645 100644 --- a/src/libs/blockchain/mempool.ts +++ b/src/libs/blockchain/mempool.ts @@ -399,9 +399,18 @@ export default class Mempool { public static async receive(incoming: Transaction[], returnDiff = true) { if (incoming.length === 0) { + // An idle peer (empty mempool) still pulls ours via the "mempool" + // exchange (handleMempool → receive(theirTxs).mempool). Return our + // own pool — not [] — otherwise the puller never learns our txs, + // the proposer's candidate block diverges from the shard's tx-set + // (broadcastBlockHash missingFromThem>0), and a tx submitted to a + // single node is never included. Mirrors the unseenTransactions===0 + // path below. + const blockNumber = SecretaryManager.lastBlockRef + const finalPool = await this.getMempool(blockNumber) return { success: true, - mempool: [], + mempool: finalPool.filter(tx => tx.blockNumber <= blockNumber), } }