Skip to content

Commit 9924706

Browse files
committed
accrual mod WIP
1 parent e2c47a0 commit 9924706

File tree

7 files changed

+177
-48
lines changed

7 files changed

+177
-48
lines changed

src/chainparams.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,5 +134,5 @@ inline int GetNewbieSnapshotFixHeight()
134134
{
135135
// This was the original hard fork point for the newbie accrual fix that didn't work.
136136
// return fTestNet ? 1393000 : 2104000;
137-
return fTestNet ? 1479000 : 2104000;
137+
return fTestNet ? 1393000 : 2104000;
138138
}

src/gridcoin/beacon.cpp

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,10 @@ uint256 HashBeaconPayload(const BeaconPayload& payload)
4444
//! \return \c true if the supplied beacon contract matches an active beacon.
4545
//! This updates the matched beacon with a new timestamp.
4646
//!
47-
bool TryRenewal(BeaconRegistry::BeaconMap& beacons, const BeaconPayload& payload)
47+
bool TryRenewal(BeaconRegistry::BeaconMap& beacons,
48+
BeaconRegistry::HistoricalBeaconMap& historical_beacons,
49+
const BeaconPayload& payload,
50+
const uint256& ctx_hash)
4851
{
4952
auto beacon_pair_iter = beacons.find(payload.m_cpid);
5053

@@ -62,7 +65,12 @@ bool TryRenewal(BeaconRegistry::BeaconMap& beacons, const BeaconPayload& payload
6265
return false;
6366
}
6467

68+
// Insert current beacon into historical map.
69+
historical_beacons.emplace(std::make_pair(ctx_hash, current_beacon));
70+
71+
// Update current beacon record.
6572
current_beacon.m_timestamp = payload.m_beacon.m_timestamp;
73+
current_beacon.m_prev_beacon_txn_hash = ctx_hash;
6674

6775
return true;
6876
}
@@ -93,6 +101,7 @@ Beacon::Beacon(CPubKey public_key)
93101
Beacon::Beacon(CPubKey public_key, int64_t timestamp)
94102
: m_public_key(std::move(public_key))
95103
, m_timestamp(timestamp)
104+
, m_prev_beacon_txn_hash()
96105
{
97106
}
98107

@@ -157,6 +166,12 @@ bool Beacon::Renewable(const int64_t now) const
157166
return Age(now) > RENEWAL_AGE;
158167
}
159168

169+
bool Beacon::Renewed() const
170+
{
171+
// If not empty, the beacon was a renewal.
172+
return (m_prev_beacon_txn_hash != uint256());
173+
}
174+
160175
CKeyID Beacon::GetId() const
161176
{
162177
return m_public_key.GetID();
@@ -276,6 +291,11 @@ const BeaconRegistry::PendingBeaconMap& BeaconRegistry::PendingBeacons() const
276291
return m_pending;
277292
}
278293

