Skip to content

Commit 43caa1f

Browse files
committed
accrual mod WIP
1 parent e2c47a0 commit 43caa1f

File tree

5 files changed

+143
-40
lines changed

5 files changed

+143
-40
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/tally.cpp

Lines changed: 65 additions & 35 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,7 +645,7 @@ 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
//!
649650
CAmount GetNewbieSuperblockAccrualCorrection(Cpid cpid)
650651
{
@@ -658,22 +659,7 @@ 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;
662+
//const GRC::BeaconRegistry& beacons = GRC::GetBeaconRegistry();
677663

678664
// This lambda is almost a straight lift from the auditsnapshotaccrual RPC function. It is simplifed,
679665
// because since the accrual account doesn't exist, there has been no staking for this CPID and no payout,
@@ -685,10 +671,18 @@ class ResearcherTally
685671
{
686672
int64_t time_interval = high_time - low_time;
687673

674+
int64_t abs_time_interval = time_interval;
675+
676+
int sign = (time_interval >= 0) ? 1 : -1;
677+
678+
if (sign < 0) {
679+
abs_time_interval = -time_interval;
680+
}
681+
688682
// This is the same way that AccrualDelta calculates accruals in the snapshot calculator. Here
689683
// we use the absolute value of the time interval to ensure negative values are carried through
690684
// correctly in the bignumber calculations.
691-
const uint64_t base_accrual = time_interval
685+
const uint64_t base_accrual = abs_time_interval
692686
* magnitude.Scaled()
693687
* MAG_UNIT_NUMERATOR;
694688

@@ -701,11 +695,11 @@ class ResearcherTally
701695
accrual_bn /= Magnitude::SCALE_FACTOR;
702696
accrual_bn /= MAG_UNIT_DENOMINATOR;
703697

704-
period = accrual_bn.GetLow64();
698+
period = accrual_bn.GetLow64() * (int64_t) sign;
705699
}
706700
else
707701
{
708-
period = base_accrual
702+
period = base_accrual * (int64_t) sign
709703
* COIN
710704
/ 86400
711705
/ Magnitude::SCALE_FACTOR
@@ -729,27 +723,63 @@ class ResearcherTally
729723
return period;
730724
};
731725

726+
727+
// This had better succeed, because it is coming from the incoming superblock cpids! If not just
728+
// return 0 accrual, because the beacon is not actually active.
729+
//const GRC::BeaconOption beacon = beacons.Try(cpid);
730+
731+
//if (!beacon) return accrual;
732+
733+
const CBlockIndex* pindex_baseline = GRC::Tally::GetBaseline();
734+
735+
// Start at the tip.
736+
const CBlockIndex* pindex_high = mapBlockIndex[hashBestChain];
737+
738+
// Rewind pindex_high to the current superblock.
739+
while (pindex_high->nHeight > m_current_superblock.m_height)
740+
{
741+
pindex_high = pindex_high->pprev;
742+
}
743+
744+
// Set pindex to the block before: (pindex_high->pprev).
745+
const CBlockIndex* pindex = pindex_high->pprev;
746+
747+
SuperblockPtr superblock;
732748
unsigned int period_num = 0;
733-
while (pindex->nHeight < m_current_superblock.m_height)
749+
750+
while (pindex->nHeight >= pindex_baseline->nHeight)
734751
{
735-
// This ensures we move to the next (lower height) superblock as the first period to
736-
// accrue.
737-
if (period_num && pindex->IsSuperblock())
752+
if (pindex->IsSuperblock())
738753
{
739754
superblock = SuperblockPtr::ReadFromDisk(pindex);
740755

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

743-
tally_accrual_period(pindex->nTime, pindex_prev->nTime, magnitude);
758+
CAmount period = tally_accrual_period(pindex->nTime, pindex_high->nTime, magnitude);
759+
760+
LogPrint(BCLog::LogFlags::ACCRUAL, "INFO %s: period_num = %u, "
761+
"low height = %i, high height = %u, magnitude at low height SB = %f, "
762+
"low time = %u, high time = %u, "
763+
"accrual for period = %" PRId64 ", accrual = %" PRId64 ".",
764+
__func__,
765+
period_num,
766+
pindex->nHeight,
767+
pindex_high->nHeight,
768+
magnitude.Floating(),
769+
pindex->nTime,
770+
pindex_high->nTime,
771+
period,
772+
accrual);
744773

745774
// Stop the accrual when we get to a superblock that is before the beacon advertisement.
746-
if (pindex->nTime < beacon->m_timestamp) break;
775+
//if (pindex->nTime < beacon->m_timestamp) break;
776+
777+
// We are going backwards through the chain.
778+
pindex_high = pindex;
779+
++period_num;
747780
}
748781

749-
// We are going backwards through the chain.
750-
pindex_prev = pindex;
751782
pindex = pindex->pprev;
752-
++period_num;
753783
}
754784

755785
return accrual;

src/rpc/mining.cpp

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,23 @@ UniValue auditsnapshotaccrual(const UniValue& params, bool fHelp)
316316
}
317317
}
318318

