Skip to content

Commit 912de7f

Browse files
Fix bugs in I2P implementation
Bug fixes: 1. i2p_tests.cpp: Fix comment/assertion mismatch in i2p_service test - Updated comments to clarify that CService preserves ports but SAM rejects non-zero ports 2. net.cpp: Fix I2P connections when pszDest is provided - Parse .b32.i2p addresses from pszDest before checking IsI2P() - Update addrConnect with parsed I2P address for correct CNode creation - This ensures -addnode=xxx.b32.i2p works correctly 3. i2p.cpp: Validate corrupted private keys, not just empty ones - Call MyDestination() after loading private key to detect corruption - Regenerate key if validation fails (truncated/corrupted files) Co-authored-by: reuben <[email protected]>
1 parent 7060ed8 commit 912de7f

File tree

3 files changed

+44
-3
lines changed

3 files changed

+44
-3
lines changed

src/i2p.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,16 @@ void Session::CreateIfNotCreatedAlready()
518518
if (m_private_key.empty()) {
519519
LogPrintf("I2P: Private key file %s is empty, regenerating\n", m_private_key_file.string());
520520
GenerateAndSavePrivateKey(sock);
521+
} else {
522+
// Validate the private key by attempting to derive the destination
523+
// This will detect truncated or corrupted key files
524+
try {
525+
MyDestination();
526+
} catch (const std::runtime_error& e) {
527+
LogPrintf("I2P: Private key file %s is corrupted (%s), regenerating\n",
528+
m_private_key_file.string(), e.what());
529+
GenerateAndSavePrivateKey(sock);
530+
}
521531
}
522532
} else {
523533
GenerateAndSavePrivateKey(sock);

src/net.cpp

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
#include "evo/mnauth.h"
3232
#include "i2p.h"
3333

34+
#include <algorithm>
35+
3436
#ifdef WIN32
3537
#include <string.h>
3638
#else
@@ -400,8 +402,36 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo
400402
bool proxyConnectionFailed = false;
401403
bool connected = false;
402404

405+
// Check if this is an I2P connection - either via addrConnect or pszDest
406+
bool isI2P = addrConnect.IsI2P();
407+
CService i2pDest;
408+
409+
// If pszDest is provided, check if it's an I2P address (.b32.i2p suffix)
410+
if (!isI2P && pszDest) {
411+
std::string dest(pszDest);
412+
// Check for I2P address suffix (case-insensitive)
413+
if (dest.size() > 8) {
414+
std::string suffix = dest.substr(dest.size() - 8);
415+
std::transform(suffix.begin(), suffix.end(), suffix.begin(), ::tolower);
416+
if (suffix == ".b32.i2p") {
417+
CNetAddr i2pAddr;
418+
if (i2pAddr.SetSpecial(dest)) {
419+
i2pDest = CService(i2pAddr, i2p::I2P_SAM31_PORT);
420+
isI2P = true;
421+
LogPrint("i2p", "I2P: Parsed destination %s from pszDest\n", i2pDest.ToString());
422+
}
423+
}
424+
}
425+
}
426+
403427
// Handle I2P connections via SAM session
404-
if (addrConnect.IsI2P()) {
428+
if (isI2P) {
429+
// Use i2pDest if we parsed from pszDest, otherwise use addrConnect
430+
if (i2pDest.IsValid()) {
431+
// Update addrConnect so it's used correctly for CNode creation and address manager
432+
addrConnect = CAddress(i2pDest, addrConnect.nServices);
433+
}
434+
405435
if (m_i2p_sam_session) {
406436
i2p::Connection conn;
407437
if (m_i2p_sam_session->Connect(addrConnect, conn, proxyConnectionFailed)) {

src/test/i2p_tests.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,12 +113,13 @@ BOOST_AUTO_TEST_CASE(i2p_service)
113113
const std::string valid_i2p = "ukeu3k5oycgaauneqgtnvselmt4yemvoilkln7jpvamvfx7dnkdq.b32.i2p";
114114
BOOST_CHECK(addr.SetSpecial(valid_i2p));
115115

116-
// I2P uses port 0 (SAM 3.1 doesn't use ports)
116+
// I2P SAM 3.1 uses port 0 as the standard port
117117
CService service(addr, 0);
118118
BOOST_CHECK(service.IsI2P());
119119
BOOST_CHECK_EQUAL(service.GetPort(), 0);
120120

121-
// The port in I2P is always 0, so testing with non-zero port
121+
// CService preserves whatever port is supplied, even for I2P addresses.
122+
// However, the I2P SAM session will reject non-zero ports when connecting.
122123
CService service2(addr, 8333);
123124
BOOST_CHECK_EQUAL(service2.GetPort(), 8333);
124125
}

0 commit comments

Comments
 (0)