From b0e9ca334f9d1b1ed81475d91c149a2930231e34 Mon Sep 17 00:00:00 2001 From: Sami Ahmed Date: Fri, 10 Apr 2026 23:54:16 -0700 Subject: [PATCH] Use deterministic time check in CheckBlock to fix Tor chain splits (v5.7.9) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace FutureDrift(GetAdjustedTime()) with GetTime() + 15min in CheckBlock and header-sync validation. GetAdjustedTime() incorporates peer-reported time offsets that vary between Tor nodes, causing the same block to be accepted by some nodes and rejected by others — the primary cause of persistent chain forks. AcceptBlock still enforces tight 3-min drift rules deterministically against the previous block timestamp. Co-Authored-By: Claude Opus 4.6 --- CMakeLists.txt | 2 +- src/clientversion.h | 2 +- src/main.cpp | 12 +++++++++--- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5d3200e..3836949 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ if(POLICY CMP0167) endif() project(Triangles - VERSION 5.7.8.0 + VERSION 5.7.9.0 DESCRIPTION "Cryptographic Triangles Wallet" LANGUAGES C CXX ) diff --git a/src/clientversion.h b/src/clientversion.h index e22d33d..2bbd8fe 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 7 -#define CLIENT_VERSION_REVISION 8 +#define CLIENT_VERSION_REVISION 9 #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 294576d..a159d71 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -247,7 +247,7 @@ static bool AddHeaderSyncNode(const CBlock& header, const uint256& hashHeader) return false; } - if (header.GetBlockTime() > FutureDrift(GetAdjustedTime())) + if (header.GetBlockTime() > GetTime() + 15 * 60) { printf("IBD-DIAG: header rejected (future time) hash=%s time=%u\n", hashHeader.ToString().substr(0,20).c_str(), header.nTime); @@ -2829,8 +2829,14 @@ bool CBlock::CheckBlock(bool fCheckPOW, bool fCheckMerkleRoot, bool fCheckSig) c if (fCheckPOW && IsProofOfWork() && !CheckProofOfWork(GetHash(), nBits)) return DoS(50, error("CheckBlock() : proof of work failed")); - // Check timestamp - if (GetBlockTime() > FutureDrift(GetAdjustedTime())) + // Check timestamp: reject blocks obviously too far in the future. + // Use a generous 15-minute window from the raw system clock. + // GetAdjustedTime() is NOT used here because it incorporates peer-reported + // time offsets that differ between Tor nodes, causing nondeterministic + // block rejection — the primary cause of persistent chain splits. + // The deterministic timestamp checks in AcceptBlock (median-time-past, + // prev-block-time with 3-min drift) still enforce tight rules. + if (GetBlockTime() > GetTime() + 15 * 60) return error("CheckBlock() : block timestamp too far in the future"); // First transaction must be coinbase, the rest must not be