1
0

Merge pull request #10448 from f321x/gossip_0126

lnpeermgr: fix proxy check in add_peer, don't connect to onion peers if no proxy
This commit is contained in:
ghost43
2026-01-29 18:52:10 +00:00
committed by GitHub
5 changed files with 141 additions and 8 deletions

View File

@@ -26,7 +26,7 @@ from electrum import bitcoin
from electrum import util
from electrum import constants
from electrum import bip32
from electrum.network import Network
from electrum.network import Network, ProxySettings
from electrum import simple_config, lnutil
from electrum.lnaddr import lnencode, LnAddr, lndecode
from electrum.bitcoin import COIN, sha256
@@ -71,6 +71,7 @@ class MockNetwork:
self.path_finder = LNPathFinder(self.channel_db)
self.lngossip = MockLNGossip()
self.tx_queue = asyncio.Queue()
self.proxy = ProxySettings()
self._blockchain = MockBlockchain()
def get_local_height(self):

90
tests/test_lnpeermgr.py Normal file
View File

@@ -0,0 +1,90 @@
import logging
import os
import socket
import asyncio
from unittest import mock
from . import ElectrumTestCase
from electrum.lntransport import ConnStringFormatError
from electrum.logging import console_stderr_handler
class TestLNPeerManager(ElectrumTestCase):
TESTNET = True
@classmethod
def setUpClass(cls):
super().setUpClass()
console_stderr_handler.setLevel(logging.DEBUG)
async def asyncSetUp(self):
lnwallet = self.create_mock_lnwallet(name='mock_lnwallet_anchors', has_anchors=True)
self.lnpeermgr = lnwallet.lnpeermgr
await super().asyncSetUp()
async def test_add_peer_conn_string_errors(self):
unknown_node_id = os.urandom(33)
peermgr = self.lnpeermgr
peermgr._add_peer = mock.Mock(side_effect=NotImplementedError)
# Trampoline enabled, unknown node (no address in trampolines)
channel_db = peermgr.network.channel_db
peermgr.network.channel_db = None
try:
with self.assertRaises(ConnStringFormatError) as cm:
await peermgr.add_peer(unknown_node_id.hex())
self.assertIn("Address unknown for node", str(cm.exception))
finally:
peermgr.network.channel_db = channel_db # re-set channel db
# Trampoline disabled, unknown node (no address in channel_db)
with mock.patch.object(peermgr.network.channel_db, 'get_node_addresses', return_value=[]):
with self.assertRaises(ConnStringFormatError) as cm:
await peermgr.add_peer(unknown_node_id.hex())
self.assertIn("Don't know any addresses for node", str(cm.exception))
# .onion address, but no proxy configured
onion_conn_str = unknown_node_id.hex() + "@somewhere.onion:9735"
self.assertFalse(peermgr.network.proxy.enabled)
with self.assertRaises(ConnStringFormatError) as cm:
await peermgr.add_peer(onion_conn_str)
self.assertIn(".onion address, but no proxy configured", str(cm.exception))
# Hostname does not resolve (getaddrinfo failed)
bad_host_conn_str = unknown_node_id.hex() + "@badhost:9735"
loop = asyncio.get_running_loop()
with mock.patch.object(loop, 'getaddrinfo', side_effect=socket.gaierror):
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())