Skip to content

polls, voting, staking: Enhance voting consensus rules to allow for changeable magnitude weight factor and enhance CBR #2781

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
7e6ffec
Add several parameters to blockchain consensus
jamescowens Oct 22, 2024
46bcae4
Extend fraction class to construct from string
jamescowens Oct 22, 2024
f397bd2
Add TryLastBeforeTimestamp to Protocol Registry
jamescowens Oct 22, 2024
2ad8bca
Rewrite GRC::GetConstantBlockReward
jamescowens Oct 22, 2024
ec333ad
Introduce changeable magnitude weight factors for polling
jamescowens Oct 22, 2024
68b98f3
Additional changes to wire in magnitude weight factor
jamescowens Oct 23, 2024
9e3684c
Fix for AVW not correct with modified magnitude weight factor
jamescowens Oct 24, 2024
efea824
Change WaitMessage() to PollWaitMessage()
jamescowens Oct 24, 2024
5096b9c
Document overflow analysis for magnitude weight factor as fraction
jamescowens Oct 25, 2024
6eff430
Ensure ResolveMagnitudeWeightFactor returns Fraction(100, 567) prior …
jamescowens Oct 25, 2024
3dbbc21
Implement GRC::GetAvgNetworkWeight
jamescowens Oct 26, 2024
60362bd
Add thread safety keywords to difficulty functions
jamescowens Oct 27, 2024
9b8c8fd
Fix segmentation fault in GetMagnitudeWeightFactor
jamescowens Oct 27, 2024
0684b30
Ensure GetActiveNetworkWeight behavior is correct for all poll weight…
jamescowens Oct 27, 2024
2221ae0
Implement protocol entry changeable magnitude unit
jamescowens Dec 16, 2024
367ee55
Correct contract version for protocol contracts for block V13+
jamescowens Dec 16, 2024
838482e
Remove hardcoded accrual limit in UI warning tooltip
jamescowens Dec 18, 2024
a4bab8f
Enhance Fraction class FromString() and add tests
jamescowens Dec 28, 2024
4c765d4
Add MaxMagnitudeUnit to chain parameters
jamescowens Dec 28, 2024
ef683fc
Enforce MaxMagnitudeUnit clamp in GetMagnitudeUnit()
jamescowens Dec 28, 2024
c16bc50
Adjust CBR ceiling to 500 GRC.
jamescowens Feb 15, 2025
4f93788
Enforce clamp on MagnitudeWeightFactor
jamescowens Apr 8, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Enforce MaxMagnitudeUnit clamp in GetMagnitudeUnit()
Also implement 256 bit integer arithmetic in ComputeMRCFee() as an
overflow fallback.
  • Loading branch information
jamescowens committed Apr 8, 2025
commit ef683fc6517737846fca52f1ddc435eb741e63c7
52 changes: 29 additions & 23 deletions src/gridcoin/accrual/snapshot.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,20 +32,6 @@ namespace {
using namespace GRC;
using LogFlags = BCLog::LogFlags;

/*
//!
//! \brief Numerator of the static magnitude unit coefficient for snapshot
//! accrual (block version 11 and greater).
//!
constexpr int64_t MAG_UNIT_NUMERATOR = 1;

//!
//! \brief Denominator of the static magnitude unit coefficient for snapshot
//! accrual (block version 11 and greater).
//!
constexpr int64_t MAG_UNIT_DENOMINATOR = 4;
*/

//!
//! \brief Calculates the current accrual for a CPID by adding the snapshot of
//! accrued research rewards of the CPID's research account to rewards accrued
Expand Down Expand Up @@ -77,13 +63,14 @@ class SnapshotCalculator
//!
Allocation GetMagnitudeUnit() const
{
Allocation magnitude_unit = Params().GetConsensus().DefaultMagnitudeUnit;

// Before V13 magnitude unit is 1/4.
// Fern+ and before V13 magnitude unit is fixed at 1/4.
if (!IsV13Enabled(m_superblock.m_height)) {
return Allocation(1, 4);
}

Allocation magnitude_unit = Params().GetConsensus().DefaultMagnitudeUnit;
Allocation max_magnitude_unit = Params().GetConsensus().MaxMagnitudeUnit;

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

Expand All @@ -93,6 +80,15 @@ class SnapshotCalculator
magnitude_unit = Fraction().FromString(protocol_entry->m_value);
}

// Clamp to MaxMagnitudeUnit if necessary
if (magnitude_unit > max_magnitude_unit) {
magnitude_unit = max_magnitude_unit;
LogPrintf("WARN: %s: Magnitude Unit specified by protocol is greater than %s. Clamping to %s.",
__func__,
max_magnitude_unit.ToString(),
max_magnitude_unit.ToString());
}

return magnitude_unit;
}

