diff --git a/CMakeLists.txt b/CMakeLists.txt index bc87ee9..45fd8d0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ if(POLICY CMP0167) endif() project(Triangles - VERSION 5.8.2 + VERSION 5.8.3 DESCRIPTION "Cryptographic Triangles Wallet" LANGUAGES C CXX ) diff --git a/src/clientversion.h b/src/clientversion.h index 1f31b6e..b06a99f 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -8,7 +8,7 @@ // These need to be macros, as version.cpp's and triangles-qt.rc's voodoo requires it #define CLIENT_VERSION_MAJOR 5 #define CLIENT_VERSION_MINOR 8 -#define CLIENT_VERSION_REVISION 2 +#define CLIENT_VERSION_REVISION 3 #define CLIENT_VERSION_BUILD 0 // Converts the parameter X to a string after macro replacement on X has been performed. diff --git a/src/main.cpp b/src/main.cpp index d809724..f1ee29f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2970,15 +2970,15 @@ bool CBlock::AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos, const u // 2. Equal trust: deterministic hash tiebreaker — lower tip hash wins. // This ensures all nodes converge on the same chain even when two // forks have identical cumulative difficulty (common in PoS). - // Rate-limited to one equal-trust reorg per 10 minutes to prevent - // oscillation from Tor-latency-induced competing announcements. + // Rate-limited to one equal-trust reorg per 2 minutes — short enough + // for fast convergence but long enough to prevent oscillation on Tor. bool fNewBest = false; static int64_t nLastEqualTrustReorg = 0; if (pindexNew->nChainTrust > nBestChainTrust) fNewBest = true; else if (pindexNew->nChainTrust == nBestChainTrust && pindexBest && pindexNew->GetBlockHash() < pindexBest->GetBlockHash() && - GetTime() - nLastEqualTrustReorg > 10 * 60) + GetTime() - nLastEqualTrustReorg > 2 * 60) { fNewBest = true; nLastEqualTrustReorg = GetTime(); @@ -3190,14 +3190,20 @@ bool CBlock::AcceptBlock() if (!AddToBlockIndex(nFile, nBlockPos, hashProofOfStake)) return error("AcceptBlock() : AddToBlockIndex failed"); - // Relay inventory, but don't relay old inventory during initial block download + // Push new tip block directly to all peers. On a small Tor-only + // network the inv→getdata→block round-trip adds 1-2 seconds of latency + // per hop — enough for a competing staker to create a fork. Pushing + // the full block immediately cuts propagation to a single hop. int nBlockEstimate = Checkpoints::GetTotalBlocksEstimate(); if (hashBestChain == hash) { LOCK(cs_vNodes); for (CNode* pnode : vNodes) if (nBestHeight > (pnode->nStartingHeight != -1 ? pnode->nStartingHeight - 2000 : nBlockEstimate)) - pnode->PushInventory(CInv(MSG_BLOCK, hash)); + { + pnode->PushMessage("block", *this); + pnode->AddInventoryKnown(CInv(MSG_BLOCK, hash)); + } } return true; @@ -5308,6 +5314,20 @@ bool SendMessages(CNode* pto, bool fSendTrickle) pto->PushMessage("inv", vInv); + // + // Periodic chain-tip sync: every 45 seconds, ask each peer if they + // have blocks we don't. On a small Tor-only network, transient + // partitions can cause forks that persist silently — this ensures + // nodes discover the longer chain even without explicit announcement. + // + if (!IsInitialBlockDownload() && !pto->fClient && pindexBest && + GetTime() - pto->nLastTipCheck > 45) + { + pto->nLastTipCheck = GetTime(); + pto->pindexLastGetBlocksBegin = NULL; // reset dedup to force request + pto->PushGetBlocks(pindexBest, uint256(0)); + } + // // Stall detection: if we're still catching up and no new blocks for // a while, re-request. Active during IBD (5s timeout) and also diff --git a/src/main.h b/src/main.h index 8469702..b70e958 100644 --- a/src/main.h +++ b/src/main.h @@ -59,10 +59,10 @@ static const int fHaveUPnP = false; static const uint256 hashGenesisBlockOfficial("0x7e7a6e4dd5fe895106fca912dfbacaeaf2a89e76c6a588df8ff96e0e18b96021"); static const uint256 hashGenesisBlockTestNet ("0x7e7a6e4dd5fe895106fca912dfbacaeaf2a89e76c6a588df8ff96e0e18b96021"); -inline int64_t GetMaxTimeDrift(int nHeight) { return (nHeight >= FORK_HEIGHT_V5_4) ? 3 * 60 : 10 * 60; } +inline int64_t GetMaxTimeDrift(int nHeight) { return (nHeight >= FORK_HEIGHT_V5_4) ? 90 : 10 * 60; } inline int64_t PastDrift(int64_t nTime, int nHeight) { return nTime - GetMaxTimeDrift(nHeight); } inline int64_t FutureDrift(int64_t nTime, int nHeight) { return nTime + GetMaxTimeDrift(nHeight); } -// Height-less overloads always use post-V5.4 rules (3-min drift). +// Height-less overloads always use post-V5.4 rules (90-second drift). // All nodes are well past FORK_HEIGHT_V5_4; using the global nBestHeight // here previously caused nodes at different heights to disagree on block // validity during the fork transition — a consensus-splitting bug. diff --git a/src/miner.cpp b/src/miner.cpp index 95f96b1..16b1f5c 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -413,7 +413,7 @@ void StakeMiner(CWallet *pwallet) if (fTryToSync) { fTryToSync = false; - if (vNodes.size() < 1 || nBestHeight < GetNumBlocksOfPeers()) + if (vNodes.size() < 2 || nBestHeight < GetNumBlocksOfPeers()) { MilliSleep(60000); continue; diff --git a/src/net.h b/src/net.h index 20f643f..4ffa833 100644 --- a/src/net.h +++ b/src/net.h @@ -272,6 +272,7 @@ public: CBlockIndex* pindexLastGetHeadersBegin; uint256 hashLastGetHeadersEnd; int nStartingHeight; + int64_t nLastTipCheck; // last time we asked this peer for chain tip // flood relay std::vector vAddrToSend; @@ -319,6 +320,7 @@ public: pindexLastGetHeadersBegin = 0; hashLastGetHeadersEnd = 0; nStartingHeight = -1; + nLastTipCheck = 0; fGetAddr = false; nMisbehavior = 0; hashCheckpointKnown = 0;