Skip to content

Commit b88f766

Browse files
authored
Merge pull request #2008 from jamescowens/beacon_storage
beacon: Change beacon map to pointers.
2 parents f678144 + 019719d commit b88f766

File tree

7 files changed

+129
-73
lines changed

7 files changed

+129
-73
lines changed

src/gridcoin/beacon.cpp

Lines changed: 32 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -46,16 +46,15 @@ uint256 HashBeaconPayload(const BeaconPayload& payload)
4646
//!
4747
bool TryRenewal(BeaconRegistry::BeaconMap& beacons,
4848
BeaconRegistry::HistoricalBeaconMap& historical_beacons,
49-
const BeaconPayload& payload,
50-
const uint256& ctx_hash)
49+
const BeaconPayload& payload)
5150
{
5251
auto beacon_pair_iter = beacons.find(payload.m_cpid);
5352

5453
if (beacon_pair_iter == beacons.end()) {
5554
return false;
5655
}
5756

58-
Beacon& current_beacon = beacon_pair_iter->second;
57+
Beacon& current_beacon = *beacon_pair_iter->second;
5958

6059
if (current_beacon.Expired(payload.m_beacon.m_timestamp)) {
6160
return false;
@@ -65,12 +64,15 @@ bool TryRenewal(BeaconRegistry::BeaconMap& beacons,
6564
return false;
6665
}
6766

68-
// Insert current beacon into historical map.
69-
historical_beacons.emplace(std::make_pair(ctx_hash, current_beacon));
67+
// Insert copy of current beacon into historical map.
68+
historical_beacons.emplace(std::make_pair(current_beacon.m_ctx_hash, current_beacon));
7069

71-
// Update current beacon record.
70+
// Set the previous transaction hash to the current.
71+
current_beacon.m_prev_beacon_ctx_hash = current_beacon.m_ctx_hash;
72+
// Update current beacon record timestamp to the incoming payload transaction hash.
7273
current_beacon.m_timestamp = payload.m_beacon.m_timestamp;
73-
current_beacon.m_prev_beacon_txn_hash = ctx_hash;
74+
// Update the current transaction hash to the incoming payload transaction hash.
75+
current_beacon.m_ctx_hash = payload.m_beacon.m_ctx_hash;
7476

7577
return true;
7678
}
@@ -89,19 +91,20 @@ BeaconRegistry& GRC::GetBeaconRegistry()
8991
// Class: Beacon
9092
// -----------------------------------------------------------------------------
9193

92-
Beacon::Beacon() : m_public_key(), m_timestamp(0)
94+
Beacon::Beacon() : m_public_key(), m_timestamp(0), m_ctx_hash()
9395
{
9496
}
9597

9698
Beacon::Beacon(CPubKey public_key)
97-
: Beacon(std::move(public_key), 0)
99+
: Beacon(std::move(public_key), 0, uint256 {})
98100
{
99101
}
100102

101-
Beacon::Beacon(CPubKey public_key, int64_t timestamp)
103+
Beacon::Beacon(CPubKey public_key, int64_t timestamp, uint256 hash)
102104
: m_public_key(std::move(public_key))
103-
, m_timestamp(timestamp)
104-
, m_prev_beacon_txn_hash()
105+
, m_timestamp(timestamp),
106+
m_ctx_hash(hash)
107+
, m_prev_beacon_ctx_hash()
105108
{
106109
}
107110

@@ -169,7 +172,7 @@ bool Beacon::Renewable(const int64_t now) const
169172
bool Beacon::Renewed() const
170173
{
171174
// If not empty, the beacon was a renewal.
172-
return (m_prev_beacon_txn_hash != uint256());
175+
return (m_prev_beacon_ctx_hash != uint256());
173176
}
174177

175178
CKeyID Beacon::GetId() const
@@ -304,7 +307,7 @@ BeaconOption BeaconRegistry::Try(const Cpid& cpid) const
304307
return nullptr;
305308
}
306309

307-
return &iter->second;
310+
return iter->second;
308311
}
309312

