Skip to content

Commit f7a64df

Browse files
committed
Modify scraper and superblock code (part 3)
This actually makes the changes to wire the autogreylist in.
1 parent dc87d8e commit f7a64df

File tree

6 files changed

+140
-37
lines changed

6 files changed

+140
-37
lines changed

src/gridcoin/project.cpp

Lines changed: 77 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -308,8 +308,6 @@ AutoGreylist::AutoGreylist()
308308
: m_greylist_ptr(std::make_shared<Greylist>())
309309
, m_superblock_hash(uint256 {})
310310
{
311-
//m_greylist_ptr = std::make_shared<Greylist>();
312-
313311
Refresh();
314312
}
315313

@@ -328,6 +326,21 @@ AutoGreylist::Greylist::size_type AutoGreylist::size() const
328326
return m_greylist_ptr->size();
329327
}
330328

329+
bool AutoGreylist::Contains(const std::string& name, const bool& only_auto_greylisted) const
330+
{
331+
auto iter = m_greylist_ptr->find(name);
332+
333+
if (iter != m_greylist_ptr->end()) {
334+
if (only_auto_greylisted) {
335+
return (only_auto_greylisted && iter->second.m_meets_greylisting_crit);
336+
} else {
337+
return true;
338+
}
339+
} else {
340+
return false;
341+
}
342+
}
343+
331344
void AutoGreylist::Refresh()
332345
{
333346
LOCK(cs_main);
@@ -349,15 +362,23 @@ void AutoGreylist::RefreshWithSuperblock(SuperblockPtr superblock_ptr_in)
349362
LOCK(lock);
350363

351364
// We need the current whitelist, including all records except deleted. This will include greylisted projects,
352-
// whether currently marked as manually greylisted from protocol or overridden to auto greylisted by the auto greylist class.
353-
const WhitelistSnapshot whitelist = GetWhitelist().Snapshot(GRC::ProjectEntry::ProjectFilterFlag::ALL_BUT_DELETED);
365+
// whether currently marked as manually greylisted from protocol or overridden to auto greylisted by the auto greylist class,
366+
// based on the current state of the autogreylist. NOTE that the refresh_greylist is set to false here and MUST be this
367+
// when called in the AutoGreylist class itself, to avoid an infinite loop.
368+
const WhitelistSnapshot whitelist = GetWhitelist().Snapshot(GRC::ProjectEntry::ProjectFilterFlag::ALL_BUT_DELETED, false);
354369

355370
m_greylist_ptr->clear();
356371

372+
373+
// Notice the superblock_ptr_in m_projects_all_cpid_total_credits MUST ALEADY BE POPULATED to record the TC state into
374+
// the auto greylist.
357375
for (const auto& iter : whitelist) {
358-
if (auto project = superblock_ptr_in->m_projects.Try(iter.m_name)) {
376+
auto project = superblock_ptr_in->m_projects_all_cpids_total_credits.m_projects_all_cpid_total_credits.find(iter.m_name);
377+
378+
if (project != superblock_ptr_in->m_projects_all_cpids_total_credits.m_projects_all_cpid_total_credits.end()) {
359379
// Record new greylist candidate entry baseline with the total credit for each project present in superblock.
360-
m_greylist_ptr->insert(std::make_pair(iter.m_name, GreylistCandidateEntry(iter.m_name, project->m_total_credit)));
380+
m_greylist_ptr->insert(std::make_pair(iter.m_name,
381+
GreylistCandidateEntry(iter.m_name, std::nearbyint(project->second))));
361382
} else {
362383
// Record new greylist candidate entry with nullopt total credit. This is for a project that is in the whitelist,
363384
// but does not have a project entry in the superblock. This would be because the scrapers could not converge on the
@@ -373,7 +394,6 @@ void AutoGreylist::RefreshWithSuperblock(SuperblockPtr superblock_ptr_in)
373394
index_ptr = GRC::BlockFinder::FindByHeight(superblock_ptr_in.m_height - 1);
374395
}
375396

376-
//SuperblockPtr superblock_ptr;
377397
unsigned int superblock_count = 1; // The 0 (baseline) superblock was processed above. Here we start with 1 and go up to 40
378398

379399
while (index_ptr != nullptr && index_ptr->pprev != nullptr && superblock_count <= 40) {
@@ -400,9 +420,11 @@ void AutoGreylist::RefreshWithSuperblock(SuperblockPtr superblock_ptr_in)
400420
// This is guaranteed to succeed, because every whitelisted project was inserted as a new baseline entry above.
401421
auto greylist_entry = m_greylist_ptr->find(iter.m_name);
402422

403-
if (auto project = superblock_ptr->m_projects.Try(iter.m_name)) {
423+
auto project = superblock_ptr->m_projects_all_cpids_total_credits.m_projects_all_cpid_total_credits.find(iter.m_name);
424+
425+
if (project != superblock_ptr->m_projects_all_cpids_total_credits.m_projects_all_cpid_total_credits.end()) {
404426
// Update greylist candidate entry with the total credit for each project present in superblock.
405-
greylist_entry->second.UpdateGreylistCandidateEntry(project->m_total_credit, superblock_count);
427+
greylist_entry->second.UpdateGreylistCandidateEntry(project->second, superblock_count);
406428
} else {
407429
// Record updated greylist candidate entry with nullopt total credit. This is for a project that is in the whitelist,
408430
// but does not have a project entry in this superblock. This would be because the scrapers could not converge on the
@@ -415,13 +437,38 @@ void AutoGreylist::RefreshWithSuperblock(SuperblockPtr superblock_ptr_in)
415437
index_ptr = index_ptr->pprev;
416438
}
417439

418-
// Purge candidate elements that do not meet auto greylist criteria.
419-
for (auto iter = m_greylist_ptr->begin(); iter != m_greylist_ptr->end(); ) {
440+
// Mark elements with whether they meet greylist criteria.
441+
for (auto iter = m_greylist_ptr->begin(); iter != m_greylist_ptr->end(); ++iter) {
420442
if (iter->second.GetZCD() < 7 && iter->second.GetWAS() >= Fraction(1, 10)) {
421-
// Candidate greylist entry does not meet auto greylist criteria, so remove from greylist entry map.
422-
iter = m_greylist_ptr->erase(iter);
423-
} else {
424-
iter++;
443+
iter->second.m_meets_greylisting_crit = true;
444+
}
445+
}
446+
}
447+
448+
void AutoGreylist::RefreshWithSuperblock(Superblock& superblock)
449+
{
450+
SuperblockPtr superblock_ptr;
451+
452+
// For the purposes of forming a superblock as the mining of a new block adding to the head of the chain, we will
453+
// form a superblock ptr referencing the current head of the chain. The actual superblock will be the next block if it
454+
// is added to the chain, for for the purposes here, this is what we want, because it is simply used to feed the
455+
// overloaded version which takes the superblock_ptr and follows the chain backwards to do the greylist calculations.
456+
superblock_ptr.Replace(superblock);
457+
458+
{
459+
LOCK(cs_main);
460+
461+
superblock_ptr.Rebind(pindexBest);
462+
}
463+
464+
RefreshWithSuperblock(superblock_ptr);
465+
466+
const WhitelistSnapshot whitelist = GetWhitelist().Snapshot(GRC::ProjectEntry::ProjectFilterFlag::ALL_BUT_DELETED, false);
467+
468+
// Update the superblock object with the project greylist status.
469+
for (const auto& project : whitelist) {
470+
if (project.m_status == ProjectEntryStatus::AUTO_GREYLISTED || project.m_status == ProjectEntryStatus::MAN_GREYLISTED) {
471+
superblock.m_project_status.m_project_status.insert(std::make_pair(project.m_name, project.m_status));
425472
}
426473
}
427474
}
@@ -438,15 +485,27 @@ std::shared_ptr<AutoGreylist> AutoGreylist::GetAutoGreylistCache()
438485
// Class: Whitelist (Registry)
439486
// -----------------------------------------------------------------------------
440487

441-
WhitelistSnapshot Whitelist::Snapshot(const ProjectEntry::ProjectFilterFlag& filter) const
488+
WhitelistSnapshot Whitelist::Snapshot(const ProjectEntry::ProjectFilterFlag& filter, const bool& refresh_greylist) const
442489
{
443490
LOCK(cs_lock);
444491

445-
//AutoGreylist::GetAutoGreylistCache()->Refresh();
492+
std::shared_ptr<GRC::AutoGreylist> greylist_ptr = GRC::AutoGreylist::GetAutoGreylistCache();
493+
494+
if (refresh_greylist) {
495+
greylist_ptr->Refresh();
496+
}
446497

447498
ProjectList projects;
448499

449-
for (const auto& iter : m_project_entries) {
500+
// This is the override for automatic greylisting. If the AutoGreylist class refresh determines
501+
// that the project meets greylisting criteria, it will be in the AutoGreylist object pointed to
502+
// by the greylist_ptr. This will override the whitelist entries from the project whitelist registry.
503+
for (auto iter : m_project_entries) {
504+
if ((iter.second->m_status == ProjectEntryStatus::ACTIVE || iter.second->m_status == ProjectEntryStatus::MAN_GREYLISTED)
505+
&& greylist_ptr->Contains(iter.first)) {
506+
iter.second->m_status = ProjectEntryStatus::AUTO_GREYLISTED;
507+
}
508+
450509
switch (filter) {
451510
case ProjectEntry::ProjectFilterFlag::ACTIVE:
452511
if (iter.second->m_status == ProjectEntryStatus::ACTIVE) {

src/gridcoin/project.h

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -508,6 +508,7 @@ class AutoGreylist
508508
, m_zcd_20_SB_count(0)
509509
, m_TC_7_SB_sum(0)
510510
, m_TC_40_SB_sum(0)
511+
, m_meets_greylisting_crit(0)
511512
, m_TC_initial_bookmark(0)
512513
, m_TC_bookmark(0)
513514
, m_sb_from_baseline_processed(0)
@@ -519,6 +520,7 @@ class AutoGreylist
519520
, m_zcd_20_SB_count(0)
520521
, m_TC_7_SB_sum(0)
521522
, m_TC_40_SB_sum(0)
523+
, m_meets_greylisting_crit(0)
522524
, m_TC_initial_bookmark(TC_initial_bookmark)
523525
, m_TC_bookmark(0)
524526
, m_sb_from_baseline_processed(0)
@@ -608,6 +610,7 @@ class AutoGreylist
608610
uint8_t m_zcd_20_SB_count;
609611
uint64_t m_TC_7_SB_sum;
610612
uint64_t m_TC_40_SB_sum;
613+
bool m_meets_greylisting_crit;
611614

612615
private:
613616
std::optional<uint64_t> m_TC_initial_bookmark; //!< This is a "reverse" bookmark - we are going backwards in SB's.
@@ -649,25 +652,40 @@ class AutoGreylist
649652
//!
650653
//! \param name Project name matching the contract key.
651654
//!
655+
//! \param only_auto_greylisted A boolean that specifies whether the search is against all projects or only those
656+
//! that meet auto greylisting criteria.
657+
//!
652658
//! \return \c true if the auto greylist contains a project with matching name.
653659
//!
654-
bool Contains(const std::string& name) const;
660+
bool Contains(const std::string& name, const bool& only_auto_greylisted = true) const;
655661

656662
void Refresh();
657663

658664
//!
659-
//! \brief This refreshes a local instantiation of the AutoGreylist from an input Superblock. This mode is used
660-
//! in the scraper during the construction of the superblock contract.
665+
//! \brief This refreshes a local instantiation of the AutoGreylist from an input Superblock pointer.
661666
//!
662667
//! Note that the AutoGreylist object refreshed this way will also be used to update the referenced superblock
663668
//! object
664669
//!
665-
//! \param superblock The superblock with which to refresh the automatic greylist. This can be a candidate superblock
670+
//! \param superblock_ptr The superblock pointer with which to refresh the automatic greylist. This can be a candidate superblock
666671
//! from a scraper convergence, or in the instance of this being called from Refresh(), could be the current
667672
//! superblock on the chain.
668673
//!
669674
void RefreshWithSuperblock(SuperblockPtr superblock_ptr_in);
670675

676+
//!
677+
//! \brief This refreshes a local instantiation of the AutoGreylist from an input Superblock that is going to be associated
678+
//! with the current head of the chain. This mode is used in the scraper during the construction of the superblock contract.
679+
//!
680+
//! Note that the AutoGreylist object refreshed this way will also be used to update the referenced superblock
681+
//! object
682+
//!
683+
//! \param superblock The superblock with which to refresh the automatic greylist. This will generally be a candidate superblock
684+
//! from a scraper convergence, and is used in the call chain from the miner loop. The superblock object project status
685+
//! will be updated.
686+
//!
687+
void RefreshWithSuperblock(Superblock& superblock);
688+
671689
static std::shared_ptr<AutoGreylist> GetAutoGreylistCache();
672690

673691
private:
@@ -717,9 +735,11 @@ class Whitelist : public IContractHandler
717735

718736
//!
719737
//! \brief Get a read-only view of the projects in the whitelist. The default filter is ACTIVE, which
720-
//! provides the original ACTIVE project only view.
738+
//! provides the original ACTIVE project only view. The refresh_greylist filter is used to refresh
739+
//! the AutoGreylist as part of taking the snapshot.
721740
//!
722-
WhitelistSnapshot Snapshot(const ProjectEntry::ProjectFilterFlag& filter = ProjectEntry::ProjectFilterFlag::ACTIVE) const;
741+
WhitelistSnapshot Snapshot(const ProjectEntry::ProjectFilterFlag& filter = ProjectEntry::ProjectFilterFlag::ACTIVE,
742+
const bool& refresh_greylist = false) const;
723743

724744
//!
725745
//! \brief Destroy the contract handler state to prepare for historical

src/gridcoin/superblock.cpp

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
#include "chainparams.h"
66
#include "compat/endian.h"
7+
#include "gridcoin/project.h"
78
#include "hash.h"
89
#include "main.h"
910
#include <gridcoin/md5.h>
@@ -607,20 +608,29 @@ Superblock Superblock::FromConvergence(
607608
if (!stats.Convergence.bByParts) {
608609
superblock.m_manifest_content_hint
609610
= stats.Convergence.nUnderlyingManifestContentHash.GetUint64(0) >> 32;
611+
} else {
612+
ProjectIndex& projects = superblock.m_projects;
610613

611-
return superblock;
614+
// Add hints created from the hashes of converged manifest parts to each
615+
// superblock project section to assist receiving nodes with validation:
616+
//
617+
for (const auto& part_pair : stats.Convergence.ConvergedManifestPartPtrsMap) {
618+
const std::string& project_name = part_pair.first;
619+
const CSplitBlob::CPart* part_data_ptr = part_pair.second;
620+
621+
projects.SetHint(project_name, part_data_ptr);
622+
}
612623
}
613624

614-
ProjectIndex& projects = superblock.m_projects;
625+
if (version > 2) {
626+
// Populate the total credits into the superblock object from the convergence. This must be done BEFORE
627+
// the auto greylist RefreshWithSuperblock is called.
628+
superblock.m_projects_all_cpids_total_credits.Reset(stats.mScraperConvergedStats.m_total_credit_map);
615629

616-
// Add hints created from the hashes of converged manifest parts to each
617-
// superblock project section to assist receiving nodes with validation:
618-
//
619-
for (const auto& part_pair : stats.Convergence.ConvergedManifestPartPtrsMap) {
620-
const std::string& project_name = part_pair.first;
621-
const CSplitBlob::CPart* part_data_ptr = part_pair.second;
630+
// Refresh the auto greylist and refresh this superblock with the greylist status.
631+
std::shared_ptr<GRC::AutoGreylist> greylist_ptr = GRC::AutoGreylist::GetAutoGreylistCache();
622632

623-
projects.SetHint(project_name, part_data_ptr);
633+
greylist_ptr->RefreshWithSuperblock(superblock);
624634
}
625635

626636
return superblock;

src/rpc/blockchain.cpp

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2634,13 +2634,21 @@ UniValue listprojects(const UniValue& params, bool fHelp)
26342634

26352635
UniValue getautogreylist(const UniValue& params, bool fHelp)
26362636
{
2637-
if (fHelp || params.size() > 0) {
2637+
if (fHelp || params.size() > 1) {
26382638
throw runtime_error(
2639-
"getautogreylist \n"
2639+
"getautogreylist <bool> \n"
2640+
"\n"
2641+
"<bool> -> true to show all projects, including those that do not meet greylisting criteria. Defaults to false. \n"
26402642
"\n"
26412643
"Displays information about projects that meet auto greylisting criteria.");
26422644
}
26432645

2646+
bool show_all_projects = false;
2647+
2648+
if (params.size()) {
2649+
show_all_projects = params[0].get_bool();
2650+
}
2651+
26442652
UniValue res(UniValue::VOBJ);
26452653

26462654
std::shared_ptr<GRC::AutoGreylist> greylist_ptr = GRC::AutoGreylist::GetAutoGreylistCache();
@@ -2650,11 +2658,16 @@ UniValue getautogreylist(const UniValue& params, bool fHelp)
26502658
UniValue autogreylist(UniValue::VARR);
26512659

26522660
for (auto iter : *greylist_ptr) {
2661+
if (!show_all_projects && !iter.second.m_meets_greylisting_crit) {
2662+
continue;
2663+
}
2664+
26532665
UniValue entry(UniValue::VOBJ);
26542666

26552667
entry.pushKV("project:", iter.first);
26562668
entry.pushKV("zcd", iter.second.GetZCD());
26572669
entry.pushKV("WAS", iter.second.GetWAS().ToDouble());
2670+
entry.pushKV("meets_greylist_criteria", iter.second.m_meets_greylisting_crit);
26582671

26592672
autogreylist.push_back(entry);
26602673
}

src/rpc/client.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
215215
{ "inspectaccrualsnapshot" , 0 },
216216
{ "listmanifests" , 0 },
217217
{ "listprojects" , 0 },
218+
{ "getautogreylist" , 0 },
218219
{ "sendalert" , 2 },
219220
{ "sendalert" , 3 },
220221
{ "sendalert" , 4 },

src/test/gridcoin/superblock_tests.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -656,9 +656,9 @@ BOOST_AUTO_TEST_CASE(it_initializes_from_a_fallback_by_project_scraper_convergen
656656
{
657657
const ScraperStatsMeta meta;
658658
GRC::Superblock superblock = GRC::Superblock::FromConvergence(
659-
GetTestConvergence(meta, true)); // Set fallback by project flag
659+
GetTestConvergence(meta, true), 2); // Set fallback by project flag
660660

661-
BOOST_CHECK(superblock.m_version == GRC::Superblock::CURRENT_VERSION);
661+
BOOST_CHECK(superblock.m_version == 2);
662662
BOOST_CHECK(superblock.m_convergence_hint == 0x11111111);
663663
// Manifest content hint not set for fallback convergence:
664664
BOOST_CHECK(superblock.m_manifest_content_hint == 0x00000000);

0 commit comments

Comments
 (0)