Remove unused Python imports
[bitcoinplatinum.git] / test / functional / blockchain.py
blob49fafbc9aa5de1aead0936a68fdf2cc4152688bb
1 #!/usr/bin/env python3
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.
5 """Test RPCs related to blockchainstate.
7 Test the following RPCs:
8 - getblockchaininfo
9 - gettxoutsetinfo
10 - getdifficulty
11 - getbestblockhash
12 - getblockhash
13 - getblockheader
14 - getchaintxstats
15 - getnetworkhashps
16 - verifychain
18 Tests correspond to code in rpc/blockchain.cpp.
19 """
21 from decimal import Decimal
22 import http.client
23 import subprocess
25 from test_framework.test_framework import BitcoinTestFramework
26 from test_framework.util import (
27 assert_equal,
28 assert_greater_than,
29 assert_greater_than_or_equal,
30 assert_raises,
31 assert_raises_rpc_error,
32 assert_is_hex_string,
33 assert_is_hash_string,
36 class BlockchainTest(BitcoinTestFramework):
37 def set_test_params(self):
38 self.num_nodes = 1
39 self.extra_args = [['-stopatheight=207', '-prune=1']]
41 def run_test(self):
42 self._test_getblockchaininfo()
43 self._test_getchaintxstats()
44 self._test_gettxoutsetinfo()
45 self._test_getblockheader()
46 self._test_getdifficulty()
47 self._test_getnetworkhashps()
48 self._test_stopatheight()
49 assert self.nodes[0].verifychain(4, 0)
51 def _test_getblockchaininfo(self):
52 self.log.info("Test getblockchaininfo")
54 keys = [
55 'bestblockhash',
56 'bip9_softforks',
57 'blocks',
58 'chain',
59 'chainwork',
60 'difficulty',
61 'headers',
62 'initialblockdownload',
63 'mediantime',
64 'pruned',
65 'size_on_disk',
66 'softforks',
67 'verificationprogress',
68 'warnings',
70 res = self.nodes[0].getblockchaininfo()
72 # result should have these additional pruning keys if manual pruning is enabled
73 assert_equal(sorted(res.keys()), sorted(['pruneheight', 'automatic_pruning'] + keys))
75 # size_on_disk should be > 0
76 assert_greater_than(res['size_on_disk'], 0)
78 # pruneheight should be greater or equal to 0
79 assert_greater_than_or_equal(res['pruneheight'], 0)
81 # check other pruning fields given that prune=1
82 assert res['pruned']
83 assert not res['automatic_pruning']
85 self.restart_node(0, ['-stopatheight=207'])
86 res = self.nodes[0].getblockchaininfo()
87 # should have exact keys
88 assert_equal(sorted(res.keys()), keys)
90 self.restart_node(0, ['-stopatheight=207', '-prune=550'])
91 res = self.nodes[0].getblockchaininfo()
92 # result should have these additional pruning keys if prune=550
93 assert_equal(sorted(res.keys()), sorted(['pruneheight', 'automatic_pruning', 'prune_target_size'] + keys))
95 # check related fields
96 assert res['pruned']
97 assert_equal(res['pruneheight'], 0)
98 assert res['automatic_pruning']
99 assert_equal(res['prune_target_size'], 576716800)
100 assert_greater_than(res['size_on_disk'], 0)
102 def _test_getchaintxstats(self):
103 chaintxstats = self.nodes[0].getchaintxstats(1)
104 # 200 txs plus genesis tx
105 assert_equal(chaintxstats['txcount'], 201)
106 # tx rate should be 1 per 10 minutes, or 1/600
107 # we have to round because of binary math
108 assert_equal(round(chaintxstats['txrate'] * 600, 10), Decimal(1))
110 b1 = self.nodes[0].getblock(self.nodes[0].getblockhash(1))
111 b200 = self.nodes[0].getblock(self.nodes[0].getblockhash(200))
112 time_diff = b200['mediantime'] - b1['mediantime']
114 chaintxstats = self.nodes[0].getchaintxstats()
115 assert_equal(chaintxstats['time'], b200['time'])
116 assert_equal(chaintxstats['txcount'], 201)
117 assert_equal(chaintxstats['window_block_count'], 199)
118 assert_equal(chaintxstats['window_tx_count'], 199)
119 assert_equal(chaintxstats['window_interval'], time_diff)
120 assert_equal(round(chaintxstats['txrate'] * time_diff, 10), Decimal(199))
122 chaintxstats = self.nodes[0].getchaintxstats(blockhash=b1['hash'])
123 assert_equal(chaintxstats['time'], b1['time'])
124 assert_equal(chaintxstats['txcount'], 2)
125 assert_equal(chaintxstats['window_block_count'], 0)
126 assert('window_tx_count' not in chaintxstats)
127 assert('window_interval' not in chaintxstats)
128 assert('txrate' not in chaintxstats)
130 assert_raises_rpc_error(-8, "Invalid block count: should be between 0 and the block's height - 1", self.nodes[0].getchaintxstats, 201)
132 def _test_gettxoutsetinfo(self):
133 node = self.nodes[0]
134 res = node.gettxoutsetinfo()
136 assert_equal(res['total_amount'], Decimal('8725.00000000'))
137 assert_equal(res['transactions'], 200)
138 assert_equal(res['height'], 200)
139 assert_equal(res['txouts'], 200)
140 assert_equal(res['bogosize'], 17000),
141 assert_equal(res['bestblock'], node.getblockhash(200))
142 size = res['disk_size']
143 assert size > 6400
144 assert size < 64000
145 assert_equal(len(res['bestblock']), 64)
146 assert_equal(len(res['hash_serialized_2']), 64)
148 self.log.info("Test that gettxoutsetinfo() works for blockchain with just the genesis block")
149 b1hash = node.getblockhash(1)
150 node.invalidateblock(b1hash)
152 res2 = node.gettxoutsetinfo()
153 assert_equal(res2['transactions'], 0)
154 assert_equal(res2['total_amount'], Decimal('0'))
155 assert_equal(res2['height'], 0)
156 assert_equal(res2['txouts'], 0)
157 assert_equal(res2['bogosize'], 0),
158 assert_equal(res2['bestblock'], node.getblockhash(0))
159 assert_equal(len(res2['hash_serialized_2']), 64)
161 self.log.info("Test that gettxoutsetinfo() returns the same result after invalidate/reconsider block")
162 node.reconsiderblock(b1hash)
164 res3 = node.gettxoutsetinfo()
165 assert_equal(res['total_amount'], res3['total_amount'])
166 assert_equal(res['transactions'], res3['transactions'])
167 assert_equal(res['height'], res3['height'])
168 assert_equal(res['txouts'], res3['txouts'])
169 assert_equal(res['bogosize'], res3['bogosize'])
170 assert_equal(res['bestblock'], res3['bestblock'])
171 assert_equal(res['hash_serialized_2'], res3['hash_serialized_2'])
173 def _test_getblockheader(self):
174 node = self.nodes[0]
176 assert_raises_rpc_error(-5, "Block not found",
177 node.getblockheader, "nonsense")
179 besthash = node.getbestblockhash()
180 secondbesthash = node.getblockhash(199)
181 header = node.getblockheader(besthash)
183 assert_equal(header['hash'], besthash)
184 assert_equal(header['height'], 200)
185 assert_equal(header['confirmations'], 1)
186 assert_equal(header['previousblockhash'], secondbesthash)
187 assert_is_hex_string(header['chainwork'])
188 assert_is_hash_string(header['hash'])
189 assert_is_hash_string(header['previousblockhash'])
190 assert_is_hash_string(header['merkleroot'])
191 assert_is_hash_string(header['bits'], length=None)
192 assert isinstance(header['time'], int)
193 assert isinstance(header['mediantime'], int)
194 assert isinstance(header['nonce'], int)
195 assert isinstance(header['version'], int)
196 assert isinstance(int(header['versionHex'], 16), int)
197 assert isinstance(header['difficulty'], Decimal)
199 def _test_getdifficulty(self):
200 difficulty = self.nodes[0].getdifficulty()
201 # 1 hash in 2 should be valid, so difficulty should be 1/2**31
202 # binary => decimal => binary math is why we do this check
203 assert abs(difficulty * 2**31 - 1) < 0.0001
205 def _test_getnetworkhashps(self):
206 hashes_per_second = self.nodes[0].getnetworkhashps()
207 # This should be 2 hashes every 10 minutes or 1/300
208 assert abs(hashes_per_second * 300 - 1) < 0.0001
210 def _test_stopatheight(self):
211 assert_equal(self.nodes[0].getblockcount(), 200)
212 self.nodes[0].generate(6)
213 assert_equal(self.nodes[0].getblockcount(), 206)
214 self.log.debug('Node should not stop at this height')
215 assert_raises(subprocess.TimeoutExpired, lambda: self.nodes[0].process.wait(timeout=3))
216 try:
217 self.nodes[0].generate(1)
218 except (ConnectionError, http.client.BadStatusLine):
219 pass # The node already shut down before response
220 self.log.debug('Node should stop at this height...')
221 self.nodes[0].wait_until_stopped()
222 self.start_node(0)
223 assert_equal(self.nodes[0].getblockcount(), 207)
226 if __name__ == '__main__':
227 BlockchainTest().main()