bugfix: compare non-adjusted chunk weight against block weight limit #35580

pull ismaelsadeeq wants to merge 2 commits into bitcoin:master from ismaelsadeeq:07-2026-fix-chunk-weight-limit changing 3 files +51 −16
  1. ismaelsadeeq commented at 10:49 AM on June 22, 2026: member

    Partially fixes #35596

    When assembling a block template, BlockAssembler::addChunks() adds chunks of transactions until the block is close to being full. For each chunk, TestChunkBlockLimits() checks both the weight and the sigop-cost limits before the chunk is included.

    The weight check compared the chunk's sigops-adjusted weight against block_max_weight:

    if (nBlockWeight + chunk_feerate.size >= m_options.block_max_weight) {
        return false;
    }
    

    Whereas nBlockWeight accumulates the actual chunk weight.

    A chunk whose sigop-adjusted weight exceeds the actual weight can be wrongly skipped even though the block sigop limit is enforced independently on the next line, and that could pass. Those chunks pay higher fees, so this could potentially cause miners to needlessly forfeit some fees revenue.

    This PR fixes this by passing the chunk's real weight (sum of GetTxWeight(), accumulated in the same loop that already sums sigop cost) to TestChunkBlockLimits(). The separate sigop-cost check is unchanged.

    • The first commit adds TestSigOpsAdjustedWeightChunkLimit: it builds one sigop-dense transaction sized to fit by real weight but not by adjusted weight, and asserts that the tx is skipped and only the coinbase is mined.

    • The second commit applies the fix and flips the assertion to show the transaction is now included.

  2. DrahtBot commented at 10:49 AM on June 22, 2026: contributor

    <!--e57a25ab6845829454e8d69fc972939a-->

    The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

    <!--006a51241073e994b41acfe9ec718e94-->

    Code Coverage & Benchmarks

    For details see: https://corecheck.dev/bitcoin/bitcoin/pulls/35580.

    <!--021abf342d371248e50ceaed478a90ca-->

    Reviews

    See the guideline and AI policy for information on the review process.

    Type Reviewers
    ACK pablomartin4btc
    Concept ACK gmaxwell

    If your review is incorrectly listed, please copy-paste <code>&lt;!--meta-tag:bot-skip--&gt;</code> into the comment that the bot should ignore.

    <!--174a7506f384e20aa4161008e828411d-->

    Conflicts

    Reviewers, this pull request conflicts with the following ones:

    • #35569 (Encapsulation for CTransaction by purpleKarrot)
    • #35511 (RFC: consensus: Make CAmount a class by hodlinator)

    If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

    <!--5faf32d7da4f0f540f40219e4f7537a3-->

  3. ismaelsadeeq renamed this:
    bugfix: compare non-adjusted chunk weight against block weight limit in `TestBlockChunklimit`
    bugfix: compare non-adjusted chunk weight against block weight limit
    on Jun 22, 2026
  4. DrahtBot added the label Needs rebase on Jun 23, 2026
  5. ismaelsadeeq force-pushed on Jun 24, 2026
  6. DrahtBot removed the label Needs rebase on Jun 24, 2026
  7. willcl-ark added the label Mining on Jul 9, 2026
  8. willcl-ark added the label Bug on Jul 9, 2026
  9. in src/test/miner_tests.cpp:305 in 1754401de4
     299 | @@ -299,6 +300,22 @@ void MinerTestingSetup::TestPackageSelection(const CScript& scriptPubKey, const
     300 |      BOOST_CHECK(block.vtx[8]->GetHash() == hashLowFeeTx2);
     301 |  }
     302 |  
     303 | +// One sigop-dense tx spending `input`: num_outputs bare CHECKMULTISIG outputs,
     304 | +// i.e. 20 * num_outputs legacy sigops (OP_NOP forces the inaccurate max-20 count).
     305 | +CMutableTransaction CreateBigSigOpsTx(const COutPoint& input, unsigned int num_outputs)
    


    pablomartin4btc commented at 4:48 PM on July 23, 2026:

    nit: in 1754401de41d43abe5404844c2d622b92a09dcc3, I think CreateBigSigOpsTx should be static, as CreateBlockIndex is (same applies to CreateBigSigOpsCluster but that's pre-existing)


    ismaelsadeeq commented at 1:52 PM on July 26, 2026:

    Good idea, done.

  10. in src/test/miner_tests.cpp:366 in 1754401de4 outdated
     373 | +    BOOST_REQUIRE(sigop_entry.GetAdjustedWeight() > sigop_entry.GetTxWeight());
     374 | +    BOOST_REQUIRE(sigop_entry.GetSigOpCost() < MAX_BLOCK_SIGOPS_COST);
     375 | +    TryAddToMempool(tx_mempool, sigop_entry);
     376 | +
     377 | +    BlockCreateOptions options{
     378 | +        // +1 because TestChunkBlockLimits rejects on >= (exact fit doesn't count).
    


    pablomartin4btc commented at 5:17 PM on July 23, 2026:

    minor nit: in 1754401, perhaps something like: The +1 here is a workaround for issue 1 from #35596 (>= should be > in TestChunkBlockLimits); to be fixed in a follow-up


    ismaelsadeeq commented at 1:53 PM on July 26, 2026:

    I think this is okay as is; it described the issue very well.

    When the status quo changes, it should be updated as well.

  11. pablomartin4btc commented at 5:33 PM on July 23, 2026: member

    Approach ACK

    A chunk whose sigop-adjusted weight exceeds the actual weight can be wrongly skipped even though the block sigop limit is enforced independently on the next line, and that could pass. Those chunks pay higher fees, so this could potentially cause miners to needlessly forfeit some fees revenue.

    It seems that the sigop-adjusted weight was designed purely for ordering (fee-rate priority), not for limit checking. Block validity depends on real weight and real sigops — two separate physical constraints. The fix checks each with the right metric:

    • Weight limit → real weight ✓
    • Sigops limit → real sigop count ✓

    These were already independent checks, the bug was just feeding the wrong number into the first one.


    Tested indirectly through CreateNewBlock, building a transaction that demonstrates the bug (excluded before fix, included after).

    Issue 1 from #35596 (>=> in TestChunkBlockLimits) seems like a natural follow-up — same function, similar pattern for the test.

  12. test: `TestChunkBlockLimits` uses incorrect weight for comparison
    addChunks() passes the chunk's sigops-adjusted fee rate to
    TestChunkBlockLimits() and the adjusted weight is used for block weight
    limit check while `nBlockWeight` accumulates real transaction weight.
    
    A sigop-dense chunk that fits the block by real weight is therefore
    checked against block_max_weight by its larger adjusted weight and wrongly
    skipped.
    
    Add a transaction sized to fit by real weight; but is left out of the
    template (only the coinbase is mined) due to this issue.
    
    The next commit fixes this and flips the assertion.
    fc98790869
  13. bugfix: compare real chunk weight against block weight limit
    TestChunkBlockLimits() compared the chunk's sigops-adjusted weight against
    block_max_weight, while nBlockWeight tracks real transaction weight. This
    over-counted sigop-dense chunks and could skip ones that actually fit,
    losing fees; the block sigop limit is enforced separately on the next line.
    
    Pass the chunk's real weight (sum of GetTxWeight()) instead, and update the
    test to show the chunk is now included.
    5be248341a
  14. ismaelsadeeq force-pushed on Jul 26, 2026
  15. sedited requested review from Sjors on Jul 27, 2026
  16. ismaelsadeeq requested review from pablomartin4btc on Jul 30, 2026
  17. pablomartin4btc commented at 4:10 PM on July 30, 2026: member

    Code Review ACK 5be248341a8e9ad97143647e7f480eecf1f90eb4

    static nit addressed.

    I think the fix is correct: TestChunkBlockLimits now receives and checks the chunk's real weight (sum of GetTxWeight()) instead of the sigop-adjusted value from FeePerWeight.size. The sigop-adjustment belongs in fee-rate ordering only, not in block limit checks. The test properly validates this by constructing a sigop-dense tx whose adjusted weight exceeds the real weight, asserting GetSigOpCost() < MAX_BLOCK_SIGOPS_COST so the sigop check won't interfere, and showing the tx goes from excluded before the fix to included after the fix.

  18. gmaxwell commented at 7:41 AM on August 9, 2026: contributor

    Tested ACK. I ran this with several other fixes and have been mining an occasional 4m weight block without issue.

  19. fanquake added this to the milestone 32.0 on Aug 10, 2026
  20. fanquake commented at 9:55 AM on August 10, 2026: member

    @Sjors Can you take a look here?


github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-08-11 10:51 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me