16
16
"""
17
17
18
18
import os
19
+ import shutil
19
20
20
21
from test_framework .test_framework import BitcoinTestFramework , SkipTest
21
22
22
23
from test_framework .util import (
23
24
assert_equal ,
24
- sync_blocks
25
+ sync_blocks ,
26
+ sync_mempools
25
27
)
26
28
27
29
class BackwardsCompatibilityTest (BitcoinTestFramework ):
@@ -30,10 +32,10 @@ def set_test_params(self):
30
32
self .num_nodes = 4
31
33
# Add new version after each release:
32
34
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
37
39
]
38
40
39
41
def setup_nodes (self ):
@@ -66,13 +68,178 @@ def setup_nodes(self):
66
68
self .start_nodes ()
67
69
68
70
def run_test (self ):
69
- self .nodes [0 ].generate (101 )
71
+ self .nodes [0 ].generatetoaddress (101 , self . nodes [ 0 ]. getnewaddress () )
70
72
71
73
sync_blocks (self .nodes )
72
74
73
75
# Sanity check the test framework:
74
76
res = self .nodes [self .num_nodes - 1 ].getblockchaininfo ()
75
77
assert_equal (res ['blocks' ], 101 )
76
78
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
+
77
244
if __name__ == '__main__' :
78
245
BackwardsCompatibilityTest ().main ()
0 commit comments