From 1462be75580752c74db022dbfa063c474f82a6b3 Mon Sep 17 00:00:00 2001 From: hairetikos <19870044+hairetikos@users.noreply.github.com> Date: Sat, 6 Dec 2025 16:39:38 +0000 Subject: [PATCH 1/2] Implement Tor v3 local address fix Add validation for Tor v3 addresses in CNetAddr. fixes bidirectional onlynet=onion connections also now shows the local onion V3 address with `getnetworkinfo` remote peers onion V3 addresses now show in `getpeerinfo` inbound Onion V3 nodes show as 127.0.0.1, this is normal behaviour, bitcoin and other coins display it like this. only outbound shows V3 addresses "us" when connecting is still a zeroed 0.0.0.0 "IP" address, this is just cosmetic, and we do not have P2P gossip of onion v3 yet, for now we use manual `addnodes`, as explained before --- src/netbase.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/netbase.cpp b/src/netbase.cpp index efa039973be..bc70b3c0da4 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -895,6 +895,11 @@ bool CNetAddr::IsMulticast() const bool CNetAddr::IsValid() const { + // Tor v3 addresses are valid if they have a properly-sized pubkey stored + // V3 onion addresses store data in torv3_addr (32 bytes), not in ip[16] + if (!torv3_addr.empty()) { + return torv3_addr.size() == ADDR_TORV3_SIZE; + } // Cleanup 3-byte shifted addresses caused by garbage in size field // of addr messages from versions before 0.2.9 checksum. // Two consecutive addr messages look like this: From 6d2b14a1bd6f63b575c47f76fe0afbb9d9dc7705 Mon Sep 17 00:00:00 2001 From: hairetikos <19870044+hairetikos@users.noreply.github.com> Date: Sat, 6 Dec 2025 16:42:35 +0000 Subject: [PATCH 2/2] Add tests for V3 onion address functionality --- src/test/netbase_tests.cpp | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/test/netbase_tests.cpp b/src/test/netbase_tests.cpp index b508edcf1e5..b445f0c34f3 100644 --- a/src/test/netbase_tests.cpp +++ b/src/test/netbase_tests.cpp @@ -104,6 +104,31 @@ BOOST_AUTO_TEST_CASE(onioncat_test) BOOST_CHECK(addr1.IsRoutable()); } +BOOST_AUTO_TEST_CASE(onion_v3_test) +{ + // Test V3 onion address (56 character base32-encoded address) + // This is a valid V3 onion address format + CNetAddr addr1("pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscryd.onion"); + BOOST_CHECK(addr1.IsTor()); + BOOST_CHECK(addr1.IsValid()); + BOOST_CHECK(addr1.IsRoutable()); + BOOST_CHECK(addr1.GetNetwork() == NET_ONION); + BOOST_CHECK(addr1.ToStringIP() == "pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscryd.onion"); + + // Test that V3 address survives round-trip through string conversion + CNetAddr addr2(addr1.ToStringIP()); + BOOST_CHECK(addr2.IsTor()); + BOOST_CHECK(addr2.IsValid()); + BOOST_CHECK(addr2.IsRoutable()); + + // Test CService with V3 onion address + CService svc(addr1, 8333); + BOOST_CHECK(svc.IsValid()); + BOOST_CHECK(svc.IsTor()); + BOOST_CHECK(svc.IsRoutable()); + BOOST_CHECK(svc.GetPort() == 8333); +} + BOOST_AUTO_TEST_CASE(subnet_test) { BOOST_CHECK(CSubNet("1.2.3.0/24") == CSubNet("1.2.3.0/255.255.255.0"));