From 9d5ce4d1616d598a27e9ad4931ab49cd0bf77e5d Mon Sep 17 00:00:00 2001 From: "James C. Owens" Date: Sun, 20 Oct 2024 17:25:12 -0400 Subject: [PATCH] Introduce changeable magnitude weight factors for polling --- src/gridcoin/protocol.cpp | 30 ++++++++++++++++++++++++++++++ src/gridcoin/protocol.h | 11 +++++++++++ src/gridcoin/voting/result.cpp | 23 +++++++++++++++++++++++ src/test/util_tests.cpp | 12 ++++++++++++ src/util.h | 16 ++++++++++++++++ 5 files changed, 92 insertions(+) diff --git a/src/gridcoin/protocol.cpp b/src/gridcoin/protocol.cpp index bd32a6838d..0a23f3cacf 100644 --- a/src/gridcoin/protocol.cpp +++ b/src/gridcoin/protocol.cpp @@ -291,6 +291,36 @@ 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 (iter == m_protocol_entries.end()) { + return nullptr; + } + + // If the latest (current) protocol entry has a timestamp before or equal to the provided timestamp then + // return the latest entry. + if (iter->second->m_timestamp <= timestamp) { + return iter->second; + } + + // Walk the revision history chain for the protocol entries with the provided key to find a 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_timestamp > timestamp) + { + hist_protocol_entry_iter = m_protocol_db.find(hist_protocol_entry_iter->second->m_previous_hash); + } + + return hist_protocol_entry_iter->second; +} + void ProtocolRegistry::Reset() { LOCK(cs_lock); diff --git a/src/gridcoin/protocol.h b/src/gridcoin/protocol.h index 3e8f400e17..022c149598 100644 --- a/src/gridcoin/protocol.h +++ b/src/gridcoin/protocol.h @@ -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 diff --git a/src/gridcoin/voting/result.cpp b/src/gridcoin/voting/result.cpp index 962cf21303..35ada03c00 100644 --- a/src/gridcoin/voting/result.cpp +++ b/src/gridcoin/voting/result.cpp @@ -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" @@ -1133,6 +1134,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 // ----------------------------------------------------------------------------- diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp index 1aeccd2785..1c22fb1f26 100755 --- a/src/test/util_tests.cpp +++ b/src/test/util_tests.cpp @@ -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); diff --git a/src/util.h b/src/util.h index b51db0661f..a1cf95490c 100644 --- a/src/util.h +++ b/src/util.h @@ -340,6 +340,22 @@ class Fraction { return strprintf("%" PRId64 "/" "%" PRId64, m_numerator, m_denominator); } + Fraction FromString(const std::string& string) const + { + std::vector 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();