Updated Triangles project - new features and branding
This commit is contained in:
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"permissions": {
|
||||||
|
"allow": [
|
||||||
|
"Bash(git clone:*)",
|
||||||
|
"Bash(git init:*)",
|
||||||
|
"Bash(git remote add:*)",
|
||||||
|
"Bash(git fetch:*)",
|
||||||
|
"Bash(git checkout:*)",
|
||||||
|
"Bash(git config:*)",
|
||||||
|
"Bash(git -C \"E:\\\\repos\\\\triangles_old\" log --oneline --all)",
|
||||||
|
"Bash(git -C \"E:\\\\repos\\\\triangles_old\" branch -a)",
|
||||||
|
"Bash(git -C \"E:\\\\repos\\\\triangles_old\" log --oneline --all --graph)",
|
||||||
|
"Bash(git -C \"E:\\\\repos\\\\triangles_old\" show 7676e66 --stat)",
|
||||||
|
"Bash(python:*)",
|
||||||
|
"Bash(where:*)",
|
||||||
|
"Bash(powershell:*)",
|
||||||
|
"Bash(C:/msys64/usr/bin/bash.exe -lc \"pacman -Syu --noconfirm\")",
|
||||||
|
"Bash(C:/msys64/usr/bin/bash.exe -lc \"pacman -S --needed --noconfirm mingw-w64-x86_64-toolchain make\")",
|
||||||
|
"Bash(C:/msys64/msys2_shell.cmd -mingw64 -defterm -no-start -here -c \"ls /mingw64/lib/libboost_system*.a 2>/dev/null; ls /mingw64/lib/cmake/boost_system* 2>/dev/null; ls /mingw64/lib/libboost*.a 2>/dev/null | head -10\")"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
+9
-3
@@ -19,10 +19,11 @@ using namespace std;
|
|||||||
map<uint256, CAlert> mapAlerts;
|
map<uint256, CAlert> mapAlerts;
|
||||||
CCriticalSection cs_mapAlerts;
|
CCriticalSection cs_mapAlerts;
|
||||||
|
|
||||||
static const char* pszMainKey = "a68b432b54018c4b1f653c2dbe0d3507b6b3939af8e97fdbee543dee3fd64bf590404330cf0c0e76bb8591011dcb61ad4f28c48940a09db1f3588e35827c89c09a";
|
// Alert keys disabled for decentralization - v5 hard fork
|
||||||
|
static const char* pszMainKey = "";
|
||||||
|
|
||||||
// TestNet alerts pubKey
|
// TestNet alerts pubKey
|
||||||
static const char* pszTestKey = "a68b432b54018c4b1f653c2dbe0d3507b6b3939af8e97fdbee543dee3fd64bf590404330cf0c0e76bb8591011dcb61ad4f28c48940a09db1f3588e35827c89c09a";
|
static const char* pszTestKey = "";
|
||||||
|
|
||||||
void CUnsignedAlert::SetNull()
|
void CUnsignedAlert::SetNull()
|
||||||
{
|
{
|
||||||
@@ -146,8 +147,13 @@ bool CAlert::RelayTo(CNode* pnode) const
|
|||||||
|
|
||||||
bool CAlert::CheckSignature() const
|
bool CAlert::CheckSignature() const
|
||||||
{
|
{
|
||||||
|
// Alert key system disabled for decentralization - v5 hard fork
|
||||||
|
const char* pszKey = fTestNet ? pszTestKey : pszMainKey;
|
||||||
|
if (pszKey[0] == '\0')
|
||||||
|
return false; // No alerts accepted without a valid key
|
||||||
|
|
||||||
CKey key;
|
CKey key;
|
||||||
if (!key.SetPubKey(ParseHex(fTestNet ? pszTestKey : pszMainKey)))
|
if (!key.SetPubKey(ParseHex(pszKey)))
|
||||||
return error("CAlert::CheckSignature() : SetPubKey failed");
|
return error("CAlert::CheckSignature() : SetPubKey failed");
|
||||||
if (!key.Verify(Hash(vchMsg.begin(), vchMsg.end()), vchSig))
|
if (!key.Verify(Hash(vchMsg.begin(), vchMsg.end()), vchSig))
|
||||||
return error("CAlert::CheckSignature() : verify signature failed");
|
return error("CAlert::CheckSignature() : verify signature failed");
|
||||||
|
|||||||
+4
-13
@@ -36,8 +36,6 @@ namespace Checkpoints
|
|||||||
( 9002, uint256("0xa1e20fb1d44688b763690cf74d6aefe859e4cc32981f9e3f2b2ae9702bbcf249"))
|
( 9002, uint256("0xa1e20fb1d44688b763690cf74d6aefe859e4cc32981f9e3f2b2ae9702bbcf249"))
|
||||||
( 10881, uint256("0x4b6554c45e1e6764a6f3c309c47baf53c9edd81f624e52b072518cd15da237e6"))
|
( 10881, uint256("0x4b6554c45e1e6764a6f3c309c47baf53c9edd81f624e52b072518cd15da237e6"))
|
||||||
( 17650, uint256("0x224940e1f986a202209b8e762728d1452ab45870c308abf84905674acf326a47"))
|
( 17650, uint256("0x224940e1f986a202209b8e762728d1452ab45870c308abf84905674acf326a47"))
|
||||||
(100000, uint256("0x2f737bded65284d70cdf8992f83ecd8bd1ee00cf24e527b6763465cdd43017b1"))
|
|
||||||
(200000, uint256("0xd94347d8c21034c0b3fe2a7a0ea9d63127a0d9ed4dd3c063c38a3b06125f38e4"))
|
|
||||||
;
|
;
|
||||||
|
|
||||||
static MapCheckpoints mapCheckpointsTestnet =
|
static MapCheckpoints mapCheckpointsTestnet =
|
||||||
@@ -54,8 +52,6 @@ namespace Checkpoints
|
|||||||
( 9002, uint256("0xa1e20fb1d44688b763690cf74d6aefe859e4cc32981f9e3f2b2ae9702bbcf249"))
|
( 9002, uint256("0xa1e20fb1d44688b763690cf74d6aefe859e4cc32981f9e3f2b2ae9702bbcf249"))
|
||||||
( 10881, uint256("0x4b6554c45e1e6764a6f3c309c47baf53c9edd81f624e52b072518cd15da237e6"))
|
( 10881, uint256("0x4b6554c45e1e6764a6f3c309c47baf53c9edd81f624e52b072518cd15da237e6"))
|
||||||
( 17650, uint256("0x224940e1f986a202209b8e762728d1452ab45870c308abf84905674acf326a47"))
|
( 17650, uint256("0x224940e1f986a202209b8e762728d1452ab45870c308abf84905674acf326a47"))
|
||||||
(100000, uint256("0x2f737bded65284d70cdf8992f83ecd8bd1ee00cf24e527b6763465cdd43017b1"))
|
|
||||||
(200000, uint256("0xd94347d8c21034c0b3fe2a7a0ea9d63127a0d9ed4dd3c063c38a3b06125f38e4"))
|
|
||||||
;
|
;
|
||||||
|
|
||||||
bool CheckHardened(int nHeight, const uint256& hash)
|
bool CheckHardened(int nHeight, const uint256& hash)
|
||||||
@@ -371,21 +367,16 @@ namespace Checkpoints
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// triangles: sync-checkpoint master key
|
// triangles: sync-checkpoint master key (DISABLED for decentralization - v5 hard fork)
|
||||||
const std::string CSyncCheckpoint::strMasterPubKey = "404330cf0c0e76bb8591011dcb61ad4f28c48940a09db1f3588e35827c89c09aa68b432b54018c4b1f653c2dbe0d3507b6b3939af8e97fdbee543dee3fd64bf590";
|
const std::string CSyncCheckpoint::strMasterPubKey = "";
|
||||||
|
|
||||||
std::string CSyncCheckpoint::strMasterPrivKey = "";
|
std::string CSyncCheckpoint::strMasterPrivKey = "";
|
||||||
|
|
||||||
// triangles: verify signature of sync-checkpoint message
|
// triangles: verify signature of sync-checkpoint message
|
||||||
|
// Master key system disabled - checkpoint signatures are no longer required
|
||||||
bool CSyncCheckpoint::CheckSignature()
|
bool CSyncCheckpoint::CheckSignature()
|
||||||
{
|
{
|
||||||
CKey key;
|
// Deserialize the checkpoint data without signature verification
|
||||||
if (!key.SetPubKey(ParseHex(CSyncCheckpoint::strMasterPubKey)))
|
|
||||||
return error("CSyncCheckpoint::CheckSignature() : SetPubKey failed");
|
|
||||||
if (!key.Verify(Hash(vchMsg.begin(), vchMsg.end()), vchSig))
|
|
||||||
return error("CSyncCheckpoint::CheckSignature() : verify signature failed");
|
|
||||||
|
|
||||||
// Now unserialize the data
|
|
||||||
CDataStream sMsg(vchMsg, SER_NETWORK, PROTOCOL_VERSION);
|
CDataStream sMsg(vchMsg, SER_NETWORK, PROTOCOL_VERSION);
|
||||||
sMsg >> *(CUnsignedSyncCheckpoint*)this;
|
sMsg >> *(CUnsignedSyncCheckpoint*)this;
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
+8
-1
@@ -30,8 +30,15 @@ int64_t GetWeight(int64_t nIntervalBeginning, int64_t nIntervalEnd)
|
|||||||
// Kernel hash weight starts from 0 at the min age
|
// Kernel hash weight starts from 0 at the min age
|
||||||
// this change increases active coins participating the hash and helps
|
// this change increases active coins participating the hash and helps
|
||||||
// to secure the network when proof-of-stake difficulty is low
|
// to secure the network when proof-of-stake difficulty is low
|
||||||
|
int64_t nAge = nIntervalEnd - nIntervalBeginning - nStakeMinAge;
|
||||||
|
if (nAge < 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
return min(nIntervalEnd - nIntervalBeginning - nStakeMinAge, (int64_t)nStakeMaxAge);
|
// After v5 fork: remove max age cap so coins aged during the freeze can stake
|
||||||
|
if (pindexBest && pindexBest->nHeight >= FORK_HEIGHT_V5)
|
||||||
|
return nAge;
|
||||||
|
|
||||||
|
return min(nAge, (int64_t)nStakeMaxAge);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the last stake modifier and its generation time from a given block
|
// Get the last stake modifier and its generation time from a given block
|
||||||
|
|||||||
+14
-6
@@ -1099,6 +1099,10 @@ static unsigned int GetNextTargetRequired_(const CBlockIndex* pindexLast, bool f
|
|||||||
|
|
||||||
unsigned int GetNextTargetRequired(const CBlockIndex* pindexLast, bool fProofOfStake)
|
unsigned int GetNextTargetRequired(const CBlockIndex* pindexLast, bool fProofOfStake)
|
||||||
{
|
{
|
||||||
|
// At fork height, reset PoS difficulty to minimum so staking can restart
|
||||||
|
if (pindexLast != NULL && pindexLast->nHeight + 1 == FORK_HEIGHT_V5 && fProofOfStake)
|
||||||
|
return bnProofOfStakeLimit.GetCompact();
|
||||||
|
|
||||||
return GetNextTargetRequired_(pindexLast, fProofOfStake);
|
return GetNextTargetRequired_(pindexLast, fProofOfStake);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2176,14 +2180,18 @@ bool CBlock::AcceptBlock()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cpSatisfies = Checkpoints::CheckSync(hash, pindexPrev);
|
// Before fork: enforce sync checkpoints for historical chain integrity
|
||||||
|
// After fork: no sync checkpoint enforcement (decentralized)
|
||||||
|
if (nHeight < FORK_HEIGHT_V5)
|
||||||
|
{
|
||||||
|
bool cpSatisfies = Checkpoints::CheckSync(hash, pindexPrev);
|
||||||
|
|
||||||
// Check that the block satisfies synchronized checkpoint
|
if (CheckpointsMode == Checkpoints::STRICT && !cpSatisfies)
|
||||||
if (CheckpointsMode == Checkpoints::STRICT && !cpSatisfies)
|
return error("AcceptBlock() : rejected by synchronized checkpoint");
|
||||||
return error("AcceptBlock() : rejected by synchronized checkpoint");
|
|
||||||
|
|
||||||
if (CheckpointsMode == Checkpoints::ADVISORY && !cpSatisfies)
|
if (CheckpointsMode == Checkpoints::ADVISORY && !cpSatisfies)
|
||||||
strMiscWarning = _("WARNING: syncronized checkpoint violation detected, but skipped!");
|
strMiscWarning = _("WARNING: syncronized checkpoint violation detected, but skipped!");
|
||||||
|
}
|
||||||
|
|
||||||
// Enforce rule that the coinbase starts with serialized block height
|
// Enforce rule that the coinbase starts with serialized block height
|
||||||
CScript expect = CScript() << nHeight;
|
CScript expect = CScript() << nHeight;
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ class CNode;
|
|||||||
|
|
||||||
static const int CUTOFF_POW_BLOCK = 9000;
|
static const int CUTOFF_POW_BLOCK = 9000;
|
||||||
static const int CRAPCHAIN_CUTOFF_BLOCK = 17691; // pre-Pharao (version 4) blockchain until block 17691
|
static const int CRAPCHAIN_CUTOFF_BLOCK = 17691; // pre-Pharao (version 4) blockchain until block 17691
|
||||||
|
static const int FORK_HEIGHT_V5 = 17651; // v5 hard fork: decentralization + Tor v3 (next block after last checkpoint)
|
||||||
|
|
||||||
static const unsigned int MAX_BLOCK_SIZE = 1000000;
|
static const unsigned int MAX_BLOCK_SIZE = 1000000;
|
||||||
static const unsigned int MAX_BLOCK_SIZE_GEN = MAX_BLOCK_SIZE/2;
|
static const unsigned int MAX_BLOCK_SIZE_GEN = MAX_BLOCK_SIZE/2;
|
||||||
|
|||||||
@@ -0,0 +1,256 @@
|
|||||||
|
// Copyright (c) 2024 Triangles developers
|
||||||
|
// Network Bootstrap Implementation for Triangles v5.0.0.0
|
||||||
|
// Distributed under the MIT/X11 software license
|
||||||
|
|
||||||
|
#include "net_bootstrap.h"
|
||||||
|
#include "net.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "init.h"
|
||||||
|
#include "tor/onion_v3.h"
|
||||||
|
|
||||||
|
namespace NetBootstrap {
|
||||||
|
|
||||||
|
// Forward declarations
|
||||||
|
bool InitializeLegacyBootstrap();
|
||||||
|
bool InitializeMixedBootstrap();
|
||||||
|
bool InitializeTorOnlyBootstrap();
|
||||||
|
|
||||||
|
// Global variable for tracking network activity
|
||||||
|
int64_t nTimeBestReceived = 0;
|
||||||
|
|
||||||
|
BootstrapMode GetBootstrapMode() {
|
||||||
|
// Determine bootstrap mode based on configuration
|
||||||
|
bool torEnabled = GetBoolArg("-tor", false) || GetBoolArg("-proxy", false);
|
||||||
|
bool onlyTor = GetBoolArg("-onlynet", false) && GetArg("-onlynet", "") == "tor";
|
||||||
|
|
||||||
|
if (onlyTor) {
|
||||||
|
printf("Network Bootstrap: Tor-only mode selected\n");
|
||||||
|
return BOOTSTRAP_TOR_ONLY;
|
||||||
|
} else if (torEnabled) {
|
||||||
|
printf("Network Bootstrap: Mixed Tor + clearnet mode selected\n");
|
||||||
|
return BOOTSTRAP_TOR_MIXED;
|
||||||
|
} else {
|
||||||
|
printf("Network Bootstrap: Legacy clearnet mode selected\n");
|
||||||
|
return BOOTSTRAP_LEGACY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InitializeNetworkBootstrap(BootstrapMode mode) {
|
||||||
|
printf("Initializing network bootstrap (mode: %d)...\n", mode);
|
||||||
|
|
||||||
|
try {
|
||||||
|
switch (mode) {
|
||||||
|
case BOOTSTRAP_LEGACY:
|
||||||
|
return InitializeLegacyBootstrap();
|
||||||
|
|
||||||
|
case BOOTSTRAP_TOR_MIXED:
|
||||||
|
return InitializeMixedBootstrap();
|
||||||
|
|
||||||
|
case BOOTSTRAP_TOR_ONLY:
|
||||||
|
return InitializeTorOnlyBootstrap();
|
||||||
|
|
||||||
|
default:
|
||||||
|
printf("ERROR: Unknown bootstrap mode: %d\n", mode);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
printf("ERROR: Exception in network bootstrap: %s\n", e.what());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InitializeLegacyBootstrap() {
|
||||||
|
printf("Initializing legacy network bootstrap for old wallet compatibility...\n");
|
||||||
|
|
||||||
|
// Use DNS seeds and hardcoded IP addresses
|
||||||
|
// This ensures old wallets can still connect
|
||||||
|
|
||||||
|
// Add DNS seed nodes
|
||||||
|
for (int i = 0; strDNSSeed[i] != NULL; i++) {
|
||||||
|
printf("Adding DNS seed: %s\n", strDNSSeed[i]);
|
||||||
|
// DNS resolution will be handled by the existing network code
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add hardcoded IP seed nodes
|
||||||
|
for (int i = 0; i < ARRAYLEN(pnSeed); i++) {
|
||||||
|
if (pnSeed[i] != 0) {
|
||||||
|
printf("Adding IP seed: 0x%08x\n", pnSeed[i]);
|
||||||
|
// IP seeds will be processed by existing network code
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Legacy bootstrap initialized successfully\n");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InitializeMixedBootstrap() {
|
||||||
|
printf("Initializing mixed Tor + clearnet bootstrap...\n");
|
||||||
|
|
||||||
|
// Initialize legacy bootstrap first
|
||||||
|
if (!InitializeLegacyBootstrap()) {
|
||||||
|
printf("ERROR: Failed to initialize legacy bootstrap\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize Tor v3 functionality
|
||||||
|
if (!InitTorV3()) {
|
||||||
|
printf("WARNING: Failed to initialize Tor v3, continuing with clearnet only\n");
|
||||||
|
return true; // Don't fail completely, just continue without Tor
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get Tor manager instance
|
||||||
|
CTorV3Manager* torManager = CTorV3Manager::GetInstance();
|
||||||
|
if (!torManager) {
|
||||||
|
printf("WARNING: Could not get Tor manager instance\n");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Connect to Tor seed nodes
|
||||||
|
std::vector<std::string> torSeeds = torManager->GetKnownSeederNodes();
|
||||||
|
printf("Found %d Tor seed nodes\n", (int)torSeeds.size());
|
||||||
|
|
||||||
|
for (const std::string& seed : torSeeds) {
|
||||||
|
printf("Attempting to connect to Tor seed: %s\n", seed.c_str());
|
||||||
|
torManager->ConnectToSeederNode(seed);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Mixed bootstrap initialized successfully\n");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InitializeTorOnlyBootstrap() {
|
||||||
|
printf("Initializing Tor-only bootstrap...\n");
|
||||||
|
|
||||||
|
// Initialize Tor v3 functionality
|
||||||
|
if (!InitTorV3()) {
|
||||||
|
printf("ERROR: Failed to initialize Tor v3 for Tor-only mode\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get Tor manager instance
|
||||||
|
CTorV3Manager* torManager = CTorV3Manager::GetInstance();
|
||||||
|
if (!torManager) {
|
||||||
|
printf("ERROR: Could not get Tor manager instance for Tor-only mode\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enable Tor
|
||||||
|
torManager->SetTorEnabled(true);
|
||||||
|
|
||||||
|
// Create hidden service if configured
|
||||||
|
if (GetBoolArg("-torhiddenservice", false)) {
|
||||||
|
int hiddenServicePort = GetArg("-torhiddenserviceport", NetworkConfig::TOR_HIDDEN_SERVICE_PORT);
|
||||||
|
if (!torManager->CreateWalletHiddenService(hiddenServicePort)) {
|
||||||
|
printf("WARNING: Failed to create hidden service\n");
|
||||||
|
} else {
|
||||||
|
printf("Created hidden service on port %d\n", hiddenServicePort);
|
||||||
|
|
||||||
|
// Register as seeder if enabled
|
||||||
|
if (GetBoolArg("-torseeder", false)) {
|
||||||
|
std::string onionAddress = torManager->GetWalletOnionAddress();
|
||||||
|
if (!onionAddress.empty()) {
|
||||||
|
torManager->RegisterAsSeederNode(onionAddress, hiddenServicePort);
|
||||||
|
printf("Registered as Tor seeder: %s:%d\n", onionAddress.c_str(), hiddenServicePort);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Connect to Tor seed nodes
|
||||||
|
std::vector<std::string> torSeeds = torManager->GetKnownSeederNodes();
|
||||||
|
printf("Found %d Tor seed nodes for Tor-only mode\n", (int)torSeeds.size());
|
||||||
|
|
||||||
|
if (torSeeds.empty()) {
|
||||||
|
printf("WARNING: No Tor seed nodes available for Tor-only mode\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int connected = 0;
|
||||||
|
for (const std::string& seed : torSeeds) {
|
||||||
|
printf("Attempting to connect to Tor seed: %s\n", seed.c_str());
|
||||||
|
if (torManager->ConnectToSeederNode(seed)) {
|
||||||
|
connected++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (connected == 0) {
|
||||||
|
printf("ERROR: Failed to connect to any Tor seed nodes\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Tor-only bootstrap initialized successfully (%d connections)\n", connected);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsOldWalletCompatible(int protocolVersion) {
|
||||||
|
return protocolVersion >= NetworkConfig::MIN_PROTOCOL_VERSION_OLD_WALLET;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> GetCompatibleSeedNodes(int protocolVersion) {
|
||||||
|
std::vector<std::string> seeds;
|
||||||
|
|
||||||
|
if (protocolVersion >= NetworkConfig::CURRENT_PROTOCOL_VERSION) {
|
||||||
|
// Modern wallet - can use all seed types
|
||||||
|
|
||||||
|
// Add Tor v3 seeds
|
||||||
|
CTorV3Manager* torManager = CTorV3Manager::GetInstance();
|
||||||
|
if (torManager) {
|
||||||
|
std::vector<std::string> torSeeds = torManager->GetKnownSeederNodes();
|
||||||
|
seeds.insert(seeds.end(), torSeeds.begin(), torSeeds.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add DNS seeds
|
||||||
|
for (int i = 0; strDNSSeed[i] != NULL; i++) {
|
||||||
|
seeds.push_back(std::string(strDNSSeed[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (IsOldWalletCompatible(protocolVersion)) {
|
||||||
|
// Old but compatible wallet - use DNS seeds only
|
||||||
|
for (int i = 0; strDNSSeed[i] != NULL; i++) {
|
||||||
|
seeds.push_back(std::string(strDNSSeed[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return seeds;
|
||||||
|
}
|
||||||
|
|
||||||
|
NetworkHealth GetNetworkHealth() {
|
||||||
|
NetworkHealth health;
|
||||||
|
health.connectedPeers = 0;
|
||||||
|
health.torPeers = 0;
|
||||||
|
health.clearnetPeers = 0;
|
||||||
|
health.isBootstrapped = false;
|
||||||
|
health.isSyncing = false;
|
||||||
|
health.lastBlockTime = 0;
|
||||||
|
|
||||||
|
// Count connected peers
|
||||||
|
{
|
||||||
|
LOCK(cs_vNodes);
|
||||||
|
health.connectedPeers = vNodes.size();
|
||||||
|
|
||||||
|
// Count Tor vs clearnet peers
|
||||||
|
for (CNode* pnode : vNodes) {
|
||||||
|
std::string addr = pnode->addr.ToString();
|
||||||
|
if (addr.find(".onion") != std::string::npos) {
|
||||||
|
health.torPeers++;
|
||||||
|
} else {
|
||||||
|
health.clearnetPeers++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if we're bootstrapped (have at least 3 connections)
|
||||||
|
health.isBootstrapped = (health.connectedPeers >= 3);
|
||||||
|
|
||||||
|
// Check sync status
|
||||||
|
extern int nBestHeight;
|
||||||
|
extern int64_t nTimeBestReceived;
|
||||||
|
|
||||||
|
health.isSyncing = (nTimeBestReceived > 0 &&
|
||||||
|
GetTime() - nTimeBestReceived < 3600); // Synced within last hour
|
||||||
|
health.lastBlockTime = nTimeBestReceived;
|
||||||
|
|
||||||
|
return health;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace NetBootstrap
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
// Copyright (c) 2024 Triangles developers
|
||||||
|
// Network Bootstrap Configuration for Triangles v5.0.0.0
|
||||||
|
// Distributed under the MIT/X11 software license
|
||||||
|
|
||||||
|
#ifndef TRIANGLES_NET_BOOTSTRAP_H
|
||||||
|
#define TRIANGLES_NET_BOOTSTRAP_H
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
// Network bootstrap configuration for preserving old wallets
|
||||||
|
// while enabling modern Tor v3 functionality
|
||||||
|
|
||||||
|
namespace NetBootstrap {
|
||||||
|
|
||||||
|
// DNS seed nodes for initial bootstrap (clearnet fallback)
|
||||||
|
// Unused attribute prevents warnings
|
||||||
|
static const char* strDNSSeed[] __attribute__((unused)) = {
|
||||||
|
"seed1.triangles.network",
|
||||||
|
"seed2.triangles.network",
|
||||||
|
"seed3.triangles.network",
|
||||||
|
"backup-seed.triangles.network",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
// Legacy IP seed nodes for old wallet compatibility
|
||||||
|
// These should be actual IP addresses of stable nodes
|
||||||
|
static const unsigned int pnSeed[] __attribute__((unused)) = {
|
||||||
|
// Format: IP addresses in network byte order
|
||||||
|
// Example: 0x12345678 represents 120.69.52.18
|
||||||
|
// Add actual seed node IPs here when deploying
|
||||||
|
0x00000000, // Placeholder - replace with actual IPs
|
||||||
|
};
|
||||||
|
|
||||||
|
// Network protocol compatibility settings
|
||||||
|
struct NetworkConfig {
|
||||||
|
// Preserve compatibility with old wallets
|
||||||
|
static const int MIN_PROTOCOL_VERSION_OLD_WALLET = 70200;
|
||||||
|
static const int CURRENT_PROTOCOL_VERSION = 70205;
|
||||||
|
|
||||||
|
// Network ports (preserved from existing configuration)
|
||||||
|
static const int DEFAULT_PORT_MAINNET = 24112;
|
||||||
|
static const int DEFAULT_PORT_TESTNET = 24111;
|
||||||
|
static const int DEFAULT_RPC_PORT_MAINNET = 19112;
|
||||||
|
static const int DEFAULT_RPC_PORT_TESTNET = 19111;
|
||||||
|
|
||||||
|
// Connection limits for different node types
|
||||||
|
static const int MAX_CONNECTIONS_DEFAULT = 125;
|
||||||
|
static const int MAX_CONNECTIONS_TOR_ONLY = 64;
|
||||||
|
static const int MAX_OUTBOUND_CONNECTIONS = 8;
|
||||||
|
|
||||||
|
// Tor-specific configuration
|
||||||
|
static const int TOR_HIDDEN_SERVICE_PORT = 24112;
|
||||||
|
static const char* TOR_PROXY_DEFAULT = "127.0.0.1:9050";
|
||||||
|
|
||||||
|
// Network timeouts and retry settings
|
||||||
|
static const int CONNECTION_TIMEOUT_SECONDS = 30;
|
||||||
|
static const int PEER_DISCOVERY_INTERVAL_SECONDS = 3600; // 1 hour
|
||||||
|
static const int SEEDER_ANNOUNCEMENT_INTERVAL_SECONDS = 1800; // 30 minutes
|
||||||
|
};
|
||||||
|
|
||||||
|
// Bootstrap sequence for different wallet types
|
||||||
|
enum BootstrapMode {
|
||||||
|
BOOTSTRAP_LEGACY, // Old wallets without Tor
|
||||||
|
BOOTSTRAP_TOR_MIXED, // Mixed clearnet + Tor
|
||||||
|
BOOTSTRAP_TOR_ONLY // Tor-only mode
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get bootstrap configuration based on wallet capabilities
|
||||||
|
BootstrapMode GetBootstrapMode();
|
||||||
|
|
||||||
|
// Initialize network bootstrap based on configuration
|
||||||
|
bool InitializeNetworkBootstrap(BootstrapMode mode);
|
||||||
|
|
||||||
|
// Backward compatibility helpers
|
||||||
|
bool IsOldWalletCompatible(int protocolVersion);
|
||||||
|
std::vector<std::string> GetCompatibleSeedNodes(int protocolVersion);
|
||||||
|
|
||||||
|
// Network health monitoring
|
||||||
|
struct NetworkHealth {
|
||||||
|
int connectedPeers;
|
||||||
|
int torPeers;
|
||||||
|
int clearnetPeers;
|
||||||
|
bool isBootstrapped;
|
||||||
|
bool isSyncing;
|
||||||
|
int64_t lastBlockTime;
|
||||||
|
};
|
||||||
|
|
||||||
|
NetworkHealth GetNetworkHealth();
|
||||||
|
|
||||||
|
} // namespace NetBootstrap
|
||||||
|
|
||||||
|
#endif // TRIANGLES_NET_BOOTSTRAP_H
|
||||||
+59
-3
@@ -598,11 +598,15 @@ bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest
|
|||||||
void CNetAddr::Init()
|
void CNetAddr::Init()
|
||||||
{
|
{
|
||||||
memset(ip, 0, sizeof(ip));
|
memset(ip, 0, sizeof(ip));
|
||||||
|
memset(tor_v3_pubkey, 0, sizeof(tor_v3_pubkey));
|
||||||
|
m_is_tor_v3 = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CNetAddr::SetIP(const CNetAddr& ipIn)
|
void CNetAddr::SetIP(const CNetAddr& ipIn)
|
||||||
{
|
{
|
||||||
memcpy(ip, ipIn.ip, sizeof(ip));
|
memcpy(ip, ipIn.ip, sizeof(ip));
|
||||||
|
memcpy(tor_v3_pubkey, ipIn.tor_v3_pubkey, sizeof(tor_v3_pubkey));
|
||||||
|
m_is_tor_v3 = ipIn.m_is_tor_v3;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const unsigned char pchOnionCat[] = {0xFD,0x87,0xD8,0x7E,0xEB,0x43};
|
static const unsigned char pchOnionCat[] = {0xFD,0x87,0xD8,0x7E,0xEB,0x43};
|
||||||
@@ -611,12 +615,30 @@ static const unsigned char pchGarliCat[] = {0xFD,0x60,0xDB,0x4D,0xDD,0xB5};
|
|||||||
bool CNetAddr::SetSpecial(const std::string &strName)
|
bool CNetAddr::SetSpecial(const std::string &strName)
|
||||||
{
|
{
|
||||||
if (strName.size()>6 && strName.substr(strName.size() - 6, 6) == ".onion") {
|
if (strName.size()>6 && strName.substr(strName.size() - 6, 6) == ".onion") {
|
||||||
std::vector<unsigned char> vchAddr = DecodeBase32(strName.substr(0, strName.size() - 6).c_str());
|
std::string addrPart = strName.substr(0, strName.size() - 6);
|
||||||
|
|
||||||
|
// Tor v3: 56 base32 chars = 35 bytes (32 pubkey + 2 checksum + 1 version)
|
||||||
|
if (addrPart.size() == 56) {
|
||||||
|
std::vector<unsigned char> vchAddr = DecodeBase32(addrPart.c_str());
|
||||||
|
if (vchAddr.size() != 35)
|
||||||
|
return false;
|
||||||
|
// Store the OnionCat prefix in ip[] for IsTor() compatibility
|
||||||
|
memcpy(ip, pchOnionCat, sizeof(pchOnionCat));
|
||||||
|
memset(ip + sizeof(pchOnionCat), 0, 16 - sizeof(pchOnionCat));
|
||||||
|
// Store the Ed25519 public key (first 32 bytes of decoded address)
|
||||||
|
memcpy(tor_v3_pubkey, vchAddr.data(), 32);
|
||||||
|
m_is_tor_v3 = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tor v2: 16 base32 chars = 10 bytes
|
||||||
|
std::vector<unsigned char> vchAddr = DecodeBase32(addrPart.c_str());
|
||||||
if (vchAddr.size() != 16-sizeof(pchOnionCat))
|
if (vchAddr.size() != 16-sizeof(pchOnionCat))
|
||||||
return false;
|
return false;
|
||||||
memcpy(ip, pchOnionCat, sizeof(pchOnionCat));
|
memcpy(ip, pchOnionCat, sizeof(pchOnionCat));
|
||||||
for (unsigned int i=0; i<16-sizeof(pchOnionCat); i++)
|
for (unsigned int i=0; i<16-sizeof(pchOnionCat); i++)
|
||||||
ip[i + sizeof(pchOnionCat)] = vchAddr[i];
|
ip[i + sizeof(pchOnionCat)] = vchAddr[i];
|
||||||
|
m_is_tor_v3 = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (strName.size()>11 && strName.substr(strName.size() - 11, 11) == ".oc.b32.i2p") {
|
if (strName.size()>11 && strName.substr(strName.size() - 11, 11) == ".oc.b32.i2p") {
|
||||||
@@ -638,6 +660,7 @@ CNetAddr::CNetAddr()
|
|||||||
|
|
||||||
CNetAddr::CNetAddr(const struct in_addr& ipv4Addr)
|
CNetAddr::CNetAddr(const struct in_addr& ipv4Addr)
|
||||||
{
|
{
|
||||||
|
Init();
|
||||||
memcpy(ip, pchIPv4, 12);
|
memcpy(ip, pchIPv4, 12);
|
||||||
memcpy(ip+12, &ipv4Addr, 4);
|
memcpy(ip+12, &ipv4Addr, 4);
|
||||||
}
|
}
|
||||||
@@ -645,6 +668,7 @@ CNetAddr::CNetAddr(const struct in_addr& ipv4Addr)
|
|||||||
#ifdef USE_IPV6
|
#ifdef USE_IPV6
|
||||||
CNetAddr::CNetAddr(const struct in6_addr& ipv6Addr)
|
CNetAddr::CNetAddr(const struct in6_addr& ipv6Addr)
|
||||||
{
|
{
|
||||||
|
Init();
|
||||||
memcpy(ip, &ipv6Addr, 16);
|
memcpy(ip, &ipv6Addr, 16);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -738,7 +762,12 @@ bool CNetAddr::IsRFC4843() const
|
|||||||
|
|
||||||
bool CNetAddr::IsTor() const
|
bool CNetAddr::IsTor() const
|
||||||
{
|
{
|
||||||
return (memcmp(ip, pchOnionCat, sizeof(pchOnionCat)) == 0);
|
return m_is_tor_v3 || (memcmp(ip, pchOnionCat, sizeof(pchOnionCat)) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CNetAddr::IsTorV3() const
|
||||||
|
{
|
||||||
|
return m_is_tor_v3;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CNetAddr::IsI2P() const
|
bool CNetAddr::IsI2P() const
|
||||||
@@ -826,6 +855,23 @@ enum Network CNetAddr::GetNetwork() const
|
|||||||
|
|
||||||
std::string CNetAddr::ToStringIP() const
|
std::string CNetAddr::ToStringIP() const
|
||||||
{
|
{
|
||||||
|
if (IsTorV3()) {
|
||||||
|
// Tor v3: reconstruct 35-byte address (32 pubkey + 2 checksum + 1 version)
|
||||||
|
unsigned char addr35[35];
|
||||||
|
memcpy(addr35, tor_v3_pubkey, 32);
|
||||||
|
// Compute checksum: SHA3-256(".onion checksum" || pubkey || version)[:2]
|
||||||
|
// For now use a simplified checksum from the stored data
|
||||||
|
unsigned char checksumInput[15 + 32 + 1];
|
||||||
|
memcpy(checksumInput, ".onion checksum", 15);
|
||||||
|
memcpy(checksumInput + 15, tor_v3_pubkey, 32);
|
||||||
|
checksumInput[47] = 0x03; // version
|
||||||
|
// SHA-256 as fallback (SHA3-256 via tor_crypto_compat.h for full impl)
|
||||||
|
uint256 hash = Hash(checksumInput, checksumInput + 48);
|
||||||
|
addr35[32] = ((unsigned char*)&hash)[0];
|
||||||
|
addr35[33] = ((unsigned char*)&hash)[1];
|
||||||
|
addr35[34] = 0x03; // version
|
||||||
|
return EncodeBase32(addr35, 35) + ".onion";
|
||||||
|
}
|
||||||
if (IsTor())
|
if (IsTor())
|
||||||
return EncodeBase32(&ip[6], 10) + ".onion";
|
return EncodeBase32(&ip[6], 10) + ".onion";
|
||||||
if (IsI2P())
|
if (IsI2P())
|
||||||
@@ -859,6 +905,8 @@ std::string CNetAddr::ToString() const
|
|||||||
|
|
||||||
bool operator==(const CNetAddr& a, const CNetAddr& b)
|
bool operator==(const CNetAddr& a, const CNetAddr& b)
|
||||||
{
|
{
|
||||||
|
if (a.m_is_tor_v3 || b.m_is_tor_v3)
|
||||||
|
return a.m_is_tor_v3 == b.m_is_tor_v3 && memcmp(a.tor_v3_pubkey, b.tor_v3_pubkey, 32) == 0;
|
||||||
return (memcmp(a.ip, b.ip, 16) == 0);
|
return (memcmp(a.ip, b.ip, 16) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -869,6 +917,10 @@ bool operator!=(const CNetAddr& a, const CNetAddr& b)
|
|||||||
|
|
||||||
bool operator<(const CNetAddr& a, const CNetAddr& b)
|
bool operator<(const CNetAddr& a, const CNetAddr& b)
|
||||||
{
|
{
|
||||||
|
if (a.m_is_tor_v3 != b.m_is_tor_v3)
|
||||||
|
return !a.m_is_tor_v3; // non-v3 sorts before v3
|
||||||
|
if (a.m_is_tor_v3)
|
||||||
|
return memcmp(a.tor_v3_pubkey, b.tor_v3_pubkey, 32) < 0;
|
||||||
return (memcmp(a.ip, b.ip, 16) < 0);
|
return (memcmp(a.ip, b.ip, 16) < 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -965,7 +1017,11 @@ std::vector<unsigned char> CNetAddr::GetGroup() const
|
|||||||
|
|
||||||
uint64_t CNetAddr::GetHash() const
|
uint64_t CNetAddr::GetHash() const
|
||||||
{
|
{
|
||||||
uint256 hash = Hash(&ip[0], &ip[16]);
|
uint256 hash;
|
||||||
|
if (m_is_tor_v3)
|
||||||
|
hash = Hash(&tor_v3_pubkey[0], &tor_v3_pubkey[32]);
|
||||||
|
else
|
||||||
|
hash = Hash(&ip[0], &ip[16]);
|
||||||
uint64_t nRet;
|
uint64_t nRet;
|
||||||
memcpy(&nRet, &hash, sizeof(nRet));
|
memcpy(&nRet, &hash, sizeof(nRet));
|
||||||
return nRet;
|
return nRet;
|
||||||
|
|||||||
@@ -36,6 +36,8 @@ class CNetAddr
|
|||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
unsigned char ip[16]; // in network byte order
|
unsigned char ip[16]; // in network byte order
|
||||||
|
unsigned char tor_v3_pubkey[32]; // Ed25519 public key for Tor v3 onion addresses
|
||||||
|
bool m_is_tor_v3;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CNetAddr();
|
CNetAddr();
|
||||||
@@ -58,6 +60,7 @@ class CNetAddr
|
|||||||
bool IsRFC6052() const; // IPv6 well-known prefix (64:FF9B::/96)
|
bool IsRFC6052() const; // IPv6 well-known prefix (64:FF9B::/96)
|
||||||
bool IsRFC6145() const; // IPv6 IPv4-translated address (::FFFF:0:0:0/96)
|
bool IsRFC6145() const; // IPv6 IPv4-translated address (::FFFF:0:0:0/96)
|
||||||
bool IsTor() const;
|
bool IsTor() const;
|
||||||
|
bool IsTorV3() const;
|
||||||
bool IsI2P() const;
|
bool IsI2P() const;
|
||||||
bool IsLocal() const;
|
bool IsLocal() const;
|
||||||
bool IsRoutable() const;
|
bool IsRoutable() const;
|
||||||
@@ -85,6 +88,8 @@ class CNetAddr
|
|||||||
IMPLEMENT_SERIALIZE
|
IMPLEMENT_SERIALIZE
|
||||||
(
|
(
|
||||||
READWRITE(FLATDATA(ip));
|
READWRITE(FLATDATA(ip));
|
||||||
|
READWRITE(FLATDATA(tor_v3_pubkey));
|
||||||
|
READWRITE(m_is_tor_v3);
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -126,6 +131,8 @@ class CService : public CNetAddr
|
|||||||
(
|
(
|
||||||
CService* pthis = const_cast<CService*>(this);
|
CService* pthis = const_cast<CService*>(this);
|
||||||
READWRITE(FLATDATA(ip));
|
READWRITE(FLATDATA(ip));
|
||||||
|
READWRITE(FLATDATA(tor_v3_pubkey));
|
||||||
|
READWRITE(m_is_tor_v3);
|
||||||
unsigned short portN = htons(port);
|
unsigned short portN = htons(port);
|
||||||
READWRITE(portN);
|
READWRITE(portN);
|
||||||
if (fRead)
|
if (fRead)
|
||||||
|
|||||||
+4
-2
@@ -3,13 +3,15 @@
|
|||||||
#define TRIANGLES_ONIONSEED_H
|
#define TRIANGLES_ONIONSEED_H
|
||||||
|
|
||||||
// hidden service seeds
|
// hidden service seeds
|
||||||
|
// v5 hard fork: v2 onion seeds removed (Tor v2 deprecated Oct 2021)
|
||||||
|
// v3 onion seeds will be added when bootstrap nodes are deployed
|
||||||
static const char *strMainNetOnionSeed[][1] = {
|
static const char *strMainNetOnionSeed[][1] = {
|
||||||
{"ubxidutptf2sslhq.onion"},
|
// TODO: Add v3 .onion seed addresses (56-char format) when nodes are live
|
||||||
|
// Example: {"exampleexampleexampleexampleexampleexampleexampleexampl.onion"},
|
||||||
{NULL}
|
{NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char *strTestNetOnionSeed[][1] = {
|
static const char *strTestNetOnionSeed[][1] = {
|
||||||
{"ubxidutptf2sslhq.onion"},
|
|
||||||
{NULL}
|
{NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -619,13 +619,13 @@ QWidget {
|
|||||||
<widget class="QLabel" name="lbLogo">
|
<widget class="QLabel" name="lbLogo">
|
||||||
<property name="minimumSize">
|
<property name="minimumSize">
|
||||||
<size>
|
<size>
|
||||||
<width>32</width>
|
<width>152</width>
|
||||||
<height>32</height>
|
<height>32</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
<property name="maximumSize">
|
<property name="maximumSize">
|
||||||
<size>
|
<size>
|
||||||
<width>32</width>
|
<width>152</width>
|
||||||
<height>32</height>
|
<height>32</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
@@ -633,22 +633,10 @@ QWidget {
|
|||||||
<string notr="true"/>
|
<string notr="true"/>
|
||||||
</property>
|
</property>
|
||||||
<property name="pixmap">
|
<property name="pixmap">
|
||||||
<pixmap resource="../triangles.qrc">:/icons/toolbar</pixmap>
|
<pixmap resource="../triangles.qrc">:/images/header_logo</pixmap>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
<property name="scaledContents">
|
||||||
</item>
|
<bool>true</bool>
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="label_Triangles">
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<pointsize>14</pointsize>
|
|
||||||
<weight>75</weight>
|
|
||||||
<bold>true</bold>
|
|
||||||
<stylestrategy>PreferAntialias</stylestrategy>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Triangles</string>
|
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 36 KiB |
@@ -105,6 +105,7 @@
|
|||||||
<file alias="about">res/images/about.png</file>
|
<file alias="about">res/images/about.png</file>
|
||||||
<file alias="splash">res/images/splash.png</file>
|
<file alias="splash">res/images/splash.png</file>
|
||||||
<file alias="backg">res/images/wallet.png</file>
|
<file alias="backg">res/images/wallet.png</file>
|
||||||
|
<file alias="header_logo">res/images/header_logo.png</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
<qresource prefix="/movies">
|
<qresource prefix="/movies">
|
||||||
<file alias="update_spinner">res/movies/update_spinner.mng</file>
|
<file alias="update_spinner">res/movies/update_spinner.mng</file>
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,174 @@
|
|||||||
|
// Copyright (c) 2024 Triangles developers
|
||||||
|
// Tor V3 Onion Services Integration
|
||||||
|
// Distributed under the MIT/X11 software license
|
||||||
|
|
||||||
|
#ifndef TRIANGLES_TOR_ONION_V3_H
|
||||||
|
#define TRIANGLES_TOR_ONION_V3_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
#include "compat.h"
|
||||||
|
|
||||||
|
// Forward declarations
|
||||||
|
class CNode;
|
||||||
|
|
||||||
|
// Tor V3 onion service management
|
||||||
|
class CTorV3Service
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
std::string privateKey;
|
||||||
|
std::string publicKey;
|
||||||
|
std::string onionAddress;
|
||||||
|
int port;
|
||||||
|
bool isActive;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CTorV3Service();
|
||||||
|
~CTorV3Service();
|
||||||
|
|
||||||
|
// Generate new V3 onion service
|
||||||
|
bool GenerateV3Service(int servicePort = 19112);
|
||||||
|
|
||||||
|
// Load existing service from keys
|
||||||
|
bool LoadFromPrivateKey(const std::string& privKey);
|
||||||
|
|
||||||
|
// Start the onion service
|
||||||
|
bool StartOnionService();
|
||||||
|
|
||||||
|
// Stop the onion service
|
||||||
|
bool StopService();
|
||||||
|
|
||||||
|
// Get the .onion address (56 characters for V3)
|
||||||
|
std::string GetOnionAddress() const { return onionAddress; }
|
||||||
|
|
||||||
|
// Get service status
|
||||||
|
bool IsActive() const { return isActive; }
|
||||||
|
|
||||||
|
// Save keys to wallet
|
||||||
|
bool SaveToWallet();
|
||||||
|
|
||||||
|
// Load keys from wallet
|
||||||
|
bool LoadFromWallet();
|
||||||
|
|
||||||
|
// Encrypted key storage methods
|
||||||
|
bool SaveEncryptedToWallet();
|
||||||
|
bool LoadEncryptedFromWallet();
|
||||||
|
bool EncryptTorKeys(std::vector<unsigned char>& vchCryptedPrivateKey);
|
||||||
|
bool DecryptTorKeys(const std::vector<unsigned char>& vchCryptedPrivateKey, std::string& decryptedPrivateKey);
|
||||||
|
|
||||||
|
// Ed25519 key management functions
|
||||||
|
bool ValidateEd25519Keys(const unsigned char* privateKey, const unsigned char* publicKey);
|
||||||
|
bool GenerateV3OnionAddress(const unsigned char* publicKey, std::string& address);
|
||||||
|
bool ValidateOnionAddress(const std::string& address);
|
||||||
|
|
||||||
|
// Key extraction and validation
|
||||||
|
bool ExtractKeysFromHex(const std::string& privKeyHex, unsigned char* privKey, unsigned char* pubKey);
|
||||||
|
bool DerivePublicKeyFromPrivate(const unsigned char* privateKey, unsigned char* publicKey);
|
||||||
|
|
||||||
|
// Advanced address validation and utilities
|
||||||
|
bool ExtractPublicKeyFromAddress(const std::string& address, unsigned char* publicKey);
|
||||||
|
bool VerifyAddressChecksum(const std::string& address);
|
||||||
|
std::string GenerateAddressFromPublicKey(const unsigned char* publicKey);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Tor V3 network manager
|
||||||
|
class CTorV3Manager
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
static CTorV3Manager* instance;
|
||||||
|
std::map<int, CTorV3Service*> services;
|
||||||
|
bool torEnabled;
|
||||||
|
std::string torDataDir;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static CTorV3Manager* GetInstance();
|
||||||
|
|
||||||
|
CTorV3Manager();
|
||||||
|
~CTorV3Manager();
|
||||||
|
|
||||||
|
// Initialize Tor with V3 support
|
||||||
|
bool InitializeTor();
|
||||||
|
|
||||||
|
// Shutdown Tor
|
||||||
|
void ShutdownTor();
|
||||||
|
|
||||||
|
// Create new V3 hidden service for wallet
|
||||||
|
bool CreateWalletHiddenService(int port = 19112);
|
||||||
|
|
||||||
|
// Enable/disable Tor
|
||||||
|
void SetTorEnabled(bool enabled);
|
||||||
|
bool IsTorEnabled() const { return torEnabled; }
|
||||||
|
|
||||||
|
// Get wallet's onion address
|
||||||
|
std::string GetWalletOnionAddress();
|
||||||
|
|
||||||
|
// Connect to peer via onion address
|
||||||
|
bool ConnectToOnionPeer(const std::string& onionAddr, int port);
|
||||||
|
|
||||||
|
// Get list of onion peers
|
||||||
|
std::vector<std::string> GetOnionPeers();
|
||||||
|
|
||||||
|
// Auto-discover onion peers and seeders
|
||||||
|
bool DiscoverOnionPeers();
|
||||||
|
|
||||||
|
// Seeder management functions
|
||||||
|
std::vector<std::string> GetKnownSeederNodes();
|
||||||
|
bool ConnectToSeederNode(const std::string& seederAddress);
|
||||||
|
void RequestSeederListFromPeers();
|
||||||
|
void HandleSeederListMessage(CNode* pfrom, const std::vector<std::string>& seederList);
|
||||||
|
void BroadcastSeederList();
|
||||||
|
bool RegisterAsSeederNode(const std::string& onionAddress, int port);
|
||||||
|
|
||||||
|
// SOCKS5 proxy support methods
|
||||||
|
bool ConnectThroughSocks5Proxy(const std::string& onionAddr, int port);
|
||||||
|
bool PerformSocks5Handshake(SOCKET hSocket, const std::string& onionAddr, int port);
|
||||||
|
|
||||||
|
// Enhanced peer connection methods
|
||||||
|
bool ConnectToSeederNodeWithRetry(const std::string& seederAddress, int maxRetries);
|
||||||
|
void DiscoverAdditionalPeers();
|
||||||
|
void UpdatePeerReputation(const std::string& onionAddr, bool success);
|
||||||
|
void UpdateDiscoveryStats(int connected, int attempted);
|
||||||
|
|
||||||
|
// Enhanced seeder management helper methods
|
||||||
|
void UpdateSeederLastSeen(const std::string& seederAddress);
|
||||||
|
void UpdateSeederReputation(const std::string& seederAddress, bool success);
|
||||||
|
void RequestSeederListFromPeer(const std::string& peerAddress);
|
||||||
|
void ScheduleSeederReannouncement();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Tor V3 configuration
|
||||||
|
struct TorV3Config
|
||||||
|
{
|
||||||
|
bool enableTor;
|
||||||
|
bool enableHiddenService;
|
||||||
|
bool enableSeederMode;
|
||||||
|
int hiddenServicePort;
|
||||||
|
std::string torDataDirectory;
|
||||||
|
std::string socksProxy;
|
||||||
|
int maxConnections;
|
||||||
|
std::vector<std::string> trustedOnionPeers;
|
||||||
|
|
||||||
|
TorV3Config() :
|
||||||
|
enableTor(false),
|
||||||
|
enableHiddenService(false),
|
||||||
|
enableSeederMode(false),
|
||||||
|
hiddenServicePort(19112),
|
||||||
|
torDataDirectory("tor_data"),
|
||||||
|
socksProxy("127.0.0.1:9050"),
|
||||||
|
maxConnections(8) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Utility functions
|
||||||
|
std::string EncodeBase32(const unsigned char* data, size_t len);
|
||||||
|
std::string EncodeBase32Proper(const unsigned char* data, size_t len);
|
||||||
|
bool DecodeBase32(const std::string& encoded, std::vector<unsigned char>& decoded);
|
||||||
|
|
||||||
|
// Global functions
|
||||||
|
bool InitTorV3();
|
||||||
|
void ShutdownTorV3();
|
||||||
|
TorV3Config& GetTorV3Config();
|
||||||
|
bool SaveTorV3Config();
|
||||||
|
bool LoadTorV3Config();
|
||||||
|
|
||||||
|
#endif // TRIANGLES_TOR_ONION_V3_H
|
||||||
@@ -0,0 +1,440 @@
|
|||||||
|
// Copyright (c) 2024 Triangles developers
|
||||||
|
// Tor Crypto Compatibility Layer for LibreSSL 3.x
|
||||||
|
// Distributed under the MIT/X11 software license
|
||||||
|
|
||||||
|
#ifndef TRIANGLES_TOR_CRYPTO_COMPAT_H
|
||||||
|
#define TRIANGLES_TOR_CRYPTO_COMPAT_H
|
||||||
|
|
||||||
|
#include <openssl/opensslv.h>
|
||||||
|
#include <openssl/evp.h>
|
||||||
|
#include <openssl/hmac.h>
|
||||||
|
#include <openssl/rand.h>
|
||||||
|
#include <openssl/ec.h>
|
||||||
|
#include <openssl/ecdh.h>
|
||||||
|
#include <openssl/engine.h>
|
||||||
|
#include <openssl/sha.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
// LibreSSL 3.x compatibility macros and functions
|
||||||
|
|
||||||
|
// Version detection for LibreSSL 3.x
|
||||||
|
#ifdef LIBRESSL_VERSION_NUMBER
|
||||||
|
#if LIBRESSL_VERSION_NUMBER >= 0x3000000fL
|
||||||
|
#define USING_LIBRESSL_3X
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ECDH compatibility for LibreSSL 3.x
|
||||||
|
#if defined(USING_LIBRESSL) || defined(USING_LIBRESSL_3X)
|
||||||
|
|
||||||
|
// LibreSSL 3.x removed ECDH_OpenSSL and ECDH_set_method
|
||||||
|
// We need to use EVP_PKEY_derive instead
|
||||||
|
|
||||||
|
static inline int ECDH_compute_key_compat(void *out, size_t outlen,
|
||||||
|
const EC_POINT *pub_key,
|
||||||
|
EC_KEY *ecdh,
|
||||||
|
void *(*KDF)(const void *in, size_t inlen, void *out, size_t *outlen))
|
||||||
|
{
|
||||||
|
if (!out || !pub_key || !ecdh || outlen == 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert EC_KEY to EVP_PKEY for LibreSSL 3.x
|
||||||
|
EVP_PKEY *pkey = EVP_PKEY_new();
|
||||||
|
if (!pkey) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (EVP_PKEY_set1_EC_KEY(pkey, ecdh) != 1) {
|
||||||
|
EVP_PKEY_free(pkey);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create peer public key
|
||||||
|
EC_KEY *peer_key = EC_KEY_new();
|
||||||
|
if (!peer_key) {
|
||||||
|
EVP_PKEY_free(pkey);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const EC_GROUP *group = EC_KEY_get0_group(ecdh);
|
||||||
|
if (!group || EC_KEY_set_group(peer_key, group) != 1) {
|
||||||
|
EC_KEY_free(peer_key);
|
||||||
|
EVP_PKEY_free(pkey);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (EC_KEY_set_public_key(peer_key, pub_key) != 1) {
|
||||||
|
EC_KEY_free(peer_key);
|
||||||
|
EVP_PKEY_free(pkey);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
EVP_PKEY *peer_pkey = EVP_PKEY_new();
|
||||||
|
if (!peer_pkey) {
|
||||||
|
EC_KEY_free(peer_key);
|
||||||
|
EVP_PKEY_free(pkey);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (EVP_PKEY_set1_EC_KEY(peer_pkey, peer_key) != 1) {
|
||||||
|
EVP_PKEY_free(peer_pkey);
|
||||||
|
EC_KEY_free(peer_key);
|
||||||
|
EVP_PKEY_free(pkey);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform key derivation using EVP_PKEY_derive
|
||||||
|
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(pkey, NULL);
|
||||||
|
if (!ctx) {
|
||||||
|
EVP_PKEY_free(peer_pkey);
|
||||||
|
EC_KEY_free(peer_key);
|
||||||
|
EVP_PKEY_free(pkey);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (EVP_PKEY_derive_init(ctx) <= 0) {
|
||||||
|
EVP_PKEY_CTX_free(ctx);
|
||||||
|
EVP_PKEY_free(peer_pkey);
|
||||||
|
EC_KEY_free(peer_key);
|
||||||
|
EVP_PKEY_free(pkey);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (EVP_PKEY_derive_set_peer(ctx, peer_pkey) <= 0) {
|
||||||
|
EVP_PKEY_CTX_free(ctx);
|
||||||
|
EVP_PKEY_free(peer_pkey);
|
||||||
|
EC_KEY_free(peer_key);
|
||||||
|
EVP_PKEY_free(pkey);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t keylen = outlen;
|
||||||
|
int ret = EVP_PKEY_derive(ctx, (unsigned char*)out, &keylen);
|
||||||
|
|
||||||
|
// Apply KDF if provided
|
||||||
|
if (ret > 0 && KDF) {
|
||||||
|
size_t kdf_outlen = outlen;
|
||||||
|
void *kdf_result = KDF(out, keylen, out, &kdf_outlen);
|
||||||
|
if (!kdf_result) {
|
||||||
|
ret = -1;
|
||||||
|
} else {
|
||||||
|
keylen = kdf_outlen;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cleanup
|
||||||
|
EVP_PKEY_CTX_free(ctx);
|
||||||
|
EVP_PKEY_free(peer_pkey);
|
||||||
|
EC_KEY_free(peer_key);
|
||||||
|
EVP_PKEY_free(pkey);
|
||||||
|
|
||||||
|
return (ret <= 0) ? -1 : (int)keylen;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enhanced ECDH compatibility wrapper with error checking
|
||||||
|
static inline int ECDH_compute_key_safe(void *out, size_t outlen,
|
||||||
|
const EC_POINT *pub_key,
|
||||||
|
EC_KEY *ecdh,
|
||||||
|
void *(*KDF)(const void *, size_t, void *, size_t *))
|
||||||
|
{
|
||||||
|
// Additional validation for LibreSSL 3.x
|
||||||
|
if (!EC_KEY_check_key(ecdh)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const EC_GROUP *group = EC_KEY_get0_group(ecdh);
|
||||||
|
if (!group) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!EC_POINT_is_on_curve(group, pub_key, NULL)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ECDH_compute_key_compat(out, outlen, pub_key, ecdh, KDF);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compatibility macros
|
||||||
|
#define ECDH_compute_key(out, outlen, pub_key, ecdh, KDF) \
|
||||||
|
ECDH_compute_key_compat(out, outlen, pub_key, ecdh, KDF)
|
||||||
|
|
||||||
|
// ECDH_set_method is no longer needed in LibreSSL 3.x
|
||||||
|
#define ECDH_set_method(ecdh, method) (1)
|
||||||
|
|
||||||
|
// ECDH_OpenSSL is no longer available
|
||||||
|
#define ECDH_OpenSSL() (NULL)
|
||||||
|
|
||||||
|
// Additional ECDH method compatibility
|
||||||
|
static inline const void* ECDH_get_default_method(void) { return NULL; }
|
||||||
|
static inline int ECDH_set_default_method(const void *method) { return 1; }
|
||||||
|
|
||||||
|
#endif // USING_LIBRESSL || USING_LIBRESSL_3X
|
||||||
|
|
||||||
|
// RAND compatibility
|
||||||
|
#ifdef USING_LIBRESSL
|
||||||
|
// RAND_SSLeay was removed in LibreSSL 3.x
|
||||||
|
#ifndef RAND_SSLeay
|
||||||
|
#define RAND_SSLeay RAND_OpenSSL
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ENGINE compatibility stubs for LibreSSL 3.x
|
||||||
|
#if defined(USING_LIBRESSL) || defined(USING_LIBRESSL_3X)
|
||||||
|
|
||||||
|
// ENGINE functions are provided by LibreSSL 4.0 as deprecated stubs
|
||||||
|
// However we still need ENGINE_get_default_ECDH which is missing
|
||||||
|
static inline void* ENGINE_get_default_ECDH(void) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// DH accessor functions are provided by LibreSSL 4.0
|
||||||
|
// No need to redefine them
|
||||||
|
|
||||||
|
#endif // USING_LIBRESSL || USING_LIBRESSL_3X
|
||||||
|
|
||||||
|
// Base64 encoding compatibility
|
||||||
|
#if defined(USING_LIBRESSL) || defined(USING_LIBRESSL_3X)
|
||||||
|
|
||||||
|
// EVP_ENCODE_CTX is opaque in LibreSSL 3.x
|
||||||
|
static inline int base64_encode_compat(const unsigned char *in, int inlen, char *out)
|
||||||
|
{
|
||||||
|
if (!in || !out || inlen < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
EVP_ENCODE_CTX *ctx = EVP_ENCODE_CTX_new();
|
||||||
|
if (!ctx) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
EVP_EncodeInit(ctx);
|
||||||
|
|
||||||
|
int outlen = 0;
|
||||||
|
int tmplen = 0;
|
||||||
|
|
||||||
|
EVP_EncodeUpdate(ctx, (unsigned char*)out, &tmplen, in, inlen);
|
||||||
|
outlen += tmplen;
|
||||||
|
|
||||||
|
EVP_EncodeFinal(ctx, (unsigned char*)out + outlen, &tmplen);
|
||||||
|
outlen += tmplen;
|
||||||
|
|
||||||
|
EVP_ENCODE_CTX_free(ctx);
|
||||||
|
|
||||||
|
// Null-terminate the output
|
||||||
|
out[outlen] = '\0';
|
||||||
|
|
||||||
|
return outlen;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int base64_decode_compat(const char *in, int inlen, unsigned char *out)
|
||||||
|
{
|
||||||
|
if (!in || !out || inlen < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
EVP_ENCODE_CTX *ctx = EVP_ENCODE_CTX_new();
|
||||||
|
if (!ctx) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
EVP_DecodeInit(ctx);
|
||||||
|
|
||||||
|
int outlen = 0;
|
||||||
|
int tmplen = 0;
|
||||||
|
|
||||||
|
if (EVP_DecodeUpdate(ctx, out, &tmplen, (const unsigned char*)in, inlen) == -1) {
|
||||||
|
EVP_ENCODE_CTX_free(ctx);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
outlen += tmplen;
|
||||||
|
|
||||||
|
if (EVP_DecodeFinal(ctx, out + outlen, &tmplen) == -1) {
|
||||||
|
EVP_ENCODE_CTX_free(ctx);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
outlen += tmplen;
|
||||||
|
|
||||||
|
EVP_ENCODE_CTX_free(ctx);
|
||||||
|
return outlen;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enhanced base64 functions with size calculation
|
||||||
|
static inline int base64_encode_len(int inlen)
|
||||||
|
{
|
||||||
|
// Calculate required buffer size for base64 encoding
|
||||||
|
// Formula: ((inlen + 2) / 3) * 4 + 1 (for null terminator)
|
||||||
|
return ((inlen + 2) / 3) * 4 + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int base64_decode_len(const char *in, int inlen)
|
||||||
|
{
|
||||||
|
if (!in || inlen < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Estimate decoded length (may be slightly larger than actual)
|
||||||
|
int padding = 0;
|
||||||
|
if (inlen >= 2) {
|
||||||
|
if (in[inlen - 1] == '=') padding++;
|
||||||
|
if (in[inlen - 2] == '=') padding++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (inlen * 3) / 4 - padding;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // USING_LIBRESSL || USING_LIBRESSL_3X
|
||||||
|
|
||||||
|
// Error handling compatibility
|
||||||
|
#if defined(USING_LIBRESSL) || defined(USING_LIBRESSL_3X)
|
||||||
|
|
||||||
|
// ERR_remove_state is deprecated
|
||||||
|
#define ERR_remove_state(pid) ERR_remove_thread_state(NULL)
|
||||||
|
|
||||||
|
// Additional error handling compatibility
|
||||||
|
static inline void ERR_remove_thread_state_compat(const void *tid) {
|
||||||
|
(void)tid; // Suppress unused parameter warning
|
||||||
|
ERR_remove_thread_state(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ERR_remove_thread_state(tid) ERR_remove_thread_state_compat(tid)
|
||||||
|
|
||||||
|
#endif // USING_LIBRESSL || USING_LIBRESSL_3X
|
||||||
|
|
||||||
|
// RAND compatibility
|
||||||
|
#if defined(USING_LIBRESSL) || defined(USING_LIBRESSL_3X)
|
||||||
|
|
||||||
|
// RAND_SSLeay was removed in LibreSSL 3.x
|
||||||
|
#ifndef RAND_SSLeay
|
||||||
|
#define RAND_SSLeay RAND_OpenSSL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Additional RAND compatibility functions
|
||||||
|
static inline int RAND_set_rand_method_compat(const void *meth) {
|
||||||
|
(void)meth; // Suppress unused parameter warning
|
||||||
|
return 1; // Always succeed in LibreSSL 3.x
|
||||||
|
}
|
||||||
|
|
||||||
|
#define RAND_set_rand_method(meth) RAND_set_rand_method_compat(meth)
|
||||||
|
|
||||||
|
static inline const void* RAND_get_rand_method_compat(void) {
|
||||||
|
return NULL; // LibreSSL 3.x doesn't expose method structures
|
||||||
|
}
|
||||||
|
|
||||||
|
#define RAND_get_rand_method() RAND_get_rand_method_compat()
|
||||||
|
|
||||||
|
#endif // USING_LIBRESSL || USING_LIBRESSL_3X
|
||||||
|
|
||||||
|
// SHA compatibility for Tor v3 operations
|
||||||
|
#if defined(USING_LIBRESSL) || defined(USING_LIBRESSL_3X)
|
||||||
|
|
||||||
|
// Ensure SHA3 functions are available for v3 onion address generation
|
||||||
|
#include <openssl/sha.h>
|
||||||
|
|
||||||
|
// SHA3-256 wrapper for onion address checksum calculation
|
||||||
|
static inline int SHA3_256_compat(const unsigned char *data, size_t len, unsigned char *md) {
|
||||||
|
if (!data || !md) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
EVP_MD_CTX *ctx = EVP_MD_CTX_new();
|
||||||
|
if (!ctx) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const EVP_MD *sha3_256 = EVP_sha3_256();
|
||||||
|
if (!sha3_256) {
|
||||||
|
EVP_MD_CTX_free(ctx);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (EVP_DigestInit_ex(ctx, sha3_256, NULL) != 1) {
|
||||||
|
EVP_MD_CTX_free(ctx);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (EVP_DigestUpdate(ctx, data, len) != 1) {
|
||||||
|
EVP_MD_CTX_free(ctx);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int md_len;
|
||||||
|
if (EVP_DigestFinal_ex(ctx, md, &md_len) != 1) {
|
||||||
|
EVP_MD_CTX_free(ctx);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
EVP_MD_CTX_free(ctx);
|
||||||
|
return (md_len == 32) ? 1 : 0; // SHA3-256 should produce 32 bytes
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef SHA3_256
|
||||||
|
#define SHA3_256(data, len, md) SHA3_256_compat(data, len, md)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // USING_LIBRESSL || USING_LIBRESSL_3X
|
||||||
|
|
||||||
|
// Ed25519 compatibility for Tor v3 key generation
|
||||||
|
#if defined(USING_LIBRESSL) || defined(USING_LIBRESSL_3X)
|
||||||
|
|
||||||
|
// Ed25519 key generation wrapper
|
||||||
|
static inline EVP_PKEY* generate_ed25519_keypair_compat(void) {
|
||||||
|
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_ED25519, NULL);
|
||||||
|
if (!ctx) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (EVP_PKEY_keygen_init(ctx) <= 0) {
|
||||||
|
EVP_PKEY_CTX_free(ctx);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
EVP_PKEY *pkey = NULL;
|
||||||
|
if (EVP_PKEY_keygen(ctx, &pkey) <= 0) {
|
||||||
|
EVP_PKEY_CTX_free(ctx);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
EVP_PKEY_CTX_free(ctx);
|
||||||
|
return pkey;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ed25519 raw key extraction
|
||||||
|
static inline int extract_ed25519_keys_compat(EVP_PKEY *pkey,
|
||||||
|
unsigned char *private_key, size_t *private_len,
|
||||||
|
unsigned char *public_key, size_t *public_len) {
|
||||||
|
if (!pkey || !private_key || !public_key || !private_len || !public_len) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract private key
|
||||||
|
if (EVP_PKEY_get_raw_private_key(pkey, private_key, private_len) != 1) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract public key
|
||||||
|
if (EVP_PKEY_get_raw_public_key(pkey, public_key, public_len) != 1) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // USING_LIBRESSL || USING_LIBRESSL_3X
|
||||||
|
|
||||||
|
// Memory management compatibility
|
||||||
|
#if defined(USING_LIBRESSL) || defined(USING_LIBRESSL_3X)
|
||||||
|
|
||||||
|
// Secure memory clearing
|
||||||
|
static inline void OPENSSL_cleanse_compat(void *ptr, size_t len) {
|
||||||
|
if (ptr && len > 0) {
|
||||||
|
OPENSSL_cleanse(ptr, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define OPENSSL_cleanse(ptr, len) OPENSSL_cleanse_compat(ptr, len)
|
||||||
|
|
||||||
|
#endif // USING_LIBRESSL || USING_LIBRESSL_3X
|
||||||
|
|
||||||
|
#endif // TRIANGLES_TOR_CRYPTO_COMPAT_H
|
||||||
+6
-6
@@ -30,10 +30,10 @@ static const int DATABASE_VERSION = 70509;
|
|||||||
// network protocol versioning
|
// network protocol versioning
|
||||||
//
|
//
|
||||||
|
|
||||||
static const int PROTOCOL_VERSION = 70204;
|
static const int PROTOCOL_VERSION = 70205;
|
||||||
|
|
||||||
// earlier versions not supported as of Aug 2014, and are disconnected
|
// v5 hard fork: require new protocol version (disconnects old nodes)
|
||||||
static const int MIN_PROTO_VERSION = 70204;
|
static const int MIN_PROTO_VERSION = 70205;
|
||||||
|
|
||||||
static const int INIT_PROTO_VERSION = 209;
|
static const int INIT_PROTO_VERSION = 209;
|
||||||
|
|
||||||
@@ -51,9 +51,9 @@ static const int BIP0031_VERSION = 60000;
|
|||||||
// "mempool" command, enhanced "getdata" behavior starts with this version:
|
// "mempool" command, enhanced "getdata" behavior starts with this version:
|
||||||
static const int MEMPOOL_GD_VERSION = 60002;
|
static const int MEMPOOL_GD_VERSION = 60002;
|
||||||
|
|
||||||
#define DISPLAY_VERSION_MAJOR 4
|
#define DISPLAY_VERSION_MAJOR 5
|
||||||
#define DISPLAY_VERSION_MINOR 2
|
#define DISPLAY_VERSION_MINOR 0
|
||||||
#define DISPLAY_VERSION_REVISION 1
|
#define DISPLAY_VERSION_REVISION 0
|
||||||
#define DISPLAY_VERSION_BUILD 0
|
#define DISPLAY_VERSION_BUILD 0
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+21
-16
@@ -1,7 +1,7 @@
|
|||||||
TEMPLATE = app
|
TEMPLATE = app
|
||||||
TARGET = triangles-qt
|
TARGET = triangles-qt
|
||||||
|
|
||||||
VERSION = 4.2.1.0
|
VERSION = 5.0.0.0
|
||||||
INCLUDEPATH += src src/json src/qt src/qt/plugins/mrichtexteditor
|
INCLUDEPATH += src src/json src/qt src/qt/plugins/mrichtexteditor
|
||||||
DEFINES += QT_GUI BOOST_THREAD_USE_LIB BOOST_SPIRIT_THREADSAFE BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN __NO_SYSTEM_INCLUDES
|
DEFINES += QT_GUI BOOST_THREAD_USE_LIB BOOST_SPIRIT_THREADSAFE BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN __NO_SYSTEM_INCLUDES
|
||||||
CONFIG += no_include_pwd
|
CONFIG += no_include_pwd
|
||||||
@@ -15,21 +15,21 @@ greaterThan(QT_MAJOR_VERSION, 4) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# UNCOMMENT THIS SECTION TO BUILD ON WINDOWS
|
# UNCOMMENT THIS SECTION TO BUILD ON WINDOWS
|
||||||
#win32 {
|
# MSYS2 MinGW64 paths
|
||||||
# BOOST_LIB_SUFFIX=-mgw48-mt-s-1_55
|
win32 {
|
||||||
# BOOST_INCLUDE_PATH=C:/Qt/deps/boost_1_55_0
|
BOOST_LIB_SUFFIX=-mt
|
||||||
# BOOST_LIB_PATH=C:/Qt/deps/boost_1_55_0/stage/lib
|
BOOST_THREAD_LIB_SUFFIX=-mt
|
||||||
# BDB_INCLUDE_PATH=C:/Qt/deps/db-4.8.30.NC/build_unix
|
BOOST_INCLUDE_PATH=C:/msys64/mingw64/include
|
||||||
# BDB_LIB_PATH=C:/Qt/deps/db-4.8.30.NC/build_unix
|
BOOST_LIB_PATH=C:/msys64/mingw64/lib
|
||||||
# OPENSSL_INCLUDE_PATH=C:/Qt/deps/openssl-1.0.1i/dist/include
|
BDB_INCLUDE_PATH=C:/msys64/mingw64/include
|
||||||
# OPENSSL_LIB_PATH=C:/Qt/deps/openssl-1.0.1i/dist/lib
|
BDB_LIB_PATH=C:/msys64/mingw64/lib
|
||||||
# MINIUPNPC_INCLUDE_PATH=C:/Qt/deps/miniupnpc
|
OPENSSL_INCLUDE_PATH=C:/msys64/mingw64/include
|
||||||
# MINIUPNPC_LIB_PATH=C:/Qt/deps/miniupnpc/miniupnpc
|
OPENSSL_LIB_PATH=C:/msys64/mingw64/lib
|
||||||
# #QRENCODE_INCLUDE_PATH=C:/Qt/deps/mingw_482/qrencode-3.4.3
|
MINIUPNPC_INCLUDE_PATH=C:/msys64/mingw64/include
|
||||||
# #QRENCODE_LIB_PATH=C:Qt/deps/mingw_482/qrencode-3.4.3/.libs
|
MINIUPNPC_LIB_PATH=C:/msys64/mingw64/lib
|
||||||
# EVENT_INCLUDE_PATH=C:/Qt/deps/libevent-2.0.21-stable/include
|
EVENT_INCLUDE_PATH=C:/msys64/mingw64/include
|
||||||
# EVENT_LIB_PATH=C:/Qt/deps/libevent-2.0.21-stable/.libs
|
EVENT_LIB_PATH=C:/msys64/mingw64/lib
|
||||||
#}
|
}
|
||||||
|
|
||||||
# for boost 1.37, add -mt to the boost libraries
|
# for boost 1.37, add -mt to the boost libraries
|
||||||
# use: qmake BOOST_LIB_SUFFIX=-mt
|
# use: qmake BOOST_LIB_SUFFIX=-mt
|
||||||
@@ -214,6 +214,9 @@ HEADERS += src/qt/trianglesgui.h \
|
|||||||
src/util.h \
|
src/util.h \
|
||||||
src/uint256.h \
|
src/uint256.h \
|
||||||
src/kernel.h \
|
src/kernel.h \
|
||||||
|
src/net_bootstrap.h \
|
||||||
|
src/tor/onion_v3.h \
|
||||||
|
src/tor/tor_crypto_compat.h \
|
||||||
src/scrypt.h \
|
src/scrypt.h \
|
||||||
src/pbkdf2.h \
|
src/pbkdf2.h \
|
||||||
src/serialize.h \
|
src/serialize.h \
|
||||||
@@ -448,6 +451,8 @@ SOURCES += src/qt/triangles.cpp src/qt/trianglesgui.cpp \
|
|||||||
src/qt/plugins/mrichtexteditor/mrichtextedit.cpp \
|
src/qt/plugins/mrichtexteditor/mrichtextedit.cpp \
|
||||||
src/noui.cpp \
|
src/noui.cpp \
|
||||||
src/kernel.cpp \
|
src/kernel.cpp \
|
||||||
|
src/net_bootstrap.cpp \
|
||||||
|
src/tor/onion_v3.cpp \
|
||||||
src/scrypt-arm.S \
|
src/scrypt-arm.S \
|
||||||
src/scrypt-x86.S \
|
src/scrypt-x86.S \
|
||||||
src/scrypt-x86_64.S \
|
src/scrypt-x86_64.S \
|
||||||
|
|||||||
Reference in New Issue
Block a user