310313
BeaconOption BeaconRegistry::TryActive(const Cpid& cpid, const int64_t now) const
@@ -363,18 +366,21 @@ void BeaconRegistry::Add(const ContractContext& ctx)
363366
{
364367
BeaconPayload payload = ctx->CopyPayloadAs<BeaconPayload>();
365368
payload.m_beacon.m_timestamp = ctx.m_tx.nTime;
369+
payload.m_beacon.m_ctx_hash = ctx.m_tx.GetHash();
370+
payload.m_beacon.m_prev_beacon_ctx_hash = uint256 {};
366371

367372
// Legacy beacon contracts before block version 11--just load the beacon:
368373
//
369374
if (ctx->m_version == 1) {
370-
m_beacons[payload.m_cpid] = std::move(payload.m_beacon);
375+
m_historical[ctx.m_tx.GetHash()] = std::move(payload.m_beacon);
376+
m_beacons[payload.m_cpid] = std::make_shared<Beacon>(m_historical[ctx.m_tx.GetHash()]);
371377
return;
372378
}
373379

374380
// For beacon renewals, check that the new beacon contains the same public
375381
// key. If it matches, we don't need to verify it again:
376382
//
377-
if (TryRenewal(m_beacons, m_historical, payload, ctx.m_tx.GetHash())) {
383+
if (TryRenewal(m_beacons, m_historical, payload)) {
378384
return;
379385
}
380386

@@ -384,6 +390,8 @@ void BeaconRegistry::Add(const ContractContext& ctx)
384390
PendingBeacon pending(payload.m_cpid, std::move(payload.m_beacon));
385391

386392
m_pending.emplace(pending.GetId(), std::move(pending));
393+
394+
// Note that pending beacons do not get added to the historical map.
387395
}
388396

389397
void BeaconRegistry::Delete(const ContractContext& ctx)
@@ -395,6 +403,7 @@ void BeaconRegistry::Delete(const ContractContext& ctx)
395403
}
396404

397405
m_beacons.erase(payload->m_cpid);
406+
m_historical.erase(ctx.m_tx.GetHash());
398407
}
399408

