mempool_accept.py
1 #!/usr/bin/env python3 2 # Copyright (c) 2017-2022 The Bitcoin Core developers 3 # Distributed under the MIT software license, see the accompanying 4 # file COPYING or http://www.opensource.org/licenses/mit-license.php. 5 """Test mempool acceptance of raw transactions.""" 6 7 from copy import deepcopy 8 from decimal import Decimal 9 import math 10 11 from test_framework.test_framework import BitcoinTestFramework 12 from test_framework.messages import ( 13 MAX_BIP125_RBF_SEQUENCE, 14 COIN, 15 COutPoint, 16 CTransaction, 17 CTxIn, 18 CTxInWitness, 19 CTxOut, 20 MAX_BLOCK_WEIGHT, 21 WITNESS_SCALE_FACTOR, 22 MAX_MONEY, 23 SEQUENCE_FINAL, 24 tx_from_hex, 25 ) 26 from test_framework.script import ( 27 CScript, 28 OP_0, 29 OP_HASH160, 30 OP_RETURN, 31 OP_TRUE, 32 SIGHASH_ALL, 33 sign_input_legacy, 34 ) 35 from test_framework.script_util import ( 36 DUMMY_MIN_OP_RETURN_SCRIPT, 37 keys_to_multisig_script, 38 MIN_PADDING, 39 MIN_STANDARD_TX_NONWITNESS_SIZE, 40 PAY_TO_ANCHOR, 41 script_to_p2sh_script, 42 script_to_p2wsh_script, 43 ) 44 from test_framework.util import ( 45 assert_equal, 46 assert_greater_than, 47 assert_raises_rpc_error, 48 sync_txindex, 49 ) 50 from test_framework.wallet import MiniWallet 51 from test_framework.wallet_util import generate_keypair 52 53 54 class MempoolAcceptanceTest(BitcoinTestFramework): 55 def set_test_params(self): 56 self.num_nodes = 1 57 self.extra_args = [[ 58 '-txindex','-permitbaremultisig=0', 59 ]] * self.num_nodes 60 self.supports_cli = False 61 62 def check_mempool_result(self, result_expected, *args, **kwargs): 63 """Wrapper to check result of testmempoolaccept on node_0's mempool""" 64 result_test = self.nodes[0].testmempoolaccept(*args, **kwargs) 65 for r in result_test: 66 # Skip these checks for now 67 r.pop('wtxid') 68 if "fees" in r: 69 r["fees"].pop("effective-feerate") 70 r["fees"].pop("effective-includes") 71 if "reject-details" in r: 72 r.pop("reject-details") 73 assert_equal(result_expected, result_test) 74 assert_equal(self.nodes[0].getmempoolinfo()['size'], self.mempool_size) # Must not change mempool state 75 76 def run_test(self): 77 node = self.nodes[0] 78 self.wallet = MiniWallet(node) 79 80 self.log.info('Start with empty mempool, and 200 blocks') 81 self.mempool_size = 0 82 assert_equal(node.getblockcount(), 200) 83 assert_equal(node.getmempoolinfo()['size'], self.mempool_size) 84 85 self.log.info('Should not accept garbage to testmempoolaccept') 86 assert_raises_rpc_error(-3, 'JSON value of type string is not of expected type array', lambda: node.testmempoolaccept(rawtxs='ff00baar')) 87 assert_raises_rpc_error(-8, 'Array must contain between 1 and 25 transactions.', lambda: node.testmempoolaccept(rawtxs=['ff22']*26)) 88 assert_raises_rpc_error(-8, 'Array must contain between 1 and 25 transactions.', lambda: node.testmempoolaccept(rawtxs=[])) 89 assert_raises_rpc_error(-22, 'TX decode failed', lambda: node.testmempoolaccept(rawtxs=['ff00baar'])) 90 91 self.log.info('A transaction already in the blockchain') 92 tx = self.wallet.create_self_transfer()['tx'] # Pick a random coin(base) to spend 93 tx.vout.append(deepcopy(tx.vout[0])) 94 tx.vout[0].nValue = int(0.3 * COIN) 95 tx.vout[1].nValue = int(49 * COIN) 96 raw_tx_in_block = tx.serialize().hex() 97 txid_in_block = self.wallet.sendrawtransaction(from_node=node, tx_hex=raw_tx_in_block) 98 self.generate(node, 1) 99 self.mempool_size = 0 100 # Also check feerate. 1BTC/kvB fails 101 assert_raises_rpc_error(-8, "Fee rates larger than or equal to 1BTC/kvB are not accepted", lambda: self.check_mempool_result( 102 result_expected=None, 103 rawtxs=[raw_tx_in_block], 104 maxfeerate=1, 105 )) 106 # Check negative feerate 107 assert_raises_rpc_error(-3, "Amount out of range", lambda: self.check_mempool_result( 108 result_expected=None, 109 rawtxs=[raw_tx_in_block], 110 maxfeerate=-0.01, 111 )) 112 # ... 0.99 passes 113 self.check_mempool_result( 114 result_expected=[{'txid': txid_in_block, 'allowed': False, 'reject-reason': 'txn-already-known'}], 115 rawtxs=[raw_tx_in_block], 116 maxfeerate=0.99, 117 ) 118 119 self.log.info('A transaction not in the mempool') 120 fee = Decimal('0.000007') 121 utxo_to_spend = self.wallet.get_utxo(txid=txid_in_block) # use 0.3 BTC UTXO 122 tx = self.wallet.create_self_transfer(utxo_to_spend=utxo_to_spend, sequence=MAX_BIP125_RBF_SEQUENCE)['tx'] 123 tx.vout[0].nValue = int((Decimal('0.3') - fee) * COIN) 124 raw_tx_0 = tx.serialize().hex() 125 txid_0 = tx.rehash() 126 self.check_mempool_result( 127 result_expected=[{'txid': txid_0, 'allowed': True, 'vsize': tx.get_vsize(), 'fees': {'base': fee}}], 128 rawtxs=[raw_tx_0], 129 ) 130 131 self.log.info('A final transaction not in the mempool') 132 output_amount = Decimal('0.025') 133 tx = self.wallet.create_self_transfer( 134 sequence=SEQUENCE_FINAL, 135 locktime=node.getblockcount() + 2000, # Can be anything 136 )['tx'] 137 tx.vout[0].nValue = int(output_amount * COIN) 138 raw_tx_final = tx.serialize().hex() 139 tx = tx_from_hex(raw_tx_final) 140 fee_expected = Decimal('50.0') - output_amount 141 self.check_mempool_result( 142 result_expected=[{'txid': tx.rehash(), 'allowed': True, 'vsize': tx.get_vsize(), 'fees': {'base': fee_expected}}], 143 rawtxs=[tx.serialize().hex()], 144 maxfeerate=0, 145 ) 146 node.sendrawtransaction(hexstring=raw_tx_final, maxfeerate=0) 147 self.mempool_size += 1 148 149 self.log.info('A transaction in the mempool') 150 node.sendrawtransaction(hexstring=raw_tx_0) 151 self.mempool_size += 1 152 self.check_mempool_result( 153 result_expected=[{'txid': txid_0, 'allowed': False, 'reject-reason': 'txn-already-in-mempool'}], 154 rawtxs=[raw_tx_0], 155 ) 156 157 self.log.info('A transaction that replaces a mempool transaction') 158 tx = tx_from_hex(raw_tx_0) 159 tx.vout[0].nValue -= int(fee * COIN) # Double the fee 160 raw_tx_0 = tx.serialize().hex() 161 txid_0 = tx.rehash() 162 self.check_mempool_result( 163 result_expected=[{'txid': txid_0, 'allowed': True, 'vsize': tx.get_vsize(), 'fees': {'base': (2 * fee)}}], 164 rawtxs=[raw_tx_0], 165 ) 166 node.sendrawtransaction(hexstring=tx.serialize().hex(), maxfeerate=0) 167 168 self.log.info('A transaction with missing inputs, that never existed') 169 tx = tx_from_hex(raw_tx_0) 170 tx.vin[0].prevout = COutPoint(hash=int('ff' * 32, 16), n=14) 171 self.check_mempool_result( 172 result_expected=[{'txid': tx.rehash(), 'allowed': False, 'reject-reason': 'missing-inputs'}], 173 rawtxs=[tx.serialize().hex()], 174 ) 175 176 self.log.info('A transaction with missing inputs, that existed once in the past') 177 tx = tx_from_hex(raw_tx_0) 178 tx.vin[0].prevout.n = 1 # Set vout to 1, to spend the other outpoint (49 coins) of the in-chain-tx we want to double spend 179 raw_tx_1 = tx.serialize().hex() 180 txid_1 = node.sendrawtransaction(hexstring=raw_tx_1, maxfeerate=0) 181 # Now spend both to "clearly hide" the outputs, ie. remove the coins from the utxo set by spending them 182 tx = self.wallet.create_self_transfer()['tx'] 183 tx.vin.append(deepcopy(tx.vin[0])) 184 tx.wit.vtxinwit.append(deepcopy(tx.wit.vtxinwit[0])) 185 tx.vin[0].prevout = COutPoint(hash=int(txid_0, 16), n=0) 186 tx.vin[1].prevout = COutPoint(hash=int(txid_1, 16), n=0) 187 tx.vout[0].nValue = int(0.1 * COIN) 188 raw_tx_spend_both = tx.serialize().hex() 189 txid_spend_both = self.wallet.sendrawtransaction(from_node=node, tx_hex=raw_tx_spend_both) 190 self.generate(node, 1) 191 self.mempool_size = 0 192 # Now see if we can add the coins back to the utxo set by sending the exact txs again 193 self.check_mempool_result( 194 result_expected=[{'txid': txid_0, 'allowed': False, 'reject-reason': 'missing-inputs'}], 195 rawtxs=[raw_tx_0], 196 ) 197 self.check_mempool_result( 198 result_expected=[{'txid': txid_1, 'allowed': False, 'reject-reason': 'missing-inputs'}], 199 rawtxs=[raw_tx_1], 200 ) 201 202 self.log.info('Create a "reference" tx for later use') 203 utxo_to_spend = self.wallet.get_utxo(txid=txid_spend_both) 204 tx = self.wallet.create_self_transfer(utxo_to_spend=utxo_to_spend, sequence=SEQUENCE_FINAL)['tx'] 205 tx.vout[0].nValue = int(0.05 * COIN) 206 raw_tx_reference = tx.serialize().hex() 207 # Reference tx should be valid on itself 208 self.check_mempool_result( 209 result_expected=[{'txid': tx.rehash(), 'allowed': True, 'vsize': tx.get_vsize(), 'fees': { 'base': Decimal('0.1') - Decimal('0.05')}}], 210 rawtxs=[tx.serialize().hex()], 211 maxfeerate=0, 212 ) 213 214 self.log.info('A transaction with no outputs') 215 tx = tx_from_hex(raw_tx_reference) 216 tx.vout = [] 217 self.check_mempool_result( 218 result_expected=[{'txid': tx.rehash(), 'allowed': False, 'reject-reason': 'bad-txns-vout-empty'}], 219 rawtxs=[tx.serialize().hex()], 220 ) 221 222 self.log.info('A really large transaction') 223 tx = tx_from_hex(raw_tx_reference) 224 tx.vin = [tx.vin[0]] * math.ceil((MAX_BLOCK_WEIGHT // WITNESS_SCALE_FACTOR) / len(tx.vin[0].serialize())) 225 self.check_mempool_result( 226 result_expected=[{'txid': tx.rehash(), 'allowed': False, 'reject-reason': 'bad-txns-oversize'}], 227 rawtxs=[tx.serialize().hex()], 228 ) 229 230 self.log.info('A transaction with negative output value') 231 tx = tx_from_hex(raw_tx_reference) 232 tx.vout[0].nValue *= -1 233 self.check_mempool_result( 234 result_expected=[{'txid': tx.rehash(), 'allowed': False, 'reject-reason': 'bad-txns-vout-negative'}], 235 rawtxs=[tx.serialize().hex()], 236 ) 237 238 # The following two validations prevent overflow of the output amounts (see CVE-2010-5139). 239 self.log.info('A transaction with too large output value') 240 tx = tx_from_hex(raw_tx_reference) 241 tx.vout[0].nValue = MAX_MONEY + 1 242 self.check_mempool_result( 243 result_expected=[{'txid': tx.rehash(), 'allowed': False, 'reject-reason': 'bad-txns-vout-toolarge'}], 244 rawtxs=[tx.serialize().hex()], 245 ) 246 247 self.log.info('A transaction with too large sum of output values') 248 tx = tx_from_hex(raw_tx_reference) 249 tx.vout = [tx.vout[0]] * 2 250 tx.vout[0].nValue = MAX_MONEY 251 self.check_mempool_result( 252 result_expected=[{'txid': tx.rehash(), 'allowed': False, 'reject-reason': 'bad-txns-txouttotal-toolarge'}], 253 rawtxs=[tx.serialize().hex()], 254 ) 255 256 self.log.info('A transaction with duplicate inputs') 257 tx = tx_from_hex(raw_tx_reference) 258 tx.vin = [tx.vin[0]] * 2 259 self.check_mempool_result( 260 result_expected=[{'txid': tx.rehash(), 'allowed': False, 'reject-reason': 'bad-txns-inputs-duplicate'}], 261 rawtxs=[tx.serialize().hex()], 262 ) 263 264 self.log.info('A non-coinbase transaction with coinbase-like outpoint') 265 tx = tx_from_hex(raw_tx_reference) 266 tx.vin.append(CTxIn(COutPoint(hash=0, n=0xffffffff))) 267 self.check_mempool_result( 268 result_expected=[{'txid': tx.rehash(), 'allowed': False, 'reject-reason': 'bad-txns-prevout-null'}], 269 rawtxs=[tx.serialize().hex()], 270 ) 271 272 self.log.info('A coinbase transaction') 273 # Pick the input of the first tx we created, so it has to be a coinbase tx 274 sync_txindex(self, node) 275 raw_tx_coinbase_spent = node.getrawtransaction(txid=node.decoderawtransaction(hexstring=raw_tx_in_block)['vin'][0]['txid']) 276 tx = tx_from_hex(raw_tx_coinbase_spent) 277 self.check_mempool_result( 278 result_expected=[{'txid': tx.rehash(), 'allowed': False, 'reject-reason': 'coinbase'}], 279 rawtxs=[tx.serialize().hex()], 280 ) 281 282 self.log.info('Some nonstandard transactions') 283 tx = tx_from_hex(raw_tx_reference) 284 tx.version = 4 # A version currently non-standard 285 self.check_mempool_result( 286 result_expected=[{'txid': tx.rehash(), 'allowed': False, 'reject-reason': 'version'}], 287 rawtxs=[tx.serialize().hex()], 288 ) 289 tx = tx_from_hex(raw_tx_reference) 290 tx.vout[0].scriptPubKey = CScript([OP_0]) # Some non-standard script 291 self.check_mempool_result( 292 result_expected=[{'txid': tx.rehash(), 'allowed': False, 'reject-reason': 'scriptpubkey'}], 293 rawtxs=[tx.serialize().hex()], 294 ) 295 tx = tx_from_hex(raw_tx_reference) 296 _, pubkey = generate_keypair() 297 tx.vout[0].scriptPubKey = keys_to_multisig_script([pubkey] * 3, k=2) # Some bare multisig script (2-of-3) 298 self.check_mempool_result( 299 result_expected=[{'txid': tx.rehash(), 'allowed': False, 'reject-reason': 'bare-multisig'}], 300 rawtxs=[tx.serialize().hex()], 301 ) 302 tx = tx_from_hex(raw_tx_reference) 303 tx.vin[0].scriptSig = CScript([OP_HASH160]) # Some not-pushonly scriptSig 304 self.check_mempool_result( 305 result_expected=[{'txid': tx.rehash(), 'allowed': False, 'reject-reason': 'scriptsig-not-pushonly'}], 306 rawtxs=[tx.serialize().hex()], 307 ) 308 tx = tx_from_hex(raw_tx_reference) 309 tx.vin[0].scriptSig = CScript([b'a' * 1648]) # Some too large scriptSig (>1650 bytes) 310 self.check_mempool_result( 311 result_expected=[{'txid': tx.rehash(), 'allowed': False, 'reject-reason': 'scriptsig-size'}], 312 rawtxs=[tx.serialize().hex()], 313 ) 314 tx = tx_from_hex(raw_tx_reference) 315 output_p2sh_burn = CTxOut(nValue=540, scriptPubKey=script_to_p2sh_script(b'burn')) 316 num_scripts = 100000 // len(output_p2sh_burn.serialize()) # Use enough outputs to make the tx too large for our policy 317 tx.vout = [output_p2sh_burn] * num_scripts 318 self.check_mempool_result( 319 result_expected=[{'txid': tx.rehash(), 'allowed': False, 'reject-reason': 'tx-size'}], 320 rawtxs=[tx.serialize().hex()], 321 ) 322 tx = tx_from_hex(raw_tx_reference) 323 tx.vout[0] = output_p2sh_burn 324 tx.vout[0].nValue -= 1 # Make output smaller, such that it is dust for our policy 325 self.check_mempool_result( 326 result_expected=[{'txid': tx.rehash(), 'allowed': False, 'reject-reason': 'dust'}], 327 rawtxs=[tx.serialize().hex()], 328 ) 329 tx = tx_from_hex(raw_tx_reference) 330 tx.vout[0].scriptPubKey = CScript([OP_RETURN, b'\xff']) 331 tx.vout = [tx.vout[0]] * 2 332 self.check_mempool_result( 333 result_expected=[{'txid': tx.rehash(), 'allowed': False, 'reject-reason': 'multi-op-return'}], 334 rawtxs=[tx.serialize().hex()], 335 ) 336 337 self.log.info('A timelocked transaction') 338 tx = tx_from_hex(raw_tx_reference) 339 tx.vin[0].nSequence -= 1 # Should be non-max, so locktime is not ignored 340 tx.nLockTime = node.getblockcount() + 1 341 self.check_mempool_result( 342 result_expected=[{'txid': tx.rehash(), 'allowed': False, 'reject-reason': 'non-final'}], 343 rawtxs=[tx.serialize().hex()], 344 ) 345 346 self.log.info('A transaction that is locked by BIP68 sequence logic') 347 tx = tx_from_hex(raw_tx_reference) 348 tx.vin[0].nSequence = 2 # We could include it in the second block mined from now, but not the very next one 349 self.check_mempool_result( 350 result_expected=[{'txid': tx.rehash(), 'allowed': False, 'reject-reason': 'non-BIP68-final'}], 351 rawtxs=[tx.serialize().hex()], 352 maxfeerate=0, 353 ) 354 355 # Prep for tiny-tx tests with wsh(OP_TRUE) output 356 seed_tx = self.wallet.send_to(from_node=node, scriptPubKey=script_to_p2wsh_script(CScript([OP_TRUE])), amount=COIN) 357 self.generate(node, 1) 358 359 self.log.info('A tiny transaction(in non-witness bytes) that is disallowed') 360 tx = CTransaction() 361 tx.vin.append(CTxIn(COutPoint(int(seed_tx["txid"], 16), seed_tx["sent_vout"]), b"", SEQUENCE_FINAL)) 362 tx.wit.vtxinwit = [CTxInWitness()] 363 tx.wit.vtxinwit[0].scriptWitness.stack = [CScript([OP_TRUE])] 364 tx.vout.append(CTxOut(0, CScript([OP_RETURN] + ([OP_0] * (MIN_PADDING - 2))))) 365 # Note it's only non-witness size that matters! 366 assert_equal(len(tx.serialize_without_witness()), 64) 367 assert_equal(MIN_STANDARD_TX_NONWITNESS_SIZE - 1, 64) 368 assert_greater_than(len(tx.serialize()), 64) 369 370 self.check_mempool_result( 371 result_expected=[{'txid': tx.rehash(), 'allowed': False, 'reject-reason': 'tx-size-small'}], 372 rawtxs=[tx.serialize().hex()], 373 maxfeerate=0, 374 ) 375 376 self.log.info('Minimally-small transaction(in non-witness bytes) that is allowed') 377 tx.vout[0] = CTxOut(COIN - 1000, DUMMY_MIN_OP_RETURN_SCRIPT) 378 assert_equal(len(tx.serialize_without_witness()), MIN_STANDARD_TX_NONWITNESS_SIZE) 379 self.check_mempool_result( 380 result_expected=[{'txid': tx.rehash(), 'allowed': True, 'vsize': tx.get_vsize(), 'fees': { 'base': Decimal('0.00001000')}}], 381 rawtxs=[tx.serialize().hex()], 382 maxfeerate=0, 383 ) 384 385 self.log.info('OP_1 <0x4e73> is able to be created and spent') 386 anchor_value = 10000 387 create_anchor_tx = self.wallet.send_to(from_node=node, scriptPubKey=PAY_TO_ANCHOR, amount=anchor_value) 388 self.generate(node, 1) 389 390 # First spend has non-empty witness, will be rejected to prevent third party wtxid malleability 391 anchor_nonempty_wit_spend = CTransaction() 392 anchor_nonempty_wit_spend.vin.append(CTxIn(COutPoint(int(create_anchor_tx["txid"], 16), create_anchor_tx["sent_vout"]), b"")) 393 anchor_nonempty_wit_spend.vout.append(CTxOut(anchor_value - int(fee*COIN), script_to_p2wsh_script(CScript([OP_TRUE])))) 394 anchor_nonempty_wit_spend.wit.vtxinwit.append(CTxInWitness()) 395 anchor_nonempty_wit_spend.wit.vtxinwit[0].scriptWitness.stack.append(b"f") 396 anchor_nonempty_wit_spend.rehash() 397 398 self.check_mempool_result( 399 result_expected=[{'txid': anchor_nonempty_wit_spend.rehash(), 'allowed': False, 'reject-reason': 'bad-witness-nonstandard'}], 400 rawtxs=[anchor_nonempty_wit_spend.serialize().hex()], 401 maxfeerate=0, 402 ) 403 404 # but is consensus-legal 405 self.generateblock(node, self.wallet.get_address(), [anchor_nonempty_wit_spend.serialize().hex()]) 406 407 # Without witness elements it is standard 408 create_anchor_tx = self.wallet.send_to(from_node=node, scriptPubKey=PAY_TO_ANCHOR, amount=anchor_value) 409 self.generate(node, 1) 410 411 anchor_spend = CTransaction() 412 anchor_spend.vin.append(CTxIn(COutPoint(int(create_anchor_tx["txid"], 16), create_anchor_tx["sent_vout"]), b"")) 413 anchor_spend.vout.append(CTxOut(anchor_value - int(fee*COIN), script_to_p2wsh_script(CScript([OP_TRUE])))) 414 anchor_spend.wit.vtxinwit.append(CTxInWitness()) 415 # It's "segwit" but txid == wtxid since there is no witness data 416 assert_equal(anchor_spend.rehash(), anchor_spend.getwtxid()) 417 418 self.check_mempool_result( 419 result_expected=[{'txid': anchor_spend.rehash(), 'allowed': True, 'vsize': anchor_spend.get_vsize(), 'fees': { 'base': Decimal('0.00000700')}}], 420 rawtxs=[anchor_spend.serialize().hex()], 421 maxfeerate=0, 422 ) 423 424 self.log.info('But cannot be spent if nested sh()') 425 nested_anchor_tx = self.wallet.create_self_transfer(sequence=SEQUENCE_FINAL)['tx'] 426 nested_anchor_tx.vout[0].scriptPubKey = script_to_p2sh_script(PAY_TO_ANCHOR) 427 nested_anchor_tx.rehash() 428 self.generateblock(node, self.wallet.get_address(), [nested_anchor_tx.serialize().hex()]) 429 430 nested_anchor_spend = CTransaction() 431 nested_anchor_spend.vin.append(CTxIn(COutPoint(nested_anchor_tx.sha256, 0), b"")) 432 nested_anchor_spend.vin[0].scriptSig = CScript([bytes(PAY_TO_ANCHOR)]) 433 nested_anchor_spend.vout.append(CTxOut(nested_anchor_tx.vout[0].nValue - int(fee*COIN), script_to_p2wsh_script(CScript([OP_TRUE])))) 434 nested_anchor_spend.rehash() 435 436 self.check_mempool_result( 437 result_expected=[{'txid': nested_anchor_spend.rehash(), 'allowed': False, 'reject-reason': 'non-mandatory-script-verify-flag (Witness version reserved for soft-fork upgrades)'}], 438 rawtxs=[nested_anchor_spend.serialize().hex()], 439 maxfeerate=0, 440 ) 441 # but is consensus-legal 442 self.generateblock(node, self.wallet.get_address(), [nested_anchor_spend.serialize().hex()]) 443 444 self.log.info('Spending a confirmed bare multisig is okay') 445 address = self.wallet.get_address() 446 tx = tx_from_hex(raw_tx_reference) 447 privkey, pubkey = generate_keypair() 448 tx.vout[0].scriptPubKey = keys_to_multisig_script([pubkey] * 3, k=1) # Some bare multisig script (1-of-3) 449 tx.rehash() 450 self.generateblock(node, address, [tx.serialize().hex()]) 451 tx_spend = CTransaction() 452 tx_spend.vin.append(CTxIn(COutPoint(tx.sha256, 0), b"")) 453 tx_spend.vout.append(CTxOut(tx.vout[0].nValue - int(fee*COIN), script_to_p2wsh_script(CScript([OP_TRUE])))) 454 tx_spend.rehash() 455 sign_input_legacy(tx_spend, 0, tx.vout[0].scriptPubKey, privkey, sighash_type=SIGHASH_ALL) 456 tx_spend.vin[0].scriptSig = bytes(CScript([OP_0])) + tx_spend.vin[0].scriptSig 457 self.check_mempool_result( 458 result_expected=[{'txid': tx_spend.rehash(), 'allowed': True, 'vsize': tx_spend.get_vsize(), 'fees': { 'base': Decimal('0.00000700')}}], 459 rawtxs=[tx_spend.serialize().hex()], 460 maxfeerate=0, 461 ) 462 463 if __name__ == '__main__': 464 MempoolAcceptanceTest(__file__).main()