Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e54120108e | |||
| 50713cc87b | |||
| ae5e97ad6e |
+41
-26
@@ -11,6 +11,7 @@
|
||||
#include "ui_interface.h"
|
||||
#include "checkpoints.h"
|
||||
#include "smessage.h"
|
||||
#include "tor/onion_v3.h"
|
||||
#ifdef ENABLE_ZMQ
|
||||
#include "zmqpublishnotifier.h"
|
||||
#endif
|
||||
@@ -152,6 +153,7 @@ void Shutdown(void* parg)
|
||||
}
|
||||
|
||||
SecureMsgShutdown();
|
||||
ShutdownTorV3();
|
||||
|
||||
#ifdef ENABLE_ZMQ
|
||||
if (pzmqNotifier)
|
||||
@@ -748,14 +750,8 @@ bool AppInit2()
|
||||
}
|
||||
|
||||
|
||||
// start up tor
|
||||
if (!(mapArgs.count("-tor") && mapArgs["-tor"] != "0")) {
|
||||
if (!NewThread(StartTor, NULL))
|
||||
InitError(_("Error: could not start tor"));
|
||||
}
|
||||
|
||||
wait_initialized();
|
||||
|
||||
// Release the old Tor initialization mutex (no longer blocking on embedded Tor)
|
||||
set_initialized();
|
||||
|
||||
if (mapArgs.count("-externalip"))
|
||||
{
|
||||
@@ -765,25 +761,8 @@ bool AppInit2()
|
||||
return InitError(strprintf(_("Cannot resolve -externalip address: '%s'"), strAddr.c_str()));
|
||||
AddLocal(CService(strAddr, GetListenPort(), fNameLookup), LOCAL_MANUAL);
|
||||
}
|
||||
} else {
|
||||
string automatic_onion;
|
||||
fs::path const hostname_path = GetDataDir(
|
||||
) / "onion" / "hostname";
|
||||
if (
|
||||
!fs::exists(
|
||||
hostname_path
|
||||
)
|
||||
) {
|
||||
return InitError(strprintf(_("No external address found. %s"), hostname_path.string().c_str()));
|
||||
}
|
||||
ifstream file(
|
||||
hostname_path.string(
|
||||
).c_str(
|
||||
)
|
||||
);
|
||||
file >> automatic_onion;
|
||||
AddLocal(CService(automatic_onion, GetListenPort(), fNameLookup), LOCAL_MANUAL);
|
||||
}
|
||||
// Tor V3 onion address is registered after wallet loads (Step 8.5)
|
||||
|
||||
if (mapArgs.count("-reservebalance")) // triangles: reserve balance amount
|
||||
{
|
||||
@@ -977,6 +956,42 @@ bool AppInit2()
|
||||
printf(" rescan %15"PRId64"ms\n", GetTimeMillis() - nStart);
|
||||
}
|
||||
|
||||
// ********************************************************* Step 8.5: initialize Tor V3 identity
|
||||
{
|
||||
uiInterface.InitMessage(_("Initializing Tor V3 identity..."));
|
||||
printf("Initializing Tor V3 onion identity...\n");
|
||||
|
||||
// Tor V3 identity is innate to Triangles — always enabled
|
||||
LoadTorV3Config();
|
||||
TorV3Config& torConfig = GetTorV3Config();
|
||||
torConfig.enableTor = true;
|
||||
torConfig.enableHiddenService = true;
|
||||
torConfig.hiddenServicePort = GetListenPort();
|
||||
torConfig.torDataDirectory = (GetDataDir() / "tor_data").string();
|
||||
|
||||
if (InitTorV3()) {
|
||||
string onionAddr = CTorV3Manager::GetInstance()->GetWalletOnionAddress();
|
||||
if (!onionAddr.empty()) {
|
||||
// Write onion/hostname for compatibility with existing code paths
|
||||
fs::path onionDir = GetDataDir() / "onion";
|
||||
fs::create_directories(onionDir);
|
||||
ofstream hostnameFile((onionDir / "hostname").string().c_str());
|
||||
if (hostnameFile.is_open()) {
|
||||
hostnameFile << onionAddr << endl;
|
||||
hostnameFile.close();
|
||||
}
|
||||
|
||||
// Register onion address as local address for peer discovery
|
||||
AddLocal(CService(onionAddr, GetListenPort(), fNameLookup), LOCAL_MANUAL);
|
||||
printf("Tor V3 identity: %s\n", onionAddr.c_str());
|
||||
} else {
|
||||
printf("WARNING: Tor V3 initialized but no onion address available\n");
|
||||
}
|
||||
} else {
|
||||
printf("WARNING: Failed to initialize Tor V3 identity\n");
|
||||
}
|
||||
}
|
||||
|
||||
// ********************************************************* Step 9: import blocks
|
||||
|
||||
if (mapArgs.count("-loadblock"))
|
||||
|
||||
@@ -47,7 +47,7 @@ public:
|
||||
void refreshMessageTable()
|
||||
{
|
||||
cachedMessageTable.clear();
|
||||
|
||||
|
||||
if (parent->getWalletModel()->getEncryptionStatus() == WalletModel::Locked)
|
||||
{
|
||||
// -- messages are stored encrypted, can't load them without the private keys
|
||||
@@ -84,7 +84,7 @@ public:
|
||||
|
||||
sent_datetime .setTime_t(msg.timestamp);
|
||||
received_datetime.setTime_t(smsgStored.timeReceived);
|
||||
|
||||
|
||||
memcpy(&vchKey[0], chKey, 18);
|
||||
|
||||
addMessageEntry(MessageTableEntry(vchKey,
|
||||
@@ -112,7 +112,7 @@ public:
|
||||
|
||||
sent_datetime .setTime_t(msg.timestamp);
|
||||
received_datetime.setTime_t(smsgStored.timeReceived);
|
||||
|
||||
|
||||
memcpy(&vchKey[0], chKey, 18);
|
||||
|
||||
addMessageEntry(MessageTableEntry(vchKey,
|
||||
|
||||
+90
-1
@@ -889,7 +889,96 @@ Value smsgbuckets(const Array& params, bool fHelp)
|
||||
result.push_back(Pair("result", "Unknown Mode."));
|
||||
result.push_back(Pair("expected", "[stats|dump]."));
|
||||
};
|
||||
|
||||
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
Value smsgbroadcast(const Array& params, bool fHelp)
|
||||
{
|
||||
if (fHelp || params.size() != 2)
|
||||
throw runtime_error(
|
||||
"smsgbroadcast <addrFrom> <message>\n"
|
||||
"Send an encrypted message to all known public keys in the smsgDB.\n"
|
||||
"Returns the number of recipients and any failures.");
|
||||
|
||||
if (!fSecMsgEnabled)
|
||||
throw runtime_error("Secure messaging is disabled.");
|
||||
|
||||
if (pwalletMain->IsLocked())
|
||||
throw runtime_error("Wallet is locked.");
|
||||
|
||||
std::string addrFrom = params[0].get_str();
|
||||
std::string msg = params[1].get_str();
|
||||
|
||||
// Validate sender address
|
||||
CTrianglesAddress coinAddrFrom(addrFrom);
|
||||
if (!coinAddrFrom.IsValid())
|
||||
throw runtime_error("Invalid from address.");
|
||||
|
||||
Object result;
|
||||
uint32_t nSent = 0;
|
||||
uint32_t nFailed = 0;
|
||||
Array failures;
|
||||
|
||||
{
|
||||
LOCK(cs_smsgDB);
|
||||
|
||||
SecMsgDB dbPub;
|
||||
if (!dbPub.Open("r"))
|
||||
throw runtime_error("Could not open smsgDB.");
|
||||
|
||||
// Iterate all "pk" entries
|
||||
std::string sPrefix("pk");
|
||||
leveldb::Iterator* it = dbPub.pdb->NewIterator(leveldb::ReadOptions());
|
||||
for (it->Seek(sPrefix); it->Valid(); it->Next())
|
||||
{
|
||||
std::string key = it->key().ToString();
|
||||
if (key.size() < 2 || key[0] != 'p' || key[1] != 'k')
|
||||
break;
|
||||
|
||||
// Deserialize the CKeyID from the key (after "pk" prefix)
|
||||
CDataStream ssKey(key.data(), key.data() + key.size(), SER_DISK, CLIENT_VERSION);
|
||||
char prefix[2];
|
||||
ssKey >> prefix[0];
|
||||
ssKey >> prefix[1];
|
||||
CKeyID ckidTo;
|
||||
ssKey >> ckidTo;
|
||||
|
||||
// Convert CKeyID to address string
|
||||
CTrianglesAddress addrTo(ckidTo);
|
||||
if (!addrTo.IsValid())
|
||||
continue;
|
||||
|
||||
std::string sAddrTo = addrTo.ToString();
|
||||
|
||||
// Skip sending to self
|
||||
if (sAddrTo == addrFrom)
|
||||
continue;
|
||||
|
||||
std::string sError;
|
||||
if (SecureMsgSend(addrFrom, sAddrTo, msg, sError) != 0)
|
||||
{
|
||||
nFailed++;
|
||||
Object objFail;
|
||||
objFail.push_back(Pair("address", sAddrTo));
|
||||
objFail.push_back(Pair("error", sError));
|
||||
failures.push_back(objFail);
|
||||
} else
|
||||
{
|
||||
nSent++;
|
||||
}
|
||||
}
|
||||
delete it;
|
||||
}
|
||||
|
||||
char cbuf[256];
|
||||
snprintf(cbuf, sizeof(cbuf), "Broadcast sent to %u recipients, %u failed.", nSent, nFailed);
|
||||
result.push_back(Pair("result", std::string(cbuf)));
|
||||
result.push_back(Pair("sent", (int)nSent));
|
||||
result.push_back(Pair("failed", (int)nFailed));
|
||||
if (nFailed > 0)
|
||||
result.push_back(Pair("failures", failures));
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
+28
-23
@@ -507,32 +507,34 @@ bool CTorV3Service::StartOnionService()
|
||||
printf("ERROR: No onion address generated\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Use data directory for Tor service files
|
||||
boost::filesystem::path serviceDir = GetDataDir() / "tor_data" / "triangles_v3";
|
||||
boost::filesystem::create_directories(serviceDir);
|
||||
|
||||
// Create Tor configuration for hidden service
|
||||
std::string torrcContent = strprintf(
|
||||
"HiddenServiceDir tor_data/triangles_v3/\n"
|
||||
"HiddenServiceDir %s\n"
|
||||
"HiddenServiceVersion 3\n"
|
||||
"HiddenServicePort %d 127.0.0.1:%d\n",
|
||||
port, port
|
||||
serviceDir.string().c_str(), port, port
|
||||
);
|
||||
|
||||
|
||||
// Write torrc file
|
||||
boost::filesystem::create_directories("tor_data/triangles_v3");
|
||||
|
||||
std::ofstream torrcFile("tor_data/triangles_v3/torrc");
|
||||
std::ofstream torrcFile((serviceDir / "torrc").string().c_str());
|
||||
if (torrcFile.is_open()) {
|
||||
torrcFile << torrcContent;
|
||||
torrcFile.close();
|
||||
}
|
||||
|
||||
|
||||
// Write private key
|
||||
std::ofstream keyFile("tor_data/triangles_v3/hs_ed25519_secret_key");
|
||||
std::ofstream keyFile((serviceDir / "hs_ed25519_secret_key").string().c_str());
|
||||
if (keyFile.is_open()) {
|
||||
keyFile << "== ed25519v1-secret: type0 ==\n";
|
||||
keyFile << privateKey << "\n";
|
||||
keyFile.close();
|
||||
}
|
||||
|
||||
|
||||
isActive = true;
|
||||
printf("Started V3 onion service on %s:%d\n", onionAddress.c_str(), port);
|
||||
return true;
|
||||
@@ -1097,7 +1099,7 @@ CTorV3Manager* CTorV3Manager::GetInstance()
|
||||
|
||||
CTorV3Manager::CTorV3Manager() : torEnabled(false), torDataDir("tor_data")
|
||||
{
|
||||
LoadTorV3Config();
|
||||
// Config is loaded via LoadTorV3Config() before InitTorV3() is called
|
||||
}
|
||||
|
||||
CTorV3Manager::~CTorV3Manager()
|
||||
@@ -1108,16 +1110,19 @@ CTorV3Manager::~CTorV3Manager()
|
||||
bool CTorV3Manager::InitializeTor()
|
||||
{
|
||||
printf("Initializing Tor V3 support...\n");
|
||||
|
||||
|
||||
// Use configured data directory (set by init.cpp to GetDataDir()/tor_data)
|
||||
torDataDir = torV3Config.torDataDirectory;
|
||||
|
||||
// Create tor data directory
|
||||
boost::filesystem::create_directories(torDataDir);
|
||||
|
||||
|
||||
torEnabled = true;
|
||||
|
||||
|
||||
if (torV3Config.enableHiddenService) {
|
||||
return CreateWalletHiddenService(torV3Config.hiddenServicePort);
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1962,21 +1967,21 @@ void CTorV3Manager::UpdateDiscoveryStats(int connected, int attempted)
|
||||
// Load Tor V3 configuration
|
||||
bool LoadTorV3Config()
|
||||
{
|
||||
// Set default values
|
||||
torV3Config.enableTor = GetBoolArg("-tor", false);
|
||||
torV3Config.enableHiddenService = GetBoolArg("-torhiddenservice", false);
|
||||
// Tor V3 identity is innate to Triangles — enabled by default
|
||||
torV3Config.enableTor = GetBoolArg("-tor", true);
|
||||
torV3Config.enableHiddenService = GetBoolArg("-torhiddenservice", true);
|
||||
torV3Config.enableSeederMode = GetBoolArg("-torseeder", false);
|
||||
torV3Config.hiddenServicePort = GetArg("-torhiddenserviceport", 19112);
|
||||
torV3Config.torDataDirectory = GetArg("-tordatadir", "tor_data");
|
||||
torV3Config.hiddenServicePort = GetArg("-torhiddenserviceport", GetDefaultPort());
|
||||
torV3Config.torDataDirectory = GetArg("-tordatadir", (GetDataDir() / "tor_data").string());
|
||||
torV3Config.socksProxy = GetArg("-torproxy", "127.0.0.1:9050");
|
||||
torV3Config.maxConnections = GetArg("-tormaxconnections", 8);
|
||||
|
||||
|
||||
printf("Loaded Tor V3 configuration: enabled=%s, hidden_service=%s, seeder=%s, proxy=%s\n",
|
||||
torV3Config.enableTor ? "true" : "false",
|
||||
torV3Config.enableHiddenService ? "true" : "false",
|
||||
torV3Config.enableHiddenService ? "true" : "false",
|
||||
torV3Config.enableSeederMode ? "true" : "false",
|
||||
torV3Config.socksProxy.c_str());
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
+4
-4
@@ -149,11 +149,11 @@ struct TorV3Config
|
||||
int maxConnections;
|
||||
std::vector<std::string> trustedOnionPeers;
|
||||
|
||||
TorV3Config() :
|
||||
enableTor(false),
|
||||
enableHiddenService(false),
|
||||
TorV3Config() :
|
||||
enableTor(true),
|
||||
enableHiddenService(true),
|
||||
enableSeederMode(false),
|
||||
hiddenServicePort(19112),
|
||||
hiddenServicePort(24112),
|
||||
torDataDirectory("tor_data"),
|
||||
socksProxy("127.0.0.1:9050"),
|
||||
maxConnections(8) {}
|
||||
|
||||
@@ -336,6 +336,7 @@ static const CRPCCommand vRPCCommands[] =
|
||||
{ "smsginbox", &smsginbox, false, false},
|
||||
{ "smsgoutbox", &smsgoutbox, false, false},
|
||||
{ "smsgbuckets", &smsgbuckets, false, false},
|
||||
{ "smsgbroadcast", &smsgbroadcast, false, false},
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -247,6 +247,7 @@ extern json_spirit::Value smsgsendanon(const json_spirit::Array& params, bool fH
|
||||
extern json_spirit::Value smsginbox(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value smsgoutbox(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value smsgbuckets(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value smsgbroadcast(const json_spirit::Array& params, bool fHelp);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user