400409
bool BeaconRegistry::Validate(const Contract& contract, const CTransaction& tx) const
@@ -466,15 +475,18 @@ void BeaconRegistry::ActivatePending(
466475
const std::vector<uint160>& beacon_ids,
467476
const int64_t superblock_time)
468477
{
478+
// Activate the pending beacons that are not expired with respect to pending age.
469479
for (const auto& id : beacon_ids) {
470480
auto iter_pair = m_pending.find(id);
471481

472482
if (iter_pair != m_pending.end()) {
473-
m_beacons[iter_pair->second.m_cpid] = std::move(iter_pair->second);
483+
m_historical.emplace(std::make_pair(iter_pair->second.m_ctx_hash, iter_pair->second));
484+
m_beacons[iter_pair->second.m_cpid] = std::make_shared<Beacon>(m_historical[iter_pair->second.m_ctx_hash]);
474485
m_pending.erase(iter_pair);
475486
}
476487
}
477488

489+
// Discard pending beacons that are expired with respect to pending age.
478490
for (auto iter = m_pending.begin(); iter != m_pending.end(); /* no-op */) {
479491
if (iter->second.Expired(superblock_time)) {
480492
iter = m_pending.erase(iter);
@@ -487,10 +499,10 @@ void BeaconRegistry::ActivatePending(
487499
void BeaconRegistry::Deactivate(const int64_t superblock_time)
488500
{
489501
for (auto iter = m_beacons.begin(); iter != m_beacons.end(); /* no-op */) {
490-
if (iter->second.m_timestamp >= superblock_time) {
491-
PendingBeacon pending(iter->first, std::move(iter->second));
502+
if (iter->second->m_timestamp >= superblock_time) {
503+
PendingBeacon pending(iter->first, *iter->second);
492504
m_pending.emplace(pending.GetId(), std::move(pending));
493-
505+
m_historical.erase(iter->second->m_ctx_hash);
494506
iter = m_beacons.erase(iter);
495507
} else {
496508
++iter;

src/gridcoin/beacon.h

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "gridcoin/cpid.h"
1212
#include "serialize.h"
1313

14+
#include <memory>
1415
#include <string>
1516
#include <vector>
1617

@@ -66,14 +67,16 @@ class Beacon
6667
static constexpr int64_t RENEWAL_AGE = 60 * 60 * 24 * 30 * 5;
6768

6869
CPubKey m_public_key; //!< Verifies blocks that claim research rewards.
69-
int64_t m_timestamp; //!< Time of the the beacon contract transaction.
70+
int64_t m_timestamp; //!< Time of the beacon contract transaction.
71+
72+
uint256 m_ctx_hash; //!< The hash of the transaction that advertised the beacon.
7073

7174
// The reason the transaction hash is included here instead of a pointer
7275
// to the previous beacon, is that given the limited lookback scope, the
7376
// previous beacon may not be in the map. This makes the linked list harder
7477
// to deal with, but relieves us of dealing with the leading edge of the
7578
// lookback window.
76-
uint256 m_prev_beacon_txn_hash; //!< If a renewal contains the txn hash of the previous beacon.
79+
uint256 m_prev_beacon_ctx_hash; //!< If a renewal contains the txn hash of the previous beacon.
7780

7881
//!
7982
//! \brief Initialize an empty, invalid beacon instance.
@@ -93,7 +96,7 @@ class Beacon
9396
//! \param public_key Used to verify blocks that claim research rewards.
9497
//! \param tx_timestamp Time of the transaction with the beacon contract.
9598
//!
96-
Beacon(CPubKey public_key, int64_t tx_timestamp);
99+
Beacon(CPubKey public_key, int64_t tx_timestamp, uint256 hash);
97100

98101
//!
99102
//! \brief Initialize a beacon instance from a contract that contains beacon
@@ -209,9 +212,14 @@ class Beacon
209212
};
210213

211214
//!
212-
//! \brief A type that either points to to some beacon or does not.
215+
//! \brief The type that defines a shared pointer to a Beacon
216+
//!
217+
typedef std::shared_ptr<Beacon> Beacon_ptr;
218+
219+
//!
220+
//! \brief A type that either points to some beacon or does not.
213221
//!
214-
typedef const Beacon* BeaconOption;
222+
typedef const Beacon_ptr BeaconOption;
215223

216224
//!
217225
//! \brief The body of a beacon contract advertised in a transaction.
@@ -393,6 +401,8 @@ class PendingBeacon : public Beacon
393401

394402
Cpid m_cpid; // Identifies the researcher that advertised the beacon.
395403

404+
// There is no previous transaction hash here because renewed beacons are never
405+
// pending.
396406
//!
397407
//! \brief Initialize a pending beacon.
398408
//!
@@ -421,7 +431,7 @@ class BeaconRegistry : public IContractHandler
421431
//!
422432
//! \brief The type that associates beacons with CPIDs in the registry.
423433
//!
424-
typedef std::unordered_map<Cpid, Beacon> BeaconMap;
434+
typedef std::unordered_map<Cpid, Beacon_ptr> BeaconMap;
425435

426436
//!
427437
//! \brief The type that associates historical beacons with the ctx hash.

src/gridcoin/scraper/scraper.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ const CBlockIndex* GetBeaconConsensusHeight()
204204
BeaconConsensus GetConsensusBeaconList()
205205
{
206206
BeaconConsensus consensus;
207-
std::vector<std::pair<Cpid, Beacon>> beacons;
207+
std::vector<std::pair<Cpid, Beacon_ptr>> beacon_ptrs;
208208
std::vector<std::pair<CKeyID, PendingBeacon>> pending_beacons;
209209
int64_t max_time;
210210

@@ -223,16 +223,16 @@ BeaconConsensus GetConsensusBeaconList()
223223
// Copy the set of beacons out of the registry so we can release the
224224
// lock on cs_main before stringifying them:
225225
//
226-
beacons.reserve(beacon_map.size());
227-
beacons.assign(beacon_map.begin(), beacon_map.end());
226+
beacon_ptrs.reserve(beacon_map.size());
227+
beacon_ptrs.assign(beacon_map.begin(), beacon_map.end());
228228
pending_beacons.reserve(pending_beacon_map.size());
229229
pending_beacons.assign(pending_beacon_map.begin(), pending_beacon_map.end());
230230
}
231231

232-
for (const auto& beacon_pair : beacons)
232+
for (const auto& beacon_pair : beacon_ptrs)
233233
{
234234
const Cpid& cpid = beacon_pair.first;
235-
const Beacon& beacon = beacon_pair.second;
235+
const Beacon& beacon = *beacon_pair.second;
236236

237237
if (beacon.Expired(max_time) || beacon.m_timestamp >= max_time)
238238
{
@@ -3926,8 +3926,8 @@ bool IsScraperMaximumManifestPublishingRateExceeded(int64_t& nTime, CPubKey& Pub
39263926
nAvgTimeBetweenManifests = nTotalTime / nIntervals;
39273927

39283928
// nScraperSleep is in milliseconds. If the average interval is less than 25% of nScraperSleep in seconds, ban the scraper.
3929-
// Note that this is at least a factor of 12 faster than the expected rate given usual project update velocity.
3930-
if (nAvgTimeBetweenManifests < nScraperSleep / 4000)
3929+
// Note that this is a factor of 24 faster than the expected rate given usual project update velocity.
3930+
if (nAvgTimeBetweenManifests < nScraperSleep / 8000)
39313931
{
39323932
_log(logattribute::CRITICAL, "IsScraperMaximumManifestPublishingRateExceeded", "Scraper " + sManifestAddress +
39333933
" has published too many manifests in too short a time:\n" +

src/gridcoin/tally.cpp

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1034,25 +1034,25 @@ CAmount Tally::GetNewbieSuperblockAccrualCorrection(const Cpid& cpid, const Supe
10341034

10351035
LogPrint(BCLog::LogFlags::ACCRUAL, "INFO %s: beacon registry size = %u", __func__, beacons.Beacons().size());
10361036

1037-
if (beacon)
1037+
// Bail if there is no active beacon.
1038+
if (!beacon)
10381039
{
1039-
// Walk back the entries in the historical beacon map linked by renewal prev tx hash until the first
1040-
// beacon in the renewal chain is found (the original advertisement). The accrual starts no earlier
1041-
// than here.
1042-
while (beacon->Renewed())
1043-
{
1044-
beacon = &beacons.HistoricalBeacons().find(beacon->m_prev_beacon_txn_hash)->second;
1045-
}
1046-
}
1047-
else
1048-
{
1049-
10501040
LogPrint(BCLog::LogFlags::ACCRUAL, "ERROR: %s: No active beacon for cpid %s.",
10511041
__func__, cpid.ToString());
10521042

10531043
return accrual;
10541044
}
10551045

1046+
Beacon_ptr beacon_ptr = beacon;
1047+
1048+
// Walk back the entries in the historical beacon map linked by renewal prev tx hash until the first
1049+
// beacon in the renewal chain is found (the original advertisement). The accrual starts no earlier
1050+
// than here.
1051+
while (beacon_ptr->Renewed())
1052+
{
1053+
beacon_ptr = std::make_shared<Beacon>(beacons.HistoricalBeacons().find(beacon->m_prev_beacon_ctx_hash)->second);
1054+
}
1055+
10561056
const CBlockIndex* pindex_baseline = GRC::Tally::GetBaseline();
10571057

10581058
// Start at the tip.

src/rpc/blockchain.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -745,25 +745,25 @@ UniValue beaconreport(const UniValue& params, bool fHelp)
745745

746746
UniValue results(UniValue::VARR);
747747

748-
std::vector<std::pair<GRC::Cpid, GRC::Beacon>> active_beacons;
748+
std::vector<std::pair<GRC::Cpid, GRC::Beacon_ptr>> active_beacon_ptrs;
749749

750750
// Minimize the lock on cs_main.
751751
{
752752
LOCK(cs_main);
753753

754754
const auto& beacon_map = GRC::GetBeaconRegistry().Beacons();
755755

756-
active_beacons.reserve(beacon_map.size());
757-
active_beacons.assign(beacon_map.begin(), beacon_map.end());
756+
active_beacon_ptrs.reserve(beacon_map.size());
757+
active_beacon_ptrs.assign(beacon_map.begin(), beacon_map.end());
758758
}
759759

760-
for (const auto& beacon_pair : active_beacons)
760+
for (const auto& beacon_pair : active_beacon_ptrs)
761761
{
762762
UniValue entry(UniValue::VOBJ);
763763

764764
entry.pushKV("cpid", beacon_pair.first.ToString());
765-
entry.pushKV("address", beacon_pair.second.GetAddress().ToString());
766-
entry.pushKV("timestamp", beacon_pair.second.m_timestamp);
765+
entry.pushKV("address", beacon_pair.second->GetAddress().ToString());
766+
entry.pushKV("timestamp", beacon_pair.second->m_timestamp);
767767

768768
results.push_back(entry);
769769
}

0 commit comments

Comments
 (0)