2 # Copyright (c) 2014-2016 The Bitcoin Core developers
3 # Distributed under the MIT software license, see the accompanying
4 # file COPYING or http://www.opensource.org/licenses/mit-license.php.
7 Exercise the wallet backup code. Ported from walletbackup.sh.
10 4 nodes. 1 2 and 3 send transactions between each other,
11 fourth node is a miner.
12 1 2 3 each mine a block to start, then
13 Miner creates 100 blocks so 1 2 3 each have 50 mature
15 Then 5 iterations of 1/2/3 sending coins amongst
16 themselves to get transactions in the wallets,
17 and the miner mining one block.
19 Wallets are backed up using dumpwallet/backupwallet.
20 Then 5 more iterations of transactions and mining a block.
22 Miner then generates 101 more blocks, so any
23 transaction fees paid mature.
26 Sum(1,2,3,4 balances) == 114*50
28 1/2/3 are shutdown, and their wallets erased.
29 Then restore using wallet.dat backup. And
30 confirm 1/2/3/4 balances are same as before.
32 Shutdown again, restore using importwallet,
33 and confirm again balances are correct.
36 from test_framework
.test_framework
import BitcoinTestFramework
37 from test_framework
.util
import *
38 from random
import randint
40 logging
.basicConfig(format
='%(levelname)s: %(message)s', level
=logging
.INFO
, stream
=sys
.stdout
)
42 class WalletBackupTest(BitcoinTestFramework
):
46 self
.setup_clean_chain
= True
48 # nodes 1, 2,3 are spenders, let's give them a keypool=100
49 self
.extra_args
= [["-keypool=100"], ["-keypool=100"], ["-keypool=100"], []]
51 # This mirrors how the network was setup in the bash test
52 def setup_network(self
, split
=False):
53 self
.nodes
= start_nodes(self
.num_nodes
, self
.options
.tmpdir
, self
.extra_args
)
54 connect_nodes(self
.nodes
[0], 3)
55 connect_nodes(self
.nodes
[1], 3)
56 connect_nodes(self
.nodes
[2], 3)
57 connect_nodes(self
.nodes
[2], 0)
58 self
.is_network_split
=False
61 def one_send(self
, from_node
, to_address
):
62 if (randint(1,2) == 1):
63 amount
= Decimal(randint(1,10)) / Decimal(10)
64 self
.nodes
[from_node
].sendtoaddress(to_address
, amount
)
66 def do_one_round(self
):
67 a0
= self
.nodes
[0].getnewaddress()
68 a1
= self
.nodes
[1].getnewaddress()
69 a2
= self
.nodes
[2].getnewaddress()
78 # Have the miner (node3) mine a block.
79 # Must sync mempools before mining.
80 sync_mempools(self
.nodes
)
81 self
.nodes
[3].generate(1)
82 sync_blocks(self
.nodes
)
84 # As above, this mirrors the original bash test.
85 def start_three(self
):
86 self
.nodes
[0] = start_node(0, self
.options
.tmpdir
)
87 self
.nodes
[1] = start_node(1, self
.options
.tmpdir
)
88 self
.nodes
[2] = start_node(2, self
.options
.tmpdir
)
89 connect_nodes(self
.nodes
[0], 3)
90 connect_nodes(self
.nodes
[1], 3)
91 connect_nodes(self
.nodes
[2], 3)
92 connect_nodes(self
.nodes
[2], 0)
95 stop_node(self
.nodes
[0], 0)
96 stop_node(self
.nodes
[1], 1)
97 stop_node(self
.nodes
[2], 2)
99 def erase_three(self
):
100 os
.remove(self
.options
.tmpdir
+ "/node0/regtest/wallet.dat")
101 os
.remove(self
.options
.tmpdir
+ "/node1/regtest/wallet.dat")
102 os
.remove(self
.options
.tmpdir
+ "/node2/regtest/wallet.dat")
105 logging
.info("Generating initial blockchain")
106 self
.nodes
[0].generate(1)
107 sync_blocks(self
.nodes
)
108 self
.nodes
[1].generate(1)
109 sync_blocks(self
.nodes
)
110 self
.nodes
[2].generate(1)
111 sync_blocks(self
.nodes
)
112 self
.nodes
[3].generate(100)
113 sync_blocks(self
.nodes
)
115 assert_equal(self
.nodes
[0].getbalance(), 50)
116 assert_equal(self
.nodes
[1].getbalance(), 50)
117 assert_equal(self
.nodes
[2].getbalance(), 50)
118 assert_equal(self
.nodes
[3].getbalance(), 0)
120 logging
.info("Creating transactions")
121 # Five rounds of sending each other transactions.
125 logging
.info("Backing up")
126 tmpdir
= self
.options
.tmpdir
127 self
.nodes
[0].backupwallet(tmpdir
+ "/node0/wallet.bak")
128 self
.nodes
[0].dumpwallet(tmpdir
+ "/node0/wallet.dump")
129 self
.nodes
[1].backupwallet(tmpdir
+ "/node1/wallet.bak")
130 self
.nodes
[1].dumpwallet(tmpdir
+ "/node1/wallet.dump")
131 self
.nodes
[2].backupwallet(tmpdir
+ "/node2/wallet.bak")
132 self
.nodes
[2].dumpwallet(tmpdir
+ "/node2/wallet.dump")
134 logging
.info("More transactions")
138 # Generate 101 more blocks, so any fees paid mature
139 self
.nodes
[3].generate(101)
142 balance0
= self
.nodes
[0].getbalance()
143 balance1
= self
.nodes
[1].getbalance()
144 balance2
= self
.nodes
[2].getbalance()
145 balance3
= self
.nodes
[3].getbalance()
146 total
= balance0
+ balance1
+ balance2
+ balance3
148 # At this point, there are 214 blocks (103 for setup, then 10 rounds, then 101.)
149 # 114 are mature, so the sum of all wallets should be 114 * 50 = 5700.
150 assert_equal(total
, 5700)
153 # Test restoring spender wallets from backups
155 logging
.info("Restoring using wallet.dat")
159 # Start node2 with no chain
160 shutil
.rmtree(self
.options
.tmpdir
+ "/node2/regtest/blocks")
161 shutil
.rmtree(self
.options
.tmpdir
+ "/node2/regtest/chainstate")
163 # Restore wallets from backup
164 shutil
.copyfile(tmpdir
+ "/node0/wallet.bak", tmpdir
+ "/node0/regtest/wallet.dat")
165 shutil
.copyfile(tmpdir
+ "/node1/wallet.bak", tmpdir
+ "/node1/regtest/wallet.dat")
166 shutil
.copyfile(tmpdir
+ "/node2/wallet.bak", tmpdir
+ "/node2/regtest/wallet.dat")
168 logging
.info("Re-starting nodes")
170 sync_blocks(self
.nodes
)
172 assert_equal(self
.nodes
[0].getbalance(), balance0
)
173 assert_equal(self
.nodes
[1].getbalance(), balance1
)
174 assert_equal(self
.nodes
[2].getbalance(), balance2
)
176 logging
.info("Restoring using dumped wallet")
180 #start node2 with no chain
181 shutil
.rmtree(self
.options
.tmpdir
+ "/node2/regtest/blocks")
182 shutil
.rmtree(self
.options
.tmpdir
+ "/node2/regtest/chainstate")
186 assert_equal(self
.nodes
[0].getbalance(), 0)
187 assert_equal(self
.nodes
[1].getbalance(), 0)
188 assert_equal(self
.nodes
[2].getbalance(), 0)
190 self
.nodes
[0].importwallet(tmpdir
+ "/node0/wallet.dump")
191 self
.nodes
[1].importwallet(tmpdir
+ "/node1/wallet.dump")
192 self
.nodes
[2].importwallet(tmpdir
+ "/node2/wallet.dump")
194 sync_blocks(self
.nodes
)
196 assert_equal(self
.nodes
[0].getbalance(), balance0
)
197 assert_equal(self
.nodes
[1].getbalance(), balance1
)
198 assert_equal(self
.nodes
[2].getbalance(), balance2
)
201 if __name__
== '__main__':
202 WalletBackupTest().main()