From 3f749b983f48235063a2141cc3f7467fb59f7782 Mon Sep 17 00:00:00 2001 From: "James C. Owens" Date: Sun, 14 Jan 2024 15:25:30 -0500 Subject: [PATCH] Extend beacon registry db template to cover expired entries This also fixes the HandleCurrentHistoricalEntries specialization in the beacon registry to properly deal with expired pending beacons. --- src/gridcoin/beacon.cpp | 19 +++++++++- src/gridcoin/beacon.h | 1 + src/gridcoin/contract/registry_db.h | 12 ++++-- src/gridcoin/project.cpp | 2 +- src/gridcoin/project.h | 6 ++- src/gridcoin/protocol.cpp | 2 +- src/gridcoin/protocol.h | 6 ++- src/gridcoin/scraper/scraper_registry.cpp | 2 +- src/gridcoin/scraper/scraper_registry.h | 6 ++- src/gridcoin/sidestake.cpp | 2 +- src/gridcoin/sidestake.h | 6 ++- src/test/gridcoin/beacon_tests.cpp | 46 ++++++++++------------- 12 files changed, 70 insertions(+), 40 deletions(-) diff --git a/src/gridcoin/beacon.cpp b/src/gridcoin/beacon.cpp index 900c157cd4..1270a319cd 100644 --- a/src/gridcoin/beacon.cpp +++ b/src/gridcoin/beacon.cpp @@ -390,6 +390,7 @@ void BeaconRegistry::Reset() { m_beacons.clear(); m_pending.clear(); + m_expired_pending.clear(); m_beacon_db.clear(); } @@ -1182,6 +1183,7 @@ void BeaconRegistry::Deactivate(const uint256 superblock_hash) //! template<> void BeaconRegistry::BeaconDB::HandleCurrentHistoricalEntries(GRC::BeaconRegistry::BeaconMap& entries, GRC::BeaconRegistry::PendingBeaconMap& pending_entries, + std::set& expired_entries, const Beacon& entry, entry_ptr& historical_entry_ptr, const uint64_t& recnum, @@ -1216,7 +1218,7 @@ template<> void BeaconRegistry::BeaconDB::HandleCurrentHistoricalEntries(GRC::Be if (entry.m_status == BeaconStatusForStorage::ACTIVE || entry.m_status == BeaconStatusForStorage::RENEWAL) { - LogPrint(LogFlags::CONTRACT, "INFO: %s: %ss: entry insert: cpid %s, address %s, timestamp %" PRId64 ", " + LogPrint(LogFlags::CONTRACT, "INFO: %s: %s: entry insert: cpid %s, address %s, timestamp %" PRId64 ", " "hash %s, previous_hash %s, status %s, recnum %" PRId64 ".", __func__, key_type, @@ -1253,6 +1255,15 @@ template<> void BeaconRegistry::BeaconDB::HandleCurrentHistoricalEntries(GRC::Be } } + if (entry.m_status == BeaconStatusForStorage::ACTIVE) { + // Note that in the orginal activation, all the activations happen for a superblock, and then the expired_entry set is + // cleared and then new expired entries recorded from the just committed SB. This method operates at the record level, but + // clearing the expired_entries for each ACTIVE record posting will achieve the same effect, because the entries are ordered + // the proper way. It is a little bit of undesired work, but it is not worth the complexity of feeding the boundaries + // of the group of verified beacons to activate. + expired_entries.clear(); + } + if (entry.m_status == BeaconStatusForStorage::EXPIRED_PENDING) { LogPrint(LogFlags::CONTRACT, "INFO: %s: %s: expired pending entry delete: cpid %s, address %s, timestamp %" PRId64 ", " @@ -1268,6 +1279,9 @@ template<> void BeaconRegistry::BeaconDB::HandleCurrentHistoricalEntries(GRC::Be recnum ); + // Insert the expired pending entry into the expired entries set. + expired_entries.insert(historical_entry_ptr); + // Delete any entry in the pending map that is marked expired. pending_entries.erase(entry.GetId()); } @@ -1294,7 +1308,7 @@ template<> void BeaconRegistry::BeaconDB::HandleCurrentHistoricalEntries(GRC::Be int BeaconRegistry::Initialize() { - int height = m_beacon_db.Initialize(m_beacons, m_pending); + int height = m_beacon_db.Initialize(m_beacons, m_pending, m_expired_pending); LogPrint(LogFlags::BEACON, "INFO: %s: m_beacon_db size after load: %u", __func__, m_beacon_db.size()); LogPrint(LogFlags::BEACON, "INFO: %s: m_beacons size after load: %u", __func__, m_beacons.size()); @@ -1306,6 +1320,7 @@ void BeaconRegistry::ResetInMemoryOnly() { m_beacons.clear(); m_pending.clear(); + m_expired_pending.clear(); m_beacon_db.clear_in_memory_only(); } diff --git a/src/gridcoin/beacon.h b/src/gridcoin/beacon.h index 04ff3998ea..24567c479a 100644 --- a/src/gridcoin/beacon.h +++ b/src/gridcoin/beacon.h @@ -811,6 +811,7 @@ class BeaconRegistry : public IContractHandler BeaconStatusForStorage, BeaconMap, PendingBeaconMap, + std::set, HistoricalBeaconMap> BeaconDB; private: diff --git a/src/gridcoin/contract/registry_db.h b/src/gridcoin/contract/registry_db.h index 30694edfe2..ab27f6314b 100644 --- a/src/gridcoin/contract/registry_db.h +++ b/src/gridcoin/contract/registry_db.h @@ -26,9 +26,11 @@ namespace GRC { //! M: the map type for the entries //! P: the map type for pending entries. This is really only used for beacons. In all other registries it is typedef'd to //! the same as M. +//! X: the map type for expired pending entries. This is really only used for beacons. In all other registries it is typedef'd to +//! the same as M. //! H: the historical map type for historical entries //! -template +template class RegistryDB { public: @@ -62,10 +64,12 @@ class RegistryDB //! \param entries The map of current entries. //! \param pending_entries. The map of pending entries. This is not used in the general template, only in the beacons //! specialization. + //! \param expired_entries. The map of expired pending entries. This is not used in the geenral template, only in the + //! beacons specialization. //! //! \return block height up to and including which the entry records were stored. //! - int Initialize(M& entries, P& pending_entries) + int Initialize(M& entries, P& pending_entries, X& expired_entries) { bool status = true; int height = 0; @@ -169,7 +173,7 @@ class RegistryDB m_historical[iter.second.m_hash] = std::make_shared(entry); entry_ptr& historical_entry_ptr = m_historical[iter.second.m_hash]; - HandleCurrentHistoricalEntries(entries, pending_entries, entry, + HandleCurrentHistoricalEntries(entries, pending_entries, expired_entries, entry, historical_entry_ptr, recnum, key_type); number_passivated += (uint64_t) HandlePreviousHistoricalEntries(historical_entry_ptr); @@ -199,7 +203,7 @@ class RegistryDB //! \param recnum //! \param key_type //! - void HandleCurrentHistoricalEntries(M& entries, P& pending_entries, const E& entry, + void HandleCurrentHistoricalEntries(M& entries, P& pending_entries, X& expired_entries, const E& entry, entry_ptr& historical_entry_ptr, const uint64_t& recnum, const std::string& key_type) { diff --git a/src/gridcoin/project.cpp b/src/gridcoin/project.cpp index 45d6321d3a..0364744b4d 100644 --- a/src/gridcoin/project.cpp +++ b/src/gridcoin/project.cpp @@ -495,7 +495,7 @@ int Whitelist::Initialize() { LOCK(cs_lock); - int height = m_project_db.Initialize(m_project_entries, m_pending_project_entries); + int height = m_project_db.Initialize(m_project_entries, m_pending_project_entries, m_expired_project_entries); LogPrint(LogFlags::CONTRACT, "INFO: %s: m_project_db size after load: %u", __func__, m_project_db.size()); LogPrint(LogFlags::CONTRACT, "INFO: %s: m_project_entries size after load: %u", __func__, m_project_entries.size()); diff --git a/src/gridcoin/project.h b/src/gridcoin/project.h index 54c509c60a..007e9586d5 100644 --- a/src/gridcoin/project.h +++ b/src/gridcoin/project.h @@ -618,13 +618,15 @@ class Whitelist : public IContractHandler static void RunDBPassivation(); //! - //! \brief Specializes the template RegistryDB for the ScraperEntry class + //! \brief Specializes the template RegistryDB for the ScraperEntry class. Note that std::set is not + //! actually used. //! typedef RegistryDB, HistoricalProjectEntryMap> ProjectEntryDB; private: @@ -644,6 +646,8 @@ class Whitelist : public IContractHandler ProjectEntryMap m_project_entries; //!< The set of whitelisted projects. PendingProjectEntryMap m_pending_project_entries {}; //!< Not actually used. Only to satisfy the template. + std::set m_expired_project_entries {}; //!< Not actually used. Only to satisfy the template. + ProjectEntryDB m_project_db; //!< The project db member public: diff --git a/src/gridcoin/protocol.cpp b/src/gridcoin/protocol.cpp index 793dd207b3..44a193e9c6 100644 --- a/src/gridcoin/protocol.cpp +++ b/src/gridcoin/protocol.cpp @@ -482,7 +482,7 @@ int ProtocolRegistry::Initialize() { LOCK(cs_lock); - int height = m_protocol_db.Initialize(m_protocol_entries, m_pending_protocol_entries); + int height = m_protocol_db.Initialize(m_protocol_entries, m_pending_protocol_entries, m_expired_protocol_entries); LogPrint(LogFlags::CONTRACT, "INFO: %s: m_protocol_db size after load: %u", __func__, m_protocol_db.size()); LogPrint(LogFlags::CONTRACT, "INFO: %s: m_protocol_entries size after load: %u", __func__, m_protocol_entries.size()); diff --git a/src/gridcoin/protocol.h b/src/gridcoin/protocol.h index d1b93150a6..eefa0f1330 100644 --- a/src/gridcoin/protocol.h +++ b/src/gridcoin/protocol.h @@ -567,13 +567,15 @@ class ProtocolRegistry : public IContractHandler static void RunDBPassivation(); //! - //! \brief Specializes the template RegistryDB for the ProtocolEntry class + //! \brief Specializes the template RegistryDB for the ProtocolEntry class. Note that std::set + //! is not actually used. //! typedef RegistryDB, HistoricalProtocolEntryMap> ProtocolEntryDB; private: @@ -593,6 +595,8 @@ class ProtocolRegistry : public IContractHandler ProtocolEntryMap m_protocol_entries; //!< Contains the current protocol entries including entries marked DELETED. PendingProtocolEntryMap m_pending_protocol_entries {}; //!< Not used. Only to satisfy the template. + std::set m_expired_protocol_entries {}; //!< Not used. Only to satisfy the template. + ProtocolEntryDB m_protocol_db; public: diff --git a/src/gridcoin/scraper/scraper_registry.cpp b/src/gridcoin/scraper/scraper_registry.cpp index 147253f39a..bf481e0216 100644 --- a/src/gridcoin/scraper/scraper_registry.cpp +++ b/src/gridcoin/scraper/scraper_registry.cpp @@ -527,7 +527,7 @@ int ScraperRegistry::Initialize() { LOCK(cs_lock); - int height = m_scraper_db.Initialize(m_scrapers, m_pending_scrapers); + int height = m_scraper_db.Initialize(m_scrapers, m_pending_scrapers, m_expired_scraper_entries); LogPrint(LogFlags::SCRAPER, "INFO: %s: m_scraper_db size after load: %u", __func__, m_scraper_db.size()); LogPrint(LogFlags::SCRAPER, "INFO: %s: m_scrapers size after load: %u", __func__, m_scrapers.size()); diff --git a/src/gridcoin/scraper/scraper_registry.h b/src/gridcoin/scraper/scraper_registry.h index 5705c15d57..5686c25991 100644 --- a/src/gridcoin/scraper/scraper_registry.h +++ b/src/gridcoin/scraper/scraper_registry.h @@ -606,13 +606,15 @@ class ScraperRegistry : public IContractHandler static void RunDBPassivation(); //! - //! \brief Specializes the template RegistryDB for the ScraperEntry class + //! \brief Specializes the template RegistryDB for the ScraperEntry class. Note that std::set is + //! not actually used. //! typedef RegistryDB, HistoricalScraperMap> ScraperEntryDB; private: @@ -632,6 +634,8 @@ class ScraperRegistry : public IContractHandler ScraperMap m_scrapers; //!< Contains the current scraper entries, including entries marked DELETED. PendingScraperMap m_pending_scrapers {}; //!< Not actually used for scrapers. To satisfy the template only. + std::set m_expired_scraper_entries {}; //!< Not actually used for scrapers. To satisfy the template only. + ScraperEntryDB m_scraper_db; public: diff --git a/src/gridcoin/sidestake.cpp b/src/gridcoin/sidestake.cpp index a9c285b02f..86d9f5fdaf 100644 --- a/src/gridcoin/sidestake.cpp +++ b/src/gridcoin/sidestake.cpp @@ -684,7 +684,7 @@ int SideStakeRegistry::Initialize() { LOCK(cs_lock); - int height = m_sidestake_db.Initialize(m_mandatory_sidestake_entries, m_pending_sidestake_entries); + int height = m_sidestake_db.Initialize(m_mandatory_sidestake_entries, m_pending_sidestake_entries, m_expired_sidestake_entries); SubscribeToCoreSignals(); diff --git a/src/gridcoin/sidestake.h b/src/gridcoin/sidestake.h index f5ba1ba474..534ce021d0 100644 --- a/src/gridcoin/sidestake.h +++ b/src/gridcoin/sidestake.h @@ -739,13 +739,15 @@ class SideStakeRegistry : public IContractHandler static void RunDBPassivation(); //! - //! \brief Specializes the template RegistryDB for the SideStake class + //! \brief Specializes the template RegistryDB for the SideStake class. Note that std::set + //! is not actually used. //! typedef RegistryDB, HistoricalSideStakeMap> SideStakeDB; private: @@ -783,6 +785,8 @@ class SideStakeRegistry : public IContractHandler MandatorySideStakeMap m_mandatory_sidestake_entries; //!< Contains the mandatory sidestake entries, including DELETED. PendingSideStakeMap m_pending_sidestake_entries {}; //!< Not used. Only to satisfy the template. + std::set m_expired_sidestake_entries {}; //!< Not used. Only to satisfy the template. + SideStakeDB m_sidestake_db; //!< The internal sidestake db object for leveldb persistence. bool m_local_entry_already_saved_to_config = false; //!< Flag to prevent reload on signal if individual entry saved already. diff --git a/src/test/gridcoin/beacon_tests.cpp b/src/test/gridcoin/beacon_tests.cpp index c1ff4f34f7..369eed61c4 100644 --- a/src/test/gridcoin/beacon_tests.cpp +++ b/src/test/gridcoin/beacon_tests.cpp @@ -182,7 +182,6 @@ class BeaconRegistryTest if (beacon != nullptr) { std::cout << "add beacon record: " << "blockheight = " << ctx.m_pindex->nHeight - << ", hash = " << beacon->m_hash.GetHex() << ", cpid = " << beacon->m_cpid.ToString() << ", public key = " << HexStr(beacon->m_public_key) << ", address = " << beacon->GetAddress().ToString() @@ -203,7 +202,6 @@ class BeaconRegistryTest if (beacon != nullptr) { std::cout << "delete beacon record: " << "blockheight = " << ctx.m_pindex->nHeight - << ", hash = " << beacon->m_hash.GetHex() << ", cpid = " << beacon->m_cpid.ToString() << ", public key = " << HexStr(beacon->m_public_key) << ", address = " << beacon->GetAddress().ToString() @@ -242,7 +240,6 @@ class BeaconRegistryTest if (activated_beacon != nullptr) { std::cout << "activated beacon record: " << "blockheight = " << pindex->nHeight - << ", hash = " << activated_beacon->m_hash.GetHex() << ", cpid = " << activated_beacon->m_cpid.ToString() << ", public key = " << HexStr(activated_beacon->m_public_key) << ", address = " << activated_beacon->GetAddress().ToString() @@ -258,7 +255,6 @@ class BeaconRegistryTest if (iter != nullptr) { std::cout << "expired beacon record: " << "blockheight = " << pindex->nHeight - << ", hash = " << iter->m_hash.GetHex() << ", cpid = " << iter->m_cpid.ToString() << ", public key = " << HexStr(iter->m_public_key) << ", address = " << iter->GetAddress().ToString() @@ -279,17 +275,6 @@ class BeaconRegistryTest for (const auto& iter : registry.Beacons()) { m_beacons_init[iter.first] = *iter.second; - - std::cout << "init beacon record: " - << "hash = " << iter.second->m_hash.GetHex() - << ", cpid = " << iter.second->m_cpid.ToString() - << ", public key = " << HexStr(iter.second->m_public_key) - << ", address = " << iter.second->GetAddress().ToString() - << ", timestamp = " << iter.second->m_timestamp - << ", hash = " << iter.second->m_hash.GetHex() - << ", prev beacon hash = " << iter.second->m_previous_hash.GetHex() - << ", status = " << iter.second->StatusToString() - << std::endl; } m_init_number_beacons = m_beacons_init.size(); @@ -314,6 +299,16 @@ class BeaconRegistryTest // Create a copy of the referenced beacon object with a shared pointer to it and store. m_local_historical_beacon_map_init[hash] = std::make_shared(*beacon_ptr); + std::cout << "init beacon db record: " + << ", cpid = " << beacon_ptr->m_cpid.ToString() + << ", public key = " << HexStr(beacon_ptr->m_public_key) + << ", address = " << beacon_ptr->GetAddress().ToString() + << ", timestamp = " << beacon_ptr->m_timestamp + << ", hash = " << beacon_ptr->m_hash.GetHex() + << ", prev beacon hash = " << beacon_ptr->m_previous_hash.GetHex() + << ", status = " << beacon_ptr->StatusToString() + << std::endl; + init_beacon_db_iter = init_beacon_db.advance(init_beacon_db_iter); } @@ -331,17 +326,6 @@ class BeaconRegistryTest for (const auto& iter : registry.Beacons()) { m_beacons_reinit[iter.first] = *iter.second; - - std::cout << "reinit beacon record: " - << "hash = " << iter.second->m_hash.GetHex() - << ", cpid = " << iter.second->m_cpid.ToString() - << ", public key = " << HexStr(iter.second->m_public_key) - << ", address = " << iter.second->GetAddress().ToString() - << ", timestamp = " << iter.second->m_timestamp - << ", hash = " << iter.second->m_hash.GetHex() - << ", prev beacon hash = " << iter.second->m_previous_hash.GetHex() - << ", status = " << iter.second->StatusToString() - << std::endl; } m_reinit_number_beacons = m_beacons_reinit.size(); @@ -366,6 +350,16 @@ class BeaconRegistryTest // Create a copy of the referenced beacon object with a shared pointer to it and store. m_local_historical_beacon_map_reinit[hash] = std::make_shared(*beacon_ptr); + std::cout << "init beacon db record: " + << ", cpid = " << beacon_ptr->m_cpid.ToString() + << ", public key = " << HexStr(beacon_ptr->m_public_key) + << ", address = " << beacon_ptr->GetAddress().ToString() + << ", timestamp = " << beacon_ptr->m_timestamp + << ", hash = " << beacon_ptr->m_hash.GetHex() + << ", prev beacon hash = " << beacon_ptr->m_previous_hash.GetHex() + << ", status = " << beacon_ptr->StatusToString() + << std::endl; + reinit_beacon_db_iter = reinit_beacon_db.advance(reinit_beacon_db_iter); } };