88import time
99from pathlib import Path
1010from threading import Event
11+ from xmlrpc .client import Boolean
1112
1213import click
1314import psutil
1415from flask import Config
16+ from requests .exceptions import ConnectionError
1517
1618from ..config import DEFAULT_CONFIG
1719from ..process_controller .elementsd_controller import ElementsPlainController
@@ -352,15 +354,15 @@ def cleanup():
352354
353355 if node_impl == "elements" :
354356 prepare_elements_default_wallet (my_node )
355-
356- if mining :
357- miner_loop (
358- node_impl ,
359- my_node ,
360- config_obj ["SPECTER_DATA_FOLDER" ],
361- mining_every_x_seconds ,
362- echo ,
363- )
357+ # Mining/NOP loop (necessary to keep the Python process running)
358+ endless_loop (
359+ node_impl ,
360+ my_node ,
361+ mining ,
362+ config_obj ["SPECTER_DATA_FOLDER" ],
363+ mining_every_x_seconds ,
364+ echo ,
365+ )
364366
365367
366368def prepare_elements_default_wallet (my_node ):
@@ -386,61 +388,75 @@ def prepare_elements_default_wallet(my_node):
386388 rpc .generatetoaddress (101 , unconfidential )
387389
388390
389- def miner_loop (node_impl , my_node , data_folder , mining_every_x_seconds , echo ):
390- "An endless loop mining bitcoin"
391-
392- echo (
393- "Now, mining a block every %f seconds, avoid it via --no-mining"
394- % mining_every_x_seconds
395- )
396- mine_2_specter_wallets (node_impl , my_node , data_folder , echo )
391+ def endless_loop (
392+ node_impl , my_node , mining : Boolean , data_folder , mining_every_x_seconds , echo
393+ ):
394+ """This loop can enable continuous mining"""
397395
398- # make them spendable
399- my_node .mine (block_count = 100 )
400- echo (
401- f"height: { my_node .rpcconn .get_rpc ().getblockchaininfo ()['blocks' ]} | " ,
402- nl = False ,
403- )
396+ # To stop the Python process
404397 exit = Event ()
405398
406- def exit_now (signo , _frame ):
399+ def exit_now (signum , frame ):
400+ echo (f"Signal { signum } received. Terminating the Python process. Bye, bye!" )
407401 exit .set ()
408402
409- for sig in ("HUP" , "INT" ):
410- signal .signal (getattr (signal , "SIG" + sig ), exit_now )
403+ signal .signal (signal .SIGINT , exit_now )
404+ signal .signal (signal .SIGHUP , exit_now )
405+ signal .signal (signal .SIGTERM , exit_now )
406+ # SIGKILL cannot be caught
407+
408+ if mining :
409+ echo (
410+ "Now, mining a block every %f seconds, avoid it via --no-mining"
411+ % mining_every_x_seconds
412+ )
413+ mine_2_specter_wallets (node_impl , my_node , data_folder , echo )
414+ # make them spendable
415+ my_node .mine (block_count = 100 )
416+ echo (
417+ f"height: { my_node .rpcconn .get_rpc ().getblockchaininfo ()['blocks' ]} | " ,
418+ nl = False ,
419+ )
420+ else :
421+ echo ("Press Ctrl-C to abort and stop the node" )
422+
411423 prevent_mining_file = Path ("prevent_mining" )
412424 i = 0
413- while True :
425+ while not exit . is_set () :
414426 try :
415427 current_height = my_node .rpcconn .get_rpc ().getblockchaininfo ()["blocks" ]
416428 exit .wait (mining_every_x_seconds )
417- if not prevent_mining_file .is_file ():
429+ # Having a prevent_mining_file overrides the mining cli option
430+ if mining and not prevent_mining_file .is_file ():
418431 my_node .mine ()
419- else :
432+ echo ("%i" % (i % 10 ), prefix = False , nl = False )
433+ if i % 10 == 9 :
434+ echo (" " , prefix = False , nl = False )
435+ i += 1
436+ if i >= 50 :
437+ i = 0
438+ echo ("" , prefix = False )
439+ echo (
440+ f"height: { current_height } | " ,
441+ nl = False ,
442+ )
443+ elif mining :
420444 echo ("X" , prefix = False , nl = False )
421445 continue
422446
423- echo ("%i" % (i % 10 ), prefix = False , nl = False )
424- if i % 10 == 9 :
425- echo (" " , prefix = False , nl = False )
426- i += 1
427- if i >= 50 :
428- i = 0
429- echo ("" , prefix = False )
430- echo (
431- f"height: { current_height } | " ,
432- nl = False ,
433- )
434-
447+ except ConnectionError as nce :
448+ # This terminates the Python processes if the bitcoind / elementsd (child) processes are somehow terminated
449+ echo ("Exiting endless loop due to lost RPC connection." )
450+ break
435451 except Exception as e :
436452 logger .debug (
437- f"Caught { e } , Couldn't mine, assume SIGTERM occured => exiting!"
453+ f"Caught { e . __module__ } , Couldn't mine, assume SIGTERM occured => exiting!"
438454 )
439- echo (f"THE_END(@height:{ current_height } )" )
440- if prevent_mining_file .is_file ():
441- echo ("Deleting file prevent_mining" )
442- prevent_mining_file .unlink ()
443455 break
456+ if prevent_mining_file .is_file ():
457+ echo ("Deleting file prevent_mining" )
458+ prevent_mining_file .unlink ()
459+ echo (f"THE_END(@height:{ current_height } )" )
444460
445461
446462def mine_2_specter_wallets (node_impl , my_node , data_folder , echo ):
@@ -451,6 +467,7 @@ def mine_2_specter_wallets(node_impl, my_node, data_folder, echo):
451467 # Using the dict key, not the wallet name
452468 exception = "fresh_wallet"
453469 try :
470+ logger .debug (f"Funding wallets in { data_folder } /wallets" )
454471 for address in fetch_wallet_addresses_for_mining (
455472 node_impl , data_folder , exception
456473 ):
0 commit comments