Fix null pointer crashes causing seed node crash-loops (v5.8.1)

Guard pindexBest and pprev dereferences that segfault during IBD
block serving when chain state is incomplete:
- kernel.cpp: CheckStakeKernelHash null pindexBest during PoS validation
- main.cpp: InvalidChainFound null pprev/pindexBest on rejected blocks
- main.cpp: SetBestChain null pprev in trust calculation
- main.cpp: ProcessBlock orphan handler null pindexBest

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-17 00:55:48 -07:00
parent a0e8e74d0d
commit cd7b68f7cb
4 changed files with 18 additions and 12 deletions
+1 -1
View File
@@ -6,7 +6,7 @@ if(POLICY CMP0167)
endif()
project(Triangles
VERSION 5.8.0.0
VERSION 5.8.1.0
DESCRIPTION "Cryptographic Triangles Wallet"
LANGUAGES C CXX
)
+1 -1
View File
@@ -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 0
#define CLIENT_VERSION_REVISION 1
#define CLIENT_VERSION_BUILD 0
// Converts the parameter X to a string after macro replacement on X has been performed.
+6 -4
View File
@@ -334,9 +334,11 @@ bool CheckStakeKernelHash(unsigned int nBits, const CBlock& blockFrom, unsigned
// Now check if proof-of-stake hash meets target protocol
if (CBigNum(hashProofOfStake) > bnCoinDayWeight * bnTargetPerCoinDay)
{
// Guard against null pindexBest during early startup / IBD
int nCurrentHeight = pindexBest ? pindexBest->nHeight : 0;
// triangles fix: accept hash to get blockchain moving again with Pharao release (v 4.0.0.1) for first 10 blocks after release
//printf(">>>> pindexBest->nHeight %d\n",pindexBest->nHeight);
if (pindexBest->nHeight > CRAPCHAIN_CUTOFF_BLOCK)
if (nCurrentHeight > CRAPCHAIN_CUTOFF_BLOCK)
{
if(fDebug)
{
@@ -349,8 +351,8 @@ bool CheckStakeKernelHash(unsigned int nBits, const CBlock& blockFrom, unsigned
else
{
//accept hash
if (pindexBest->nHeight % 10000 == 0 || pindexBest->nHeight > 2186900)
printf(">>>> pindexBest->nHeight %d, Pharao release - hash accepted\n", pindexBest->nHeight);
if (nCurrentHeight % 10000 == 0 || nCurrentHeight > 2186900)
printf(">>>> pindexBest->nHeight %d, Pharao release - hash accepted\n", nCurrentHeight);
}
}
+10 -6
View File
@@ -1504,8 +1504,12 @@ void static InvalidChainFound(CBlockIndex* pindexNew)
uiInterface.NotifyBlocksChanged();
}
uint256 nBestInvalidBlockTrust = pindexNew->nChainTrust - pindexNew->pprev->nChainTrust;
uint256 nBestBlockTrust = pindexBest->nHeight != 0 ? (pindexBest->nChainTrust - pindexBest->pprev->nChainTrust) : pindexBest->nChainTrust;
uint256 nBestInvalidBlockTrust = pindexNew->pprev
? pindexNew->nChainTrust - pindexNew->pprev->nChainTrust
: pindexNew->nChainTrust;
uint256 nBestBlockTrust = (pindexBest && pindexBest->nHeight != 0 && pindexBest->pprev)
? (pindexBest->nChainTrust - pindexBest->pprev->nChainTrust)
: (pindexBest ? pindexBest->nChainTrust : uint256(0));
printf("InvalidChainFound: invalid block=%s height=%d trust=%s blocktrust=%" PRId64 " date=%s\n",
pindexNew->GetBlockHash().ToString().substr(0,20).c_str(), pindexNew->nHeight,
@@ -1513,9 +1517,9 @@ void static InvalidChainFound(CBlockIndex* pindexNew)
DateTimeStrFormat("%x %H:%M:%S", pindexNew->GetBlockTime()).c_str());
printf("InvalidChainFound: current best=%s height=%d trust=%s blocktrust=%" PRId64 " date=%s\n",
hashBestChain.ToString().substr(0,20).c_str(), nBestHeight,
CBigNum(pindexBest->nChainTrust).ToString().c_str(),
pindexBest ? CBigNum(pindexBest->nChainTrust).ToString().c_str() : "0",
nBestBlockTrust.Get64(),
DateTimeStrFormat("%x %H:%M:%S", pindexBest->GetBlockTime()).c_str());
pindexBest ? DateTimeStrFormat("%x %H:%M:%S", pindexBest->GetBlockTime()).c_str() : "unknown");
}
@@ -2536,7 +2540,7 @@ bool CBlock::SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew)
nTimeBestReceived = GetTime();
nTransactionsUpdated++;
uint256 nBestBlockTrust = pindexBest->nHeight != 0 ? (pindexBest->nChainTrust - pindexBest->pprev->nChainTrust) : pindexBest->nChainTrust;
uint256 nBestBlockTrust = (pindexBest->nHeight != 0 && pindexBest->pprev) ? (pindexBest->nChainTrust - pindexBest->pprev->nChainTrust) : pindexBest->nChainTrust;
// Log every 5000 blocks during sync, every block once caught up
if (nBestHeight % 5000 == 0 || !IsInitialBlockDownload())
@@ -3165,7 +3169,7 @@ bool ProcessBlock(CNode* pfrom, CBlock* pblock)
}
// Ask this guy to fill in what we're missing
if (pfrom)
if (pfrom && pindexBest)
{
pfrom->PushGetBlocks(pindexBest, GetOrphanRoot(pblock2));
// triangles: getblocks may not obtain the ancestor block rejected