Skip to content

Commit b5190e8

Browse files
committed
Verify hardened checkpoints on start up
This adds a routine that compares the block index entries with the hardened checkpoints when a node starts. It provides user feedback for some forks and database corruption.
1 parent b40a513 commit b5190e8

File tree

2 files changed

+70
-13
lines changed

2 files changed

+70
-13
lines changed

src/gridcoin/gridcoin.cpp

Lines changed: 67 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,68 @@ void Scraper(bool bSingleShot = false);
2828
void ScraperSubscriber();
2929

3030
namespace {
31+
//!
32+
//! \brief Display a message that warns about a corrupted blockchain database.
33+
//!
34+
//! For the GUI, this displays a modal dialog. It prints a message to the log
35+
//! and to stderr on headless nodes.
36+
//!
37+
void ShowChainCorruptedMessage()
38+
{
39+
uiInterface.ThreadSafeMessageBox(
40+
_("WARNING: Blockchain data may be corrupted.\n\n"
41+
"Gridcoin detected bad index entries. This may occur because of an "
42+
"unexpected exit, a power failure, or a late software upgrade.\n\n"
43+
"Please exit Gridcoin, open the data directory, and delete:\n"
44+
" - the blk****.dat files\n"
45+
" - the txleveldb folder\n\n"
46+
"Your wallet will re-download the blockchain. Your balance may "
47+
"appear incorrect until the synchronization finishes.\n" ),
48+
"Gridcoin",
49+
CClientUIInterface::OK | CClientUIInterface::MODAL);
50+
}
51+
52+
//!
53+
//! \brief Compare the block index to the hardened checkpoints and display a
54+
//! warning message and exit if an entry does not match.
55+
//!
56+
//! \param pindexBest Block index entry for the tip of the chain.
57+
//!
58+
//! \return \c false if a checkpoint does not match its corresponding block
59+
//! index entry.
60+
//!
61+
bool VerifyCheckpoints(const CBlockIndex* const pindexBest)
62+
{
63+
LogPrintf("Gridcoin: verifying checkpoints...");
64+
uiInterface.InitMessage(_("Verifying checkpoints..."));
65+
66+
for (const auto& checkpoint_pair : Params().Checkpoints().mapCheckpoints) {
67+
if (checkpoint_pair.first > pindexBest->nHeight) {
68+
return true;
69+
}
70+
71+
const auto iter_pair = mapBlockIndex.find(checkpoint_pair.second);
72+
73+
if (iter_pair == mapBlockIndex.end()
74+
|| iter_pair->second == nullptr
75+
|| !iter_pair->second->IsInMainChain()
76+
|| iter_pair->second->nHeight != checkpoint_pair.first)
77+
{
78+
// We could rewind the blockchain, but doing so might take longer
79+
// than a genesis sync for deep reorganizations. For now, we only
80+
// show the message, exit, and let the user choose a resolution:
81+
//
82+
LogPrintf("WARNING: checkpoint mismatch at %d", checkpoint_pair.first);
83+
ShowChainCorruptedMessage();
84+
Shutdown(nullptr);
85+
86+
return false;
87+
}
88+
}
89+
90+
return true;
91+
}
92+
3193
//!
3294
//! \brief Initialize the service that creates and validate superblocks.
3395
//!
@@ -286,18 +348,7 @@ void CheckBlockIndexJob()
286348
return;
287349
}
288350

289-
// This prints a message to the log and stderr on headless:
290-
uiInterface.ThreadSafeMessageBox(
291-
_("WARNING: Blockchain data may be corrupt.\n\n"
292-
"Gridcoin detected bad index entries. This may occur because of an "
293-
"unexpected exit or power failure.\n\n"
294-
"Please exit Gridcoin, open the data directory, and delete:\n"
295-
" - the blk****.dat files\n"
296-
" - the txleveldb folder\n\n"
297-
"Your wallet will re-download the blockchain. Your balance may "
298-
"appear incorrect until the synchronization finishes.\n" ),
299-
"Gridcoin",
300-
CClientUIInterface::OK | CClientUIInterface::MODAL);
351+
ShowChainCorruptedMessage();
301352
}
302353

303354
//!
@@ -388,6 +439,10 @@ bool GRC::Initialize(ThreadHandlerPtr threads, CBlockIndex* pindexBest)
388439
{
389440
LogPrintf("Gridcoin: initializing...");
390441

442+
if (!VerifyCheckpoints(pindexBest)) {
443+
return false;
444+
}
445+
391446
InitializeSuperblockQuorum(pindexBest);
392447

393448
// This has to be before InitializeResearchRewardAccounting, because we need the beacon registry

src/init.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1098,7 +1098,9 @@ bool AppInit2(ThreadHandlerPtr threads)
10981098

10991099
RandAddSeedPerfmon();
11001100

1101-
GRC::Initialize(threads, pindexBest);
1101+
if (!GRC::Initialize(threads, pindexBest)) {
1102+
return false;
1103+
}
11021104

11031105
//// debug print
11041106
if (LogInstance().WillLogCategory(BCLog::LogFlags::VERBOSE))

0 commit comments

Comments
 (0)