Skip to content

Commit 1c31aa3

Browse files
authored
Merge pull request #2758 from jamescowens/enhance_checkpoint_fail_actions
gui, util: Enhance verify checkpoints fail handling; use RegistryBookmarks for DB passivation
2 parents 7847923 + ddf33f6 commit 1c31aa3

File tree

14 files changed

+88
-137
lines changed

14 files changed

+88
-137
lines changed

src/gridcoin/beacon.cpp

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1391,21 +1391,6 @@ BeaconRegistry::BeaconDB &BeaconRegistry::GetBeaconDB()
13911391
return m_beacon_db;
13921392
}
13931393

1394-
// This is static and called by the scheduler.
1395-
void BeaconRegistry::RunDBPassivation()
1396-
{
1397-
TRY_LOCK(cs_main, locked_main);
1398-
1399-
if (!locked_main)
1400-
{
1401-
return;
1402-
}
1403-
1404-
BeaconRegistry& beacons = GetBeaconRegistry();
1405-
1406-
beacons.PassivateDB();
1407-
}
1408-
14091394
template<> const std::string BeaconRegistry::BeaconDB::KeyType()
14101395
{
14111396
return std::string("beacon");

src/gridcoin/beacon.h

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -768,7 +768,7 @@ class BeaconRegistry : public IContractHandler
768768
//!
769769
//! \return The number of elements passivated.
770770
//!
771-
uint64_t PassivateDB();
771+
uint64_t PassivateDB() override;
772772

773773
//!
774774
//! \brief This function walks the linked beacon entries back (using the m_previous_hash member) from a provided
@@ -795,11 +795,6 @@ class BeaconRegistry : public IContractHandler
795795
//!
796796
bool SetNeedsIsContractCorrection(bool flag);
797797

798-
//!
799-
//! \brief A static function that is called by the scheduler to run the beacon database passivation.
800-
//!
801-
static void RunDBPassivation();
802-
803798
//!
804799
//! \brief Specializes the template RegistryDB for the ScraperEntry class
805800
//!

src/gridcoin/contract/handler.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#ifndef GRIDCOIN_CONTRACT_HANDLER_H
66
#define GRIDCOIN_CONTRACT_HANDLER_H
77

8+
#include <cstdint>
89
#include <string>
910

1011
class CBlockIndex;
@@ -153,6 +154,20 @@ struct IContractHandler
153154
//! \param height
154155
//!
155156
virtual void SetDBHeight(int& height);
157+
158+
//!
159+
//! \brief Passivates the elements in the underlying db, which means remove from memory elements in the
160+
//! historical map that are not referenced by any of the in memory maps. The backing store of
161+
//! the element removed from memory is retained and will be transparently restored if find()
162+
//! is called on the hash key for the element.
163+
//!
164+
//! \return The number of elements passivated.
165+
//!
166+
virtual uint64_t PassivateDB()
167+
{
168+
// The default method here does nothing.
169+
return uint64_t {0};
170+
};
156171
};
157172

158173
} // namespace GRC

src/gridcoin/gridcoin.cpp

Lines changed: 52 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ extern bool fExplorer;
2727
extern unsigned int nScraperSleep;
2828
extern unsigned int nActiveBeforeSB;
2929
extern bool fScraperActive;
30+
extern bool fQtActive;
3031

3132
void Scraper(bool bSingleShot = false);
3233
void ScraperSubscriber();
@@ -40,17 +41,29 @@ namespace {
4041
//!
4142
void ShowChainCorruptedMessage()
4243
{
43-
uiInterface.ThreadSafeMessageBox(
44-
_("WARNING: Blockchain data may be corrupted.\n\n"
45-
"Gridcoin detected bad index entries. This may occur because of an "
46-
"unexpected exit, a power failure, or a late software upgrade.\n\n"
47-
"Please exit Gridcoin, open the data directory, and delete:\n"
48-
" - the blk****.dat files\n"
49-
" - the txleveldb folder\n\n"
50-
"Your wallet will re-download the blockchain. Your balance may "
51-
"appear incorrect until the synchronization finishes.\n" ),
52-
"Gridcoin",
53-
CClientUIInterface::BTN_OK | CClientUIInterface::MODAL);
44+
fResetBlockchainRequest = true;
45+
46+
if (fQtActive) {
47+
uiInterface.ThreadSafeMessageBox(
48+
_("ERROR: Checkpoint mismatch: Blockchain data may be corrupted.\n\n"
49+
"Gridcoin detected bad index entries. This may occur because of a "
50+
"late software upgrade, unexpected exit, or a power failure. "
51+
"Your blockchain data is being reset and your wallet will resync "
52+
"from genesis when you restart. Your balance may appear incorrect "
53+
"until the synchronization finishes."),
54+
"Gridcoin",
55+
CClientUIInterface::BTN_OK | CClientUIInterface::MODAL);
56+
} else {
57+
uiInterface.ThreadSafeMessageBox(
58+
_("ERROR: Checkpoint mismatch: Blockchain data may be corrupted.\n\n"
59+
"Gridcoin detected bad index entries. This may occur because of a "
60+
"late software upgrade, unexpected exit, or a power failure. "
61+
"Please run gridcoinresearchd with the -resetblockchaindata "
62+
"parameter. Your wallet will re-download the blockchain. Your "
63+
"balance may appear incorrect until the synchronization finishes." ),
64+
"Gridcoin",
65+
CClientUIInterface::BTN_OK | CClientUIInterface::MODAL);
66+
}
5467
}
5568

5669
//!
@@ -361,20 +374,23 @@ void InitializeExplorerFeatures()
361374
//! whether the index contains invalid state caused by an unclean shutdown.
362375
//! This condition was originally detected by an assertion in a routine for
363376
//! stake modifier checksum verification. Because Gridcoin removed modifier
364-
//! checksums and checkpoints, we reinstate that assertion here as a formal
365-
//! inspection.
377+
//! checksums, we reinstate that assertion here as a formal inspection done
378+
//! at initialization before the VerifyCheckpoints.
366379
//!
367380
//! This function checks that no block index entries contain a null pointer
368381
//! to a previous block. The symptom may indicate a deeper problem that can
369382
//! be resolved by tuning disk synchronization in LevelDB. Until then, this
370383
//! heuristic has proven itself to be effective for identifying a corrupted
371-
//! database.
384+
//! database. This type of error has not been seen in the wild in several
385+
//! years as of Gridcoin 5.4.7.0, but is retained for thoroughness.
372386
//!
373-
void CheckBlockIndexJob()
387+
bool CheckBlockIndex()
374388
{
375389
LogPrintf("Gridcoin: checking block index...");
390+
uiInterface.InitMessage(_("Checking block index..."));
376391

377-
bool corrupted = false;
392+
// Block index integrity status
393+
bool status = true;
378394

379395
if (pindexGenesisBlock) {
380396
LOCK(cs_main);
@@ -383,18 +399,20 @@ void CheckBlockIndexJob()
383399
const CBlockIndex* const pindex = index_pair.second;
384400

385401
if (!pindex || !(pindex->pprev || pindex == pindexGenesisBlock)) {
386-
corrupted = true;
402+
status = false;
387403
break;
388404
}
389405
}
390406
}
391407

392-
if (!corrupted) {
408+
if (status) {
393409
LogPrintf("Gridcoin: block index is clean");
394-
return;
410+
return status;
395411
}
396412

397413
ShowChainCorruptedMessage();
414+
415+
return status;
398416
}
399417

400418
//!
@@ -466,11 +484,8 @@ void ScheduleRegistriesPassivation(CScheduler& scheduler)
466484
{
467485
// Run registry database passivation every 5 minutes. This is a very thin call most of the time.
468486
// Please see the PassivateDB function and passivate_db.
469-
// TODO: Turn into a loop using extension of RegistryBookmarks
470-
scheduler.scheduleEvery(BeaconRegistry::RunDBPassivation, std::chrono::minutes{5});
471-
scheduler.scheduleEvery(ScraperRegistry::RunDBPassivation, std::chrono::minutes{5});
472-
scheduler.scheduleEvery(ProtocolRegistry::RunDBPassivation, std::chrono::minutes{5});
473-
scheduler.scheduleEvery(Whitelist::RunDBPassivation, std::chrono::minutes{5});
487+
488+
scheduler.scheduleEvery(RunDBPassivation, std::chrono::minutes{5});
474489
}
475490
} // Anonymous namespace
476491

@@ -490,6 +505,9 @@ bool GRC::Initialize(ThreadHandlerPtr threads, CBlockIndex* pindexBest)
490505
{
491506
LogPrintf("Gridcoin: initializing...");
492507

508+
if (!CheckBlockIndex()) {
509+
return false;
510+
}
493511
if (!VerifyCheckpoints(pindexBest)) {
494512
return false;
495513
}
@@ -518,8 +536,6 @@ void GRC::CloseResearcherRegistryFile()
518536

519537
void GRC::ScheduleBackgroundJobs(CScheduler& scheduler)
520538
{
521-
scheduler.schedule(CheckBlockIndexJob, std::chrono::system_clock::now());
522-
523539
// Primitive, but this is what the scraper does in the scraper housekeeping
524540
// loop. It checks to see if the logs need to be archived by default every
525541
// 5 mins. Note that passing false to the archive function means that if we
@@ -589,3 +605,13 @@ skip:;
589605
return true;
590606
}
591607

608+
void GRC::RunDBPassivation()
609+
{
610+
LOCK(cs_main);
611+
612+
for (const auto& contract_type : RegistryBookmarks::CONTRACT_TYPES_WITH_REG_DB) {
613+
Registry& registry = RegistryBookmarks::GetRegistryWithDB(contract_type);
614+
615+
registry.PassivateDB();
616+
}
617+
}

src/gridcoin/gridcoin.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,12 @@ void ScheduleBackgroundJobs(CScheduler& scheduler);
4040
//! \return \c true if no errors occurred.
4141
//!
4242
bool CleanConfig();
43+
44+
//!
45+
//! \brief Function to allow cycling through DB passivation for all contract types backed
46+
//! with registry db.
47+
//!
48+
void RunDBPassivation();
4349
} // namespace GRC
4450

