From ff2bbf159ee7bedbc763e032277a22d3b5ec3151 Mon Sep 17 00:00:00 2001 From: f321x Date: Mon, 27 Oct 2025 16:11:30 +0100 Subject: [PATCH] interface: check genesis hash on connection Prevents the client from accidentally connecting to a server on a different network. I noticed its possible to connect to mainnet servers on a signet instance causing the recent peers to get populated with mainnet peers rendering the wallet instance barely usable. Doing this check should prevent this and similar issues. --- electrum/interface.py | 8 ++++++++ tests/test_interface.py | 13 +++++++++++++ 2 files changed, 21 insertions(+) diff --git a/electrum/interface.py b/electrum/interface.py index 36cfb13c4..606c9b9b4 100644 --- a/electrum/interface.py +++ b/electrum/interface.py @@ -964,6 +964,14 @@ class Interface(Logger): if not self.network.check_interface_against_healthy_spread_of_connected_servers(self): raise GracefulDisconnect(f'too many connected servers already ' f'in bucket {self.bucket_based_on_ipaddress()}') + + try: + features = await session.send_request('server.features') + server_genesis_hash = assert_dict_contains_field(features, field_name='genesis_hash') + except (aiorpcx.jsonrpc.RPCError, RequestCorrupted) as e: + raise GracefulDisconnect(e) + if server_genesis_hash != constants.net.GENESIS: + raise GracefulDisconnect(f'server on different chain: {server_genesis_hash=}. ours: {constants.net.GENESIS}') self.logger.info(f"connection established. version: {ver}") try: diff --git a/tests/test_interface.py b/tests/test_interface.py index da4f607cd..07b13338e 100644 --- a/tests/test_interface.py +++ b/tests/test_interface.py @@ -11,6 +11,7 @@ from electrum.util import OldTaskGroup, bfh from electrum.logging import Logger from electrum.simple_config import SimpleConfig from electrum.transaction import Transaction +from electrum import constants from . import ElectrumTestCase @@ -130,6 +131,7 @@ class ServerSession(aiorpcx.RPCSession, Logger): async def handle_request(self, request): handlers = { 'server.version': self._handle_server_version, + 'server.features': self._handle_server_features, 'blockchain.estimatefee': self._handle_estimatefee, 'blockchain.headers.subscribe': self._handle_headers_subscribe, 'blockchain.block.header': self._handle_block_header, @@ -146,6 +148,17 @@ class ServerSession(aiorpcx.RPCSession, Logger): async def _handle_server_version(self, client_name='', protocol_version=None): return ['best_server_impl/0.1', '1.4'] + async def _handle_server_features(self) -> dict: + return { + 'genesis_hash': constants.net.GENESIS, + 'hosts': {"14.3.140.101": {"tcp_port": 51001, "ssl_port": 51002}}, + 'protocol_max': '1.7.0', + 'protocol_min': '1.4.3', + 'pruning': None, + 'server_version': 'ElectrumX 1.19.0', + 'hash_function': 'sha256', + } + async def _handle_estimatefee(self, number, mode=None): return 1000