@@ -213,13 +213,17 @@ class Generate:
213
213
INTERVAL = 600.0 * 2016 / 2015 # 10 minutes, adjusted for the off-by-one bug
214
214
215
215
216
- def __init__ (self , multiminer = None , ultimate_target = None , poisson = False , max_interval = 1800 ):
216
+ def __init__ (self , multiminer = None , ultimate_target = None , poisson = False , max_interval = 1800 ,
217
+ standby_delay = 0 , backup_delay = 0 , set_block_time = None ):
217
218
if multiminer is None :
218
219
multiminer = (0 , 1 , 1 )
219
220
(self .multi_low , self .multi_high , self .multi_period ) = multiminer
220
221
self .ultimate_target = ultimate_target
221
222
self .poisson = poisson
222
223
self .max_interval = max_interval
224
+ self .standby_delay = standby_delay
225
+ self .backup_delay = backup_delay
226
+ self .set_block_time = set_block_time
223
227
224
228
def next_block_delta (self , last_nbits , last_hash ):
225
229
# strategy:
@@ -250,6 +254,42 @@ class Generate:
250
254
det_rand = int (last_hash [- 16 :- 8 ], 16 )
251
255
return self .multi_low <= (det_rand % self .multi_period ) < self .multi_high
252
256
257
+ def next_block_time (self , now , bestheader , is_first_block ):
258
+ if self .set_block_time is not None :
259
+ logging .debug ("Setting start time to %d" , self .set_block_time )
260
+ self .mine_time = self .set_block_time
261
+ self .action_time = now
262
+ self .is_mine = True
263
+ elif bestheader ["height" ] == 0 :
264
+ time_delta = self .INTERVAL * 100 # plenty of time to mine 100 blocks
265
+ logging .info ("Backdating time for first block to %d minutes ago" % (time_delta / 60 ))
266
+ self .mine_time = now - time_delta
267
+ self .action_time = now
268
+ self .is_mine = True
269
+ else :
270
+ time_delta = self .next_block_delta (int (bestheader ["bits" ], 16 ), bestheader ["hash" ])
271
+ self .mine_time = bestheader ["time" ] + time_delta
272
+
273
+ self .is_mine = self .next_block_is_mine (bestheader ["hash" ])
274
+
275
+ self .action_time = self .mine_time
276
+ if not self .is_mine :
277
+ self .action_time += self .backup_delay
278
+
279
+ if self .standby_delay > 0 :
280
+ self .action_time += self .standby_delay
281
+ elif is_first_block :
282
+ # for non-standby, always mine immediately on startup,
283
+ # even if the next block shouldn't be ours
284
+ self .action_time = now
285
+
286
+ # don't want fractional times so round down
287
+ self .mine_time = int (self .mine_time )
288
+ self .action_time = int (self .action_time )
289
+
290
+ # can't mine a block 2h in the future; 1h55m for some safety
291
+ self .action_time = max (self .action_time , self .mine_time - 6900 )
292
+
253
293
def do_generate (args ):
254
294
if args .max_blocks is not None :
255
295
if args .ongoing :
@@ -308,7 +348,8 @@ def do_generate(args):
308
348
309
349
ultimate_target = nbits_to_target (int (args .nbits ,16 ))
310
350
311
- gen = Generate (multiminer = my_blocks , ultimate_target = ultimate_target , poisson = args .poisson , max_interval = args .max_interval )
351
+ gen = Generate (multiminer = my_blocks , ultimate_target = ultimate_target , poisson = args .poisson , max_interval = args .max_interval ,
352
+ standby_delay = args .standby_delay , backup_delay = args .backup_delay , set_block_time = args .set_block_time )
312
353
313
354
mined_blocks = 0
314
355
bestheader = {"hash" : None }
@@ -332,52 +373,18 @@ def do_generate(args):
332
373
333
374
# when is the next block due to be mined?
334
375
now = time .time ()
335
- if args .set_block_time is not None :
336
- logging .debug ("Setting start time to %d" , args .set_block_time )
337
- mine_time = args .set_block_time
338
- action_time = now
339
- is_mine = True
340
- elif bestheader ["height" ] == 0 :
341
- time_delta = gen .next_block_delta (int (bestheader ["bits" ], 16 ), bci ["bestblockhash" ])
342
- time_delta *= 100 # 100 blocks
343
- logging .info ("Backdating time for first block to %d minutes ago" % (time_delta / 60 ))
344
- mine_time = now - time_delta
345
- action_time = now
346
- is_mine = True
347
- else :
348
- time_delta = gen .next_block_delta (int (bestheader ["bits" ], 16 ), bci ["bestblockhash" ])
349
- mine_time = bestheader ["time" ] + time_delta
350
-
351
- is_mine = gen .next_block_is_mine (bci ["bestblockhash" ])
352
-
353
- action_time = mine_time
354
- if not is_mine :
355
- action_time += args .backup_delay
356
-
357
- if args .standby_delay > 0 :
358
- action_time += args .standby_delay
359
- elif mined_blocks == 0 :
360
- # for non-standby, always mine immediately on startup,
361
- # even if the next block shouldn't be ours
362
- action_time = now
363
-
364
- # don't want fractional times so round down
365
- mine_time = int (mine_time )
366
- action_time = int (action_time )
367
-
368
- # can't mine a block 2h in the future; 1h55m for some safety
369
- action_time = max (action_time , mine_time - 6900 )
376
+ gen .next_block_time (now , bestheader , (mined_blocks == 0 ))
370
377
371
378
# ready to go? otherwise sleep and check for new block
372
- if now < action_time :
373
- sleep_for = min (action_time - now , 60 )
374
- if mine_time < now :
379
+ if now < gen . action_time :
380
+ sleep_for = min (gen . action_time - now , 60 )
381
+ if gen . mine_time < now :
375
382
# someone else might have mined the block,
376
383
# so check frequently, so we don't end up late
377
384
# mining the next block if it's ours
378
385
sleep_for = min (20 , sleep_for )
379
- minestr = "mine" if is_mine else "backup"
380
- logging .debug ("Sleeping for %s, next block due in %s (%s)" % (seconds_to_hms (sleep_for ), seconds_to_hms (mine_time - now ), minestr ))
386
+ minestr = "mine" if gen . is_mine else "backup"
387
+ logging .debug ("Sleeping for %s, next block due in %s (%s)" % (seconds_to_hms (sleep_for ), seconds_to_hms (gen . mine_time - now ), minestr ))
381
388
time .sleep (sleep_for )
382
389
continue
383
390
@@ -390,20 +397,20 @@ def do_generate(args):
390
397
391
398
logging .debug ("GBT template: %s" , tmpl )
392
399
393
- if tmpl ["mintime" ] > mine_time :
394
- logging .info ("Updating block time from %d to %d" , mine_time , tmpl ["mintime" ])
395
- mine_time = tmpl ["mintime" ]
396
- if mine_time > now :
397
- logging .error ("GBT mintime is in the future: %d is %d seconds later than %d" , mine_time , (mine_time - now ), now )
400
+ if tmpl ["mintime" ] > gen . mine_time :
401
+ logging .info ("Updating block time from %d to %d" , gen . mine_time , tmpl ["mintime" ])
402
+ gen . mine_time = tmpl ["mintime" ]
403
+ if gen . mine_time > now :
404
+ logging .error ("GBT mintime is in the future: %d is %d seconds later than %d" , gen . mine_time , (gen . mine_time - now ), now )
398
405
return 1
399
406
400
407
# address for reward
401
408
reward_addr , reward_spk = get_reward_addr_spk (args , tmpl ["height" ])
402
409
403
410
# mine block
404
- logging .debug ("Mining block delta=%s start=%s mine=%s" , seconds_to_hms (mine_time - bestheader ["time" ]), mine_time , is_mine )
411
+ logging .debug ("Mining block delta=%s start=%s mine=%s" , seconds_to_hms (gen . mine_time - bestheader ["time" ]), gen . mine_time , gen . is_mine )
405
412
mined_blocks += 1
406
- psbt = generate_psbt (tmpl , reward_spk , blocktime = mine_time )
413
+ psbt = generate_psbt (tmpl , reward_spk , blocktime = gen . mine_time )
407
414
input_stream = os .linesep .join ([psbt , "true" , "ALL" ]).encode ('utf8' )
408
415
psbt_signed = json .loads (args .bcli ("-stdin" , "walletprocesspsbt" , input = input_stream ))
409
416
if not psbt_signed .get ("complete" ,False ):
@@ -417,7 +424,7 @@ def do_generate(args):
417
424
r = args .bcli ("-stdin" , "submitblock" , input = block .serialize ().hex ().encode ('utf8' ))
418
425
419
426
# report
420
- bstr = "block" if is_mine else "backup block"
427
+ bstr = "block" if gen . is_mine else "backup block"
421
428
422
429
next_delta = gen .next_block_delta (block .nBits , block .hash )
423
430
next_delta += block .nTime - time .time ()
0 commit comments