6
6
7
7
Test the following RPCs:
8
8
- getblockchaininfo
9
+ - getchaintxstats
9
10
- gettxoutsetinfo
10
- - getdifficulty
11
- - getbestblockhash
12
- - getblockhash
13
11
- getblockheader
14
- - getchaintxstats
12
+ - getdifficulty
15
13
- getnetworkhashps
14
+ - waitforblockheight
15
+ - getblock
16
+ - getblockhash
17
+ - getbestblockhash
16
18
- verifychain
17
19
18
20
Tests correspond to code in rpc/blockchain.cpp.
49
51
from test_framework .wallet import MiniWallet
50
52
51
53
54
+ HEIGHT = 200 # blocks mined
55
+ TIME_RANGE_STEP = 600 # ten-minute steps
56
+ TIME_RANGE_MTP = TIME_GENESIS_BLOCK + (HEIGHT - 6 ) * TIME_RANGE_STEP
57
+ TIME_RANGE_END = TIME_GENESIS_BLOCK + HEIGHT * TIME_RANGE_STEP
58
+
59
+
52
60
class BlockchainTest (BitcoinTestFramework ):
53
61
def set_test_params (self ):
54
62
self .setup_clean_chain = True
@@ -71,12 +79,11 @@ def run_test(self):
71
79
assert self .nodes [0 ].verifychain (4 , 0 )
72
80
73
81
def mine_chain (self ):
74
- self .log .info ('Create some old blocks' )
75
- for t in range (TIME_GENESIS_BLOCK , TIME_GENESIS_BLOCK + 200 * 600 , 600 ):
76
- # ten-minute steps from genesis block time
82
+ self .log .info (f"Generate { HEIGHT } blocks after the genesis block in ten-minute steps" )
83
+ for t in range (TIME_GENESIS_BLOCK , TIME_RANGE_END , TIME_RANGE_STEP ):
77
84
self .nodes [0 ].setmocktime (t )
78
85
self .nodes [0 ].generatetoaddress (1 , ADDRESS_BCRT1_P2WSH_OP_TRUE )
79
- assert_equal (self .nodes [0 ].getblockchaininfo ()['blocks' ], 200 )
86
+ assert_equal (self .nodes [0 ].getblockchaininfo ()['blocks' ], HEIGHT )
80
87
81
88
def _test_getblockchaininfo (self ):
82
89
self .log .info ("Test getblockchaininfo" )
@@ -99,7 +106,8 @@ def _test_getblockchaininfo(self):
99
106
]
100
107
res = self .nodes [0 ].getblockchaininfo ()
101
108
102
- assert isinstance (res ['time' ], int )
109
+ assert_equal (res ['time' ], TIME_RANGE_END - TIME_RANGE_STEP )
110
+ assert_equal (res ['mediantime' ], TIME_RANGE_MTP )
103
111
104
112
# result should have these additional pruning keys if manual pruning is enabled
105
113
assert_equal (sorted (res .keys ()), sorted (['pruneheight' , 'automatic_pruning' ] + keys ))
@@ -148,8 +156,8 @@ def _test_getblockchaininfo(self):
148
156
'statistics' : {
149
157
'period' : 144 ,
150
158
'threshold' : 108 ,
151
- 'elapsed' : 57 ,
152
- 'count' : 57 ,
159
+ 'elapsed' : HEIGHT - 143 ,
160
+ 'count' : HEIGHT - 143 ,
153
161
'possible' : True ,
154
162
},
155
163
'min_activation_height' : 0 ,
@@ -186,33 +194,33 @@ def _test_getchaintxstats(self):
186
194
assert_raises_rpc_error (- 8 , "blockhash must be of length 64 (not 1, for '0')" , self .nodes [0 ].getchaintxstats , blockhash = '0' )
187
195
assert_raises_rpc_error (- 8 , "blockhash must be hexadecimal string (not 'ZZZ0000000000000000000000000000000000000000000000000000000000000')" , self .nodes [0 ].getchaintxstats , blockhash = 'ZZZ0000000000000000000000000000000000000000000000000000000000000' )
188
196
assert_raises_rpc_error (- 5 , "Block not found" , self .nodes [0 ].getchaintxstats , blockhash = '0000000000000000000000000000000000000000000000000000000000000000' )
189
- blockhash = self .nodes [0 ].getblockhash (200 )
197
+ blockhash = self .nodes [0 ].getblockhash (HEIGHT )
190
198
self .nodes [0 ].invalidateblock (blockhash )
191
199
assert_raises_rpc_error (- 8 , "Block is not in main chain" , self .nodes [0 ].getchaintxstats , blockhash = blockhash )
192
200
self .nodes [0 ].reconsiderblock (blockhash )
193
201
194
202
chaintxstats = self .nodes [0 ].getchaintxstats (nblocks = 1 )
195
203
# 200 txs plus genesis tx
196
- assert_equal (chaintxstats ['txcount' ], 201 )
204
+ assert_equal (chaintxstats ['txcount' ], HEIGHT + 1 )
197
205
# tx rate should be 1 per 10 minutes, or 1/600
198
206
# we have to round because of binary math
199
- assert_equal (round (chaintxstats ['txrate' ] * 600 , 10 ), Decimal (1 ))
207
+ assert_equal (round (chaintxstats ['txrate' ] * TIME_RANGE_STEP , 10 ), Decimal (1 ))
200
208
201
209
b1_hash = self .nodes [0 ].getblockhash (1 )
202
210
b1 = self .nodes [0 ].getblock (b1_hash )
203
- b200_hash = self .nodes [0 ].getblockhash (200 )
211
+ b200_hash = self .nodes [0 ].getblockhash (HEIGHT )
204
212
b200 = self .nodes [0 ].getblock (b200_hash )
205
213
time_diff = b200 ['mediantime' ] - b1 ['mediantime' ]
206
214
207
215
chaintxstats = self .nodes [0 ].getchaintxstats ()
208
216
assert_equal (chaintxstats ['time' ], b200 ['time' ])
209
- assert_equal (chaintxstats ['txcount' ], 201 )
217
+ assert_equal (chaintxstats ['txcount' ], HEIGHT + 1 )
210
218
assert_equal (chaintxstats ['window_final_block_hash' ], b200_hash )
211
- assert_equal (chaintxstats ['window_final_block_height' ], 200 )
212
- assert_equal (chaintxstats ['window_block_count' ], 199 )
213
- assert_equal (chaintxstats ['window_tx_count' ], 199 )
219
+ assert_equal (chaintxstats ['window_final_block_height' ], HEIGHT )
220
+ assert_equal (chaintxstats ['window_block_count' ], HEIGHT - 1 )
221
+ assert_equal (chaintxstats ['window_tx_count' ], HEIGHT - 1 )
214
222
assert_equal (chaintxstats ['window_interval' ], time_diff )
215
- assert_equal (round (chaintxstats ['txrate' ] * time_diff , 10 ), Decimal (199 ))
223
+ assert_equal (round (chaintxstats ['txrate' ] * time_diff , 10 ), Decimal (HEIGHT - 1 ))
216
224
217
225
chaintxstats = self .nodes [0 ].getchaintxstats (blockhash = b1_hash )
218
226
assert_equal (chaintxstats ['time' ], b1 ['time' ])
@@ -229,18 +237,18 @@ def _test_gettxoutsetinfo(self):
229
237
res = node .gettxoutsetinfo ()
230
238
231
239
assert_equal (res ['total_amount' ], Decimal ('8725.00000000' ))
232
- assert_equal (res ['transactions' ], 200 )
233
- assert_equal (res ['height' ], 200 )
234
- assert_equal (res ['txouts' ], 200 )
240
+ assert_equal (res ['transactions' ], HEIGHT )
241
+ assert_equal (res ['height' ], HEIGHT )
242
+ assert_equal (res ['txouts' ], HEIGHT )
235
243
assert_equal (res ['bogosize' ], 16800 ),
236
- assert_equal (res ['bestblock' ], node .getblockhash (200 ))
244
+ assert_equal (res ['bestblock' ], node .getblockhash (HEIGHT ))
237
245
size = res ['disk_size' ]
238
246
assert size > 6400
239
247
assert size < 64000
240
248
assert_equal (len (res ['bestblock' ]), 64 )
241
249
assert_equal (len (res ['hash_serialized_2' ]), 64 )
242
250
243
- self .log .info ("Test that gettxoutsetinfo() works for blockchain with just the genesis block" )
251
+ self .log .info ("Test gettxoutsetinfo works for blockchain with just the genesis block" )
244
252
b1hash = node .getblockhash (1 )
245
253
node .invalidateblock (b1hash )
246
254
@@ -253,7 +261,7 @@ def _test_gettxoutsetinfo(self):
253
261
assert_equal (res2 ['bestblock' ], node .getblockhash (0 ))
254
262
assert_equal (len (res2 ['hash_serialized_2' ]), 64 )
255
263
256
- self .log .info ("Test that gettxoutsetinfo() returns the same result after invalidate/reconsider block" )
264
+ self .log .info ("Test gettxoutsetinfo returns the same result after invalidate/reconsider block" )
257
265
node .reconsiderblock (b1hash )
258
266
259
267
res3 = node .gettxoutsetinfo ()
@@ -262,7 +270,7 @@ def _test_gettxoutsetinfo(self):
262
270
del res ['disk_size' ], res3 ['disk_size' ]
263
271
assert_equal (res , res3 )
264
272
265
- self .log .info ("Test hash_type option for gettxoutsetinfo() " )
273
+ self .log .info ("Test gettxoutsetinfo hash_type option" )
266
274
# Adding hash_type 'hash_serialized_2', which is the default, should
267
275
# not change the result.
268
276
res4 = node .gettxoutsetinfo (hash_type = 'hash_serialized_2' )
@@ -286,18 +294,19 @@ def _test_gettxoutsetinfo(self):
286
294
assert_raises_rpc_error (- 8 , "foohash is not a valid hash_type" , node .gettxoutsetinfo , "foohash" )
287
295
288
296
def _test_getblockheader (self ):
297
+ self .log .info ("Test getblockheader" )
289
298
node = self .nodes [0 ]
290
299
291
300
assert_raises_rpc_error (- 8 , "hash must be of length 64 (not 8, for 'nonsense')" , node .getblockheader , "nonsense" )
292
301
assert_raises_rpc_error (- 8 , "hash must be hexadecimal string (not 'ZZZ7bb8b1697ea987f3b223ba7819250cae33efacb068d23dc24859824a77844')" , node .getblockheader , "ZZZ7bb8b1697ea987f3b223ba7819250cae33efacb068d23dc24859824a77844" )
293
302
assert_raises_rpc_error (- 5 , "Block not found" , node .getblockheader , "0cf7bb8b1697ea987f3b223ba7819250cae33efacb068d23dc24859824a77844" )
294
303
295
304
besthash = node .getbestblockhash ()
296
- secondbesthash = node .getblockhash (199 )
305
+ secondbesthash = node .getblockhash (HEIGHT - 1 )
297
306
header = node .getblockheader (blockhash = besthash )
298
307
299
308
assert_equal (header ['hash' ], besthash )
300
- assert_equal (header ['height' ], 200 )
309
+ assert_equal (header ['height' ], HEIGHT )
301
310
assert_equal (header ['confirmations' ], 1 )
302
311
assert_equal (header ['previousblockhash' ], secondbesthash )
303
312
assert_is_hex_string (header ['chainwork' ])
@@ -307,7 +316,7 @@ def _test_getblockheader(self):
307
316
assert_is_hash_string (header ['merkleroot' ])
308
317
assert_is_hash_string (header ['bits' ], length = None )
309
318
assert isinstance (header ['time' ], int )
310
- assert isinstance (header ['mediantime' ], int )
319
+ assert_equal (header ['mediantime' ], TIME_RANGE_MTP )
311
320
assert isinstance (header ['nonce' ], int )
312
321
assert isinstance (header ['version' ], int )
313
322
assert isinstance (int (header ['versionHex' ], 16 ), int )
@@ -325,20 +334,23 @@ def _test_getblockheader(self):
325
334
assert 'nextblockhash' not in node .getblockheader (node .getbestblockhash ())
326
335
327
336
def _test_getdifficulty (self ):
337
+ self .log .info ("Test getdifficulty" )
328
338
difficulty = self .nodes [0 ].getdifficulty ()
329
339
# 1 hash in 2 should be valid, so difficulty should be 1/2**31
330
340
# binary => decimal => binary math is why we do this check
331
341
assert abs (difficulty * 2 ** 31 - 1 ) < 0.0001
332
342
333
343
def _test_getnetworkhashps (self ):
344
+ self .log .info ("Test getnetworkhashps" )
334
345
hashes_per_second = self .nodes [0 ].getnetworkhashps ()
335
346
# This should be 2 hashes every 10 minutes or 1/300
336
347
assert abs (hashes_per_second * 300 - 1 ) < 0.0001
337
348
338
349
def _test_stopatheight (self ):
339
- assert_equal (self .nodes [0 ].getblockcount (), 200 )
350
+ self .log .info ("Test stopping at height" )
351
+ assert_equal (self .nodes [0 ].getblockcount (), HEIGHT )
340
352
self .nodes [0 ].generatetoaddress (6 , ADDRESS_BCRT1_P2WSH_OP_TRUE )
341
- assert_equal (self .nodes [0 ].getblockcount (), 206 )
353
+ assert_equal (self .nodes [0 ].getblockcount (), HEIGHT + 6 )
342
354
self .log .debug ('Node should not stop at this height' )
343
355
assert_raises (subprocess .TimeoutExpired , lambda : self .nodes [0 ].process .wait (timeout = 3 ))
344
356
try :
@@ -348,7 +360,7 @@ def _test_stopatheight(self):
348
360
self .log .debug ('Node should stop at this height...' )
349
361
self .nodes [0 ].wait_until_stopped ()
350
362
self .start_node (0 )
351
- assert_equal (self .nodes [0 ].getblockcount (), 207 )
363
+ assert_equal (self .nodes [0 ].getblockcount (), HEIGHT + 7 )
352
364
353
365
def _test_waitforblockheight (self ):
354
366
self .log .info ("Test waitforblockheight" )
@@ -400,20 +412,20 @@ def _test_getblock(self):
400
412
miniwallet .send_self_transfer (fee_rate = fee_per_kb , from_node = node )
401
413
blockhash = node .generate (1 )[0 ]
402
414
403
- self .log .info ("Test that getblock with verbosity 1 doesn't include fee" )
415
+ self .log .info ("Test getblock with verbosity 1 doesn't include fee" )
404
416
block = node .getblock (blockhash , 1 )
405
417
assert 'fee' not in block ['tx' ][1 ]
406
418
407
- self .log .info ('Test that getblock with verbosity 2 includes expected fee' )
419
+ self .log .info ('Test getblock with verbosity 2 includes expected fee' )
408
420
block = node .getblock (blockhash , 2 )
409
421
tx = block ['tx' ][1 ]
410
422
assert 'fee' in tx
411
423
assert_equal (tx ['fee' ], tx ['vsize' ] * fee_per_byte )
412
424
413
- self .log .info ("Test that getblock with verbosity 2 still works with pruned Undo data" )
425
+ self .log .info ("Test getblock with verbosity 2 still works with pruned Undo data" )
414
426
datadir = get_datadir_path (self .options .tmpdir , 0 )
415
427
416
- self .log .info ("Test that getblock with invalid verbosity type returns proper error message" )
428
+ self .log .info ("Test getblock with invalid verbosity type returns proper error message" )
417
429
assert_raises_rpc_error (- 1 , "JSON value is not an integer as expected" , node .getblock , blockhash , "2" )
418
430
419
431
def move_block_file (old , new ):
0 commit comments