mirror of
https://github.com/luxfi/evm.git
synced 2026-09-24 00:27:44 +00:00
An assembled block with no transactions is two conditions wearing one shape. No demand is the demand-driven property working — discard it, or an idle chain grows forever. Demand the assembler failed to collect is a bug, and discarding THAT makes it permanent: no block means no nonce advances, so the pending transaction is never mined, so the pool never drains, so the condition under which a block would be built can never return. The gate read the assembled block, which cannot tell the two apart, so it took the second for the first. Measured on lux-devnet: the chain stopped at 20:38 UTC on 2026-08-11 holding ONE executable transaction, sat 41 hours, and behind it the traffic generator logged 7,100 consecutive failures while luxd-0 and luxd-3 logged errEmptyBlock ~2000 times per six hours. Every node was healthy. Nothing was wrong with consensus — CERTs gossiped the whole time. It reads the pool now. Nothing pending is idleness and the block is discarded; anything pending builds, whatever assembly managed to collect, and logs the mismatch where somebody can see it. Liveness stops depending on the assembly path being correct. The rule moves into proposeEmptyBuild so it can be tested without standing up a VM, which is why it had no test before. This does not fix the proximate cause, and is not meant to: the transaction was in exactly one node's pool (luxd-2) and never reached either proposer, so EVM transaction gossip is the next thing to look at. What changes here is that such a failure degrades throughput instead of halting the chain. Co-authored-by: Hanzo Dev <[email protected]>