294+
const BeaconRegistry::HistoricalBeaconMap &BeaconRegistry::HistoricalBeacons() const
295+
{
296+
return m_historical;
297+
}
298+
279299
BeaconOption BeaconRegistry::Try(const Cpid& cpid) const
280300
{
281301
const auto iter = m_beacons.find(cpid);
@@ -353,7 +373,7 @@ void BeaconRegistry::Add(const ContractContext& ctx)
353373
// For beacon renewals, check that the new beacon contains the same public
354374
// key. If it matches, we don't need to verify it again:
355375
//
356-
if (TryRenewal(m_beacons, payload)) {
376+
if (TryRenewal(m_beacons, m_historical, payload, ctx.m_tx.GetHash())) {
357377
return;
358378
}
359379

src/gridcoin/beacon.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,13 @@ class Beacon
6868
CPubKey m_public_key; //!< Verifies blocks that claim research rewards.
6969
int64_t m_timestamp; //!< Time of the the beacon contract transaction.
7070

71+
// The reason the transaction hash is included here instead of a pointer
72+
// to the previous beacon, is that given the limited lookback scope, the
73+
// previous beacon may not be in the map. This makes the linked list harder
74+
// to deal with, but relieves us of dealing with the leading edge of the
75+
// lookback window.
76+
uint256 m_prev_beacon_txn_hash; //!< If a renewal contains the txn hash of the previous beacon.
77+
7178
//!
7279
//! \brief Initialize an empty, invalid beacon instance.
7380
//!
@@ -140,6 +147,13 @@ class Beacon
140147
//!
141148
bool Renewable(const int64_t now) const;
142149

150+
//!
151+
//! \brief Determine whether the beacon was renewed.
152+
//!
153+
//! \return \c true if the beacon is a renewal rather than new advertisement
154+
//!
155+
bool Renewed() const;
156+
143157
//!
144158
//! \brief Get the hash of the beacon public key.
145159
//!
@@ -409,6 +423,11 @@ class BeaconRegistry : public IContractHandler
409423
//!
410424
typedef std::unordered_map<Cpid, Beacon> BeaconMap;
411425

426+
//!
427+
//! \brief The type that associates historical beacons with the ctx hash.
428+
//!
429+
typedef std::map<uint256, Beacon> HistoricalBeaconMap;
430+
412431
//!
413432
//! \brief Associates pending beacons with the hash of the beacon public
414433
//! keys.
@@ -429,6 +448,13 @@ class BeaconRegistry : public IContractHandler
429448
//!
430449
const PendingBeaconMap& PendingBeacons() const;
431450

451+
//!
452+
//! \brief Get the collection of historical beacons.
453+
//!
454+
//! \return A reference to the historical beacons stored in the registry.
455+
//!
456+
const HistoricalBeaconMap& HistoricalBeacons() const;
457+
432458
//!
433459
//! \brief Get the beacon for the specified CPID.
434460
//!
@@ -531,6 +557,7 @@ class BeaconRegistry : public IContractHandler
531557
private:
532558
BeaconMap m_beacons; //!< Contains the active registered beacons.
533559
PendingBeaconMap m_pending; //!< Contains beacons awaiting verification.
560+
HistoricalBeaconMap m_historical; //!< Contains historical beacons.
534561
}; // BeaconRegistry
535562

536563
//!

src/gridcoin/gridcoin.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -328,11 +328,14 @@ bool GRC::Initialize(ThreadHandlerPtr threads, CBlockIndex* pindexBest)
328328

329329
InitializeSuperblockQuorum(pindexBest);
330330

331+
// This has to be before InitializeResearchRewardAccounting, because we need the beacon registry
332+
// populated.
333+
InitializeContracts(pindexBest);
334+
331335
if (!InitializeResearchRewardAccounting(pindexBest)) {
332336
return false;
333337
}
334338

335-
InitializeContracts(pindexBest);
336339
InitializeResearcherContext();
337340
InitializeScraper(threads);
338341
InitializeExplorerFeatures();

src/gridcoin/tally.cpp

Lines changed: 84 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -558,8 +558,8 @@ class ResearcherTally
558558
{
559559
const SnapshotCalculator calc(superblock.m_timestamp, m_current_superblock);
560560

561-
LogPrint(BCLog::LogFlags::ACCRUAL, "INFO %s: m_researchers.size() = %u",
562-
__func__, m_researchers.size());
561+
LogPrint(BCLog::LogFlags::ACCRUAL, "INFO %s: superblock height = %u, m_researchers.size() = %u",
562+
__func__, superblock.m_height, m_researchers.size());
563563

564564
for (auto& account_pair : m_researchers) {
565565
const Cpid cpid = account_pair.first;
@@ -594,7 +594,7 @@ class ResearcherTally
594594
ResearchAccount& account = m_researchers[iter.Cpid()];
595595
account.m_accrual = calc.AccrualDelta(iter.Cpid(), account);
596596
597-
LogPrint(BCLog::LogFlags::ACCRUAL, "INFO %s: accrual account not found"
597+
LogPrint(BCLog::LogFlags::ACCRUAL, "INFO %s: accrual account not found "
598598
"for CPID %s. Creating account with accrual %" PRId64" from "
599599
"AccrualDelta() = %" PRId64 ". m_researchers.size() now %u",
600600
__func__,
@@ -626,15 +626,16 @@ class ResearcherTally
626626

627627
account.m_accrual = accrual_correction + accrual_delta;
628628

629-
LogPrint(BCLog::LogFlags::ACCRUAL, "INFO %s: accrual account not found"
629+
LogPrint(BCLog::LogFlags::ACCRUAL, "INFO %s: accrual account not found "
630630
"for CPID %s. Creating account with accrual %" PRId64" from "
631-
"Accrual Correction = %" PRId64 ", Accrual Delta = %" PRId64
632-
", m_researchers.size() now %u.",
631+
"Accrual Correction = %" PRId64 ", Accrual Delta = %" PRId64 ", "
632+
"superblock height = %" PRId64 ", m_researchers.size() = %u.",
633633
__func__,
634634
iter.Cpid().ToString(),
635635
account.m_accrual,
636636
accrual_correction,
637637
accrual_delta,
638+
superblock.m_height,
638639
m_researchers.size());
639640
}
640641
}
@@ -644,9 +645,9 @@ class ResearcherTally
644645
//!
645646
//! \brief Compute "catch-up" accrual to correct for newbie accrual bug.
646647
//!
647-
//! \param superblock Incoming superblock to calculate rewards at.
648+
//! \param cpid for which to calculate the accrual correction.
648649
//!
649-
CAmount GetNewbieSuperblockAccrualCorrection(Cpid cpid)
650+
CAmount GetNewbieSuperblockAccrualCorrection(const Cpid& cpid)
650651
{
651652
// This function is ONLY called if there is no accounting record for the CPID.
652653
// For there to be no accounting record also means there is no recorded accrual for
@@ -658,23 +659,6 @@ class ResearcherTally
658659
// similar to the calculation in the auditsnapshotaccrual RPC function.
659660
CAmount accrual = 0;
660661

661-
const GRC::BeaconRegistry& beacons = GRC::GetBeaconRegistry();
662-
663-
// This had better succeed, because it is coming from the incoming superblock cpids! If not just
664-
// return 0 accrual, because the beacon is not actually active.
665-
const GRC::BeaconOption beacon = beacons.Try(cpid);
666-
667-
if (!beacon) return accrual;
668-
669-
// Start at the tip.
670-
const CBlockIndex* pindex = mapBlockIndex[hashBestChain];
671-
672-
// In the loop below we will be going BACKWARDS through the chain, so this will be at a HIGHER
673-
// height.
674-
const CBlockIndex* pindex_prev;
675-
676-
SuperblockPtr superblock;
677-
678662
// This lambda is almost a straight lift from the auditsnapshotaccrual RPC function. It is simplifed,
679663
// because since the accrual account doesn't exist, there has been no staking for this CPID and no payout,
680664
// so only superblock to superblock periods need to be considered.
@@ -685,10 +669,18 @@ class ResearcherTally
685669
{
686670
int64_t time_interval = high_time - low_time;
687671

672+
int64_t abs_time_interval = time_interval;
673+
674+
int sign = (time_interval >= 0) ? 1 : -1;
675+
676+
if (sign < 0) {
677+
abs_time_interval = -time_interval;
678+
}
679+
688680
// This is the same way that AccrualDelta calculates accruals in the snapshot calculator. Here
689681
// we use the absolute value of the time interval to ensure negative values are carried through
690682
// correctly in the bignumber calculations.
691-
const uint64_t base_accrual = time_interval
683+
const uint64_t base_accrual = abs_time_interval
692684
* magnitude.Scaled()
693685
* MAG_UNIT_NUMERATOR;
694686

@@ -701,11 +693,11 @@ class ResearcherTally
701693
accrual_bn /= Magnitude::SCALE_FACTOR;
702694
accrual_bn /= MAG_UNIT_DENOMINATOR;
703695

704-
period = accrual_bn.GetLow64();
696+
period = accrual_bn.GetLow64() * (int64_t) sign;
705697
}
706698
else
707699
{
708-
period = base_accrual
700+
period = base_accrual * (int64_t) sign
709701
* COIN
710702
/ 86400
711703
/ Magnitude::SCALE_FACTOR
@@ -729,33 +721,87 @@ class ResearcherTally
729721
return period;
730722
};
731723

724+
const GRC::BeaconRegistry& beacons = GRC::GetBeaconRegistry();
725+
GRC::BeaconOption beacon = beacons.Try(cpid);
726+
727+
LogPrint(BCLog::LogFlags::ACCRUAL, "INFO %s: beacon registry size = %u", __func__, beacons.Beacons().size());
728+
729+
if (beacon)
730+
{
731+
// Walk back the entries in the historical beacon map linked by renewal prev tx hash until the first
732+
// beacon in the renewal chain is found (the original advertisement). The accrual starts no earlier
733+
// than here.
734+
while (beacon->Renewed())
735+
{
736+
beacon = &beacons.HistoricalBeacons().find(beacon->m_prev_beacon_txn_hash)->second;
737+
}
738+
}
739+
else
740+
{
741+
742+
LogPrint(BCLog::LogFlags::ACCRUAL, "ERROR: %s: No active beacon for cpid %s.",
743+
__func__, cpid.ToString());
744+
745+
return accrual;
746+
}
747+
748+
749+
750+
const CBlockIndex* pindex_baseline = GRC::Tally::GetBaseline();
751+
752+
// Start at the tip.
753+
const CBlockIndex* pindex_high = mapBlockIndex[hashBestChain];
754+
755+
// Rewind pindex_high to the current superblock.
756+
while (pindex_high->nHeight > m_current_superblock.m_height)
757+
{
758+
pindex_high = pindex_high->pprev;
759+
}
760+
761+
// Set pindex to the block before: (pindex_high->pprev).
762+
const CBlockIndex* pindex = pindex_high->pprev;
763+
764+
SuperblockPtr superblock;
732765
unsigned int period_num = 0;
733-
while (pindex->nHeight < m_current_superblock.m_height)
766+
767+
while (pindex->nHeight >= pindex_baseline->nHeight)
734768
{
735-
// This ensures we move to the next (lower height) superblock as the first period to
736-
// accrue.
737-
if (period_num && pindex->IsSuperblock())
769+
if (pindex->IsSuperblock())
738770
{
739771
superblock = SuperblockPtr::ReadFromDisk(pindex);
740772

741773
const GRC::Magnitude magnitude = superblock->m_cpids.MagnitudeOf(cpid);
742774

743-
tally_accrual_period(pindex->nTime, pindex_prev->nTime, magnitude);
775+
CAmount period = tally_accrual_period(pindex->nTime, pindex_high->nTime, magnitude);
776+
777+
LogPrint(BCLog::LogFlags::ACCRUAL, "INFO %s: period_num = %u, "
778+
"low height = %i, high height = %u, magnitude at low height SB = %f, "
779+
"low time = %u, high time = %u, "
780+
"accrual for period = %" PRId64 ", accrual = %" PRId64 ".",
781+
__func__,
782+
period_num,
783+
pindex->nHeight,
784+
pindex_high->nHeight,
785+
magnitude.Floating(),
786+
pindex->nTime,
787+
pindex_high->nTime,
788+
period,
789+
accrual);
744790

745791
// Stop the accrual when we get to a superblock that is before the beacon advertisement.
746-
if (pindex->nTime < beacon->m_timestamp) break;
792+
//if (pindex->nTime < beacon->m_timestamp) break;
793+
794+
// We are going backwards through the chain.
795+
pindex_high = pindex;
796+
++period_num;
747797
}
748798

749-
// We are going backwards through the chain.
750-
pindex_prev = pindex;
751799
pindex = pindex->pprev;
752-
++period_num;
753800
}
754801

755802
return accrual;
756803
}
757804

758-
759805
//!
760806
//! \brief Locate the block index entry of the superblock before the
761807
//! snapshot accrual threshold.

src/main.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2087,13 +2087,13 @@ bool TryLoadSuperblock(
20872087
// accrual taken at each superblock:
20882088
//
20892089
if (block.nVersion >= 11) {
2090-
if (!GRC::Tally::ApplySuperblock(superblock)) {
2091-
return false;
2092-
}
2093-
20942090
GRC::GetBeaconRegistry().ActivatePending(
20952091
superblock->m_verified_beacons.m_verified,
20962092
superblock.m_timestamp);
2093+
2094+
if (!GRC::Tally::ApplySuperblock(superblock)) {
2095+
return false;
2096+
}
20972097
}
20982098

20992099
GRC::Quorum::PushSuperblock(std::move(superblock));

0 commit comments

Comments
 (0)