Skip to content

Commit

Permalink
Implement GRC::GetAvgNetworkWeight
Browse files Browse the repository at this point in the history
This separates out the calculation of network weight from nBits
contained in GetActiveNetworkWeight and extends it to take a
starting and ending index to compute the average over an interval.
  • Loading branch information
jamescowens committed Oct 26, 2024
1 parent e71cec5 commit d848673
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 7 deletions.
56 changes: 56 additions & 0 deletions src/gridcoin/staking/difficulty.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,62 @@ double GRC::GetEstimatedNetworkWeight(unsigned int nPoSInterval)
return result;
}

uint64_t GRC::GetAvgNetworkWeight(CBlockIndex* index_start, CBlockIndex* index_end)
{
auto block_net_weight = [](CBlockIndex* index)
{
arith_uint256 target;

target.SetCompact(index->nBits);

return ~arith_uint256() / arith_uint256(450) / target * arith_uint256(COIN);
};

// These conditionals are ordered so that the no argument case quickly evaluates to the net weight of the current block.
if (index_end == nullptr) {
if (index_start == nullptr) {
return block_net_weight(pindexBest).GetLow64();
} else {
return block_net_weight(index_start).GetLow64();
}
} else {
if (index_start != nullptr) {
{
CBlockIndex* index;
arith_uint256 weight_sum;
unsigned int block_count;

// If we are here, both index_start and index_end are not nullptrs.

if (!index_start->IsInMainChain()) {
throw std::invalid_argument("Specified start index is not in main chain.");
}

if (!index_end->IsInMainChain()) {
throw std::invalid_argument("Specified end index is not in main chain.");
}

if (index_start->nHeight >= index_end-> nHeight) {
throw std::invalid_argument("End index if specified must be at a higher height than start index.");
}

for (index = index_start, block_count = 0; index != index_end; index = index->pnext, ++block_count)
{
weight_sum += block_net_weight(index);
}

// Get last block for inclusive interval
weight_sum += block_net_weight(index->pnext);
++block_count;

return (weight_sum / arith_uint256(block_count)).GetLow64();
}
} else {
throw std::invalid_argument("End index was specified with start index = nullptr.");
}
}
}

double GRC::GetEstimatedTimetoStake(bool ignore_staking_status, double dDiff, double dConfidence)
{
/*
Expand Down
19 changes: 19 additions & 0 deletions src/gridcoin/staking/difficulty.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#ifndef GRIDCOIN_STAKING_DIFFICULTY_H
#define GRIDCOIN_STAKING_DIFFICULTY_H

#include <cstdint>
class CBlockIndex;
class CWallet;
#include <cmath>
Expand All @@ -26,6 +27,24 @@ double GetSmoothedDifficulty(int64_t nStakeableBalance);

uint64_t GetStakeWeight(const CWallet& wallet);
double GetEstimatedNetworkWeight(unsigned int nPoSInterval = 40);

//!
//! \brief This returns the precise average network weight in units of Halfords as a 64 bit unsigned integer. The starting index
//! and the ending index are defaulted to nullptr if not provided. If neither is provided, the network weight for the current (best)
//! block will be returned. If only the starting index pointer is provided, the network weight of that block will be returned.
//! If both are provided, the network weight average will be returned over the interval of blocks inclusive of both start and end.
//! Both indexes, if specified, must be in the main chain.
//!
//! Please refer to https://gridcoin.us/assets/docs/grc-bluepaper-section-1.pdf equations 1 and 16 and footnote 5.
//! This method of computing net_weight is from first principles using the target from the nBits representation
//! recorded in the index, rather than the GetEstimatedNetworkWeight() function, which uses double fp arithmetic.
//!
//! \param index_start The CBlockIndex pointer to the starting index with which to take the average. Note that this is inclusive.
//! \param index_end The BClockIndex pointer to the ending index with which to take the average. Note that this is inclusive.
//!
//! \return uint64_t of the average network weight in Halford units.
//!
uint64_t GetAvgNetworkWeight(CBlockIndex* index_start = nullptr, CBlockIndex* index_end = nullptr);
double GetEstimatedTimetoStake(bool ignore_staking_status = false, double dDiff = 0.0, double dConfidence = DEFAULT_ETTS_CONFIDENCE);
} // namespace GRC

Expand Down
8 changes: 1 addition & 7 deletions src/gridcoin/voting/registry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -657,13 +657,7 @@ std::optional<CAmount> PollReference::GetActiveVoteWeight(const PollResultOption
}
}

// Please refer to https://gridcoin.us/assets/docs/grc-bluepaper-section-1.pdf equations 1 and 16 and footnote 5.
// This method of computing net_weight is from first principles using the target from the nBits representation
// recorded in the index, rather than the GetEstimatedNetworkWeight() function, which uses double fp arithmetic.
arith_uint256 target;
target.SetCompact(pindex->nBits);

arith_uint256 net_weight = ~arith_uint256() / arith_uint256(450) / target * arith_uint256(COIN);
arith_uint256 net_weight = GetAvgNetworkWeight(pindex);

arith_uint256 money_supply = pindex->nMoneySupply;

Expand Down

0 comments on commit d848673

Please sign in to comment.