qt/qml: delay starting network until after first-start-network-setup
The qt, qml, and kivy GUIs have a first-start network-setup screen that allows the user customising the network settings before creating a wallet. Previously the daemon used to create the network and start it, before this screen, before the GUI even starts. If the user changed network settings, those would be set on the already running network, potentially including restarting the network. Now it becomes the responsibility of the GUI to start the network, allowing this first-start customisation to take place before starting the network at all. The qt and the qml GUIs are adapted to make use of this. Kivy, and the other prototype GUIs are not adapted and just start the network right away, as before.
This commit is contained in:
@@ -53,7 +53,7 @@ from .simple_config import SimpleConfig
|
||||
from .exchange_rate import FxThread
|
||||
from .logging import get_logger, Logger
|
||||
from . import GuiImportError
|
||||
from .plugin import run_hook
|
||||
from .plugin import run_hook, Plugins
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from electrum import gui
|
||||
@@ -376,11 +376,19 @@ class WatchTowerServer(AuthenticatedServer):
|
||||
|
||||
class Daemon(Logger):
|
||||
|
||||
network: Optional[Network]
|
||||
gui_object: Optional['gui.BaseElectrumGui']
|
||||
network: Optional[Network] = None
|
||||
gui_object: Optional['gui.BaseElectrumGui'] = None
|
||||
watchtower: Optional['WatchTowerServer'] = None
|
||||
|
||||
@profiler
|
||||
def __init__(self, config: SimpleConfig, fd=None, *, listen_jsonrpc=True):
|
||||
def __init__(
|
||||
self,
|
||||
config: SimpleConfig,
|
||||
fd=None,
|
||||
*,
|
||||
listen_jsonrpc: bool = True,
|
||||
start_network: bool = True, # setting to False allows customising network settings before starting it
|
||||
):
|
||||
Logger.__init__(self)
|
||||
self.config = config
|
||||
self.listen_jsonrpc = listen_jsonrpc
|
||||
@@ -392,11 +400,9 @@ class Daemon(Logger):
|
||||
self.logger.warning("Ignoring parameter 'wallet_path' for daemon. "
|
||||
"Use the load_wallet command instead.")
|
||||
self.asyncio_loop = util.get_asyncio_loop()
|
||||
self.network = None
|
||||
if not config.get('offline'):
|
||||
self.network = Network(config, daemon=self)
|
||||
self.fx = FxThread(config=config)
|
||||
self.gui_object = None
|
||||
# path -> wallet; make sure path is standardized.
|
||||
self._wallets = {} # type: Dict[str, Abstract_Wallet]
|
||||
self._wallet_lock = threading.RLock()
|
||||
@@ -406,23 +412,14 @@ class Daemon(Logger):
|
||||
if listen_jsonrpc:
|
||||
self.commands_server = CommandsServer(self, fd)
|
||||
daemon_jobs.append(self.commands_server.run())
|
||||
# server-side watchtower
|
||||
self.watchtower = None
|
||||
watchtower_address = self.config.get_netaddress('watchtower_address')
|
||||
if not config.get('offline') and watchtower_address:
|
||||
self.watchtower = WatchTowerServer(self.network, watchtower_address)
|
||||
daemon_jobs.append(self.watchtower.run)
|
||||
if self.network:
|
||||
self.network.start(jobs=[self.fx.run])
|
||||
# prepare lightning functionality, also load channel db early
|
||||
if self.config.get('use_gossip', False):
|
||||
self.network.start_gossip()
|
||||
|
||||
self._stop_entered = False
|
||||
self._stopping_soon_or_errored = threading.Event()
|
||||
self._stopped_event = threading.Event()
|
||||
self.taskgroup = OldTaskGroup()
|
||||
asyncio.run_coroutine_threadsafe(self._run(jobs=daemon_jobs), self.asyncio_loop)
|
||||
if start_network and self.network:
|
||||
self.start_network()
|
||||
|
||||
@log_exceptions
|
||||
async def _run(self, jobs: Iterable = None):
|
||||
@@ -442,6 +439,20 @@ class Daemon(Logger):
|
||||
# not see the exception (especially if the GUI did not start yet).
|
||||
self._stopping_soon_or_errored.set()
|
||||
|
||||
def start_network(self):
|
||||
self.logger.info(f"starting network.")
|
||||
assert not self.config.get('offline')
|
||||
assert self.network
|
||||
# server-side watchtower
|
||||
if watchtower_address := self.config.get_netaddress('watchtower_address'):
|
||||
self.watchtower = WatchTowerServer(self.network, watchtower_address)
|
||||
asyncio.run_coroutine_threadsafe(self.taskgroup.spawn(self.watchtower.run), self.asyncio_loop)
|
||||
|
||||
self.network.start(jobs=[self.fx.run])
|
||||
# prepare lightning functionality, also load channel db early
|
||||
if self.config.get('use_gossip', False):
|
||||
self.network.start_gossip()
|
||||
|
||||
def with_wallet_lock(func):
|
||||
def func_wrapper(self: 'Daemon', *args, **kwargs):
|
||||
with self._wallet_lock:
|
||||
@@ -566,7 +577,7 @@ class Daemon(Logger):
|
||||
self.logger.info("stopped")
|
||||
self._stopped_event.set()
|
||||
|
||||
def run_gui(self, config, plugins):
|
||||
def run_gui(self, config: 'SimpleConfig', plugins: 'Plugins'):
|
||||
threading.current_thread().name = 'GUI'
|
||||
gui_name = config.get('gui', 'qt')
|
||||
if gui_name in ['lite', 'classic']:
|
||||
|
||||
Reference in New Issue
Block a user