Skip to content

Commit

Permalink
Introduce changeable magnitude weight factors for polling
Browse files Browse the repository at this point in the history
  • Loading branch information
jamescowens committed Oct 21, 2024
1 parent db7edad commit 7fc6d49
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 3 deletions.
38 changes: 38 additions & 0 deletions src/gridcoin/protocol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,44 @@ ProtocolEntryOption ProtocolRegistry::TryActive(const std::string& key) const
return nullptr;
}

ProtocolEntryOption ProtocolRegistry::TryByTimestamp(const std::string& key, const int64_t& timestamp)
{
LOCK(cs_lock);

// Find the latest protocol entry by key if it exists.
const auto iter = m_protocol_entries.find(key);

// If there is no entry, return nullptr. If there is no current entry, then there is also no historical entry for the same
// key.
if (iter == m_protocol_entries.end()) {
return nullptr;
}

// If the latest (current) active protocol entry for the given key has a timestamp before or equal to the provided timestamp then
// return the latest entry.
if (iter->second->m_timestamp <= timestamp && iter->second->m_status == ProtocolEntryStatus::ACTIVE) {
return iter->second;
}

// Walk the revision history chain for the protocol entries with the provided key to find an active historical entry
// with a timestamp that is equal to or less than the provided timestamp, if it exists.
auto hist_protocol_entry_iter = m_protocol_db.find(iter->second->m_previous_hash);

while (hist_protocol_entry_iter != m_protocol_db.end()
&& !hist_protocol_entry_iter->second->m_previous_hash.IsNull()
&& (hist_protocol_entry_iter->second->m_timestamp > timestamp
|| hist_protocol_entry_iter->second->m_status != ProtocolEntryStatus::ACTIVE))
{
hist_protocol_entry_iter = m_protocol_db.find(hist_protocol_entry_iter->second->m_previous_hash);
}

if (hist_protocol_entry_iter == m_protocol_db.end()) {
return nullptr;
}

return hist_protocol_entry_iter->second;
}

void ProtocolRegistry::Reset()
{
LOCK(cs_lock);
Expand Down
11 changes: 11 additions & 0 deletions src/gridcoin/protocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,17 @@ class ProtocolRegistry : public IContractHandler
//!
ProtocolEntryOption TryActive(const std::string& key) const;

//!
//! \brief Get the last protocol entry for the specified key string at or before the specified timestamp
//!
//! \param key The key string of the protocol entry.
//! \param timestamp The desired timestamp to limit the find.
//!
//! \return An object that either contains a reference to some protocol entry if it exists
//! for the key at or before the provided timestamp or does not.
//!
ProtocolEntryOption TryByTimestamp(const std::string& key, const int64_t& timestamp);

//!
//! \brief Destroy the contract handler state in case of an error in loading
//! the protocol entry registry state from LevelDB to prepare for reload from contract
Expand Down
32 changes: 29 additions & 3 deletions src/gridcoin/voting/result.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or https://opensource.org/licenses/mit-license.php.

#include "gridcoin/protocol.h"
#include "main.h"
#include "gridcoin/beacon.h"
#include "gridcoin/quorum.h"
Expand Down Expand Up @@ -787,7 +788,7 @@ class VoteCounter
//! \param supply The total network money supply as of the latest
//! block in the poll window in units of 1/100000000 GRC.
//!
void EnableMagnitudeWeight(SuperblockPtr superblock, const uint64_t supply)
void EnableMagnitudeWeight(SuperblockPtr superblock, const uint64_t supply, const Fraction magnitude_weight_factor)
{
const uint64_t total_mag = superblock->m_cpids.TotalMagnitude();

Expand All @@ -796,7 +797,9 @@ class VoteCounter
}

// Use integer arithmetic to avoid floating-point discrepancies:
m_magnitude_factor = supply / total_mag * 100 / 567;
m_magnitude_factor = supply / total_mag
* (uint64_t) magnitude_weight_factor.GetNumerator()
/ (uint64_t) magnitude_weight_factor.GetDenominator();
m_resolver.SetSuperblock(std::move(superblock));
}

Expand Down Expand Up @@ -1133,6 +1136,28 @@ CAmount ResolveMoneySupplyForPoll(const Poll& poll)

return pindex->nMoneySupply;
}

//!
//! \brief Fetch the applicable magnitude factor for the poll. This is the magnitude factor of the last entry in the
//! protocol registry database that has a timestamp at or before the poll start timestamp.
//!
//! \param poll Poll for which to fetch the Magnitude Weight Factor.
//! \return Fraction Magnitude factor expressed as a Fraction.
//!
Fraction ResolveMagnitudeWeightFactorForPoll(const Poll& poll)
{
Fraction magnitude_weight_factor = Params().GetConsensus().DefaultMagnitudeWeightFactor;

// Find the current protocol entry value for Magnitude Weight Factor, if it exists.
ProtocolEntryOption protocol_entry = GetProtocolRegistry().TryByTimestamp("magnitudeweightfactor", poll.m_timestamp);

if (protocol_entry != nullptr) {
magnitude_weight_factor = Fraction().FromString(protocol_entry->m_value);
}

return magnitude_weight_factor;
}

} // Anonymous namespace

// -----------------------------------------------------------------------------
Expand Down Expand Up @@ -1186,7 +1211,8 @@ PollResultOption PollResult::BuildFor(const PollReference& poll_ref)
if (result.m_poll.IncludesMagnitudeWeight()) {
counter.EnableMagnitudeWeight(
ResolveSuperblockForPoll(result.m_poll),
ResolveMoneySupplyForPoll(result.m_poll));
ResolveMoneySupplyForPoll(result.m_poll),
ResolveMagnitudeWeightFactorForPoll(result.m_poll));
}

LogPrint(BCLog::LogFlags::VOTE, "INFO: %s: number of votes = %u for poll %s",
Expand Down
12 changes: 12 additions & 0 deletions src/test/util_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1326,6 +1326,18 @@ BOOST_AUTO_TEST_CASE(util_Fraction_Initialization_from_int64_t)
BOOST_CHECK_EQUAL(fraction.IsNonNegative(), false);
}

BOOST_AUTO_TEST_CASE(util_Fraction_Initialization_from_string)
{
Fraction fraction = Fraction().FromString("100/-567");

BOOST_CHECK_EQUAL(fraction.GetNumerator(), -100);
BOOST_CHECK_EQUAL(fraction.GetDenominator(), 567);
BOOST_CHECK_EQUAL(fraction.IsSimplified(), true);
BOOST_CHECK_EQUAL(fraction.IsZero(), false);
BOOST_CHECK_EQUAL(fraction.IsPositive(), false);
BOOST_CHECK_EQUAL(fraction.IsNonNegative(), false);
}

BOOST_AUTO_TEST_CASE(util_Fraction_Simplify)
{
Fraction fraction(-4, -6);
Expand Down
16 changes: 16 additions & 0 deletions src/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,22 @@ class Fraction {
return strprintf("%" PRId64 "/" "%" PRId64, m_numerator, m_denominator);
}

Fraction FromString(const std::string& string) const
{
std::vector<std::string> string_fraction = split(string, "/");

int64_t numerator;
int64_t denominator;

if (string_fraction.size() != 2
|| !ParseInt64(string_fraction[0], &numerator)
|| !ParseInt64(string_fraction[1], &denominator)) {
throw std::out_of_range("Fraction input string cannot be parsed to fraction.");
}

return Fraction(numerator, denominator, true);
}

bool operator!()
{
return IsZero();
Expand Down

0 comments on commit 7fc6d49

Please sign in to comment.