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 = 156 # 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
@@ -72,9 +80,9 @@ def run_test(self):
72
80
assert self .nodes [0 ].verifychain (4 , 0 )
73
81
74
82
def mine_chain (self ):
75
- self .log .info ('Create some old blocks' )
83
+ self .log .info (f"Generate { HEIGHT } blocks after the genesis block in 156 sec" )
76
84
address = self .nodes [0 ].get_deterministic_priv_key ().address
77
- for t in range (TIME_GENESIS_BLOCK , TIME_GENESIS_BLOCK + 200 * 156 , 156 ):
85
+ for t in range (TIME_GENESIS_BLOCK , TIME_RANGE_END , TIME_RANGE_STEP ):
78
86
# 156 sec steps from genesis block time
79
87
set_node_times (self .nodes , t )
80
88
self .nodes [0 ].generatetoaddress (1 , address )
@@ -101,7 +109,8 @@ def _test_getblockchaininfo(self):
101
109
]
102
110
res = self .nodes [0 ].getblockchaininfo ()
103
111
104
- assert isinstance (res ['time' ], int )
112
+ assert_equal (res ['time' ], TIME_RANGE_END - TIME_RANGE_STEP )
113
+ assert_equal (res ['mediantime' ], TIME_RANGE_MTP )
105
114
106
115
# result should have these additional pruning keys if manual pruning is enabled
107
116
assert_equal (sorted (res .keys ()), sorted (['pruneheight' , 'automatic_pruning' ] + keys ))
@@ -177,8 +186,8 @@ def _test_getblockchaininfo(self):
177
186
'statistics' : {
178
187
'period' : 144 ,
179
188
'threshold' : 108 ,
180
- 'elapsed' : 57 ,
181
- 'count' : 57 ,
189
+ 'elapsed' : HEIGHT - 143 ,
190
+ 'count' : HEIGHT - 143 ,
182
191
'possible' : True ,
183
192
},
184
193
'min_activation_height' : 0 ,
@@ -203,33 +212,33 @@ def _test_getchaintxstats(self):
203
212
assert_raises_rpc_error (- 8 , "blockhash must be of length 64 (not 1, for '0')" , self .nodes [0 ].getchaintxstats , blockhash = '0' )
204
213
assert_raises_rpc_error (- 8 , "blockhash must be hexadecimal string (not 'ZZZ0000000000000000000000000000000000000000000000000000000000000')" , self .nodes [0 ].getchaintxstats , blockhash = 'ZZZ0000000000000000000000000000000000000000000000000000000000000' )
205
214
assert_raises_rpc_error (- 5 , "Block not found" , self .nodes [0 ].getchaintxstats , blockhash = '0000000000000000000000000000000000000000000000000000000000000000' )
206
- blockhash = self .nodes [0 ].getblockhash (200 )
215
+ blockhash = self .nodes [0 ].getblockhash (HEIGHT )
207
216
self .nodes [0 ].invalidateblock (blockhash )
208
217
assert_raises_rpc_error (- 8 , "Block is not in main chain" , self .nodes [0 ].getchaintxstats , blockhash = blockhash )
209
218
self .nodes [0 ].reconsiderblock (blockhash )
210
219
211
220
chaintxstats = self .nodes [0 ].getchaintxstats (nblocks = 1 )
212
221
# 200 txs plus genesis tx
213
- assert_equal (chaintxstats ['txcount' ], 201 )
222
+ assert_equal (chaintxstats ['txcount' ], HEIGHT + 1 )
214
223
# tx rate should be 1 per ~2.6 minutes (156 seconds), or 1/156
215
224
# we have to round because of binary math
216
- assert_equal (round (chaintxstats ['txrate' ] * 156 , 10 ), Decimal (1 ))
225
+ assert_equal (round (chaintxstats ['txrate' ] * TIME_RANGE_STEP , 10 ), Decimal (1 ))
217
226
218
227
b1_hash = self .nodes [0 ].getblockhash (1 )
219
228
b1 = self .nodes [0 ].getblock (b1_hash )
220
- b200_hash = self .nodes [0 ].getblockhash (200 )
229
+ b200_hash = self .nodes [0 ].getblockhash (HEIGHT )
221
230
b200 = self .nodes [0 ].getblock (b200_hash )
222
231
time_diff = b200 ['mediantime' ] - b1 ['mediantime' ]
223
232
224
233
chaintxstats = self .nodes [0 ].getchaintxstats ()
225
234
assert_equal (chaintxstats ['time' ], b200 ['time' ])
226
- assert_equal (chaintxstats ['txcount' ], 201 )
235
+ assert_equal (chaintxstats ['txcount' ], HEIGHT + 1 )
227
236
assert_equal (chaintxstats ['window_final_block_hash' ], b200_hash )
228
- assert_equal (chaintxstats ['window_final_block_height' ], 200 )
229
- assert_equal (chaintxstats ['window_block_count' ], 199 )
230
- assert_equal (chaintxstats ['window_tx_count' ], 199 )
237
+ assert_equal (chaintxstats ['window_final_block_height' ], HEIGHT )
238
+ assert_equal (chaintxstats ['window_block_count' ], HEIGHT - 1 )
239
+ assert_equal (chaintxstats ['window_tx_count' ], HEIGHT - 1 )
231
240
assert_equal (chaintxstats ['window_interval' ], time_diff )
232
- assert_equal (round (chaintxstats ['txrate' ] * time_diff , 10 ), Decimal (199 ))
241
+ assert_equal (round (chaintxstats ['txrate' ] * time_diff , 10 ), Decimal (HEIGHT - 1 ))
233
242
234
243
chaintxstats = self .nodes [0 ].getchaintxstats (blockhash = b1_hash )
235
244
assert_equal (chaintxstats ['time' ], b1 ['time' ])
@@ -246,17 +255,17 @@ def _test_gettxoutsetinfo(self):
246
255
res = node .gettxoutsetinfo ()
247
256
248
257
assert_equal (res ['total_amount' ], Decimal ('98214.28571450' ))
249
- assert_equal (res ['transactions' ], 200 )
250
- assert_equal (res ['height' ], 200 )
251
- assert_equal (res ['txouts' ], 200 )
258
+ assert_equal (res ['transactions' ], HEIGHT )
259
+ assert_equal (res ['height' ], HEIGHT )
260
+ assert_equal (res ['txouts' ], HEIGHT )
252
261
assert_equal (res ['bogosize' ], 15000 ),
253
262
size = res ['disk_size' ]
254
263
assert size > 6400
255
264
assert size < 64000
256
265
assert_equal (len (res ['bestblock' ]), 64 )
257
266
assert_equal (len (res ['hash_serialized_2' ]), 64 )
258
267
259
- self .log .info ("Test that gettxoutsetinfo() works for blockchain with just the genesis block" )
268
+ self .log .info ("Test gettxoutsetinfo works for blockchain with just the genesis block" )
260
269
b1hash = node .getblockhash (1 )
261
270
node .invalidateblock (b1hash )
262
271
@@ -269,7 +278,7 @@ def _test_gettxoutsetinfo(self):
269
278
assert_equal (res2 ['bestblock' ], node .getblockhash (0 ))
270
279
assert_equal (len (res2 ['hash_serialized_2' ]), 64 )
271
280
272
- self .log .info ("Test that gettxoutsetinfo() returns the same result after invalidate/reconsider block" )
281
+ self .log .info ("Test gettxoutsetinfo returns the same result after invalidate/reconsider block" )
273
282
node .reconsiderblock (b1hash )
274
283
275
284
res3 = node .gettxoutsetinfo ()
@@ -278,7 +287,7 @@ def _test_gettxoutsetinfo(self):
278
287
del res ['disk_size' ], res3 ['disk_size' ]
279
288
assert_equal (res , res3 )
280
289
281
- self .log .info ("Test hash_type option for gettxoutsetinfo() " )
290
+ self .log .info ("Test gettxoutsetinfo hash_type option" )
282
291
# Adding hash_type 'hash_serialized_2', which is the default, should
283
292
# not change the result.
284
293
res4 = node .gettxoutsetinfo (hash_type = 'hash_serialized_2' )
@@ -302,18 +311,19 @@ def _test_gettxoutsetinfo(self):
302
311
assert_raises_rpc_error (- 8 , "foohash is not a valid hash_type" , node .gettxoutsetinfo , "foohash" )
303
312
304
313
def _test_getblockheader (self ):
314
+ self .log .info ("Test getblockheader" )
305
315
node = self .nodes [0 ]
306
316
307
317
assert_raises_rpc_error (- 8 , "hash must be of length 64 (not 8, for 'nonsense')" , node .getblockheader , "nonsense" )
308
318
assert_raises_rpc_error (- 8 , "hash must be hexadecimal string (not 'ZZZ7bb8b1697ea987f3b223ba7819250cae33efacb068d23dc24859824a77844')" , node .getblockheader , "ZZZ7bb8b1697ea987f3b223ba7819250cae33efacb068d23dc24859824a77844" )
309
319
assert_raises_rpc_error (- 5 , "Block not found" , node .getblockheader , "0cf7bb8b1697ea987f3b223ba7819250cae33efacb068d23dc24859824a77844" )
310
320
311
321
besthash = node .getbestblockhash ()
312
- secondbesthash = node .getblockhash (199 )
322
+ secondbesthash = node .getblockhash (HEIGHT - 1 )
313
323
header = node .getblockheader (blockhash = besthash )
314
324
315
325
assert_equal (header ['hash' ], besthash )
316
- assert_equal (header ['height' ], 200 )
326
+ assert_equal (header ['height' ], HEIGHT )
317
327
assert_equal (header ['confirmations' ], 1 )
318
328
assert_equal (header ['previousblockhash' ], secondbesthash )
319
329
assert_is_hex_string (header ['chainwork' ])
@@ -323,7 +333,7 @@ def _test_getblockheader(self):
323
333
assert_is_hash_string (header ['merkleroot' ])
324
334
assert_is_hash_string (header ['bits' ], length = None )
325
335
assert isinstance (header ['time' ], int )
326
- assert isinstance (header ['mediantime' ], int )
336
+ assert_equal (header ['mediantime' ], TIME_RANGE_MTP )
327
337
assert isinstance (header ['nonce' ], int )
328
338
assert isinstance (header ['version' ], int )
329
339
assert isinstance (int (header ['versionHex' ], 16 ), int )
@@ -341,20 +351,22 @@ def _test_getblockheader(self):
341
351
assert 'nextblockhash' not in node .getblockheader (node .getbestblockhash ())
342
352
343
353
def _test_getdifficulty (self ):
354
+ self .log .info ("Test getdifficulty" )
344
355
difficulty = self .nodes [0 ].getdifficulty ()
345
356
# 1 hash in 2 should be valid, so difficulty should be 1/2**31
346
357
# binary => decimal => binary math is why we do this check
347
358
assert abs (difficulty * 2 ** 31 - 1 ) < 0.0001
348
359
349
360
def _test_getnetworkhashps (self ):
361
+ self .log .info ("Test getnetworkhashps" )
350
362
hashes_per_second = self .nodes [0 ].getnetworkhashps ()
351
363
# This should be 2 hashes every 2.6 minutes (156 seconds) or 1/78
352
364
assert abs (hashes_per_second * 78 - 1 ) < 0.0001
353
365
354
366
def _test_stopatheight (self ):
355
- assert_equal (self .nodes [0 ].getblockcount (), 200 )
367
+ assert_equal (self .nodes [0 ].getblockcount (), HEIGHT )
356
368
self .nodes [0 ].generatetoaddress (6 , self .nodes [0 ].get_deterministic_priv_key ().address )
357
- assert_equal (self .nodes [0 ].getblockcount (), 206 )
369
+ assert_equal (self .nodes [0 ].getblockcount (), HEIGHT + 6 )
358
370
self .log .debug ('Node should not stop at this height' )
359
371
assert_raises (subprocess .TimeoutExpired , lambda : self .nodes [0 ].process .wait (timeout = 3 ))
360
372
try :
@@ -364,7 +376,7 @@ def _test_stopatheight(self):
364
376
self .log .debug ('Node should stop at this height...' )
365
377
self .nodes [0 ].wait_until_stopped ()
366
378
self .start_node (0 , ['-txindex=0' ])
367
- assert_equal (self .nodes [0 ].getblockcount (), 207 )
379
+ assert_equal (self .nodes [0 ].getblockcount (), HEIGHT + 7 )
368
380
369
381
def _test_waitforblockheight (self ):
370
382
self .log .info ("Test waitforblockheight" )
@@ -417,17 +429,17 @@ def _test_getblock(self):
417
429
miniwallet .send_self_transfer (fee_rate = fee_per_kb , from_node = node )
418
430
blockhash = node .generate (1 )[0 ]
419
431
420
- self .log .info ("Test that getblock with verbosity 1 doesn't include fee" )
432
+ self .log .info ("Test getblock with verbosity 1 doesn't include fee" )
421
433
block = node .getblock (blockhash , 1 )
422
434
assert 'fee' not in block ['tx' ][1 ]
423
435
424
- self .log .info ('Test that getblock with verbosity 2 includes expected fee' )
436
+ self .log .info ('Test getblock with verbosity 2 includes expected fee' )
425
437
block = node .getblock (blockhash , 2 )
426
438
tx = block ['tx' ][1 ]
427
439
assert 'fee' in tx
428
440
assert_equal (tx ['fee' ], tx ['size' ] * fee_per_byte )
429
441
430
- self .log .info ("Test that getblock with verbosity 2 still works with pruned Undo data" )
442
+ self .log .info ("Test getblock with verbosity 2 still works with pruned Undo data" )
431
443
datadir = get_datadir_path (self .options .tmpdir , 0 )
432
444
433
445
def move_block_file (old , new ):
0 commit comments