1616"""
1717
1818import os
19+ import shutil
1920
2021from test_framework .test_framework import BitcoinTestFramework , SkipTest
2122
2223from test_framework .util import (
2324 assert_equal ,
24- sync_blocks
25+ sync_blocks ,
26+ sync_mempools
2527)
2628
2729class BackwardsCompatibilityTest (BitcoinTestFramework ):
@@ -30,10 +32,10 @@ def set_test_params(self):
3032 self .num_nodes = 4
3133 # Add new version after each release:
3234 self .extra_args = [
33- [], # Pre-release: use to mine blocks
34- [], # Pre-release: use to receive coins, swap wallets, etc
35- [], # v0.18.1
36- [] # v0.17.1
35+ ["-addresstype=bech32" ], # Pre-release: use to mine blocks
36+ ["-nowallet" , "-walletrbf=1" , "-addresstype=bech32" ], # Pre-release: use to receive coins, swap wallets, etc
37+ ["-nowallet" , "-walletrbf=1" , "-addresstype=bech32" ], # v0.18.1
38+ ["-nowallet" , "-walletrbf=1" , "-addresstype=bech32" ] # v0.17.1
3739 ]
3840
3941 def setup_nodes (self ):
@@ -66,13 +68,178 @@ def setup_nodes(self):
6668 self .start_nodes ()
6769
6870 def run_test (self ):
69- self .nodes [0 ].generate (101 )
71+ self .nodes [0 ].generatetoaddress (101 , self . nodes [ 0 ]. getnewaddress () )
7072
7173 sync_blocks (self .nodes )
7274
7375 # Sanity check the test framework:
7476 res = self .nodes [self .num_nodes - 1 ].getblockchaininfo ()
7577 assert_equal (res ['blocks' ], 101 )
7678
79+ node_master = self .nodes [self .num_nodes - 3 ]
80+ node_v18 = self .nodes [self .num_nodes - 2 ]
81+ node_v17 = self .nodes [self .num_nodes - 1 ]
82+
83+ self .log .info ("Test wallet backwards compatibility..." )
84+ # Create a number of wallets and open them in older versions:
85+
86+ # w1: regular wallet, created on master: update this test when default
87+ # wallets can no longer be opened by older versions.
88+ node_master .createwallet (wallet_name = "w1" )
89+ wallet = node_master .get_wallet_rpc ("w1" )
90+ info = wallet .getwalletinfo ()
91+ assert info ['private_keys_enabled' ]
92+ assert info ['keypoolsize' ] > 0
93+ # Create a confirmed transaction, receiving coins
94+ address = wallet .getnewaddress ()
95+ self .nodes [0 ].sendtoaddress (address , 10 )
96+ sync_mempools (self .nodes )
97+ self .nodes [0 ].generate (1 )
98+ sync_blocks (self .nodes )
99+ # Create a conflicting transaction using RBF
100+ return_address = self .nodes [0 ].getnewaddress ()
101+ tx1_id = self .nodes [1 ].sendtoaddress (return_address , 1 )
102+ tx2_id = self .nodes [1 ].bumpfee (tx1_id )["txid" ]
103+ # Confirm the transaction
104+ sync_mempools (self .nodes )
105+ self .nodes [0 ].generate (1 )
106+ sync_blocks (self .nodes )
107+ # Create another conflicting transaction using RBF
108+ tx3_id = self .nodes [1 ].sendtoaddress (return_address , 1 )
109+ tx4_id = self .nodes [1 ].bumpfee (tx3_id )["txid" ]
110+ # Abondon transaction, but don't confirm
111+ self .nodes [1 ].abandontransaction (tx3_id )
112+
113+ # w1_v18: regular wallet, created with v0.18
114+ node_v18 .createwallet (wallet_name = "w1_v18" )
115+ wallet = node_v18 .get_wallet_rpc ("w1_v18" )
116+ info = wallet .getwalletinfo ()
117+ assert info ['private_keys_enabled' ]
118+ assert info ['keypoolsize' ] > 0
119+
120+ # w2: wallet with private keys disabled, created on master: update this
121+ # test when default wallets private keys disabled can no longer be
122+ # opened by older versions.
123+ node_master .createwallet (wallet_name = "w2" , disable_private_keys = True )
124+ wallet = node_master .get_wallet_rpc ("w2" )
125+ info = wallet .getwalletinfo ()
126+ assert info ['private_keys_enabled' ] == False
127+ assert info ['keypoolsize' ] == 0
128+
129+ # w2_v18: wallet with private keys disabled, created with v0.18
130+ node_v18 .createwallet (wallet_name = "w2_v18" , disable_private_keys = True )
131+ wallet = node_v18 .get_wallet_rpc ("w2_v18" )
132+ info = wallet .getwalletinfo ()
133+ assert info ['private_keys_enabled' ] == False
134+ assert info ['keypoolsize' ] == 0
135+
136+ # w3: blank wallet, created on master: update this
137+ # test when default blank wallets can no longer be opened by older versions.
138+ node_master .createwallet (wallet_name = "w3" , blank = True )
139+ wallet = node_master .get_wallet_rpc ("w3" )
140+ info = wallet .getwalletinfo ()
141+ assert info ['private_keys_enabled' ]
142+ assert info ['keypoolsize' ] == 0
143+
144+ # w3_v18: blank wallet, created with v0.18
145+ node_v18 .createwallet (wallet_name = "w3_v18" , blank = True )
146+ wallet = node_v18 .get_wallet_rpc ("w3_v18" )
147+ info = wallet .getwalletinfo ()
148+ assert info ['private_keys_enabled' ]
149+ assert info ['keypoolsize' ] == 0
150+
151+ # Copy the wallets to older nodes:
152+ node_master_wallets_dir = os .path .join (node_master .datadir , "regtest/wallets" )
153+ node_v18_wallets_dir = os .path .join (node_v18 .datadir , "regtest/wallets" )
154+ node_v17_wallets_dir = os .path .join (node_v17 .datadir , "regtest/wallets" )
155+ node_master .unloadwallet ("w1" )
156+ node_master .unloadwallet ("w2" )
157+ node_v18 .unloadwallet ("w1_v18" )
158+ node_v18 .unloadwallet ("w2_v18" )
159+
160+ # Copy wallets to v0.17
161+ for wallet in os .listdir (node_master_wallets_dir ):
162+ shutil .copytree (
163+ os .path .join (node_master_wallets_dir , wallet ),
164+ os .path .join (node_v17_wallets_dir , wallet )
165+ )
166+ for wallet in os .listdir (node_v18_wallets_dir ):
167+ shutil .copytree (
168+ os .path .join (node_v18_wallets_dir , wallet ),
169+ os .path .join (node_v17_wallets_dir , wallet )
170+ )
171+
172+ # Copy wallets to v0.18
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 (node_v18_wallets_dir , wallet )
177+ )
178+
179+ # Open the wallets in v0.18
180+ node_v18 .loadwallet ("w1" )
181+ wallet = node_v18 .get_wallet_rpc ("w1" )
182+ info = wallet .getwalletinfo ()
183+ assert info ['private_keys_enabled' ]
184+ assert info ['keypoolsize' ] > 0
185+ txs = wallet .listtransactions ()
186+ assert_equal (len (txs ), 5 )
187+ assert_equal (txs [1 ]["txid" ], tx1_id )
188+ assert_equal (txs [2 ]["walletconflicts" ], [tx1_id ])
189+ assert_equal (txs [1 ]["replaced_by_txid" ], tx2_id )
190+ assert not (txs [1 ]["abandoned" ])
191+ assert_equal (txs [1 ]["confirmations" ], - 1 )
192+ assert_equal (txs [2 ]["blockindex" ], 1 )
193+ assert txs [3 ]["abandoned" ]
194+ assert_equal (txs [4 ]["walletconflicts" ], [tx3_id ])
195+ assert_equal (txs [3 ]["replaced_by_txid" ], tx4_id )
196+ assert not (hasattr (txs [3 ], "blockindex" ))
197+
198+ node_v18 .loadwallet ("w2" )
199+ wallet = node_v18 .get_wallet_rpc ("w2" )
200+ info = wallet .getwalletinfo ()
201+ assert info ['private_keys_enabled' ] == False
202+ assert info ['keypoolsize' ] == 0
203+
204+ node_v18 .loadwallet ("w3" )
205+ wallet = node_v18 .get_wallet_rpc ("w3" )
206+ info = wallet .getwalletinfo ()
207+ assert info ['private_keys_enabled' ]
208+ assert info ['keypoolsize' ] == 0
209+
210+ # Open the wallets in v0.17
211+ node_v17 .loadwallet ("w1_v18" )
212+ wallet = node_v17 .get_wallet_rpc ("w1_v18" )
213+ info = wallet .getwalletinfo ()
214+ assert info ['private_keys_enabled' ]
215+ assert info ['keypoolsize' ] > 0
216+
217+ node_v17 .loadwallet ("w1" )
218+ wallet = node_v17 .get_wallet_rpc ("w1" )
219+ info = wallet .getwalletinfo ()
220+ assert info ['private_keys_enabled' ]
221+ assert info ['keypoolsize' ] > 0
222+
223+ node_v17 .loadwallet ("w2_v18" )
224+ wallet = node_v17 .get_wallet_rpc ("w2_v18" )
225+ info = wallet .getwalletinfo ()
226+ assert info ['private_keys_enabled' ] == False
227+ assert info ['keypoolsize' ] == 0
228+
229+ node_v17 .loadwallet ("w2" )
230+ wallet = node_v17 .get_wallet_rpc ("w2" )
231+ info = wallet .getwalletinfo ()
232+ assert info ['private_keys_enabled' ] == False
233+ assert info ['keypoolsize' ] == 0
234+
235+ # RPC loadwallet failure causes bitcoind to exit, in addition to the RPC
236+ # call failure, so the following test won't work:
237+ # assert_raises_rpc_error(-4, "Wallet loading failed.", node_v17.loadwallet, 'w3_v18')
238+
239+ # Instead, we stop node and try to launch it with the wallet:
240+ self .stop_node (self .num_nodes - 1 )
241+ node_v17 .assert_start_raises_init_error (["-wallet=w3_v18" ], "Error: Error loading w3_v18: Wallet requires newer version of Bitcoin Core" )
242+ node_v17 .assert_start_raises_init_error (["-wallet=w3" ], "Error: Error loading w3: Wallet requires newer version of Bitcoin Core" )
243+
77244if __name__ == '__main__' :
78245 BackwardsCompatibilityTest ().main ()
0 commit comments