1
0

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:
SomberNight
2023-03-29 22:09:46 +00:00
parent 9ef6d6a56f
commit 1530668960
11 changed files with 57 additions and 25 deletions

View File

@@ -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']: