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

7bc64a8859 test: properly check for per-tx sigops limit (Sebastian Falbesoner)

Pull request description:

  Currently the per-tx sigops limit standardness check (bounded by `MAX_STANDARD_TX_SIGOPS_COST`, throwing "bad-txns-too-many-sigops" if exceeded):
  3f83c744ac/src/validation.cpp (L925-L927)

  is only indirectly tested with the much higher per-block consensus limit (`MAX_BLOCK_SIGOPS_COST`):
  3f83c744ac/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.
  ```diff
  diff --git a/src/policy/policy.h b/src/policy/policy.h
  index 2151ec13dd..e5766d2a55 100644
  --- a/src/policy/policy.h
  +++ b/src/policy/policy.h
  @@ -37,7 +37,7 @@ static constexpr unsigned int MIN_STANDARD_TX_NONWITNESS_SIZE{65};
   /** Maximum number of signature check operations in an IsStandard() P2SH script */
   static constexpr unsigned int MAX_P2SH_SIGOPS{15};
   /** The maximum number of sigops we're willing to relay/mine in a single tx */
  -static constexpr unsigned int MAX_STANDARD_TX_SIGOPS_COST{MAX_BLOCK_SIGOPS_COST/5};
  +static constexpr unsigned int MAX_STANDARD_TX_SIGOPS_COST{MAX_BLOCK_SIGOPS_COST/5 + 4};
   /** Default for -incrementalrelayfee, which sets the minimum feerate increase for mempool limiting or replacement **/
   static constexpr unsigned int DEFAULT_INCREMENTAL_RELAY_FEE{1000};
   /** Default for -bytespersigop */
  diff --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](https://github.com/bitcoin/bips/blob/master/bip-0054.md) draft and related preparatory PRs like #32521).

ACKs for top commit:
  fjahr:
    tACK 7bc64a8859
  tapcrafter:
    tACK 7bc64a8859
  darosior:
    ACK 7bc64a8859
  instagibbs:
    crACK 7bc64a8859

Tree-SHA512: 1365409349664a76a1d46b2fa358c0d0609fb17fffdd549423d22b61749481282c928be3c2fb428725735c82d319b4279f703bde01e94e4aec14bab206abb8cf
This commit is contained in:
merge-script
2025-05-22 10:06:03 -04:00
2 changed files with 21 additions and 2 deletions

View File

@@ -30,7 +30,11 @@ from test_framework.messages import (
MAX_MONEY,
SEQUENCE_FINAL,
)
from test_framework.blocktools import create_tx_with_script, MAX_BLOCK_SIGOPS
from test_framework.blocktools import (
create_tx_with_script,
MAX_BLOCK_SIGOPS,
MAX_STANDARD_TX_SIGOPS,
)
from test_framework.script import (
CScript,
OP_0,
@@ -233,7 +237,7 @@ class InvalidOPIFConstruction(BadTxTemplate):
amount=(self.spend_avail // 2))
class TooManySigops(BadTxTemplate):
class TooManySigopsPerBlock(BadTxTemplate):
reject_reason = "bad-txns-too-many-sigops"
block_reject_reason = "bad-blk-sigops, out-of-bounds SigOpCount"
expect_disconnect = False
@@ -245,6 +249,20 @@ class TooManySigops(BadTxTemplate):
output_script=lotsa_checksigs,
amount=1)
class TooManySigopsPerTransaction(BadTxTemplate):
reject_reason = "bad-txns-too-many-sigops"
expect_disconnect = False
valid_in_block = True
def get_tx(self):
lotsa_checksigs = CScript([OP_CHECKSIG] * (MAX_STANDARD_TX_SIGOPS + 1))
return create_tx_with_script(
self.spend_tx, 0,
output_script=lotsa_checksigs,
amount=1)
def getDisabledOpcodeTemplate(opcode):
""" Creates disabled opcode tx template class"""
def get_tx(self):

View File

@@ -49,6 +49,7 @@ from .util import assert_equal
MAX_BLOCK_SIGOPS = 20000
MAX_BLOCK_SIGOPS_WEIGHT = MAX_BLOCK_SIGOPS * WITNESS_SCALE_FACTOR
MAX_STANDARD_TX_SIGOPS = 4000
MAX_STANDARD_TX_WEIGHT = 400000
# Genesis block time (regtest)