319+
const GRC::BeaconRegistry& beacons = GRC::GetBeaconRegistry();
320+
321+
GRC::BeaconOption beacon = beacons.Try(*cpid);
322+
323+
UniValue beacon_chain(UniValue::VARR);
324+
325+
beacon_chain.push_back(beacon->m_timestamp);
326+
327+
// This walks back the entries in the historical beacon map linked by renewal prev tx hash until the first
328+
// beacon in the renewal chain is found (the original advertisement). The accrual starts no earlier than here.
329+
while (beacon->Renewed())
330+
{
331+
beacon = &beacons.HistoricalBeacons().find(beacon->m_prev_beacon_txn_hash)->second;
332+
333+
beacon_chain.push_back(beacon->m_timestamp);
334+
}
335+
319336
// Set the pindex_low to the pindex_superblock. For right now, we are going to take the accrual at the first snapshot
320337
// after the flip to v11 (the second snapshot in the accrual directory recorded at the first SB after the transition
321338
// height) as gospel. This doesn't allow us to verify the accrual between the transition height and the first snapshot
@@ -413,6 +430,10 @@ UniValue auditsnapshotaccrual(const UniValue& params, bool fHelp)
413430
};
414431

415432
for (; pindex; pindex = pindex->pnext) {
433+
434+
// Due not accrue for any block with a timestamp earlier than the first beacon in the renewal chain.
435+
//if (pindex->nTime < beacon->m_timestamp) continue;
436+
416437
if (pindex->ResearchSubsidy() > 0 && pindex->GetMiningId() == *cpid) {
417438
tally_accrual_period(
418439
"stake",
@@ -441,15 +462,20 @@ UniValue auditsnapshotaccrual(const UniValue& params, bool fHelp)
441462

442463
int64_t period = tally_accrual_period("tip", 0, pindex_low->nTime, now, 0);
443464

465+
result.pushKV("cpid", cpid->ToString());
466+
result.pushKV("accrual_account_exists", accrual_account_exists);
467+
444468
if (report_details) {
469+
result.pushKV("beacon_chain", beacon_chain);
445470
result.pushKV("audit", audit);
446471
result.pushKV("computed", computed);
447-
result.pushKV("accrual_account_exists", accrual_account_exists);
448472
} else {
473+
result.pushKV("latest_beacon_timestamp", beacon_chain[0]);
474+
result.pushKV("original_beacon_timestamp", beacon_chain[beacon_chain.size() - 1]);
475+
result.pushKV("renewals", beacon_chain.size() - 1);
449476
result.pushKV("accrual_by_audit", accrual);
450477
result.pushKV("accrual_by_GetAccrual", computed);
451478
result.pushKV("accrual_last_period", period);
452-
result.pushKV("accrual_account_exists", accrual_account_exists);
453479
}
454480

455481
return result;

0 commit comments

Comments
 (0)