What changed, and why it matters
This commit fixes a user-interface bug in the Electrum Bitcoin wallet's setup wizard. Previously, a user could type a malformed custom server address, click 'Next', and the wallet would silently ignore it and automatically pick a server instead. Now the wizard blocks the 'Next' button and highlights the bad address in red so the user notices.
Treat as a low-severity UX/security hardening fix. No emergency response is warranted, but include it in the next release so users cannot inadvertently disable their intended custom server selection during initial wallet setup.
Security signals we found
UI state validation prevents silent fallback to default/automatic behavior
Input parsing failure previously caused unintended configuration change
Wizard flow now blocks progression on invalid user-supplied network target
Evidence from the diff
ServerWidget in electrum/gui/qt/network_dialog.py now validates the server_e QLineEdit input via ServerAddr.from_str_with_inference() on every text change, emits a server_e_valid pyqtSignal, and colors the field red when invalid. The wizard component WCServerConfig in electrum/gui/qt/wizard/server_connect.py consumes that signal to set its valid flag, which disables the Next button for invalid custom server strings. This prevents silent fallback to autoconnect when a user enters an unparsable server address.
Changed components
electrum/gui/qt/network_dialog.pyelectrum/gui/qt/wizard/server_connect.pyServerWidget QLineEdit server_eWCServerConfig wizard componentInspect captured patch +17 / −1
diff --git a/electrum/gui/qt/network_dialog.py b/electrum/gui/qt/network_dialog.py
index ad4ff48..9545e45 100644
--- a/electrum/gui/qt/network_dialog.py
+++ b/electrum/gui/qt/network_dialog.py
@@ -361,6 +361,8 @@ class ServerWidget(QWidget, QtEventListener):
ConnectMode.ONESERVER: messages.MSG_CONNECTMODE_ONESERVER,
}
+ server_e_valid = pyqtSignal(bool)
+
def __init__(self, network: Network, parent=None):
super().__init__(parent)
self.network = network
@@ -390,6 +392,7 @@ class ServerWidget(QWidget, QtEventListener):
grid.addWidget(self.connect_combo, 0, 1, 1, 3)
self.server_e = QLineEdit()
+ self.server_e.textChanged.connect(self.validate_server_e)
self.server_e.editingFinished.connect(self.on_server_settings_changed)
grid.addWidget(QLabel(_('Server') + ':'), 1, 0)
grid.addWidget(self.server_e, 1, 1, 1, 3)
@@ -502,6 +505,7 @@ class ServerWidget(QWidget, QtEventListener):
self.status_label_header, self.status_label, self.status_label_helpbutton,
self.height_label_header, self.height_label, self.height_label_helpbutton]:
item.setVisible(self.network._was_started)
+ self.validate_server_e()
msg = _('Fork detection disabled') if self.is_one_server() else ''
if self.network._was_started:
# Network was started, so we don't run in initial setup wizard.
@@ -522,6 +526,15 @@ class ServerWidget(QWidget, QtEventListener):
msg += _('Your server is on branch {0} ({1} blocks)').format(name, chain.get_branch_size())
self.split_label.setText(msg)
+ def validate_server_e(self):
+ if not self.server_e.isEnabled():
+ self.server_e.setStyleSheet("")
+ self.server_e_valid.emit(True)
+ return
+ server = ServerAddr.from_str_with_inference(self.server_e.text())
+ self.server_e.setStyleSheet("background-color: rgba(255, 0, 0, 0.2);" if not server else "")
+ self.server_e_valid.emit(server is not None)
+
def update_from_config(self):
auto_connect = self.config.NETWORK_AUTO_CONNECT
one_server = self.config.NETWORK_ONESERVER
diff --git a/electrum/gui/qt/wizard/server_connect.py b/electrum/gui/qt/wizard/server_connect.py
index c7a5f3d..19b403d 100644
--- a/electrum/gui/qt/wizard/server_connect.py
+++ b/electrum/gui/qt/wizard/server_connect.py
@@ -91,7 +91,10 @@ class WCServerConfig(WizardComponent):
WizardComponent.__init__(self, parent, wizard, title=_('Server'))
self.sw = ServerWidget(wizard._daemon.network, self)
self.layout().addWidget(self.sw)
- self._valid = True
+ self.sw.server_e_valid.connect(self.on_server_e_valid)
+
+ def on_server_e_valid(self, valid):
+ self.valid = valid
def apply(self):
self.wizard_data['autoconnect'] = self.sw.server_e.text().strip() == ''
Why this scored 42/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.