diff --git a/src/gridcoin/project.cpp b/src/gridcoin/project.cpp index 1b5c61070f..46db399a90 100644 --- a/src/gridcoin/project.cpp +++ b/src/gridcoin/project.cpp @@ -432,12 +432,13 @@ void AutoGreylist::RefreshWithSuperblock(SuperblockPtr superblock_ptr_in) EXCLUS const Whitelist::ProjectEntryMap& project_first_actives = GetWhitelist().GetProjectsFirstActive(); - unsigned int v3_superblock_count = 0; - - if (superblock_ptr_in->m_version > 2) { - ++v3_superblock_count; + // If this superblock version is less than 3, then all prior ones must also be less than 3, so bail. + if (superblock_ptr_in->m_version < 3) { + return; } + unsigned int superblock_count = 0; + // Notice the superblock_ptr_in m_projects_all_cpid_total_credits MUST ALEADY BE POPULATED to record the TC state into // the auto greylist. for (const auto& iter : whitelist) { @@ -466,13 +467,14 @@ void AutoGreylist::RefreshWithSuperblock(SuperblockPtr superblock_ptr_in) EXCLUS } } + ++superblock_count; + CBlockIndex* index_ptr; { // Find the block index entry for the block before the provided superblock_ptr. index_ptr = GRC::BlockFinder::FindByHeight(superblock_ptr_in.m_height - 1); } - unsigned int superblock_count = 1; // The 0 (baseline) superblock was processed above. Here we start with 1 and go up to 40 while (index_ptr != nullptr && index_ptr->pprev != nullptr && superblock_count <= 40) { @@ -495,35 +497,37 @@ void AutoGreylist::RefreshWithSuperblock(SuperblockPtr superblock_ptr_in) EXCLUS SuperblockPtr superblock_ptr = block.GetClaim().m_superblock; superblock_ptr.Rebind(index_ptr); - if (superblock_ptr->m_version > 2) { - for (const auto& iter : whitelist) { - // This is guaranteed to succeed, because every whitelisted project was inserted as a new baseline entry above. - auto greylist_entry = m_greylist_ptr->find(iter.m_name); - - auto project = superblock_ptr->m_projects_all_cpids_total_credits.m_projects_all_cpid_total_credits.find(iter.m_name); - - // This record MUST be found, because for the record to be in the whitelist, it must have at least a first record. - auto project_first_active = project_first_actives.find(iter.m_name); - - // The purpose of this time comparison is to ONLY post greylist candidate entry (updates) for superblocks that are - // equal to or after the first entry date. Remember we are going backwards here. There cannot be entries held against - // a whitelisted project from before it was ever whitelisted. This check is required to ensure the greylist rules work - // correctly for newly whitelisted projects that are within the 40 day window for WAS and 20 day window for ZCD. - if (project_first_active != project_first_actives.end() - && superblock_ptr.m_timestamp >= project_first_active->second->m_timestamp) { - if (project != superblock_ptr->m_projects_all_cpids_total_credits.m_projects_all_cpid_total_credits.end()) { - // Update greylist candidate entry with the total credit for each project present in superblock. - greylist_entry->second.UpdateGreylistCandidateEntry(project->second, superblock_count); - } else { - // Record updated greylist candidate entry with nullopt total credit. This is for a project that is in the - // whitelist, but does not have a project entry in this superblock. This would be because the scrapers could - // not converge on the project for this superblock. - greylist_entry->second.UpdateGreylistCandidateEntry(std::optional(std::nullopt), superblock_count); - } + // Stop if superblocks less than version 3 are encountered while going backwards. This will happen until we are 40 + // superblocks past the 1st superblock after the height specified for the changeover to v3 superblocks. + if (superblock_ptr->m_version < 3) { + break; + } + + for (const auto& iter : whitelist) { + // This is guaranteed to succeed, because every whitelisted project was inserted as a new baseline entry above. + auto greylist_entry = m_greylist_ptr->find(iter.m_name); + + auto project = superblock_ptr->m_projects_all_cpids_total_credits.m_projects_all_cpid_total_credits.find(iter.m_name); + + // This record MUST be found, because for the record to be in the whitelist, it must have at least a first record. + auto project_first_active = project_first_actives.find(iter.m_name); + + // The purpose of this time comparison is to ONLY post greylist candidate entry (updates) for superblocks that are + // equal to or after the first entry date. Remember we are going backwards here. There cannot be entries held against + // a whitelisted project from before it was ever whitelisted. This check is required to ensure the greylist rules work + // correctly for newly whitelisted projects that are within the 40 day window for WAS and 20 day window for ZCD. + if (project_first_active != project_first_actives.end() + && superblock_ptr.m_timestamp >= project_first_active->second->m_timestamp) { + if (project != superblock_ptr->m_projects_all_cpids_total_credits.m_projects_all_cpid_total_credits.end()) { + // Update greylist candidate entry with the total credit for each project present in superblock. + greylist_entry->second.UpdateGreylistCandidateEntry(project->second, superblock_count); + } else { + // Record updated greylist candidate entry with nullopt total credit. This is for a project that is in the + // whitelist, but does not have a project entry in this superblock. This would be because the scrapers could + // not converge on the project for this superblock. + greylist_entry->second.UpdateGreylistCandidateEntry(std::optional(std::nullopt), superblock_count); } } - - ++v3_superblock_count; } ++superblock_count; @@ -531,16 +535,6 @@ void AutoGreylist::RefreshWithSuperblock(SuperblockPtr superblock_ptr_in) EXCLUS index_ptr = index_ptr->pprev; } - // Mark elements with whether they meet greylist criteria. - for (auto iter = m_greylist_ptr->begin(); iter != m_greylist_ptr->end(); ++iter) { - // the v3_superblock_count >= 2 test is to ensure there are at least two v3 superblocks with the total credits - // filled in to sample for the auto greylist determination. A two sb sample with positive change in TC will - // cause the ZCD and WAS rules to pass. - iter->second.m_meets_greylisting_crit = v3_superblock_count >= 2 - && (iter->second.GetZCD() > 7 - || iter->second.GetWAS() < Fraction(1, 10)); - } - m_superblock_hash = superblock_ptr_in->GetHash(); } diff --git a/src/gridcoin/project.h b/src/gridcoin/project.h index 88e1f5b9e9..2c86dfda19 100644 --- a/src/gridcoin/project.h +++ b/src/gridcoin/project.h @@ -514,7 +514,7 @@ class AutoGreylist , m_TC_initial_bookmark(0) , m_TC_bookmark(0) , m_sb_from_baseline_processed(0) - , m_updates(0) + , m_update_history({}) {} GreylistCandidateEntry(std::string project_name, std::optional TC_initial_bookmark) @@ -526,8 +526,17 @@ class AutoGreylist , m_TC_initial_bookmark(TC_initial_bookmark) , m_TC_bookmark(0) , m_sb_from_baseline_processed(0) - , m_updates(0) - {} + , m_update_history() + { + // Populate the initial historical entry from the initial baseline. + UpdateHistoryEntry entry = UpdateHistoryEntry(0, + TC_initial_bookmark, + std::optional {}, + std::optional {}, + std::optional {}); + + m_update_history.push_back(entry); + } uint8_t GetZCD() { @@ -604,9 +613,48 @@ class AutoGreylist m_TC_bookmark = *total_credit; } - ++m_updates; + uint8_t zcd = GetZCD(); + Fraction was = GetWAS(); + + // Apply rules and determine if greylisting criteria is met. + m_meets_greylisting_crit = (sb_from_baseline >= 2 && (zcd > 7 || was < Fraction(1, 10))); + + // Insert historical entry. + UpdateHistoryEntry entry(sb_from_baseline, total_credit, zcd, was, m_meets_greylisting_crit); + m_update_history.push_back(entry); } + //! + //! \brief This is used to store a update entry for historical purposes. + //! + struct UpdateHistoryEntry + { + //! + //! \brief Specific constructor for UpdateHistoryEntry. + //! + //! \param sb_from_baseline_processed + //! \param total_credit + //! \param meets_greylisting_crit + //! + UpdateHistoryEntry(uint8_t sb_from_baseline_processed, + std::optionaltotal_credit, + std::optional zcd, + std::optional was, + std::optional meets_greylisting_crit) + : m_sb_from_baseline_processed(sb_from_baseline_processed) + , m_total_credit(total_credit) + , m_zcd(zcd) + , m_was(was) + , m_meets_greylisting_crit(meets_greylisting_crit) + {} + + uint8_t m_sb_from_baseline_processed; + std::optional m_total_credit; + std::optional m_zcd; + std::optional m_was; + std::optional m_meets_greylisting_crit; + }; + const std::string m_project_name; uint8_t m_zcd_20_SB_count; @@ -618,7 +666,8 @@ class AutoGreylist std::optional m_TC_initial_bookmark; //!< This is a "reverse" bookmark - we are going backwards in SB's. uint64_t m_TC_bookmark; uint8_t m_sb_from_baseline_processed; - uint8_t m_updates; + + std::vector m_update_history; }; typedef std::map Greylist;