diff --git a/src/init.cpp b/src/init.cpp index ee42453..4ea73df 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1223,7 +1223,10 @@ bool AppInit2() fUseUPnP = false; #endif } else { - return InitError(_("Tor failed to start. Triangles requires Tor to operate.")); + std::string torError = CTorEmbedded::GetInstance()->GetLastError(); + if (torError.empty()) + torError = "No detailed Tor startup error was recorded."; + return InitError(strprintf(_("Tor failed to start. Triangles requires Tor to operate.\n\nDetails: %s"), torError)); } // Initialize Tor V3 identity (Ed25519 keys, onion address) diff --git a/src/tor/tor_embedded.cpp b/src/tor/tor_embedded.cpp index f8d4717..fe7b18e 100644 --- a/src/tor/tor_embedded.cpp +++ b/src/tor/tor_embedded.cpp @@ -114,6 +114,7 @@ bool CTorEmbedded::Start(int socks, int hsPort, bool enableHiddenService) { if (running.load()) return true; + lastError.clear(); socksPort = socks; hiddenServiceEnabled = enableHiddenService; hiddenServicePort = hiddenServiceEnabled ? hsPort : 0; @@ -202,11 +203,13 @@ bool CTorEmbedded::Start(int socks, int hsPort, bool enableHiddenService) } if (!running.load()) { + lastError = "Embedded Tor thread exited during bootstrap before the SOCKS proxy became available."; printf("ERROR: Embedded Tor thread exited during bootstrap\n"); return false; } } + lastError = strprintf("Embedded Tor did not expose SOCKS port %d within 60 seconds.", socksPort); printf("WARNING: Embedded Tor started but SOCKS not ready after 60s (still bootstrapping)\n"); return true; } @@ -241,8 +244,12 @@ bool CTorEmbedded::Start(int socks, int hsPort, bool enableHiddenService) hiddenServiceEnabled = enableHiddenService; hiddenServicePort = hiddenServiceEnabled ? hsPort : 0; onionHostname.clear(); + lastError.clear(); torDataDir = (::GetDataDir() / "tor_data").string(); running.store(StartTorProcess(torDataDir, socksPort, hiddenServicePort, hiddenServiceEnabled)); + if (!running.load()) { + lastError = CTorProcess::GetInstance()->GetLastError(); + } return running.load(); } diff --git a/src/tor/tor_embedded.h b/src/tor/tor_embedded.h index 18bd739..abe26a5 100644 --- a/src/tor/tor_embedded.h +++ b/src/tor/tor_embedded.h @@ -19,6 +19,7 @@ private: bool hiddenServiceEnabled; std::string torDataDir; std::string onionHostname; + std::string lastError; public: static CTorEmbedded* GetInstance(); @@ -43,6 +44,8 @@ public: // Get our .onion address (available after bootstrap) std::string GetOnionAddress() const { return onionHostname; } + std::string GetLastError() const { return lastError; } + void SetLastError(const std::string& value) { lastError = value; } // Get the hidden service port int GetHiddenServicePort() const { return hiddenServicePort; } diff --git a/src/tor/tor_process.cpp b/src/tor/tor_process.cpp index 7f32027..d9a630c 100644 --- a/src/tor/tor_process.cpp +++ b/src/tor/tor_process.cpp @@ -232,6 +232,7 @@ bool CTorProcess::WriteTorrc() bool CTorProcess::Start(const std::string& dataDir, int socks, int hsPort, bool enableHiddenService) { + lastError.clear(); socksPort = socks; hiddenServiceEnabled = enableHiddenService; hiddenServicePort = hiddenServiceEnabled ? hsPort : 0; @@ -240,6 +241,7 @@ bool CTorProcess::Start(const std::string& dataDir, int socks, int hsPort, bool // Check if something is already listening on our SOCKS port if (IsPortInUse(socksPort)) { printf("Tor SOCKS port %d already in use - assuming Tor is running\n", socksPort); + lastError = strprintf("SOCKS port %d is already in use; assuming an existing Tor instance is serving it.", socksPort); running = true; return true; } @@ -247,6 +249,7 @@ bool CTorProcess::Start(const std::string& dataDir, int socks, int hsPort, bool // Find Tor binary torBinaryPath = FindTorBinary(); if (torBinaryPath.empty()) { + lastError = "Tor binary was not found in the bundled install or standard search paths."; printf("WARNING: Tor binary not found. Install Tor for .onion connectivity.\n"); printf(" Windows: Download from https://www.torproject.org/download/tor/\n"); printf(" Linux: apt install tor or yum install tor\n"); @@ -256,6 +259,7 @@ bool CTorProcess::Start(const std::string& dataDir, int socks, int hsPort, bool // Write configuration if (!WriteTorrc()) { + lastError = strprintf("Failed to write Tor configuration to %s", torrcPath.c_str()); printf("ERROR: Failed to write Tor configuration\n"); return false; } @@ -282,7 +286,9 @@ bool CTorProcess::Start(const std::string& dataDir, int socks, int hsPort, bool NULL, NULL, &si, &pi)) { - printf("ERROR: Failed to start Tor process (error %lu)\n", GetLastError()); + DWORD err = GetLastError(); + lastError = strprintf("CreateProcess failed for Tor binary '%s' with Windows error %lu", torBinaryPath.c_str(), err); + printf("ERROR: Failed to start Tor process (error %lu)\n", err); return false; } @@ -329,6 +335,7 @@ bool CTorProcess::Start(const std::string& dataDir, int socks, int hsPort, bool // Defensive check: Tor must not directly occupy the node's hidden-service // virtual port. If it does, node startup will fail with a bind collision. if (hiddenServiceEnabled && IsPortInUse(hiddenServicePort)) { + lastError = strprintf("Port %d is already busy while Tor hidden service is enabled. Another process is likely blocking the node listener.", hiddenServicePort); printf("ERROR: Tor startup collision: hidden service port %d appears busy before node bind.\n", hiddenServicePort); printf(" Refusing to treat Tor as healthy because this would block the node listener.\n"); @@ -353,12 +360,14 @@ bool CTorProcess::Start(const std::string& dataDir, int socks, int hsPort, bool // Check if Tor process is still alive if (!IsRunning()) { + lastError = "Tor process exited during bootstrap before the SOCKS port became ready."; printf("ERROR: Tor process exited prematurely\n"); running = false; return false; } } + lastError = strprintf("Tor process started from '%s' but SOCKS port %d was not ready after 30 seconds.", torBinaryPath.c_str(), socksPort); printf("WARNING: Tor started but SOCKS proxy not yet ready after 30s\n"); printf(" Tor may still be bootstrapping. .onion connections will work once ready.\n"); return true; diff --git a/src/tor/tor_process.h b/src/tor/tor_process.h index f183d8f..2784e09 100644 --- a/src/tor/tor_process.h +++ b/src/tor/tor_process.h @@ -19,6 +19,7 @@ private: std::string torBinaryPath; std::string torDataDir; std::string torrcPath; + std::string lastError; int socksPort; int hiddenServicePort; bool hiddenServiceEnabled; @@ -59,6 +60,7 @@ public: // Get the Tor binary path (for diagnostics) std::string GetBinaryPath() const { return torBinaryPath; } + std::string GetLastError() const { return lastError; } // Singleton access static CTorProcess* GetInstance();