From 88d12ee18e7a3df489cc600f92c4f68506d307fe Mon Sep 17 00:00:00 2001 From: bitflash-maintainer Date: Thu, 13 Aug 2026 14:50:26 +0000 Subject: consensus: cap block size at 1 MB, and stop assembling blocks we would reject CheckBlock() validated block size against MAX_SIZE, the serializer's generic 32 MB guard, not a block rule. MAX_BLOCK_SIZE did not exist in this tree at all: Bitcoin's 1 MB cap arrived in 0.3.x, after the 0.1.0 this fork came from. A miner could produce a 32 MB block and every node would download, verify and store it. Upstream #111 (from #110 by mtg0001). The cap is a tightening, so a node that does not upgrade is the permissive one. Measured upstream over 5709 blocks: largest 34,290 bytes, median 216, so 1 MB rejects nothing that exists. Upstream shipped the validation half only. Both places that ASSEMBLE a block still filled to MAX_SIZE/2 (16 MB), which was consistent against a 32 MB validation cap and is inverted by a 1 MB one -- the node would solve a block and then reject it itself. Fixed both: main.cpp CreateNewBlock, the node's own miner rpc.cpp RebuildJob, the POOL's job builder -- the one that matters here, because every miner on the pool would be working a template the network rejects, and this pool is ~90% of hashrate Half the cap in both, preserving the original margin: each test runs against a transaction that is already counted, so the loop can overshoot by one. (cherry picked from commit a3be9f04903447fa2741aff4eb529fe45f916877) --- src/main.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index 5d0b70a..37a15c6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4226,7 +4226,19 @@ bool BitcoinMiner(int nThreadId) vector vfAlreadyAdded(mapTransactions.size()); bool fFoundSomething = true; unsigned int nBlockSize = 0; - while (fFoundSomething && nBlockSize < MAX_SIZE/2) + // Assembly must stop below the consensus cap that CheckBlock() + // enforces, or we mine a block our own node then rejects. + // + // This used to read MAX_SIZE/2 (16 MB), which was consistent while + // CheckBlock() also tested against MAX_SIZE (32 MB). Adding + // MAX_BLOCK_SIZE inverted it: assembly could fill 16 MB and + // validation would refuse anything over 1 MB, so a full mempool + // meant solving a block and throwing it away -- with this pool at + // ~90% of hashrate, that is the network stalling, not just us. + // + // Half the cap, keeping the original margin: the test runs before + // a transaction is added, so the loop can overshoot by one tx. + while (fFoundSomething && nBlockSize < MAX_BLOCK_SIZE/2) { fFoundSomething = false; unsigned int n = 0; -- cgit v1.2.3