88- Stop the node and restart it with -reindex. Verify that the node has reindexed up to block 3.
99- Stop the node and restart it with -reindex-chainstate. Verify that the node has reindexed up to block 3.
1010- Verify that out-of-order blocks are correctly processed, see LoadExternalBlockFile()
11+ - Verify that -reindex does not attempt to connect blocks when best_header chainwork is below MinimumChainWork
1112"""
1213
14+ from test_framework .blocktools import (
15+ create_block ,
16+ create_coinbase ,
17+ )
18+ from test_framework .messages import (
19+ CBlockHeader ,
20+ msg_block ,
21+ msg_headers ,
22+ )
1323from test_framework .test_framework import BitcoinTestFramework
1424from test_framework .messages import MAGIC_BYTES
25+ from test_framework .p2p import P2PInterface
1526from test_framework .util import (
1627 assert_equal ,
1728 util_xor ,
1829)
1930
31+ class BaseNode (P2PInterface ):
32+ def send_header_for_blocks (self , new_blocks ):
33+ headers_message = msg_headers ()
34+ headers_message .headers = [CBlockHeader (b ) for b in new_blocks ]
35+ self .send_without_ping (headers_message )
36+
2037
2138class ReindexTest (BitcoinTestFramework ):
2239 def set_test_params (self ):
@@ -97,6 +114,45 @@ def continue_reindex_after_shutdown(self):
97114 node .wait_for_rpc_connection (wait_for_import = False )
98115 node .stop_node ()
99116
117+ def only_connect_minchainwork_chain (self ):
118+ self .start_node (0 )
119+ node = self .nodes [0 ]
120+ self .generatetoaddress (self .nodes [0 ], 3 , self .nodes [0 ].get_deterministic_priv_key ().address )
121+ blockcount = node .getblockcount ()
122+ best_header_target = int (node .getblock (node .getbestblockhash ())['target' ], 16 )
123+ chainwork = (100 + blockcount ) * (2 ** 256 ) // (best_header_target + 1 )
124+ chainwork = format (chainwork , '064x' )
125+
126+ tip = int (node .getbestblockhash (), 16 )
127+ block_time = node .getblock (node .getbestblockhash ())['time' ] + 1
128+ height = node .getblock (node .getbestblockhash ())['height' ] + 1
129+
130+ blocks = []
131+ for _ in range (100 ):
132+ block = create_block (tip , create_coinbase (height ), block_time )
133+ block .solve ()
134+ blocks .append (block )
135+ tip = block .hash_int
136+ block_time += 1
137+ height += 1
138+
139+ self .stop_node (0 )
140+ extra_args = ["-reindex" , "-minimumchainwork=" + chainwork ]
141+ with node .assert_debug_log (expected_msgs = ["Waiting for header sync to finish before activating chain..." ]):
142+ # No blocks are connected because chainwork of best_header is too low
143+ self .start_node (0 , extra_args )
144+
145+ p2p = node .add_p2p_connection (BaseNode ())
146+ p2p .send_header_for_blocks (blocks )
147+
148+ # Reindexed blocks are connected after headers sync
149+ self .wait_until (lambda : node .getblockcount () == blockcount )
150+
151+ # Send headers again to ensure that the block is requested
152+ p2p .send_header_for_blocks (blocks )
153+ p2p .send_without_ping (msg_block (blocks [0 ]))
154+ self .wait_until (lambda : node .getblockcount () == blockcount + 1 )
155+
100156 def run_test (self ):
101157 self .reindex (False )
102158 self .reindex (True )
@@ -105,6 +161,7 @@ def run_test(self):
105161
106162 self .out_of_order ()
107163 self .continue_reindex_after_shutdown ()
164+ self .only_connect_minchainwork_chain ()
108165
109166
110167if __name__ == '__main__' :
0 commit comments