Expand All @@ -107,22 +103,32 @@ class SnapshotCalculator
{
CBlockIndex* sb_index = BlockFinder::FindLatestSuperblock(index);

Allocation magnitude_unit = Params().GetConsensus().DefaultMagnitudeUnit;

// Before V13 magnitude unit is 1/4.
// Before V13 magnitude unit is 1/4.
if (!IsV13Enabled(sb_index->nHeight)) {
return Allocation(1, 4);
}

// Find the current protocol entry value for Magnitude Weight Factor, if it exists.
Allocation magnitude_unit = Params().GetConsensus().DefaultMagnitudeUnit;
Allocation max_magnitude_unit = Params().GetConsensus().MaxMagnitudeUnit;

// Find the current protocol entry value for Magnitude Weight Factor, if it exists.
ProtocolEntryOption protocol_entry = GetProtocolRegistry().TryLastBeforeTimestamp("magnitudeunit", sb_index->GetBlockTime());

// If their is an entry prior or equal in timestamp to the superblock and it is active then set the magnitude unit
// to that value. If the last entry is not active (i.e. deleted), then leave at the default.
// If their is an entry prior or equal in timestamp to the superblock and it is active then set the magnitude unit
// to that value. If the last entry is not active (i.e. deleted), then leave at the default.
if (protocol_entry != nullptr && protocol_entry->m_status == ProtocolEntryStatus::ACTIVE) {
magnitude_unit = Fraction().FromString(protocol_entry->m_value);
}

// Clamp to MaxMagnitudeUnit if necessary
if (magnitude_unit > max_magnitude_unit) {
magnitude_unit = max_magnitude_unit;
LogPrintf("WARN: %s: Magnitude Unit specified by protocol is greater than %s. Clamping to %s.",
__func__,
max_magnitude_unit.ToString(),
max_magnitude_unit.ToString());
}

return magnitude_unit;
}

Expand Down
28 changes: 21 additions & 7 deletions src/gridcoin/mrc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -204,13 +204,27 @@ CAmount MRC::ComputeMRCFee() const
//
// If the MRC is exactly at the end of the zero_payout_interval, the fees are effectively
// fee_fraction * m_research_subsidy.
//
// Overflow analysis. The accrual limit in the snapshot computer is 16384. For a zero_payout_interval of 14 days,
// m_research_subsidy * zero_payout_interval = 19818086400. std::numeric_limits<int64_t>::max() / 19818086400
// = 465401747207, which means the numerator of the fee_fraction would have to be that number or higher to cause an
// overflow of the below. This is not likely to happen for any reasonable choice of the fee_fraction.
fee = m_research_subsidy * zero_payout_interval * fee_fraction.GetNumerator()
/ mrc_payment_interval / fee_fraction.GetDenominator();

// To accommodate V13+ blocks which can have much larger magnitude units (up to 5), we have changed the fee calculation
// to switch to 256 bit integer calculations if necessary similar to what is in AccrualDelta(). The rationale for the overflow
// test is as follows. The m_research_subsidy converted back to GRC (which divides by 100,000,000 and therefore rounds down) + 1
// to get the equivalent of rounding up, then multipled by the zero_payout_interval and the fee_fraction numerator is checked
// against the max numeric limit of CAmount divided by 100,000,000. If it is greater than this, then 256 bit integer arithmetic
// is used else the original calculation is used.
CAmount overflow_test = (m_research_subsidy / COIN + 1) * zero_payout_interval * fee_fraction.GetNumerator();

if (overflow_test > std::numeric_limits<CAmount>::max() / COIN) {
arith_uint256 fee_bn = m_research_subsidy;
fee_bn *= zero_payout_interval;
fee_bn *= fee_fraction.GetNumerator();
fee_bn /= mrc_payment_interval;
fee_bn /= fee_fraction.GetDenominator();

fee = fee_bn.GetLow64();
} else {
fee = m_research_subsidy * zero_payout_interval * fee_fraction.GetNumerator()
/ mrc_payment_interval / fee_fraction.GetDenominator();
}

return fee;
}
Expand Down