4551
#endif // GRIDCOIN_GRIDCOIN_H

src/gridcoin/project.cpp

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -541,21 +541,6 @@ Whitelist::ProjectEntryDB &Whitelist::GetProjectDB()
541541
return m_project_db;
542542
}
543543

544-
// This is static and called by the scheduler.
545-
void Whitelist::RunDBPassivation()
546-
{
547-
TRY_LOCK(cs_main, locked_main);
548-
549-
if (!locked_main)
550-
{
551-
return;
552-
}
553-
554-
Whitelist& project_entries = GetWhitelist();
555-
556-
project_entries.PassivateDB();
557-
}
558-
559544
template<> const std::string Whitelist::ProjectEntryDB::KeyType()
560545
{
561546
return std::string("project");

src/gridcoin/project.h

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -603,19 +603,14 @@ class Whitelist : public IContractHandler
603603
void ResetInMemoryOnly();
604604

605605
//!
606-
//! \brief Passivates the elements in the scraper db, which means remove from memory elements in the
606+
//! \brief Passivates the elements in the project db, which means remove from memory elements in the
607607
//! historical map that are not referenced by m_projects. The backing store of the element removed
608608
//! from memory is retained and will be transparently restored if find() is called on the hash key
609609
//! for the element.
610610
//!
611611
//! \return The number of elements passivated.
612612
//!
613-
uint64_t PassivateDB();
614-
615-
//!
616-
//! \brief A static function that is called by the scheduler to run the project entry database passivation.
617-
//!
618-
static void RunDBPassivation();
613+
uint64_t PassivateDB() override;
619614

620615
//!
621616
//! \brief Specializes the template RegistryDB for the ScraperEntry class. Note that std::set<ProjectEntry> is not

src/gridcoin/protocol.cpp

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -528,21 +528,6 @@ ProtocolRegistry::ProtocolEntryDB &ProtocolRegistry::GetProtocolEntryDB()
528528
return m_protocol_db;
529529
}
530530

531-
// This is static and called by the scheduler.
532-
void ProtocolRegistry::RunDBPassivation()
533-
{
534-
TRY_LOCK(cs_main, locked_main);
535-
536-
if (!locked_main)
537-
{
538-
return;
539-
}
540-
541-
ProtocolRegistry& protocol_entries = GetProtocolRegistry();
542-
543-
protocol_entries.PassivateDB();
544-
}
545-
546531
template<> const std::string ProtocolRegistry::ProtocolEntryDB::KeyType()
547532
{
548533
return std::string("protocol");

src/gridcoin/protocol.h

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -559,12 +559,7 @@ class ProtocolRegistry : public IContractHandler
559559
//!
560560
//! \return The number of elements passivated.
561561
//!
562-
uint64_t PassivateDB();
563-
564-
//!
565-
//! \brief A static function that is called by the scheduler to run the protocol entry database passivation.
566-
//!
567-
static void RunDBPassivation();
562+
uint64_t PassivateDB() override;
568563

569564
//!
570565
//! \brief Specializes the template RegistryDB for the ProtocolEntry class. Note that std::set<ProtocolEntry>

src/gridcoin/scraper/scraper_registry.cpp

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -573,21 +573,6 @@ ScraperRegistry::ScraperEntryDB &ScraperRegistry::GetScraperDB()
573573
return m_scraper_db;
574574
}
575575

576-
// This is static and called by the scheduler.
577-
void ScraperRegistry::RunDBPassivation()
578-
{
579-
TRY_LOCK(cs_main, locked_main);
580-
581-
if (!locked_main)
582-
{
583-
return;
584-
}
585-
586-
ScraperRegistry& scraper_entries = GetScraperRegistry();
587-
588-
scraper_entries.PassivateDB();
589-
}
590-
591576
template<> const std::string ScraperRegistry::ScraperEntryDB::KeyType()
592577
{
593578
return std::string("scraper");

0 commit comments

Comments
 (0)