diff --git a/src/governance-classes.cpp b/src/governance-classes.cpp index e21232fa6252d..2378a1f2bef25 100644 --- a/src/governance-classes.cpp +++ b/src/governance-classes.cpp @@ -547,8 +547,48 @@ CAmount CSuperblock::GetPaymentsLimit(int nBlockHeight) // min subsidy for high diff networks and vice versa int nBits = consensusParams.fPowAllowMinDifficultyBlocks ? UintToArith256(consensusParams.powLimit).GetCompact() : 1; // some part of all blocks issued during the cycle goes to superblock, see GetBlockSubsidy - CAmount nSuperblockPartOfSubsidy = GetBlockSubsidy(nBits, nBlockHeight - 1, consensusParams, true); - CAmount nPaymentsLimit = nSuperblockPartOfSubsidy * consensusParams.nSuperblockCycle; + LOCK(cs_main); + + CCoinsView *view = (CCoinsView*)pcoinsdbview; + std::unique_ptr pcursor(view->Cursor()); + + + uint256 prevkey; + std::map outputs; + while (pcursor->Valid()) { + boost::this_thread::interruption_point(); + COutPoint key; + Coin coin; + if (pcursor->GetKey(key) && pcursor->GetValue(coin)) { + if (!outputs.empty() && key.hash != prevkey) { + outputs.clear(); + } + prevkey = key.hash; + outputs[key.n] = std::move(coin); + } + else { + return error("%s: unable to read value", __func__); + } + pcursor->Next(); + } + + // Current supply + CAmount nCirculatingSupply = 0; + for (const auto output : outputs) { + nCirculatingSupply += output.second.out.nValue; + } + + // Theoretical Maximum Supply at given block + CAmount nMaxSupply = 0; + for (auto it = 0; it < nBlockHeight; it++) { + + // Get CBlockIndex pointer based on iterator + CBlockIndex *pblock = chainActive[it]; + + // Add to the Max Supply the subsidy at each block + nMaxSupply += GetCompleteBlockSubsidy(pblock->pprev->nBits, pblock->pprev->nHeight, Params().GetConsensus); + } + CAmount nPaymentsLimit = nMaxSupply - nCirculatingSupply; LogPrint("gobject", "CSuperblock::GetPaymentsLimit -- Valid superblock height %d, payments max %lld\n", nBlockHeight, nPaymentsLimit); return nPaymentsLimit; diff --git a/src/masternode-payments.cpp b/src/masternode-payments.cpp index 03b2b7d51f3b5..49bb80a27c119 100644 --- a/src/masternode-payments.cpp +++ b/src/masternode-payments.cpp @@ -84,20 +84,20 @@ bool IsBlockValueValid(const CBlock& block, int nBlockHeight, CAmount blockRewar bool isBlockRewardValueMet = (block.vtx[0]->GetValueOut() <= blockReward); if(fDebug) LogPrintf("block.vtx[0]->GetValueOut() %lld <= blockReward %lld\n", block.vtx[0]->GetValueOut(), blockReward); - CAmount nSuperblockMaxValue = blockReward + CSuperblock::GetPaymentsLimit(nBlockHeight); - bool isSuperblockMaxValueMet = (block.vtx[0]->GetValueOut() <= nSuperblockMaxValue); - - LogPrint("gobject", "block.vtx[0]->GetValueOut() %lld <= nSuperblockMaxValue %lld\n", block.vtx[0]->GetValueOut(), nSuperblockMaxValue); - if (!CSuperblock::IsValidBlockHeight(nBlockHeight)) { // can't possibly be a superblock, so lets just check for block reward limits if (!isBlockRewardValueMet) { strErrorRet = strprintf("coinbase pays too much at height %d (actual=%d vs limit=%d), exceeded block reward, only regular blocks are allowed at this height", - nBlockHeight, block.vtx[0]->GetValueOut(), blockReward); + nBlockHeight, block.vtx[0]->GetValueOut(), blockReward); } return isBlockRewardValueMet; } + CAmount nSuperblockMaxValue = blockReward + CSuperblock::GetPaymentsLimit(nBlockHeight); + bool isSuperblockMaxValueMet = (block.vtx[0]->GetValueOut() <= nSuperblockMaxValue); + + LogPrint("gobject", "block.vtx[0]->GetValueOut() %lld <= nSuperblockMaxValue %lld\n", block.vtx[0]->GetValueOut(), nSuperblockMaxValue); + // bail out in case superblock limits were exceeded if (!isSuperblockMaxValueMet) { strErrorRet = strprintf("coinbase pays too much at height %d (actual=%d vs limit=%d), exceeded superblock max value", diff --git a/src/validation.cpp b/src/validation.cpp index c38b84a6c326e..ed5ef59edab8a 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -1318,6 +1318,18 @@ NOTE: unlike bitcoin we are using PREVIOUS block height here, but current height to avoid confusion. */ CAmount GetBlockSubsidy(int nPrevBits, int nPrevHeight, const Consensus::Params& consensusParams, bool fSuperblockPartOnly) +{ + + CAmount nSubsidy = GetCompleteBlockSubsidy(nPrevBits, nPrevHeight, consensusParams); + + // Hard fork to reduce the block reward by 10 extra percent (allowing budget/superblocks) + CAmount nSuperblockPart = (nPrevHeight > consensusParams.nBudgetPaymentsStartBlock) ? nSubsidy / 10 : 0; + + return fSuperblockPartOnly ? nSuperblockPart : nSubsidy - nSuperblockPart; +} + +// Returns the total subsidy, includes the miners, masternodes and treasury +CAmount GetCompleteBlockSubsidy(int nPrevBits, int nPrevHeight, const Consensus::Params& consensusParams) { double dDiff; CAmount nSubsidyBase; @@ -1325,28 +1337,31 @@ CAmount GetBlockSubsidy(int nPrevBits, int nPrevHeight, const Consensus::Params& if (nPrevHeight <= 4500 && Params().NetworkIDString() == CBaseChainParams::MAIN) { /* a bug which caused diff to not be correctly calculated */ dDiff = (double)0x0000ffff / (double)(nPrevBits & 0x00ffffff); - } else { + } + else { dDiff = ConvertBitsToDouble(nPrevBits); } if (nPrevHeight < 5465) { // Early ages... // 1111/((x+1)^2) - nSubsidyBase = (1111.0 / (pow((dDiff+1.0),2.0))); - if(nSubsidyBase > 500) nSubsidyBase = 500; - else if(nSubsidyBase < 1) nSubsidyBase = 1; - } else if (nPrevHeight < 17000 || (dDiff <= 75 && nPrevHeight < 24000)) { + nSubsidyBase = (1111.0 / (pow((dDiff + 1.0), 2.0))); + if (nSubsidyBase > 500) nSubsidyBase = 500; + else if (nSubsidyBase < 1) nSubsidyBase = 1; + } + else if (nPrevHeight < 17000 || (dDiff <= 75 && nPrevHeight < 24000)) { // CPU mining era // 11111/(((x+51)/6)^2) - nSubsidyBase = (11111.0 / (pow((dDiff+51.0)/6.0,2.0))); - if(nSubsidyBase > 500) nSubsidyBase = 500; - else if(nSubsidyBase < 25) nSubsidyBase = 25; - } else { + nSubsidyBase = (11111.0 / (pow((dDiff + 51.0) / 6.0, 2.0))); + if (nSubsidyBase > 500) nSubsidyBase = 500; + else if (nSubsidyBase < 25) nSubsidyBase = 25; + } + else { // GPU/ASIC mining era // 2222222/(((x+2600)/9)^2) - nSubsidyBase = (2222222.0 / (pow((dDiff+2600.0)/9.0,2.0))); - if(nSubsidyBase > 25) nSubsidyBase = 25; - else if(nSubsidyBase < 5) nSubsidyBase = 5; + nSubsidyBase = (2222222.0 / (pow((dDiff + 2600.0) / 9.0, 2.0))); + if (nSubsidyBase > 25) nSubsidyBase = 25; + else if (nSubsidyBase < 5) nSubsidyBase = 5; } // LogPrintf("height %u diff %4.2f reward %d\n", nPrevHeight, dDiff, nSubsidyBase); @@ -1354,13 +1369,10 @@ CAmount GetBlockSubsidy(int nPrevBits, int nPrevHeight, const Consensus::Params& // yearly decline of production by ~7.1% per year, projected ~18M coins max by year 2050+. for (int i = consensusParams.nSubsidyHalvingInterval; i <= nPrevHeight; i += consensusParams.nSubsidyHalvingInterval) { - nSubsidy -= nSubsidy/14; + nSubsidy -= nSubsidy / 14; } - // Hard fork to reduce the block reward by 10 extra percent (allowing budget/superblocks) - CAmount nSuperblockPart = (nPrevHeight > consensusParams.nBudgetPaymentsStartBlock) ? nSubsidy/10 : 0; - - return fSuperblockPartOnly ? nSuperblockPart : nSubsidy - nSuperblockPart; + return nSubsidy; } CAmount GetMasternodePayment(int nHeight, CAmount blockValue) diff --git a/src/validation.h b/src/validation.h index 8c45bbb4e2f3a..f226bda70c103 100644 --- a/src/validation.h +++ b/src/validation.h @@ -292,6 +292,7 @@ bool ActivateBestChain(CValidationState& state, const CChainParams& chainparams, double ConvertBitsToDouble(unsigned int nBits); CAmount GetBlockSubsidy(int nBits, int nHeight, const Consensus::Params& consensusParams, bool fSuperblockPartOnly = false); +CAmount GetCompleteBlockSubsidy(int nPrevBits, int nPrevHeight, const Consensus::Params& consensusParams); CAmount GetMasternodePayment(int nHeight, CAmount blockValue); /** Guess verification progress (as a fraction between 0.0=genesis and 1.0=current tip). */