4040import time
4141
4242from test_framework .test_framework import BitcoinTestFramework
43+ from test_framework .mininode import P2PTxInvStore
4344from test_framework .util import (
4445 assert_equal ,
4546 assert_greater_than_or_equal ,
4647 assert_raises_rpc_error ,
48+ connect_nodes ,
49+ disconnect_nodes ,
4750 wait_until ,
4851)
4952
@@ -80,6 +83,11 @@ def run_test(self):
8083 assert_greater_than_or_equal (tx_creation_time , tx_creation_time_lower )
8184 assert_greater_than_or_equal (tx_creation_time_higher , tx_creation_time )
8285
86+ # disconnect nodes & make a txn that remains in the unbroadcast set.
87+ disconnect_nodes (self .nodes [0 ], 2 )
88+ self .nodes [0 ].sendtoaddress (self .nodes [2 ].getnewaddress (), Decimal ("12" ))
89+ connect_nodes (self .nodes [0 ], 2 )
90+
8391 self .log .debug ("Stop-start the nodes. Verify that node0 has the transactions in its mempool and node1 does not. Verify that node2 calculates its balance correctly after loading wallet transactions." )
8492 self .stop_nodes ()
8593 # Give this node a head-start, so we can be "extra-sure" that it didn't load anything later
@@ -89,7 +97,7 @@ def run_test(self):
8997 self .start_node (2 )
9098 wait_until (lambda : self .nodes [0 ].getmempoolinfo ()["loaded" ], timeout = 1 )
9199 wait_until (lambda : self .nodes [2 ].getmempoolinfo ()["loaded" ], timeout = 1 )
92- assert_equal (len (self .nodes [0 ].getrawmempool ()), 5 )
100+ assert_equal (len (self .nodes [0 ].getrawmempool ()), 6 )
93101 assert_equal (len (self .nodes [2 ].getrawmempool ()), 5 )
94102 # The others have loaded their mempool. If node_1 loaded anything, we'd probably notice by now:
95103 assert_equal (len (self .nodes [1 ].getrawmempool ()), 0 )
@@ -105,17 +113,18 @@ def run_test(self):
105113 self .nodes [2 ].syncwithvalidationinterfacequeue () # Flush mempool to wallet
106114 assert_equal (node2_balance , self .nodes [2 ].getbalance ())
107115
116+ # start node0 with wallet disabled so wallet transactions don't get resubmitted
108117 self .log .debug ("Stop-start node0 with -persistmempool=0. Verify that it doesn't load its mempool.dat file." )
109118 self .stop_nodes ()
110- self .start_node (0 , extra_args = ["-persistmempool=0" ])
119+ self .start_node (0 , extra_args = ["-persistmempool=0" , "-disablewallet" ])
111120 wait_until (lambda : self .nodes [0 ].getmempoolinfo ()["loaded" ])
112121 assert_equal (len (self .nodes [0 ].getrawmempool ()), 0 )
113122
114123 self .log .debug ("Stop-start node0. Verify that it has the transactions in its mempool." )
115124 self .stop_nodes ()
116125 self .start_node (0 )
117126 wait_until (lambda : self .nodes [0 ].getmempoolinfo ()["loaded" ])
118- assert_equal (len (self .nodes [0 ].getrawmempool ()), 5 )
127+ assert_equal (len (self .nodes [0 ].getrawmempool ()), 6 )
119128
120129 mempooldat0 = os .path .join (self .nodes [0 ].datadir , self .chain , 'mempool.dat' )
121130 mempooldat1 = os .path .join (self .nodes [1 ].datadir , self .chain , 'mempool.dat' )
@@ -124,12 +133,12 @@ def run_test(self):
124133 self .nodes [0 ].savemempool ()
125134 assert os .path .isfile (mempooldat0 )
126135
127- self .log .debug ("Stop nodes, make node1 use mempool.dat from node0. Verify it has 5 transactions" )
136+ self .log .debug ("Stop nodes, make node1 use mempool.dat from node0. Verify it has 6 transactions" )
128137 os .rename (mempooldat0 , mempooldat1 )
129138 self .stop_nodes ()
130139 self .start_node (1 , extra_args = [])
131140 wait_until (lambda : self .nodes [1 ].getmempoolinfo ()["loaded" ])
132- assert_equal (len (self .nodes [1 ].getrawmempool ()), 5 )
141+ assert_equal (len (self .nodes [1 ].getrawmempool ()), 6 )
133142
134143 self .log .debug ("Prevent bitcoind from writing mempool.dat to disk. Verify that `savemempool` fails" )
135144 # to test the exception we are creating a tmp folder called mempool.dat.new
@@ -139,6 +148,27 @@ def run_test(self):
139148 assert_raises_rpc_error (- 1 , "Unable to dump mempool to disk" , self .nodes [1 ].savemempool )
140149 os .rmdir (mempooldotnew1 )
141150
151+ self .test_persist_unbroadcast ()
152+
153+ def test_persist_unbroadcast (self ):
154+ node0 = self .nodes [0 ]
155+ self .start_node (0 )
156+
157+ # clear out mempool
158+ node0 .generate (1 )
159+
160+ # disconnect nodes to make a txn that remains in the unbroadcast set.
161+ disconnect_nodes (node0 , 1 )
162+ node0 .sendtoaddress (self .nodes [1 ].getnewaddress (), Decimal ("12" ))
163+
164+ # shutdown, then startup with wallet disabled
165+ self .stop_nodes ()
166+ self .start_node (0 , extra_args = ["-disablewallet" ])
167+
168+ # check that txn gets broadcast due to unbroadcast logic
169+ conn = node0 .add_p2p_connection (P2PTxInvStore ())
170+ node0 .mockscheduler (16 * 60 ) # 15 min + 1 for buffer
171+ wait_until (lambda : len (conn .get_invs ()) == 1 )
142172
143173if __name__ == '__main__' :
144174 MempoolPersistTest ().main ()
0 commit comments