1
0

lnworker: don't connect to onion peers if no proxy

When gossip is enabled we waste a lot of time trying to connect
to onion peers if we don't have a proxy enabled. We should just skip
them and try to connect to clearnet peers instead.
This commit is contained in:
f321x
2026-01-27 11:44:49 +01:00
parent db6b6a16f8
commit 79ef429b3c
4 changed files with 78 additions and 6 deletions

View File

@@ -186,6 +186,9 @@ class LNPeerAddr:
def net_addr_str(self) -> str:
return str(self._net_addr)
def is_onion(self) -> bool:
return self.host.endswith('.onion')
def __eq__(self, other):
if not isinstance(other, LNPeerAddr):
return False

View File

@@ -483,6 +483,8 @@ class LNPeerManager(Logger, EventListener, NetworkRetryManager[LNPeerAddr]):
continue
if not self.is_good_peer(peer):
continue
if peer.is_onion() and not self.network.proxy or not self.network.proxy.enabled:
continue
return [peer]
# try random peer from graph
unconnected_nodes = self.channel_db.get_200_randomly_sorted_nodes_not_in(self.peers.keys())
@@ -491,7 +493,10 @@ class LNPeerManager(Logger, EventListener, NetworkRetryManager[LNPeerAddr]):
addrs = self.channel_db.get_node_addresses(node_id)
if not addrs:
continue
host, port, timestamp = self.choose_preferred_address(list(addrs))
address = self.choose_preferred_address(list(addrs))
if not address:
continue
host, port, timestamp = address
try:
peer = LNPeerAddr(host, port, node_id)
except ValueError:
@@ -550,15 +555,17 @@ class LNPeerManager(Logger, EventListener, NetworkRetryManager[LNPeerAddr]):
self.logger.info(f'got {len(peers)} ln peers from dns seed')
return peers
@staticmethod
def choose_preferred_address(addr_list: Sequence[Tuple[str, int, int]]) -> Tuple[str, int, int]:
def choose_preferred_address(self, addr_list: Sequence[Tuple[str, int, int]]) -> Optional[Tuple[str, int, int]]:
assert len(addr_list) >= 1
# choose the most recent one that is an IP
for host, port, timestamp in sorted(addr_list, key=lambda a: -a[2]):
if is_ip_address(host):
return host, port, timestamp
if not self.network.proxy or not self.network.proxy.enabled:
addr_list = [(h, p, ts) for h, p, ts in addr_list if not h.endswith('.onion')]
if not addr_list:
return None
# otherwise choose one at random
# TODO maybe filter out onion if not on tor?
choice = random.choice(addr_list)
return choice
@@ -583,9 +590,9 @@ class LNPeerManager(Logger, EventListener, NetworkRetryManager[LNPeerAddr]):
host, port = addr.host, addr.port
else:
addrs = self.channel_db.get_node_addresses(node_id)
if not addrs:
if not addrs or not (address := self.choose_preferred_address(list(addrs))):
raise ConnStringFormatError(_('Don\'t know any addresses for node:') + ' ' + node_id.hex())
host, port, timestamp = self.choose_preferred_address(list(addrs))
host, port, timestamp = address
port = int(port)
if not self.network.proxy or not self.network.proxy.enabled:

View File

@@ -58,3 +58,33 @@ class TestLNPeerManager(ElectrumTestCase):
with self.assertRaises(ConnStringFormatError) as cm:
await peermgr.add_peer(bad_host_conn_str)
self.assertIn("Hostname does not resolve", str(cm.exception))
def test_choose_preferred_address(self):
peermgr = self.lnpeermgr
# prefer most recent IP address
addr_list = [
("192.168.1.1", 9735, 100),
("host.onion", 9735, 200),
("10.0.0.1", 9735, 150),
("host.com", 9735, 250)
]
result = peermgr.choose_preferred_address(addr_list)
self.assertEqual(result, ("10.0.0.1", 9735, 150)) # Most recent IP
# no IP, proxy disabled, filter .onion and choose random
self.assertFalse(peermgr.network.proxy.enabled)
addr_list = [("host.com", 9735, 100), ("host.onion", 9735, 200)]
result = peermgr.choose_preferred_address(addr_list)
self.assertEqual(result, ("host.com", 9735, 100))
# empty list after filtering
addr_list = [("host.onion", 9735, 100)]
result = peermgr.choose_preferred_address(addr_list)
self.assertIsNone(result)
# return onion if proxy enabled
peermgr.network.proxy.enabled = True
addr_list = [("host.onion", 9735, 100)]
result = peermgr.choose_preferred_address(addr_list)
self.assertEqual(result, ("host.onion", 9735, 100))

View File

@@ -141,3 +141,35 @@ class TestLNTransport(ElectrumTestCase):
self.assertEqual(extract_nodeid(f"{pubkey1.hex()}@[2001:41d0:e:734::1]:8888"), (pubkey1, "[2001:41d0:e:734::1]:8888"))
# just pubkey
self.assertEqual(extract_nodeid(f"{pubkey1.hex()}"), (pubkey1, None))
class TestLNPeerAddr(ElectrumTestCase):
def test_validate_net_address(self):
# Test invalid host
with self.assertRaises(ValueError):
LNPeerAddr("", 9735, b'\x00'*33)
with self.assertRaises(ValueError):
LNPeerAddr("999.999.999.999", 9735, b'\x00'*33)
# Test invalid port
with self.assertRaises(ValueError):
LNPeerAddr("127.0.0.1", -1, b'\x00'*33)
with self.assertRaises(ValueError):
LNPeerAddr("127.0.0.1", 70000, b'\x00'*33)
def test_is_onion(self):
# Test onion addresses
addr1 = LNPeerAddr("example.onion", 9735, b'\x00'*33)
self.assertTrue(addr1.is_onion())
addr2 = LNPeerAddr("subdomain.example.onion", 9735, b'\x00'*33)
self.assertTrue(addr2.is_onion())
# Test non-onion
addr3 = LNPeerAddr("example.com", 9735, b'\x00'*33)
self.assertFalse(addr3.is_onion())
addr4 = LNPeerAddr("127.0.0.1", 9735, b'\x00'*33)
self.assertFalse(addr4.is_onion())
addr5 = LNPeerAddr("::1", 9735, b'\x00'*33)
self.assertFalse(addr5.is_onion())
addr6 = LNPeerAddr("onion", 9735, b'\x00'*33)
self.assertFalse(addr6.is_onion())