test: properly check for per-tx sigops limit #32533

pull theStack wants to merge 1 commits into bitcoin:master from theStack:202505-test-exact_per_tx_sigopcost_check changing 2 files +21 −2
  1. theStack commented at 2:50 pm on May 16, 2025: contributor

    Currently the per-tx sigops limit standardness check (bounded by MAX_STANDARD_TX_SIGOPS_COST, throwing “bad-txns-too-many-sigops” if exceeded): https://github.com/bitcoin/bitcoin/blob/3f83c744ac28b700090e15b5dda2260724a56f49/src/validation.cpp#L925-L927

    is only indirectly tested with the much higher per-block consensus limit (MAX_BLOCK_SIGOPS_COST): https://github.com/bitcoin/bitcoin/blob/3f83c744ac28b700090e15b5dda2260724a56f49/test/functional/data/invalid_txs.py#L236-L242

    I.e. an increase in the per-tx limit up to the per-block one would still pass all of our tests. Refine that by splitting up the invalid tx template TooManySigops in a per-block and a per-tx template.

    The involved functional tests taking use of these templates are feature_block.py and p2p_invalid_txs.py. Can be tested by applying e.g.

     0diff --git a/src/policy/policy.h b/src/policy/policy.h
     1index 2151ec13dd..e5766d2a55 100644
     2--- a/src/policy/policy.h
     3+++ b/src/policy/policy.h
     4@@ -37,7 +37,7 @@ static constexpr unsigned int MIN_STANDARD_TX_NONWITNESS_SIZE{65};
     5 /** Maximum number of signature check operations in an IsStandard() P2SH script */
     6 static constexpr unsigned int MAX_P2SH_SIGOPS{15};
     7 /** The maximum number of sigops we're willing to relay/mine in a single tx */
     8-static constexpr unsigned int MAX_STANDARD_TX_SIGOPS_COST{MAX_BLOCK_SIGOPS_COST/5};
     9+static constexpr unsigned int MAX_STANDARD_TX_SIGOPS_COST{MAX_BLOCK_SIGOPS_COST/5 + 4};
    10 /** Default for -incrementalrelayfee, which sets the minimum feerate increase for mempool limiting or replacement **/
    11 static constexpr unsigned int DEFAULT_INCREMENTAL_RELAY_FEE{1000};
    12 /** Default for -bytespersigop */
    13diff --git a/test/functional/mempool_accept.py b/test/functional/mempool_accept.py
    

    where the tests succeed on master, but fail on this PR.

    (Found by diving deeper into the jungle of current sig-ops limit, as preparation for reviewing the BIP 54 draft and related preparatory PRs like #32521).

  2. test: properly check for per-tx sigops limit
    Currently the per-tx sigops limit standardness check (bounded by
    `MAX_STANDARD_TX_SIGOPS_COST`, throwing "bad-txns-too-many-sigops"
    if exceeded) is only indirectly tested with the much higher per-block
    consensus limit (`MAX_BLOCK_SIGOPS_COST`), i.e. an increase in the
    limit would still pass all tests. Refine that by splitting up the invalid
    tx template `TooManySigops` in a per-block and a per-tx one.
    
    The involved functional tests taking use of these templates are
    `feature_block.py` and `p2p_invalid_txs.py`.
    7bc64a8859
  3. DrahtBot commented at 2:50 pm on May 16, 2025: contributor

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

    Code Coverage & Benchmarks

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

    Reviews

    See the guideline for information on the review process.

    Type Reviewers
    ACK tapcrafter, darosior, fjahr, instagibbs
    Concept ACK Sjors

    If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update.

  4. DrahtBot added the label Tests on May 16, 2025
  5. darosior commented at 3:40 pm on May 16, 2025: member
    Concept ACK
  6. tapcrafter commented at 7:55 am on May 18, 2025: none

    tACK 7bc64a8859c3644fdf2eeff59f72a778ae60ea3f

    On master (7710a31f0cb69a04529f39840196826d0b9770ab), changing MAX_STANDARD_TX_SIGOPS_COST in src/policy/policy.h to a higher value didn’t cause the tests to fail:

    0$ ./build/test/functional/p2p_invalid_tx.py  
    1
    22025-05-18T07:49:02.383000Z TestFramework (INFO): PRNG seed is: 4606283318320792897
    3...
    42025-05-18T07:49:04.855000Z TestFramework (INFO): Testing invalid transaction: TooManySigops
    52025-05-18T07:49:04.911000Z TestFramework (INFO): Testing invalid transaction: NonStandardAndInvalid
    6...
    72025-05-18T07:49:09.279000Z TestFramework (INFO): Tests successful
    

    Then re-compiling on 7bc64a8859c3644fdf2eeff59f72a778ae60ea3f with the same increased MAX_STANDARD_TX_SIGOPS_COST value leads to an error as expected:

     0$ ./build/test/functional/p2p_invalid_tx.py
     1
     22025-05-18T07:47:10.543000Z TestFramework (INFO): Testing invalid transaction: TooManySigopsPerBlock
     32025-05-18T07:47:10.600000Z TestFramework (INFO): Testing invalid transaction: TooManySigopsPerTransaction
     42025-05-18T07:47:10.652000Z TestFramework (ERROR): Assertion failed
     5Traceback (most recent call last):
     6  File "/home/tapcrafter/bitcoin/test/functional/test_framework/test_framework.py", line 183, in main
     7    self.run_test()
     8  File "/home/tapcrafter/bitcoin/./build/test/functional/p2p_invalid_tx.py", line 74, in run_test
     9    node.p2ps[0].send_txs_and_test(
    10  File "/home/tapcrafter/bitcoin/test/functional/test_framework/p2p.py", line 934, in send_txs_and_test
    11    assert tx.hash not in raw_mempool, "{} tx found in mempool".format(tx.hash)
    12           ^^^^^^^^^^^^^^^^^^^^^^^^^^
    13AssertionError: 6713a6d0244743c4145664ccf207564b8df941ab46f0ae1ec3b44940c829cb8d tx found in mempool
    
  7. DrahtBot requested review from darosior on May 18, 2025
  8. Sjors commented at 12:07 pm on May 19, 2025: member

    Concept ACK

    It would be nice to also have a test (against an accidental soft fork) that fails if you change:

    MAX_STANDARD_TX_SIGOPS_COST{MAX_BLOCK_SIGOPS_COST/5 - 4};

    And maybe one that covers witness sigops.

  9. fjahr commented at 1:03 pm on May 19, 2025: contributor
    Concept ACK
  10. darosior approved
  11. darosior commented at 6:46 pm on May 19, 2025: member
    ACK 7bc64a8859c3644fdf2eeff59f72a778ae60ea3f
  12. DrahtBot requested review from fjahr on May 19, 2025
  13. DrahtBot requested review from Sjors on May 19, 2025
  14. darosior commented at 6:53 pm on May 19, 2025: member

    against an accidental soft fork

    You mean against a tightening of the rules, which in the context of standardness is harder than a loosening of the rules? :p

  15. Sjors commented at 7:45 am on May 20, 2025: member
    I was thinking ahead to when BIP54 is activated, but yes, “tightening”.
  16. fjahr commented at 1:15 pm on May 22, 2025: contributor

    tACK 7bc64a8859c3644fdf2eeff59f72a778ae60ea3f

    Confirmed that the test fails if the limit is not exceeded.

  17. fanquake requested review from instagibbs on May 22, 2025
  18. in test/functional/data/invalid_txs.py:259 in 7bc64a8859
    254+    reject_reason = "bad-txns-too-many-sigops"
    255+    expect_disconnect = False
    256+    valid_in_block = True
    257+
    258+    def get_tx(self):
    259+        lotsa_checksigs = CScript([OP_CHECKSIG] * (MAX_STANDARD_TX_SIGOPS + 1))
    


    instagibbs commented at 1:25 pm on May 22, 2025:

    Took me a minute to realize this is only the 2nd(?) case where it’s valid in block but non-standard-even-with-acceotnonstdtxn set.

    Also meta: would be nice if there was a border testing capability, where you could pair it with a tx that would be successful and obviously just-at the limit.

  19. in test/functional/test_framework/blocktools.py:52 in 7bc64a8859
    48@@ -49,6 +49,7 @@
    49 
    50 MAX_BLOCK_SIGOPS = 20000
    51 MAX_BLOCK_SIGOPS_WEIGHT = MAX_BLOCK_SIGOPS * WITNESS_SCALE_FACTOR
    52+MAX_STANDARD_TX_SIGOPS = 4000
    


    instagibbs commented at 1:43 pm on May 22, 2025:
    0MAX_STANDARD_TX_SIGOPS = MAX_BLOCK_SIGOPS/5
    
  20. instagibbs approved
  21. instagibbs commented at 1:57 pm on May 22, 2025: member

    crACK 7bc64a8859c3644fdf2eeff59f72a778ae60ea3f

    just nits you can ignore

  22. glozow merged this on May 22, 2025
  23. glozow closed this on May 22, 2025

  24. theStack deleted the branch on May 22, 2025

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: 2025-05-25 18:12 UTC

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