3
3
# Distributed under the MIT software license, see the accompanying
4
4
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
5
5
"""Test sigop limit mempool policy (`-bytespersigop` parameter)"""
6
+ from decimal import Decimal
6
7
from math import ceil
7
8
8
9
from test_framework .messages import (
25
26
OP_TRUE ,
26
27
)
27
28
from test_framework .script_util import (
29
+ keys_to_multisig_script ,
28
30
script_to_p2wsh_script ,
29
31
)
30
32
from test_framework .test_framework import BitcoinTestFramework
31
33
from test_framework .util import (
32
34
assert_equal ,
33
35
assert_greater_than ,
34
36
assert_greater_than_or_equal ,
37
+ assert_raises_rpc_error ,
35
38
)
36
39
from test_framework .wallet import MiniWallet
37
-
40
+ from test_framework . wallet_util import generate_keypair
38
41
39
42
DEFAULT_BYTES_PER_SIGOP = 20 # default setting
40
43
@@ -133,6 +136,45 @@ def test_sigops_limit(self, bytes_per_sigop, num_sigops):
133
136
assert_equal (entry_parent ['descendantcount' ], 2 )
134
137
assert_equal (entry_parent ['descendantsize' ], parent_tx .get_vsize () + sigop_equivalent_vsize )
135
138
139
+ def test_sigops_package (self ):
140
+ self .log .info ("Test a overly-large sigops-vbyte hits package limits" )
141
+ # Make a 2-transaction package which fails vbyte checks even though
142
+ # separately they would work.
143
+ self .restart_node (0 , extra_args = ["-bytespersigop=5000" ] + self .extra_args [0 ])
144
+
145
+ def create_bare_multisig_tx (utxo_to_spend = None ):
146
+ _ , pubkey = generate_keypair ()
147
+ amount_for_bare = 50000
148
+ tx_dict = self .wallet .create_self_transfer (fee = Decimal ("3" ), utxo_to_spend = utxo_to_spend )
149
+ tx_utxo = tx_dict ["new_utxo" ]
150
+ tx = tx_dict ["tx" ]
151
+ tx .vout .append (CTxOut (amount_for_bare , keys_to_multisig_script ([pubkey ], k = 1 )))
152
+ tx .vout [0 ].nValue -= amount_for_bare
153
+ tx_utxo ["txid" ] = tx .rehash ()
154
+ tx_utxo ["value" ] -= Decimal ("0.00005000" )
155
+ return (tx_utxo , tx )
156
+
157
+ tx_parent_utxo , tx_parent = create_bare_multisig_tx ()
158
+ tx_child_utxo , tx_child = create_bare_multisig_tx (tx_parent_utxo )
159
+
160
+ # Separately, the parent tx is ok
161
+ parent_individual_testres = self .nodes [0 ].testmempoolaccept ([tx_parent .serialize ().hex ()])[0 ]
162
+ assert parent_individual_testres ["allowed" ]
163
+ # Multisig is counted as MAX_PUBKEYS_PER_MULTISIG = 20 sigops
164
+ assert_equal (parent_individual_testres ["vsize" ], 5000 * 20 )
165
+
166
+ # But together, it's exceeding limits in the *package* context. If sigops adjusted vsize wasn't being checked
167
+ # here, it would get further in validation and give too-long-mempool-chain error instead.
168
+ packet_test = self .nodes [0 ].testmempoolaccept ([tx_parent .serialize ().hex (), tx_child .serialize ().hex ()])
169
+ assert_equal ([x ["package-error" ] for x in packet_test ], ["package-mempool-limits" , "package-mempool-limits" ])
170
+
171
+ # When we actually try to submit, the parent makes it into the mempool, but the child would exceed ancestor vsize limits
172
+ assert_raises_rpc_error (- 26 , "too-long-mempool-chain" , self .nodes [0 ].submitpackage , [tx_parent .serialize ().hex (), tx_child .serialize ().hex ()])
173
+ assert tx_parent .rehash () in self .nodes [0 ].getrawmempool ()
174
+
175
+ # Transactions are tiny in weight
176
+ assert_greater_than (2000 , tx_parent .get_weight () + tx_child .get_weight ())
177
+
136
178
def run_test (self ):
137
179
self .wallet = MiniWallet (self .nodes [0 ])
138
180
@@ -149,6 +191,8 @@ def run_test(self):
149
191
150
192
self .generate (self .wallet , 1 )
151
193
194
+ self .test_sigops_package ()
195
+
152
196
153
197
if __name__ == '__main__' :
154
198
BytesPerSigOpTest ().main ()
0 commit comments