2020import os
2121import shutil
2222
23+ from test_framework .blocktools import COINBASE_MATURITY
2324from test_framework .descriptors import descsum_create
2425from test_framework .test_framework import BitcoinTestFramework
2526
3233class BackwardsCompatibilityTest (BitcoinTestFramework ):
3334 def set_test_params (self ):
3435 self .setup_clean_chain = True
35- self .num_nodes = 7
36+ self .num_nodes = 8
3637 # Add new version after each release:
3738 self .extra_args = [
38- [], # Pre-release: use to mine blocks
39- ["-nowallet" ], # Pre-release: use to receive coins, swap wallets, etc
40- ["-nowallet" ], # v20.0.1
41- ["-nowallet" ], # v19.3.0
42- ["-nowallet" ], # v18.2.2
43- ["-nowallet" ], # v0.17.0.3
44- ["-nowallet" ], # v0.16.1.1
39+ ["-whitelist=noban@127.0.0.1" ], # Pre-release: use to mine blocks
40+ ["-nowallet" , "-whitelist=noban@127.0.0.1" ], # Pre-release: use to receive coins, swap wallets, etc
41+ ["-nowallet" , "-whitelist=noban@127.0.0.1" ], # v21.1.1 - supports descriptor wallets
42+ ["-nowallet" , "-whitelist=noban@127.0.0.1" ], # v20.1.1 - last legacy-only version, no descriptor wallets
43+ ["-nowallet" , "-whitelist=noban@127.0.0.1" ], # v19.3.0
44+ ["-nowallet" , "-whitelist=noban@127.0.0.1" ], # v18.2.2
45+ ["-nowallet" , "-whitelist=127.0.0.1" ], # v0.17.0.3
46+ ["-nowallet" , "-whitelist=127.0.0.1" ], # v0.16.1.1
4547 ]
4648 self .wallet_names = [self .default_wallet_name ]
4749
@@ -53,7 +55,8 @@ def setup_nodes(self):
5355 self .add_nodes (self .num_nodes , extra_args = self .extra_args , versions = [
5456 None ,
5557 None ,
56- 19030000 ,
58+ 21010100 ,
59+ 20010100 ,
5760 19030000 ,
5861 18020200 ,
5962 170003 ,
@@ -63,20 +66,28 @@ def setup_nodes(self):
6366 self .start_nodes ()
6467 self .import_deterministic_coinbase_privkeys ()
6568
66- def run_test (self ):
67- self .generatetoaddress (self .nodes [0 ], 101 , self .nodes [0 ].getnewaddress ())
68-
69- # Sanity check the test framework:
70- res = self .nodes [self .num_nodes - 1 ].getblockchaininfo ()
71- assert_equal (res ['blocks' ], 101 )
69+ def nodes_wallet_dir (self , node ):
70+ if node .version < 160000 :
71+ return os .path .join (node .datadir , "regtest" )
72+ return os .path .join (node .datadir , "regtest/wallets" )
7273
73- node_master = self .nodes [self .num_nodes - 6 ]
74+ def run_test (self ):
75+ node_miner = self .nodes [0 ]
76+ node_master = self .nodes [1 ]
7477 node_v20 = self .nodes [self .num_nodes - 5 ]
7578 node_v19 = self .nodes [self .num_nodes - 4 ]
7679 node_v18 = self .nodes [self .num_nodes - 3 ]
7780 node_v17 = self .nodes [self .num_nodes - 2 ]
7881 node_v16 = self .nodes [self .num_nodes - 1 ]
7982
83+ legacy_nodes = self .nodes [3 :]
84+
85+ self .generatetoaddress (node_miner , COINBASE_MATURITY + 1 , node_miner .getnewaddress ())
86+
87+ # Sanity check the test framework:
88+ res = node_v16 .getblockchaininfo ()
89+ assert_equal (res ['blocks' ], COINBASE_MATURITY + 1 )
90+
8091 self .log .info ("Test wallet backwards compatibility..." )
8192 # Create a number of wallets and open them in older versions:
8293
@@ -89,9 +100,9 @@ def run_test(self):
89100 assert info ['keypoolsize' ] > 0
90101 # Create a confirmed transaction, receiving coins
91102 address = wallet .getnewaddress ()
92- self . nodes [ 0 ] .sendtoaddress (address , 1 )
103+ node_miner .sendtoaddress (address , 1 )
93104 self .sync_mempools ()
94- self .generate (self . nodes [ 0 ] , 1 )
105+ self .generate (node_miner , 1 )
95106
96107 # w1_v19: regular wallet, created with v0.19
97108 node_v19 .rpc .createwallet (wallet_name = "w1_v19" )
@@ -102,6 +113,7 @@ def run_test(self):
102113 # Use addmultisigaddress (see #18075)
103114 address_18075 = wallet .addmultisigaddress (1 , ["0296b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52" , "037211a824f55b505228e4c3d5194c1fcfaa15a456abdf37f9b9d97a4040afc073" ], "" )["address" ]
104115 assert wallet .getaddressinfo (address_18075 )["solvable" ]
116+ node_v19 .unloadwallet ("w1_v19" )
105117
106118 # w1_v18: regular wallet, created with v0.18
107119 node_v18 .rpc .createwallet (wallet_name = "w1_v18" )
@@ -148,198 +160,78 @@ def run_test(self):
148160 assert info ['private_keys_enabled' ]
149161 assert info ['keypoolsize' ] == 0
150162
151- # w3_v19: blank wallet, created with v0.19
152- node_v19 .rpc .createwallet (wallet_name = "w3_v19" , blank = True )
153- wallet = node_v19 .get_wallet_rpc ("w3_v19" )
154- info = wallet .getwalletinfo ()
155- assert info ['private_keys_enabled' ]
156- assert info ['keypoolsize' ] == 0
157-
158- # w3_v18: blank wallet, created with v0.18
159- node_v18 .rpc .createwallet (wallet_name = "w3_v18" , blank = True )
160- wallet = node_v18 .get_wallet_rpc ("w3_v18" )
161- info = wallet .getwalletinfo ()
162- assert info ['private_keys_enabled' ]
163- assert info ['keypoolsize' ] == 0
164-
165- # Copy the wallets to older nodes:
163+ # Unload wallets and copy to older nodes:
166164 node_master_wallets_dir = os .path .join (node_master .datadir , "regtest/wallets" )
167- node_v20_wallets_dir = os .path .join (node_v20 .datadir , "regtest/wallets" )
168165 node_v19_wallets_dir = os .path .join (node_v19 .datadir , "regtest/wallets" )
169- node_v18_wallets_dir = os .path .join (node_v18 .datadir , "regtest/wallets" )
170166 node_v17_wallets_dir = os .path .join (node_v17 .datadir , "regtest/wallets" )
171- node_v16_wallets_dir = os .path .join (node_v16 .datadir , "regtest" )
172167 node_master .unloadwallet ("w1" )
173168 node_master .unloadwallet ("w2" )
174- node_v19 .unloadwallet ("w1_v19" )
175- node_v19 .unloadwallet ("w2_v19" )
176- node_v18 .unloadwallet ("w1_v18" )
177- node_v18 .unloadwallet ("w2_v18" )
178-
179- # Copy wallets to v0.16
180- for wallet in os .listdir (node_master_wallets_dir ):
181- shutil .copytree (
182- os .path .join (node_master_wallets_dir , wallet ),
183- os .path .join (node_v16_wallets_dir , wallet )
184- )
185-
186- # Copy wallets to v0.17
187- for wallet in os .listdir (node_master_wallets_dir ):
188- shutil .copytree (
189- os .path .join (node_master_wallets_dir , wallet ),
190- os .path .join (node_v17_wallets_dir , wallet )
191- )
192- for wallet in os .listdir (node_v18_wallets_dir ):
193- shutil .copytree (
194- os .path .join (node_v18_wallets_dir , wallet ),
195- os .path .join (node_v17_wallets_dir , wallet )
196- )
197-
198- # Copy wallets to v0.18
199- for wallet in os .listdir (node_master_wallets_dir ):
200- shutil .copytree (
201- os .path .join (node_master_wallets_dir , wallet ),
202- os .path .join (node_v18_wallets_dir , wallet )
203- )
204-
205- # Copy wallets to v0.19
206- for wallet in os .listdir (node_master_wallets_dir ):
207- shutil .copytree (
208- os .path .join (node_master_wallets_dir , wallet ),
209- os .path .join (node_v19_wallets_dir , wallet )
210- )
169+ node_master .unloadwallet ("w3" )
211170
212- # Copy wallets to v0.20
213- for wallet in os .listdir (node_master_wallets_dir ):
214- shutil .copytree (
215- os .path .join (node_master_wallets_dir , wallet ),
216- os .path .join (node_v20_wallets_dir , wallet )
217- )
171+ for node in legacy_nodes :
172+ # Copy wallets to previous version
173+ for wallet in os .listdir (node_master_wallets_dir ):
174+ shutil .copytree (
175+ os .path .join (node_master_wallets_dir , wallet ),
176+ os .path .join (self .nodes_wallet_dir (node ), wallet )
177+ )
218178
219179 if not self .options .descriptors :
220180 # Descriptor wallets break compatibility, only run this test for legacy wallet
221- # Open the wallets in v0.20
222- node_v20 .loadwallet ("w1" )
223- wallet = node_v20 .get_wallet_rpc ("w1" )
224- info = wallet .getwalletinfo ()
225- assert info ['private_keys_enabled' ]
226- assert info ['keypoolsize' ] > 0
227- txs = wallet .listtransactions ()
228- assert_equal (len (txs ), 1 )
229-
230- node_v20 .loadwallet ("w2" )
231- wallet = node_v20 .get_wallet_rpc ("w2" )
232- info = wallet .getwalletinfo ()
233- assert info ['private_keys_enabled' ] == False
234- assert info ['keypoolsize' ] == 0
235-
236- node_v20 .loadwallet ("w3" )
237- wallet = node_v20 .get_wallet_rpc ("w3" )
238- info = wallet .getwalletinfo ()
239- assert info ['private_keys_enabled' ]
240- assert info ['keypoolsize' ] == 0
241-
242- # Open the wallets in v0.19
243- node_v19 .loadwallet ("w1" )
244- wallet = node_v19 .get_wallet_rpc ("w1" )
245- info = wallet .getwalletinfo ()
246- assert info ['private_keys_enabled' ]
247- assert info ['keypoolsize' ] > 0
248- txs = wallet .listtransactions ()
249- assert_equal (len (txs ), 1 )
250-
251- node_v19 .loadwallet ("w2" )
252- wallet = node_v19 .get_wallet_rpc ("w2" )
253- info = wallet .getwalletinfo ()
254- assert info ['private_keys_enabled' ] == False
255- assert info ['keypoolsize' ] == 0
256-
257- node_v19 .loadwallet ("w3" )
258- wallet = node_v19 .get_wallet_rpc ("w3" )
259- info = wallet .getwalletinfo ()
260- assert info ['private_keys_enabled' ]
261- assert info ['keypoolsize' ] == 0
262-
263- # Open the wallets in v0.18
264- node_v18 .loadwallet ("w1" )
265- wallet = node_v18 .get_wallet_rpc ("w1" )
266- info = wallet .getwalletinfo ()
267- assert info ['private_keys_enabled' ]
268- assert info ['keypoolsize' ] > 0
269- txs = wallet .listtransactions ()
270- assert_equal (len (txs ), 1 )
271-
272- node_v18 .loadwallet ("w2" )
273- wallet = node_v18 .get_wallet_rpc ("w2" )
274- info = wallet .getwalletinfo ()
275- assert info ['private_keys_enabled' ] == False
276- assert info ['keypoolsize' ] == 0
277-
278- node_v18 .loadwallet ("w3" )
279- wallet = node_v18 .get_wallet_rpc ("w3" )
280- info = wallet .getwalletinfo ()
281- assert info ['private_keys_enabled' ]
282- assert info ['keypoolsize' ] == 0
283-
284- node_v17 .loadwallet ("w1" )
285- wallet = node_v17 .get_wallet_rpc ("w1" )
286- info = wallet .getwalletinfo ()
287- # doesn't have WALLET_FLAG_DISABLE_PRIVATE_KEYS in v17
288- assert 'private_keys_enabled' not in info
289- assert info ['keypoolsize' ] > 0
290-
291- node_v17 .loadwallet ("w2" )
292- wallet = node_v17 .get_wallet_rpc ("w2" )
293- info = wallet .getwalletinfo ()
294- # doesn't have WALLET_FLAG_DISABLE_PRIVATE_KEYS in v17
295- assert 'private_keys_enabled' not in info
296- assert info ['keypoolsize' ] > 0
181+ # Load modern wallet with older nodes
182+ for node in legacy_nodes :
183+ for wallet_name in ["w1" , "w2" , "w3" ]:
184+ if node .version < 180000 :
185+ # doesn't have WALLET_FLAG_DISABLE_PRIVATE_KEYS in v17
186+ continue
187+ self .log .info (f"Test wallet wallet: { wallet_name } on node { node .index } version: { node .version } " )
188+ node .loadwallet (wallet_name )
189+ wallet = node .get_wallet_rpc (wallet_name )
190+ info = wallet .getwalletinfo ()
191+ if wallet_name == "w1" :
192+ assert info ['private_keys_enabled' ] == True
193+ assert info ['keypoolsize' ] > 0
194+ txs = wallet .listtransactions ()
195+ assert_equal (len (txs ), 1 )
196+ elif wallet_name == "w2" :
197+ assert (info ['private_keys_enabled' ] == False )
198+ if node .version > 20999999 :
199+ assert info ['keypoolsize' ] > 0
200+ elif wallet_name == "w3" :
201+ assert (info ['private_keys_enabled' ] == True )
202+ assert 'keypoolsize' not in info or info ['keypoolsize' ] == 0
203+ else :
204+ assert False
297205 else :
298- # Descriptor wallets appear to be corrupted wallets to old software
299- assert_raises_rpc_error (- 4 , "Wallet requires newer version of Dash Core" , node_v19 .loadwallet , "w1" )
300- assert_raises_rpc_error (- 4 , "Wallet requires newer version of Dash Core" , node_v19 .loadwallet , "w2" )
301- assert_raises_rpc_error (- 4 , "Wallet requires newer version of Dash Core" , node_v19 .loadwallet , "w3" )
302- assert_raises_rpc_error (- 18 , "Data is not in recognized format" , node_v18 .loadwallet , "w1" )
303- assert_raises_rpc_error (- 18 , "Data is not in recognized format" , node_v18 .loadwallet , "w2" )
304- assert_raises_rpc_error (- 18 , "Data is not in recognized format" , node_v18 .loadwallet , "w3" )
305-
306- # Open the wallets in v0.17
307- node_v17 .loadwallet ("w1_v18" )
308- wallet = node_v17 .get_wallet_rpc ("w1_v18" )
309- info = wallet .getwalletinfo ()
310- # doesn't have WALLET_FLAG_DISABLE_PRIVATE_KEYS in v17
311- assert 'private_keys_enabled' not in info
312- assert info ['keypoolsize' ] > 0
313-
314- node_v17 .loadwallet ("w2_v18" )
315- wallet = node_v17 .get_wallet_rpc ("w2_v18" )
316- info = wallet .getwalletinfo ()
317- # doesn't have WALLET_FLAG_DISABLE_PRIVATE_KEYS in v17
318- assert 'private_keys_enabled' not in info
319- assert info ['keypoolsize' ] > 0
206+ for node in legacy_nodes :
207+ # Descriptor wallets appear to be corrupted wallets to old software
208+ if node .version < 210000 :
209+ for wallet_name in ["w1" , "w2" , "w3" ]:
210+ assert_raises_rpc_error (- 4 , "Wallet file verification failed: wallet.dat corrupt, salvage failed" , node .loadwallet , wallet_name )
320211
321212 # RPC loadwallet failure causes bitcoind to exit, in addition to the RPC
322213 # call failure, so the following test won't work:
323- # assert_raises_rpc_error(-4, "Wallet loading failed.", node_v17.loadwallet, 'w3_v18 ')
214+ # assert_raises_rpc_error(-4, "Wallet loading failed.", node_v17.loadwallet, 'w3 ')
324215
325216 # Instead, we stop node and try to launch it with the wallet:
326- self .stop_node (5 )
217+ self .stop_node (node_v17 . index )
327218 # it expected to fail with error 'DBErrors::TOO_NEW' but Dash Core can open v18 by version 17
328219 # can be implemented in future if there's any incompatible versions
329220 #node_v17.assert_start_raises_init_error(["-wallet=w3_v18"], "Error: Error loading w3_v18: Wallet requires newer version of Dash Core")
330221 #node_v17.assert_start_raises_init_error(["-wallet=w3"], "Error: Error loading w3: Wallet requires newer version of Dash Core")
331- self .start_node (5 )
222+ self .start_node (node_v17 . index )
332223
333- # Open most recent wallet in v0.16 (no loadwallet RPC)
334- self .restart_node (6 , extra_args = ["-wallet=w2" ])
335- wallet = node_v16 .get_wallet_rpc ("w2" )
336- info = wallet .getwalletinfo ()
337- assert info ['keypoolsize' ] == 1
224+ if not self .options .descriptors :
225+ # Open most recent wallet in v0.16 (no loadwallet RPC)
226+ self .restart_node (node_v16 .index , extra_args = ["-wallet=w2" ])
227+ wallet = node_v16 .get_wallet_rpc ("w2" )
228+ info = wallet .getwalletinfo ()
229+ assert info ['keypoolsize' ] == 1
338230
339231 self .log .info ("Test wallet upgrade path..." )
340232 # Bitcoin creates hd wallets by default since v16, but Dash Core v17 does not.
341233 # enforce it by restarting v17
342- self .restart_node (5 , extra_args = ["-usehd=1" ])
234+ self .restart_node (node_v17 . index , extra_args = ["-usehd=1" ])
343235 # u1: regular wallet, created with v0.17
344236 node_v17 .rpc .createwallet (wallet_name = "u1_v17" )
345237 wallet = node_v17 .get_wallet_rpc ("u1_v17" )
@@ -395,7 +287,7 @@ def run_test(self):
395287 wallet = node_v19 .get_wallet_rpc ("w1_v19" )
396288 assert wallet .getaddressinfo (address_18075 )["solvable" ]
397289
398- self .stop_node (5 , expected_stderr = ("Warning: Make sure to encrypt your wallet and delete all non-encrypted backups after you have verified that the wallet works!\n " * 3 )[:- 1 ])
290+ self .stop_node (node_v17 . index , expected_stderr = ("Warning: Make sure to encrypt your wallet and delete all non-encrypted backups after you have verified that the wallet works!\n " * 3 )[:- 1 ])
399291
400292if __name__ == '__main__' :
401293 BackwardsCompatibilityTest ().main ()
0 commit comments