2022-08-31 10:38:42 -04:00
#!/usr/bin/env python3
# Copyright (c) 2024 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
2024-02-12 11:55:27 -03:00
from decimal import Decimal
2022-08-31 10:38:42 -04:00
from test_framework . messages import (
MAX_BIP125_RBF_SEQUENCE ,
)
from test_framework . test_framework import BitcoinTestFramework
from test_framework . util import (
assert_equal ,
assert_greater_than ,
assert_greater_than_or_equal ,
assert_raises_rpc_error ,
)
from test_framework . wallet import (
2024-01-23 11:36:43 -03:00
COIN ,
2022-08-31 10:38:42 -04:00
DEFAULT_FEE ,
MiniWallet ,
)
2024-01-23 11:36:43 -03:00
MAX_REPLACEMENT_CANDIDATES = 100
2024-06-11 09:01:34 -04:00
TRUC_MAX_VSIZE = 10000
2024-08-26 14:00:49 -04:00
TRUC_CHILD_MAX_VSIZE = 1000
2024-01-23 11:36:43 -03:00
2022-08-31 10:38:42 -04:00
def cleanup ( extra_args = None ) :
def decorator ( func ) :
def wrapper ( self ) :
try :
if extra_args is not None :
self . restart_node ( 0 , extra_args = extra_args )
func ( self )
finally :
# Clear mempool again after test
self . generate ( self . nodes [ 0 ] , 1 )
if extra_args is not None :
self . restart_node ( 0 )
return wrapper
return decorator
2024-06-11 08:37:05 -04:00
class MempoolTRUC ( BitcoinTestFramework ) :
2022-08-31 10:38:42 -04:00
def set_test_params ( self ) :
self . num_nodes = 1
2024-02-27 19:16:51 -03:00
self . extra_args = [ [ ] ]
2022-08-31 10:38:42 -04:00
self . setup_clean_chain = True
def check_mempool ( self , txids ) :
""" Assert exact contents of the node ' s mempool (by txid). """
mempool_contents = self . nodes [ 0 ] . getrawmempool ( )
assert_equal ( len ( txids ) , len ( mempool_contents ) )
assert all ( [ txid in txids for txid in mempool_contents ] )
2024-02-27 19:16:51 -03:00
@cleanup ( extra_args = [ " -datacarriersize=20000 " ] )
2024-06-11 08:37:05 -04:00
def test_truc_max_vsize ( self ) :
2024-04-15 06:45:15 -04:00
node = self . nodes [ 0 ]
2024-06-11 08:37:05 -04:00
self . log . info ( " Test TRUC-specific maximum transaction vsize " )
2024-08-26 13:35:00 -04:00
tx_v3_heavy = self . wallet . create_self_transfer ( target_vsize = TRUC_MAX_VSIZE + 1 , version = 3 )
2024-06-11 09:01:34 -04:00
assert_greater_than_or_equal ( tx_v3_heavy [ " tx " ] . get_vsize ( ) , TRUC_MAX_VSIZE )
2024-07-02 06:56:13 -04:00
expected_error_heavy = f " TRUC-violation, version=3 tx { tx_v3_heavy [ ' txid ' ] } (wtxid= { tx_v3_heavy [ ' wtxid ' ] } ) is too big "
2024-04-15 06:45:15 -04:00
assert_raises_rpc_error ( - 26 , expected_error_heavy , node . sendrawtransaction , tx_v3_heavy [ " hex " ] )
self . check_mempool ( [ ] )
2024-06-11 08:37:05 -04:00
# Ensure we are hitting the TRUC-specific limit and not something else
2024-08-26 13:35:00 -04:00
tx_v2_heavy = self . wallet . send_self_transfer ( from_node = node , target_vsize = TRUC_MAX_VSIZE + 1 , version = 2 )
2024-04-15 06:45:15 -04:00
self . check_mempool ( [ tx_v2_heavy [ " txid " ] ] )
2024-02-27 19:16:51 -03:00
@cleanup ( extra_args = [ " -datacarriersize=1000 " ] )
2024-06-11 08:37:05 -04:00
def test_truc_acceptance ( self ) :
2022-08-31 10:38:42 -04:00
node = self . nodes [ 0 ]
2024-06-11 08:37:05 -04:00
self . log . info ( " Test a child of a TRUC transaction cannot be more than 1000vB " )
2022-08-31 10:38:42 -04:00
tx_v3_parent_normal = self . wallet . send_self_transfer ( from_node = node , version = 3 )
self . check_mempool ( [ tx_v3_parent_normal [ " txid " ] ] )
tx_v3_child_heavy = self . wallet . create_self_transfer (
utxo_to_spend = tx_v3_parent_normal [ " new_utxo " ] ,
2024-08-26 14:00:49 -04:00
target_vsize = TRUC_CHILD_MAX_VSIZE + 1 ,
2022-08-31 10:38:42 -04:00
version = 3
)
2024-08-26 14:00:49 -04:00
assert_greater_than_or_equal ( tx_v3_child_heavy [ " tx " ] . get_vsize ( ) , TRUC_CHILD_MAX_VSIZE )
2024-07-02 06:56:13 -04:00
expected_error_child_heavy = f " TRUC-violation, version=3 child tx { tx_v3_child_heavy [ ' txid ' ] } (wtxid= { tx_v3_child_heavy [ ' wtxid ' ] } ) is too big "
2022-08-31 10:38:42 -04:00
assert_raises_rpc_error ( - 26 , expected_error_child_heavy , node . sendrawtransaction , tx_v3_child_heavy [ " hex " ] )
self . check_mempool ( [ tx_v3_parent_normal [ " txid " ] ] )
# tx has no descendants
assert_equal ( node . getmempoolentry ( tx_v3_parent_normal [ " txid " ] ) [ " descendantcount " ] , 1 )
2024-06-11 08:37:05 -04:00
self . log . info ( " Test that, during replacements, only the new transaction counts for TRUC descendant limit " )
2022-08-31 10:38:42 -04:00
tx_v3_child_almost_heavy = self . wallet . send_self_transfer (
from_node = node ,
fee_rate = DEFAULT_FEE ,
utxo_to_spend = tx_v3_parent_normal [ " new_utxo " ] ,
2024-08-26 14:00:49 -04:00
target_vsize = TRUC_CHILD_MAX_VSIZE - 3 ,
2022-08-31 10:38:42 -04:00
version = 3
)
2024-08-26 14:00:49 -04:00
assert_greater_than_or_equal ( TRUC_CHILD_MAX_VSIZE , tx_v3_child_almost_heavy [ " tx " ] . get_vsize ( ) )
2022-08-31 10:38:42 -04:00
self . check_mempool ( [ tx_v3_parent_normal [ " txid " ] , tx_v3_child_almost_heavy [ " txid " ] ] )
assert_equal ( node . getmempoolentry ( tx_v3_parent_normal [ " txid " ] ) [ " descendantcount " ] , 2 )
tx_v3_child_almost_heavy_rbf = self . wallet . send_self_transfer (
from_node = node ,
fee_rate = DEFAULT_FEE * 2 ,
utxo_to_spend = tx_v3_parent_normal [ " new_utxo " ] ,
2024-08-26 13:35:00 -04:00
target_vsize = 875 ,
2022-08-31 10:38:42 -04:00
version = 3
)
2024-08-26 14:00:49 -04:00
assert_greater_than_or_equal ( tx_v3_child_almost_heavy [ " tx " ] . get_vsize ( ) + tx_v3_child_almost_heavy_rbf [ " tx " ] . get_vsize ( ) ,
TRUC_CHILD_MAX_VSIZE )
2022-08-31 10:38:42 -04:00
self . check_mempool ( [ tx_v3_parent_normal [ " txid " ] , tx_v3_child_almost_heavy_rbf [ " txid " ] ] )
assert_equal ( node . getmempoolentry ( tx_v3_parent_normal [ " txid " ] ) [ " descendantcount " ] , 2 )
2024-02-27 19:16:51 -03:00
@cleanup ( extra_args = None )
2024-06-11 08:37:05 -04:00
def test_truc_replacement ( self ) :
2022-08-31 10:38:42 -04:00
node = self . nodes [ 0 ]
2024-06-11 08:37:05 -04:00
self . log . info ( " Test TRUC transactions may be replaced by TRUC transactions " )
2022-08-31 10:38:42 -04:00
utxo_v3_bip125 = self . wallet . get_utxo ( )
tx_v3_bip125 = self . wallet . send_self_transfer (
from_node = node ,
fee_rate = DEFAULT_FEE ,
utxo_to_spend = utxo_v3_bip125 ,
sequence = MAX_BIP125_RBF_SEQUENCE ,
version = 3
)
self . check_mempool ( [ tx_v3_bip125 [ " txid " ] ] )
tx_v3_bip125_rbf = self . wallet . send_self_transfer (
from_node = node ,
fee_rate = DEFAULT_FEE * 2 ,
utxo_to_spend = utxo_v3_bip125 ,
version = 3
)
self . check_mempool ( [ tx_v3_bip125_rbf [ " txid " ] ] )
2024-06-11 08:37:05 -04:00
self . log . info ( " Test TRUC transactions may be replaced by non-TRUC (BIP125) transactions " )
2022-08-31 10:38:42 -04:00
tx_v3_bip125_rbf_v2 = self . wallet . send_self_transfer (
from_node = node ,
fee_rate = DEFAULT_FEE * 3 ,
utxo_to_spend = utxo_v3_bip125 ,
version = 2
)
self . check_mempool ( [ tx_v3_bip125_rbf_v2 [ " txid " ] ] )
2024-06-11 08:37:05 -04:00
self . log . info ( " Test that replacements cannot cause violation of inherited TRUC " )
2022-08-31 10:38:42 -04:00
utxo_v3_parent = self . wallet . get_utxo ( )
tx_v3_parent = self . wallet . send_self_transfer (
from_node = node ,
fee_rate = DEFAULT_FEE ,
utxo_to_spend = utxo_v3_parent ,
version = 3
)
tx_v3_child = self . wallet . send_self_transfer (
from_node = node ,
fee_rate = DEFAULT_FEE ,
utxo_to_spend = tx_v3_parent [ " new_utxo " ] ,
version = 3
)
self . check_mempool ( [ tx_v3_bip125_rbf_v2 [ " txid " ] , tx_v3_parent [ " txid " ] , tx_v3_child [ " txid " ] ] )
tx_v3_child_rbf_v2 = self . wallet . create_self_transfer (
fee_rate = DEFAULT_FEE * 2 ,
utxo_to_spend = tx_v3_parent [ " new_utxo " ] ,
version = 2
)
2024-07-02 06:56:13 -04:00
expected_error_v2_v3 = f " TRUC-violation, non-version=3 tx { tx_v3_child_rbf_v2 [ ' txid ' ] } (wtxid= { tx_v3_child_rbf_v2 [ ' wtxid ' ] } ) cannot spend from version=3 tx { tx_v3_parent [ ' txid ' ] } (wtxid= { tx_v3_parent [ ' wtxid ' ] } ) "
2022-08-31 10:38:42 -04:00
assert_raises_rpc_error ( - 26 , expected_error_v2_v3 , node . sendrawtransaction , tx_v3_child_rbf_v2 [ " hex " ] )
self . check_mempool ( [ tx_v3_bip125_rbf_v2 [ " txid " ] , tx_v3_parent [ " txid " ] , tx_v3_child [ " txid " ] ] )
2023-08-04 09:56:04 -04:00
@cleanup ( extra_args = [ " -mempoolfullrbf=0 " ] )
2024-06-11 08:37:05 -04:00
def test_truc_bip125 ( self ) :
2022-08-31 10:38:42 -04:00
node = self . nodes [ 0 ]
2024-06-11 08:37:05 -04:00
self . log . info ( " Test TRUC transactions that don ' t signal BIP125 are replaceable " )
2022-08-31 10:38:42 -04:00
assert_equal ( node . getmempoolinfo ( ) [ " fullrbf " ] , False )
utxo_v3_no_bip125 = self . wallet . get_utxo ( )
tx_v3_no_bip125 = self . wallet . send_self_transfer (
from_node = node ,
fee_rate = DEFAULT_FEE ,
utxo_to_spend = utxo_v3_no_bip125 ,
sequence = MAX_BIP125_RBF_SEQUENCE + 1 ,
version = 3
)
self . check_mempool ( [ tx_v3_no_bip125 [ " txid " ] ] )
assert not node . getmempoolentry ( tx_v3_no_bip125 [ " txid " ] ) [ " bip125-replaceable " ]
tx_v3_no_bip125_rbf = self . wallet . send_self_transfer (
from_node = node ,
fee_rate = DEFAULT_FEE * 2 ,
utxo_to_spend = utxo_v3_no_bip125 ,
version = 3
)
self . check_mempool ( [ tx_v3_no_bip125_rbf [ " txid " ] ] )
2024-02-27 19:16:51 -03:00
@cleanup ( extra_args = [ " -datacarriersize=40000 " ] )
2024-06-11 08:37:05 -04:00
def test_truc_reorg ( self ) :
2022-08-31 10:38:42 -04:00
node = self . nodes [ 0 ]
2024-06-11 08:37:05 -04:00
self . log . info ( " Test that, during a reorg, TRUC rules are not enforced " )
2022-08-31 10:38:42 -04:00
tx_v2_block = self . wallet . send_self_transfer ( from_node = node , version = 2 )
tx_v3_block = self . wallet . send_self_transfer ( from_node = node , version = 3 )
tx_v3_block2 = self . wallet . send_self_transfer ( from_node = node , version = 3 )
self . check_mempool ( [ tx_v3_block [ " txid " ] , tx_v2_block [ " txid " ] , tx_v3_block2 [ " txid " ] ] )
block = self . generate ( node , 1 )
self . check_mempool ( [ ] )
tx_v2_from_v3 = self . wallet . send_self_transfer ( from_node = node , utxo_to_spend = tx_v3_block [ " new_utxo " ] , version = 2 )
tx_v3_from_v2 = self . wallet . send_self_transfer ( from_node = node , utxo_to_spend = tx_v2_block [ " new_utxo " ] , version = 3 )
2024-08-26 13:35:00 -04:00
tx_v3_child_large = self . wallet . send_self_transfer ( from_node = node , utxo_to_spend = tx_v3_block2 [ " new_utxo " ] , target_vsize = 1250 , version = 3 )
2024-08-26 14:00:49 -04:00
assert_greater_than ( node . getmempoolentry ( tx_v3_child_large [ " txid " ] ) [ " vsize " ] , TRUC_CHILD_MAX_VSIZE )
2022-08-31 10:38:42 -04:00
self . check_mempool ( [ tx_v2_from_v3 [ " txid " ] , tx_v3_from_v2 [ " txid " ] , tx_v3_child_large [ " txid " ] ] )
node . invalidateblock ( block [ 0 ] )
self . check_mempool ( [ tx_v3_block [ " txid " ] , tx_v2_block [ " txid " ] , tx_v3_block2 [ " txid " ] , tx_v2_from_v3 [ " txid " ] , tx_v3_from_v2 [ " txid " ] , tx_v3_child_large [ " txid " ] ] )
# This is needed because generate() will create the exact same block again.
node . reconsiderblock ( block [ 0 ] )
2024-02-27 19:16:51 -03:00
@cleanup ( extra_args = [ " -limitdescendantsize=10 " , " -datacarriersize=40000 " ] )
2022-08-31 10:38:42 -04:00
def test_nondefault_package_limits ( self ) :
"""
2024-06-11 08:37:05 -04:00
Max standard tx size + TRUC rules imply the ancestor / descendant rules ( at their default
2022-08-31 10:38:42 -04:00
values ) , but those checks must not be skipped . Ensure both sets of checks are done by
changing the ancestor / descendant limit configurations .
"""
node = self . nodes [ 0 ]
2024-06-11 08:37:05 -04:00
self . log . info ( " Test that a decreased limitdescendantsize also applies to TRUC child " )
2024-08-26 13:35:00 -04:00
parent_target_vsize = 9990
child_target_vsize = 500
2024-04-15 06:45:15 -04:00
tx_v3_parent_large1 = self . wallet . send_self_transfer (
from_node = node ,
2024-08-26 13:35:00 -04:00
target_vsize = parent_target_vsize ,
2024-04-15 06:45:15 -04:00
version = 3
)
tx_v3_child_large1 = self . wallet . create_self_transfer (
utxo_to_spend = tx_v3_parent_large1 [ " new_utxo " ] ,
2024-08-26 13:35:00 -04:00
target_vsize = child_target_vsize ,
2024-04-15 06:45:15 -04:00
version = 3
)
# Parent and child are within v3 limits, but parent's 10kvB descendant limit is exceeded
2024-06-11 09:01:34 -04:00
assert_greater_than_or_equal ( TRUC_MAX_VSIZE , tx_v3_parent_large1 [ " tx " ] . get_vsize ( ) )
2024-08-26 14:00:49 -04:00
assert_greater_than_or_equal ( TRUC_CHILD_MAX_VSIZE , tx_v3_child_large1 [ " tx " ] . get_vsize ( ) )
2024-04-15 06:45:15 -04:00
assert_greater_than ( tx_v3_parent_large1 [ " tx " ] . get_vsize ( ) + tx_v3_child_large1 [ " tx " ] . get_vsize ( ) , 10000 )
2022-08-31 10:38:42 -04:00
assert_raises_rpc_error ( - 26 , f " too-long-mempool-chain, exceeds descendant size limit for tx { tx_v3_parent_large1 [ ' txid ' ] } " , node . sendrawtransaction , tx_v3_child_large1 [ " hex " ] )
self . check_mempool ( [ tx_v3_parent_large1 [ " txid " ] ] )
assert_equal ( node . getmempoolentry ( tx_v3_parent_large1 [ " txid " ] ) [ " descendantcount " ] , 1 )
self . generate ( node , 1 )
self . log . info ( " Test that a decreased limitancestorsize also applies to v3 parent " )
2024-02-27 19:16:51 -03:00
self . restart_node ( 0 , extra_args = [ " -limitancestorsize=10 " , " -datacarriersize=40000 " ] )
2024-04-15 06:45:15 -04:00
tx_v3_parent_large2 = self . wallet . send_self_transfer (
from_node = node ,
2024-08-26 13:35:00 -04:00
target_vsize = parent_target_vsize ,
2024-04-15 06:45:15 -04:00
version = 3
)
tx_v3_child_large2 = self . wallet . create_self_transfer (
utxo_to_spend = tx_v3_parent_large2 [ " new_utxo " ] ,
2024-08-26 13:35:00 -04:00
target_vsize = child_target_vsize ,
2024-04-15 06:45:15 -04:00
version = 3
)
2024-06-11 08:37:05 -04:00
# Parent and child are within TRUC limits
2024-06-11 09:01:34 -04:00
assert_greater_than_or_equal ( TRUC_MAX_VSIZE , tx_v3_parent_large2 [ " tx " ] . get_vsize ( ) )
2024-08-26 14:00:49 -04:00
assert_greater_than_or_equal ( TRUC_CHILD_MAX_VSIZE , tx_v3_child_large2 [ " tx " ] . get_vsize ( ) )
2024-04-15 06:45:15 -04:00
assert_greater_than ( tx_v3_parent_large2 [ " tx " ] . get_vsize ( ) + tx_v3_child_large2 [ " tx " ] . get_vsize ( ) , 10000 )
2022-08-31 10:38:42 -04:00
assert_raises_rpc_error ( - 26 , f " too-long-mempool-chain, exceeds ancestor size limit " , node . sendrawtransaction , tx_v3_child_large2 [ " hex " ] )
self . check_mempool ( [ tx_v3_parent_large2 [ " txid " ] ] )
2024-02-27 19:16:51 -03:00
@cleanup ( extra_args = [ " -datacarriersize=1000 " ] )
2024-06-11 08:37:05 -04:00
def test_truc_ancestors_package ( self ) :
self . log . info ( " Test that TRUC ancestor limits are checked within the package " )
2022-08-31 10:38:42 -04:00
node = self . nodes [ 0 ]
tx_v3_parent_normal = self . wallet . create_self_transfer (
fee_rate = 0 ,
2024-08-26 13:35:00 -04:00
target_vsize = 1001 ,
2022-08-31 10:38:42 -04:00
version = 3
)
tx_v3_parent_2_normal = self . wallet . create_self_transfer (
fee_rate = 0 ,
2024-08-26 13:35:00 -04:00
target_vsize = 1001 ,
2022-08-31 10:38:42 -04:00
version = 3
)
tx_v3_child_multiparent = self . wallet . create_self_transfer_multi (
utxos_to_spend = [ tx_v3_parent_normal [ " new_utxo " ] , tx_v3_parent_2_normal [ " new_utxo " ] ] ,
fee_per_output = 10000 ,
version = 3
)
tx_v3_child_heavy = self . wallet . create_self_transfer_multi (
utxos_to_spend = [ tx_v3_parent_normal [ " new_utxo " ] ] ,
2024-08-26 14:00:49 -04:00
target_vsize = TRUC_CHILD_MAX_VSIZE + 1 ,
2022-08-31 10:38:42 -04:00
fee_per_output = 10000 ,
version = 3
)
self . check_mempool ( [ ] )
result = node . submitpackage ( [ tx_v3_parent_normal [ " hex " ] , tx_v3_parent_2_normal [ " hex " ] , tx_v3_child_multiparent [ " hex " ] ] )
2024-06-11 08:37:05 -04:00
assert_equal ( result [ ' package_msg ' ] , f " TRUC-violation, tx { tx_v3_child_multiparent [ ' txid ' ] } (wtxid= { tx_v3_child_multiparent [ ' wtxid ' ] } ) would have too many ancestors " )
2022-08-31 10:38:42 -04:00
self . check_mempool ( [ ] )
self . check_mempool ( [ ] )
result = node . submitpackage ( [ tx_v3_parent_normal [ " hex " ] , tx_v3_child_heavy [ " hex " ] ] )
2024-08-26 13:35:00 -04:00
# tx_v3_child_heavy is heavy based on vsize, not sigops.
2024-07-02 06:56:13 -04:00
assert_equal ( result [ ' package_msg ' ] , f " TRUC-violation, version=3 child tx { tx_v3_child_heavy [ ' txid ' ] } (wtxid= { tx_v3_child_heavy [ ' wtxid ' ] } ) is too big: { tx_v3_child_heavy [ ' tx ' ] . get_vsize ( ) } > 1000 virtual bytes " )
2022-08-31 10:38:42 -04:00
self . check_mempool ( [ ] )
tx_v3_parent = self . wallet . create_self_transfer ( version = 3 )
tx_v3_child = self . wallet . create_self_transfer ( utxo_to_spend = tx_v3_parent [ " new_utxo " ] , version = 3 )
tx_v3_grandchild = self . wallet . create_self_transfer ( utxo_to_spend = tx_v3_child [ " new_utxo " ] , version = 3 )
result = node . testmempoolaccept ( [ tx_v3_parent [ " hex " ] , tx_v3_child [ " hex " ] , tx_v3_grandchild [ " hex " ] ] )
2024-06-11 08:37:05 -04:00
assert all ( [ txresult [ " package-error " ] == f " TRUC-violation, tx { tx_v3_grandchild [ ' txid ' ] } (wtxid= { tx_v3_grandchild [ ' wtxid ' ] } ) would have too many ancestors " for txresult in result ] )
2022-08-31 10:38:42 -04:00
2024-02-27 19:16:51 -03:00
@cleanup ( extra_args = None )
2024-06-11 08:37:05 -04:00
def test_truc_ancestors_package_and_mempool ( self ) :
2022-08-31 10:38:42 -04:00
"""
2024-06-11 08:37:05 -04:00
A TRUC transaction in a package cannot have 2 TRUC parents .
2022-08-31 10:38:42 -04:00
Test that if we have a transaction graph A - > B - > C , where A , B , C are
2024-06-11 08:37:05 -04:00
all TRUC transactions , that we cannot use submitpackage to get the
2022-08-31 10:38:42 -04:00
transactions all into the mempool .
Verify , in particular , that if A is already in the mempool , then
submitpackage ( B , C ) will fail .
"""
node = self . nodes [ 0 ]
2024-06-11 08:37:05 -04:00
self . log . info ( " Test that TRUC ancestor limits include transactions within the package and all in-mempool ancestors " )
2022-08-31 10:38:42 -04:00
# This is our transaction "A":
tx_in_mempool = self . wallet . send_self_transfer ( from_node = node , version = 3 )
# Verify that A is in the mempool
self . check_mempool ( [ tx_in_mempool [ " txid " ] ] )
# tx_0fee_parent is our transaction "B"; just create it.
tx_0fee_parent = self . wallet . create_self_transfer ( utxo_to_spend = tx_in_mempool [ " new_utxo " ] , fee = 0 , fee_rate = 0 , version = 3 )
# tx_child_violator is our transaction "C"; create it:
tx_child_violator = self . wallet . create_self_transfer_multi ( utxos_to_spend = [ tx_0fee_parent [ " new_utxo " ] ] , version = 3 )
# submitpackage(B, C) should fail
result = node . submitpackage ( [ tx_0fee_parent [ " hex " ] , tx_child_violator [ " hex " ] ] )
2024-06-11 08:37:05 -04:00
assert_equal ( result [ ' package_msg ' ] , f " TRUC-violation, tx { tx_child_violator [ ' txid ' ] } (wtxid= { tx_child_violator [ ' wtxid ' ] } ) would have too many ancestors " )
2022-08-31 10:38:42 -04:00
self . check_mempool ( [ tx_in_mempool [ " txid " ] ] )
2024-02-27 19:16:51 -03:00
@cleanup ( extra_args = None )
2024-01-23 11:36:43 -03:00
def test_sibling_eviction_package ( self ) :
"""
When a transaction has a mempool sibling , it may be eligible for sibling eviction .
However , this option is only available in single transaction acceptance . It doesn ' t work in
a multi - testmempoolaccept ( where RBF is disabled ) or when doing package CPFP .
"""
2024-06-11 08:37:05 -04:00
self . log . info ( " Test TRUC sibling eviction in submitpackage and multi-testmempoolaccept " )
2022-08-31 10:38:42 -04:00
node = self . nodes [ 0 ]
# Add a parent + child to mempool
tx_mempool_parent = self . wallet . send_self_transfer_multi (
from_node = node ,
utxos_to_spend = [ self . wallet . get_utxo ( ) ] ,
num_outputs = 2 ,
version = 3
)
tx_mempool_sibling = self . wallet . send_self_transfer (
from_node = node ,
utxo_to_spend = tx_mempool_parent [ " new_utxos " ] [ 0 ] ,
version = 3
)
self . check_mempool ( [ tx_mempool_parent [ " txid " ] , tx_mempool_sibling [ " txid " ] ] )
2024-01-23 11:36:43 -03:00
tx_sibling_1 = self . wallet . create_self_transfer (
2022-08-31 10:38:42 -04:00
utxo_to_spend = tx_mempool_parent [ " new_utxos " ] [ 1 ] ,
2024-01-23 11:36:43 -03:00
version = 3 ,
fee_rate = DEFAULT_FEE * 100 ,
2022-08-31 10:38:42 -04:00
)
2024-01-23 11:36:43 -03:00
tx_has_mempool_uncle = self . wallet . create_self_transfer ( utxo_to_spend = tx_sibling_1 [ " new_utxo " ] , version = 3 )
2022-08-31 10:38:42 -04:00
2024-01-23 11:36:43 -03:00
tx_sibling_2 = self . wallet . create_self_transfer (
utxo_to_spend = tx_mempool_parent [ " new_utxos " ] [ 0 ] ,
version = 3 ,
fee_rate = DEFAULT_FEE * 200 ,
)
tx_sibling_3 = self . wallet . create_self_transfer (
utxo_to_spend = tx_mempool_parent [ " new_utxos " ] [ 1 ] ,
version = 3 ,
fee_rate = 0 ,
)
tx_bumps_parent_with_sibling = self . wallet . create_self_transfer (
utxo_to_spend = tx_sibling_3 [ " new_utxo " ] ,
version = 3 ,
fee_rate = DEFAULT_FEE * 300 ,
)
2022-08-31 10:38:42 -04:00
2024-01-23 11:36:43 -03:00
# Fails with another non-related transaction via testmempoolaccept
2022-08-31 10:38:42 -04:00
tx_unrelated = self . wallet . create_self_transfer ( version = 3 )
2024-01-23 11:36:43 -03:00
result_test_unrelated = node . testmempoolaccept ( [ tx_sibling_1 [ " hex " ] , tx_unrelated [ " hex " ] ] )
2024-06-11 08:37:05 -04:00
assert_equal ( result_test_unrelated [ 0 ] [ " reject-reason " ] , " TRUC-violation " )
2022-08-31 10:38:42 -04:00
2024-01-23 11:36:43 -03:00
# Fails in a package via testmempoolaccept
result_test_1p1c = node . testmempoolaccept ( [ tx_sibling_1 [ " hex " ] , tx_has_mempool_uncle [ " hex " ] ] )
2024-06-11 08:37:05 -04:00
assert_equal ( result_test_1p1c [ 0 ] [ " reject-reason " ] , " TRUC-violation " )
2022-08-31 10:38:42 -04:00
2024-01-23 11:36:43 -03:00
# Allowed when tx is submitted in a package and evaluated individually.
# Note that the child failed since it would be the 3rd generation.
result_package_indiv = node . submitpackage ( [ tx_sibling_1 [ " hex " ] , tx_has_mempool_uncle [ " hex " ] ] )
self . check_mempool ( [ tx_mempool_parent [ " txid " ] , tx_sibling_1 [ " txid " ] ] )
2024-06-11 08:37:05 -04:00
expected_error_gen3 = f " TRUC-violation, tx { tx_has_mempool_uncle [ ' txid ' ] } (wtxid= { tx_has_mempool_uncle [ ' wtxid ' ] } ) would have too many ancestors "
2024-01-23 11:36:43 -03:00
assert_equal ( result_package_indiv [ " tx-results " ] [ tx_has_mempool_uncle [ ' wtxid ' ] ] [ ' error ' ] , expected_error_gen3 )
# Allowed when tx is submitted in a package with in-mempool parent (which is deduplicated).
node . submitpackage ( [ tx_mempool_parent [ " hex " ] , tx_sibling_2 [ " hex " ] ] )
self . check_mempool ( [ tx_mempool_parent [ " txid " ] , tx_sibling_2 [ " txid " ] ] )
2024-06-11 08:37:05 -04:00
# Child cannot pay for sibling eviction for parent, as it violates TRUC topology limits
2024-01-23 11:36:43 -03:00
result_package_cpfp = node . submitpackage ( [ tx_sibling_3 [ " hex " ] , tx_bumps_parent_with_sibling [ " hex " ] ] )
self . check_mempool ( [ tx_mempool_parent [ " txid " ] , tx_sibling_2 [ " txid " ] ] )
2024-06-11 08:37:05 -04:00
expected_error_cpfp = f " TRUC-violation, tx { tx_mempool_parent [ ' txid ' ] } (wtxid= { tx_mempool_parent [ ' wtxid ' ] } ) would exceed descendant count limit "
2024-01-23 11:36:43 -03:00
assert_equal ( result_package_cpfp [ " tx-results " ] [ tx_sibling_3 [ ' wtxid ' ] ] [ ' error ' ] , expected_error_cpfp )
2022-08-31 10:38:42 -04:00
2024-02-27 19:16:51 -03:00
@cleanup ( extra_args = [ " -datacarriersize=1000 " ] )
2024-06-11 08:37:05 -04:00
def test_truc_package_inheritance ( self ) :
self . log . info ( " Test that TRUC inheritance is checked within package " )
2022-08-31 10:38:42 -04:00
node = self . nodes [ 0 ]
tx_v3_parent = self . wallet . create_self_transfer (
fee_rate = 0 ,
2024-08-26 13:35:00 -04:00
target_vsize = 1001 ,
2022-08-31 10:38:42 -04:00
version = 3
)
tx_v2_child = self . wallet . create_self_transfer_multi (
utxos_to_spend = [ tx_v3_parent [ " new_utxo " ] ] ,
fee_per_output = 10000 ,
version = 2
)
self . check_mempool ( [ ] )
result = node . submitpackage ( [ tx_v3_parent [ " hex " ] , tx_v2_child [ " hex " ] ] )
2024-07-02 06:56:13 -04:00
assert_equal ( result [ ' package_msg ' ] , f " TRUC-violation, non-version=3 tx { tx_v2_child [ ' txid ' ] } (wtxid= { tx_v2_child [ ' wtxid ' ] } ) cannot spend from version=3 tx { tx_v3_parent [ ' txid ' ] } (wtxid= { tx_v3_parent [ ' wtxid ' ] } ) " )
2022-08-31 10:38:42 -04:00
self . check_mempool ( [ ] )
2024-02-27 19:16:51 -03:00
@cleanup ( extra_args = None )
2024-06-11 08:37:05 -04:00
def test_truc_in_testmempoolaccept ( self ) :
2022-08-31 10:38:42 -04:00
node = self . nodes [ 0 ]
2024-06-11 08:37:05 -04:00
self . log . info ( " Test that TRUC inheritance is accurately assessed in testmempoolaccept " )
2022-08-31 10:38:42 -04:00
tx_v2 = self . wallet . create_self_transfer ( version = 2 )
tx_v2_from_v2 = self . wallet . create_self_transfer ( utxo_to_spend = tx_v2 [ " new_utxo " ] , version = 2 )
tx_v3_from_v2 = self . wallet . create_self_transfer ( utxo_to_spend = tx_v2 [ " new_utxo " ] , version = 3 )
tx_v3 = self . wallet . create_self_transfer ( version = 3 )
tx_v2_from_v3 = self . wallet . create_self_transfer ( utxo_to_spend = tx_v3 [ " new_utxo " ] , version = 2 )
tx_v3_from_v3 = self . wallet . create_self_transfer ( utxo_to_spend = tx_v3 [ " new_utxo " ] , version = 3 )
# testmempoolaccept paths don't require child-with-parents topology. Ensure that topology
# assumptions aren't made in inheritance checks.
test_accept_v2_and_v3 = node . testmempoolaccept ( [ tx_v2 [ " hex " ] , tx_v3 [ " hex " ] ] )
assert all ( [ result [ " allowed " ] for result in test_accept_v2_and_v3 ] )
test_accept_v3_from_v2 = node . testmempoolaccept ( [ tx_v2 [ " hex " ] , tx_v3_from_v2 [ " hex " ] ] )
2024-07-02 06:56:13 -04:00
expected_error_v3_from_v2 = f " TRUC-violation, version=3 tx { tx_v3_from_v2 [ ' txid ' ] } (wtxid= { tx_v3_from_v2 [ ' wtxid ' ] } ) cannot spend from non-version=3 tx { tx_v2 [ ' txid ' ] } (wtxid= { tx_v2 [ ' wtxid ' ] } ) "
2022-08-31 10:38:42 -04:00
assert all ( [ result [ " package-error " ] == expected_error_v3_from_v2 for result in test_accept_v3_from_v2 ] )
test_accept_v2_from_v3 = node . testmempoolaccept ( [ tx_v3 [ " hex " ] , tx_v2_from_v3 [ " hex " ] ] )
2024-07-02 06:56:13 -04:00
expected_error_v2_from_v3 = f " TRUC-violation, non-version=3 tx { tx_v2_from_v3 [ ' txid ' ] } (wtxid= { tx_v2_from_v3 [ ' wtxid ' ] } ) cannot spend from version=3 tx { tx_v3 [ ' txid ' ] } (wtxid= { tx_v3 [ ' wtxid ' ] } ) "
2022-08-31 10:38:42 -04:00
assert all ( [ result [ " package-error " ] == expected_error_v2_from_v3 for result in test_accept_v2_from_v3 ] )
test_accept_pairs = node . testmempoolaccept ( [ tx_v2 [ " hex " ] , tx_v3 [ " hex " ] , tx_v2_from_v2 [ " hex " ] , tx_v3_from_v3 [ " hex " ] ] )
assert all ( [ result [ " allowed " ] for result in test_accept_pairs ] )
self . log . info ( " Test that descendant violations are caught in testmempoolaccept " )
tx_v3_independent = self . wallet . create_self_transfer ( version = 3 )
tx_v3_parent = self . wallet . create_self_transfer_multi ( num_outputs = 2 , version = 3 )
tx_v3_child_1 = self . wallet . create_self_transfer ( utxo_to_spend = tx_v3_parent [ " new_utxos " ] [ 0 ] , version = 3 )
tx_v3_child_2 = self . wallet . create_self_transfer ( utxo_to_spend = tx_v3_parent [ " new_utxos " ] [ 1 ] , version = 3 )
test_accept_2children = node . testmempoolaccept ( [ tx_v3_parent [ " hex " ] , tx_v3_child_1 [ " hex " ] , tx_v3_child_2 [ " hex " ] ] )
2024-06-11 08:37:05 -04:00
expected_error_2children = f " TRUC-violation, tx { tx_v3_parent [ ' txid ' ] } (wtxid= { tx_v3_parent [ ' wtxid ' ] } ) would exceed descendant count limit "
2022-08-31 10:38:42 -04:00
assert all ( [ result [ " package-error " ] == expected_error_2children for result in test_accept_2children ] )
2024-06-11 08:37:05 -04:00
# Extra TRUC transaction does not get incorrectly marked as extra descendant
2022-08-31 10:38:42 -04:00
test_accept_1child_with_exra = node . testmempoolaccept ( [ tx_v3_parent [ " hex " ] , tx_v3_child_1 [ " hex " ] , tx_v3_independent [ " hex " ] ] )
assert all ( [ result [ " allowed " ] for result in test_accept_1child_with_exra ] )
2024-06-11 08:37:05 -04:00
# Extra TRUC transaction does not make us ignore the extra descendant
2022-08-31 10:38:42 -04:00
test_accept_2children_with_exra = node . testmempoolaccept ( [ tx_v3_parent [ " hex " ] , tx_v3_child_1 [ " hex " ] , tx_v3_child_2 [ " hex " ] , tx_v3_independent [ " hex " ] ] )
2024-06-11 08:37:05 -04:00
expected_error_extra = f " TRUC-violation, tx { tx_v3_parent [ ' txid ' ] } (wtxid= { tx_v3_parent [ ' wtxid ' ] } ) would exceed descendant count limit "
2022-08-31 10:38:42 -04:00
assert all ( [ result [ " package-error " ] == expected_error_extra for result in test_accept_2children_with_exra ] )
# Same result if the parent is already in mempool
node . sendrawtransaction ( tx_v3_parent [ " hex " ] )
test_accept_2children_with_in_mempool_parent = node . testmempoolaccept ( [ tx_v3_child_1 [ " hex " ] , tx_v3_child_2 [ " hex " ] ] )
assert all ( [ result [ " package-error " ] == expected_error_extra for result in test_accept_2children_with_in_mempool_parent ] )
2024-02-27 19:16:51 -03:00
@cleanup ( extra_args = None )
2024-02-12 11:55:27 -03:00
def test_reorg_2child_rbf ( self ) :
node = self . nodes [ 0 ]
2024-06-11 08:37:05 -04:00
self . log . info ( " Test that children of a TRUC transaction can be replaced individually, even if there are multiple due to reorg " )
2024-02-12 11:55:27 -03:00
ancestor_tx = self . wallet . send_self_transfer_multi ( from_node = node , num_outputs = 2 , version = 3 )
self . check_mempool ( [ ancestor_tx [ " txid " ] ] )
block = self . generate ( node , 1 ) [ 0 ]
self . check_mempool ( [ ] )
child_1 = self . wallet . send_self_transfer ( from_node = node , version = 3 , utxo_to_spend = ancestor_tx [ " new_utxos " ] [ 0 ] )
child_2 = self . wallet . send_self_transfer ( from_node = node , version = 3 , utxo_to_spend = ancestor_tx [ " new_utxos " ] [ 1 ] )
self . check_mempool ( [ child_1 [ " txid " ] , child_2 [ " txid " ] ] )
self . generate ( node , 1 )
self . check_mempool ( [ ] )
# Create a reorg, causing ancestor_tx to exceed the 1-child limit
node . invalidateblock ( block )
self . check_mempool ( [ ancestor_tx [ " txid " ] , child_1 [ " txid " ] , child_2 [ " txid " ] ] )
assert_equal ( node . getmempoolentry ( ancestor_tx [ " txid " ] ) [ " descendantcount " ] , 3 )
# Create a replacement of child_1. It does not conflict with child_2.
child_1_conflict = self . wallet . send_self_transfer ( from_node = node , version = 3 , utxo_to_spend = ancestor_tx [ " new_utxos " ] [ 0 ] , fee_rate = Decimal ( " 0.01 " ) )
# Ensure child_1 and child_1_conflict are different transactions
assert ( child_1_conflict [ " txid " ] != child_1 [ " txid " ] )
self . check_mempool ( [ ancestor_tx [ " txid " ] , child_1_conflict [ " txid " ] , child_2 [ " txid " ] ] )
assert_equal ( node . getmempoolentry ( ancestor_tx [ " txid " ] ) [ " descendantcount " ] , 3 )
2024-02-27 19:16:51 -03:00
@cleanup ( extra_args = None )
2024-06-11 08:37:05 -04:00
def test_truc_sibling_eviction ( self ) :
self . log . info ( " Test sibling eviction for TRUC " )
2024-01-23 11:36:43 -03:00
node = self . nodes [ 0 ]
tx_v3_parent = self . wallet . send_self_transfer_multi ( from_node = node , num_outputs = 2 , version = 3 )
# This is the sibling to replace
tx_v3_child_1 = self . wallet . send_self_transfer (
from_node = node , utxo_to_spend = tx_v3_parent [ " new_utxos " ] [ 0 ] , fee_rate = DEFAULT_FEE * 2 , version = 3
)
assert tx_v3_child_1 [ " txid " ] in node . getrawmempool ( )
self . log . info ( " Test tx must be higher feerate than sibling to evict it " )
tx_v3_child_2_rule6 = self . wallet . create_self_transfer (
utxo_to_spend = tx_v3_parent [ " new_utxos " ] [ 1 ] , fee_rate = DEFAULT_FEE , version = 3
)
rule6_str = f " insufficient fee (including sibling eviction), rejecting replacement { tx_v3_child_2_rule6 [ ' txid ' ] } ; new feerate "
assert_raises_rpc_error ( - 26 , rule6_str , node . sendrawtransaction , tx_v3_child_2_rule6 [ " hex " ] )
self . check_mempool ( [ tx_v3_parent [ ' txid ' ] , tx_v3_child_1 [ ' txid ' ] ] )
self . log . info ( " Test tx must meet absolute fee rules to evict sibling " )
tx_v3_child_2_rule4 = self . wallet . create_self_transfer (
utxo_to_spend = tx_v3_parent [ " new_utxos " ] [ 1 ] , fee_rate = 2 * DEFAULT_FEE + Decimal ( " 0.00000001 " ) , version = 3
)
rule4_str = f " insufficient fee (including sibling eviction), rejecting replacement { tx_v3_child_2_rule4 [ ' txid ' ] } , not enough additional fees to relay "
assert_raises_rpc_error ( - 26 , rule4_str , node . sendrawtransaction , tx_v3_child_2_rule4 [ " hex " ] )
self . check_mempool ( [ tx_v3_parent [ ' txid ' ] , tx_v3_child_1 [ ' txid ' ] ] )
self . log . info ( " Test tx cannot cause more than 100 evictions including RBF and sibling eviction " )
# First add 4 groups of 25 transactions.
utxos_for_conflict = [ ]
txids_v2_100 = [ ]
for _ in range ( 4 ) :
confirmed_utxo = self . wallet . get_utxo ( confirmed_only = True )
utxos_for_conflict . append ( confirmed_utxo )
# 25 is within descendant limits
chain_length = int ( MAX_REPLACEMENT_CANDIDATES / 4 )
chain = self . wallet . create_self_transfer_chain ( chain_length = chain_length , utxo_to_spend = confirmed_utxo )
for item in chain :
txids_v2_100 . append ( item [ " txid " ] )
node . sendrawtransaction ( item [ " hex " ] )
self . check_mempool ( txids_v2_100 + [ tx_v3_parent [ " txid " ] , tx_v3_child_1 [ " txid " ] ] )
# Replacing 100 transactions is fine
tx_v3_replacement_only = self . wallet . create_self_transfer_multi ( utxos_to_spend = utxos_for_conflict , fee_per_output = 4000000 )
# Override maxfeerate - it costs a lot to replace these 100 transactions.
assert node . testmempoolaccept ( [ tx_v3_replacement_only [ " hex " ] ] , maxfeerate = 0 ) [ 0 ] [ " allowed " ]
# Adding another one exceeds the limit.
utxos_for_conflict . append ( tx_v3_parent [ " new_utxos " ] [ 1 ] )
tx_v3_child_2_rule5 = self . wallet . create_self_transfer_multi ( utxos_to_spend = utxos_for_conflict , fee_per_output = 4000000 , version = 3 )
rule5_str = f " too many potential replacements (including sibling eviction), rejecting replacement { tx_v3_child_2_rule5 [ ' txid ' ] } ; too many potential replacements (101 > 100) "
assert_raises_rpc_error ( - 26 , rule5_str , node . sendrawtransaction , tx_v3_child_2_rule5 [ " hex " ] )
self . check_mempool ( txids_v2_100 + [ tx_v3_parent [ " txid " ] , tx_v3_child_1 [ " txid " ] ] )
self . log . info ( " Test sibling eviction is successful if it meets all RBF rules " )
tx_v3_child_2 = self . wallet . create_self_transfer (
utxo_to_spend = tx_v3_parent [ " new_utxos " ] [ 1 ] , fee_rate = DEFAULT_FEE * 10 , version = 3
)
node . sendrawtransaction ( tx_v3_child_2 [ " hex " ] )
self . check_mempool ( txids_v2_100 + [ tx_v3_parent [ " txid " ] , tx_v3_child_2 [ " txid " ] ] )
self . log . info ( " Test that it ' s possible to do a sibling eviction and RBF at the same time " )
utxo_unrelated_conflict = self . wallet . get_utxo ( confirmed_only = True )
tx_unrelated_replacee = self . wallet . send_self_transfer ( from_node = node , utxo_to_spend = utxo_unrelated_conflict )
assert tx_unrelated_replacee [ " txid " ] in node . getrawmempool ( )
2024-04-28 08:42:28 -04:00
fee_to_beat = max ( int ( tx_v3_child_2 [ " fee " ] * COIN ) , int ( tx_unrelated_replacee [ " fee " ] * COIN ) )
2024-01-23 11:36:43 -03:00
tx_v3_child_3 = self . wallet . create_self_transfer_multi (
2024-04-28 08:42:28 -04:00
utxos_to_spend = [ tx_v3_parent [ " new_utxos " ] [ 0 ] , utxo_unrelated_conflict ] , fee_per_output = fee_to_beat * 2 , version = 3
2024-01-23 11:36:43 -03:00
)
node . sendrawtransaction ( tx_v3_child_3 [ " hex " ] )
self . check_mempool ( txids_v2_100 + [ tx_v3_parent [ " txid " ] , tx_v3_child_3 [ " txid " ] ] )
2024-02-27 19:16:51 -03:00
@cleanup ( extra_args = None )
2024-01-23 11:36:43 -03:00
def test_reorg_sibling_eviction_1p2c ( self ) :
node = self . nodes [ 0 ]
self . log . info ( " Test that sibling eviction is not allowed when multiple siblings exist " )
tx_with_multi_children = self . wallet . send_self_transfer_multi ( from_node = node , num_outputs = 3 , version = 3 , confirmed_only = True )
self . check_mempool ( [ tx_with_multi_children [ " txid " ] ] )
block_to_disconnect = self . generate ( node , 1 ) [ 0 ]
self . check_mempool ( [ ] )
tx_with_sibling1 = self . wallet . send_self_transfer ( from_node = node , version = 3 , utxo_to_spend = tx_with_multi_children [ " new_utxos " ] [ 0 ] )
tx_with_sibling2 = self . wallet . send_self_transfer ( from_node = node , version = 3 , utxo_to_spend = tx_with_multi_children [ " new_utxos " ] [ 1 ] )
self . check_mempool ( [ tx_with_sibling1 [ " txid " ] , tx_with_sibling2 [ " txid " ] ] )
# Create a reorg, bringing tx_with_multi_children back into the mempool with a descendant count of 3.
node . invalidateblock ( block_to_disconnect )
self . check_mempool ( [ tx_with_multi_children [ " txid " ] , tx_with_sibling1 [ " txid " ] , tx_with_sibling2 [ " txid " ] ] )
assert_equal ( node . getmempoolentry ( tx_with_multi_children [ " txid " ] ) [ " descendantcount " ] , 3 )
# Sibling eviction is not allowed because there are two siblings
tx_with_sibling3 = self . wallet . create_self_transfer (
version = 3 ,
utxo_to_spend = tx_with_multi_children [ " new_utxos " ] [ 2 ] ,
fee_rate = DEFAULT_FEE * 50
)
2024-06-11 08:37:05 -04:00
expected_error_2siblings = f " TRUC-violation, tx { tx_with_multi_children [ ' txid ' ] } (wtxid= { tx_with_multi_children [ ' wtxid ' ] } ) would exceed descendant count limit "
2024-01-23 11:36:43 -03:00
assert_raises_rpc_error ( - 26 , expected_error_2siblings , node . sendrawtransaction , tx_with_sibling3 [ " hex " ] )
# However, an RBF (with conflicting inputs) is possible even if the resulting cluster size exceeds 2
tx_with_sibling3_rbf = self . wallet . send_self_transfer (
from_node = node ,
version = 3 ,
utxo_to_spend = tx_with_multi_children [ " new_utxos " ] [ 0 ] ,
fee_rate = DEFAULT_FEE * 50
)
self . check_mempool ( [ tx_with_multi_children [ " txid " ] , tx_with_sibling3_rbf [ " txid " ] , tx_with_sibling2 [ " txid " ] ] )
2022-08-31 10:38:42 -04:00
def run_test ( self ) :
self . log . info ( " Generate blocks to create UTXOs " )
node = self . nodes [ 0 ]
self . wallet = MiniWallet ( node )
2024-01-23 11:36:43 -03:00
self . generate ( self . wallet , 120 )
2024-06-11 08:37:05 -04:00
self . test_truc_max_vsize ( )
self . test_truc_acceptance ( )
self . test_truc_replacement ( )
self . test_truc_bip125 ( )
self . test_truc_reorg ( )
2022-08-31 10:38:42 -04:00
self . test_nondefault_package_limits ( )
2024-06-11 08:37:05 -04:00
self . test_truc_ancestors_package ( )
self . test_truc_ancestors_package_and_mempool ( )
2024-01-23 11:36:43 -03:00
self . test_sibling_eviction_package ( )
2024-06-11 08:37:05 -04:00
self . test_truc_package_inheritance ( )
self . test_truc_in_testmempoolaccept ( )
2024-02-12 11:55:27 -03:00
self . test_reorg_2child_rbf ( )
2024-06-11 08:37:05 -04:00
self . test_truc_sibling_eviction ( )
2024-01-23 11:36:43 -03:00
self . test_reorg_sibling_eviction_1p2c ( )
2022-08-31 10:38:42 -04:00
if __name__ == " __main__ " :
2024-07-16 17:05:14 -04:00
MempoolTRUC ( __file__ ) . main ( )