1616#include < primitives/block.h>
1717#include < script/standard.h>
1818#include < tinyformat.h>
19- #include < validation.h>
2019
2120#include < cassert>
2221#include < ranges>
@@ -30,20 +29,88 @@ CAmount PlatformShare(const CAmount reward)
3029 return platformReward;
3130}
3231
32+ CAmount GetMasternodePayment (int nHeight, CAmount blockValue, const Consensus::Params& consensus_params, MnRewardEra era)
33+ {
34+ CAmount ret = blockValue/5 ; // start at 20%
35+
36+ const int nMNPIBlock = consensus_params.nMasternodePaymentsIncreaseBlock ;
37+ const int nMNPIPeriod = consensus_params.nMasternodePaymentsIncreasePeriod ;
38+ const int nReallocActivationHeight = consensus_params.BRRHeight ;
39+
40+ // mainnet:
41+ if (nHeight > nMNPIBlock) ret += blockValue / 20 ; // 158000 - 25.0% - 2014-10-24
42+ if (nHeight > nMNPIBlock+(nMNPIPeriod* 1 )) ret += blockValue / 20 ; // 175280 - 30.0% - 2014-11-25
43+ if (nHeight > nMNPIBlock+(nMNPIPeriod* 2 )) ret += blockValue / 20 ; // 192560 - 35.0% - 2014-12-26
44+ if (nHeight > nMNPIBlock+(nMNPIPeriod* 3 )) ret += blockValue / 40 ; // 209840 - 37.5% - 2015-01-26
45+ if (nHeight > nMNPIBlock+(nMNPIPeriod* 4 )) ret += blockValue / 40 ; // 227120 - 40.0% - 2015-02-27
46+ if (nHeight > nMNPIBlock+(nMNPIPeriod* 5 )) ret += blockValue / 40 ; // 244400 - 42.5% - 2015-03-30
47+ if (nHeight > nMNPIBlock+(nMNPIPeriod* 6 )) ret += blockValue / 40 ; // 261680 - 45.0% - 2015-05-01
48+ if (nHeight > nMNPIBlock+(nMNPIPeriod* 7 )) ret += blockValue / 40 ; // 278960 - 47.5% - 2015-06-01
49+ if (nHeight > nMNPIBlock+(nMNPIPeriod* 9 )) ret += blockValue / 40 ; // 313520 - 50.0% - 2015-08-03
50+
51+ if (nHeight < nReallocActivationHeight) {
52+ // Block Reward Realocation is not activated yet, nothing to do
53+ return ret;
54+ }
55+
56+ int nSuperblockCycle = consensus_params.nSuperblockCycle ;
57+ // Actual realocation starts in the cycle next to one activation happens in
58+ int nReallocStart = nReallocActivationHeight - nReallocActivationHeight % nSuperblockCycle + nSuperblockCycle;
59+
60+ if (nHeight < nReallocStart) {
61+ // Activated but we have to wait for the next cycle to start realocation, nothing to do
62+ return ret;
63+ }
64+
65+ if (era != MnRewardEra::Classic) {
66+ // Once MNRewardReallocated activates, block reward is 80% of block subsidy (+ tx fees) since treasury is 20%
67+ // Since the MN reward needs to be equal to 60% of the block subsidy (according to the proposal), MN reward is set to 75% of the block reward.
68+ // Previous reallocation periods are dropped.
69+ return blockValue * 3 / 4 ;
70+ }
71+
72+ // Periods used to reallocate the masternode reward from 50% to 60%
73+ static std::vector<int > vecPeriods{
74+ 513 , // Period 1: 51.3%
75+ 526 , // Period 2: 52.6%
76+ 533 , // Period 3: 53.3%
77+ 540 , // Period 4: 54%
78+ 546 , // Period 5: 54.6%
79+ 552 , // Period 6: 55.2%
80+ 557 , // Period 7: 55.7%
81+ 562 , // Period 8: 56.2%
82+ 567 , // Period 9: 56.7%
83+ 572 , // Period 10: 57.2%
84+ 577 , // Period 11: 57.7%
85+ 582 , // Period 12: 58.2%
86+ 585 , // Period 13: 58.5%
87+ 588 , // Period 14: 58.8%
88+ 591 , // Period 15: 59.1%
89+ 594 , // Period 16: 59.4%
90+ 597 , // Period 17: 59.7%
91+ 599 , // Period 18: 59.9%
92+ 600 // Period 19: 60%
93+ };
94+
95+ int nReallocCycle = nSuperblockCycle * 3 ;
96+ int nCurrentPeriod = std::min<int >((nHeight - nReallocStart) / nReallocCycle, vecPeriods.size () - 1 );
97+
98+ return static_cast <CAmount>(blockValue * vecPeriods[nCurrentPeriod] / 1000 );
99+ }
100+
33101[[nodiscard]] bool CMNPaymentsProcessor::GetBlockTxOuts (const CBlockIndex* pindexPrev, const CAmount blockSubsidy, const CAmount feeReward,
34- std::vector<CTxOut>& voutMasternodePaymentsRet)
102+ MnRewardEra era, std::vector<CTxOut>& voutMasternodePaymentsRet)
35103{
36104 voutMasternodePaymentsRet.clear ();
37105
38106 const int nBlockHeight = pindexPrev == nullptr ? 0 : pindexPrev->nHeight + 1 ;
39107
40- bool fV20Active = DeploymentActiveAfter (pindexPrev, m_consensus_params, Consensus::DEPLOYMENT_V20 );
41- CAmount masternodeReward = GetMasternodePayment (nBlockHeight, blockSubsidy + feeReward, fV20Active );
108+ CAmount masternodeReward = GetMasternodePayment (nBlockHeight, blockSubsidy + feeReward, m_consensus_params, era);
42109
43110 // Credit Pool doesn't exist before V20. If any part of reward will re-allocated to credit pool before v20
44111 // activation these fund will be just permanently lost. Applicable for devnets, regtest, testnet
45- if (fV20Active && DeploymentActiveAfter (pindexPrev, m_consensus_params, Consensus:: DEPLOYMENT_MN_RR ) ) {
46- CAmount masternodeSubsidyReward = GetMasternodePayment (nBlockHeight, blockSubsidy, fV20Active );
112+ if (era == MnRewardEra::EvoReward ) {
113+ CAmount masternodeSubsidyReward = GetMasternodePayment (nBlockHeight, blockSubsidy, m_consensus_params, era );
47114 const CAmount platformReward = PlatformShare (masternodeSubsidyReward);
48115 masternodeReward -= platformReward;
49116
@@ -96,12 +163,12 @@ CAmount PlatformShare(const CAmount reward)
96163* Get masternode payment tx outputs
97164*/
98165[[nodiscard]] bool CMNPaymentsProcessor::GetMasternodeTxOuts (const CBlockIndex* pindexPrev, const CAmount blockSubsidy, const CAmount feeReward,
99- std::vector<CTxOut>& voutMasternodePaymentsRet)
166+ MnRewardEra era, std::vector<CTxOut>& voutMasternodePaymentsRet)
100167{
101168 // make sure it's not filled yet
102169 voutMasternodePaymentsRet.clear ();
103170
104- if (!GetBlockTxOuts (pindexPrev, blockSubsidy, feeReward, voutMasternodePaymentsRet)) {
171+ if (!GetBlockTxOuts (pindexPrev, blockSubsidy, feeReward, era, voutMasternodePaymentsRet)) {
105172 LogPrintf (" CMNPaymentsProcessor::%s -- ERROR Failed to get payee\n " , __func__);
106173 return false ;
107174 }
@@ -117,7 +184,7 @@ CAmount PlatformShare(const CAmount reward)
117184}
118185
119186[[nodiscard]] bool CMNPaymentsProcessor::IsTransactionValid (const CTransaction& txNew, const CBlockIndex* pindexPrev, const CAmount blockSubsidy,
120- const CAmount feeReward)
187+ const CAmount feeReward, MnRewardEra era )
121188{
122189 const int nBlockHeight = pindexPrev == nullptr ? 0 : pindexPrev->nHeight + 1 ;
123190 if (!DeploymentDIP0003Enforced (nBlockHeight, m_consensus_params)) {
@@ -126,7 +193,7 @@ CAmount PlatformShare(const CAmount reward)
126193 }
127194
128195 std::vector<CTxOut> voutMasternodePayments;
129- if (!GetBlockTxOuts (pindexPrev, blockSubsidy, feeReward, voutMasternodePayments)) {
196+ if (!GetBlockTxOuts (pindexPrev, blockSubsidy, feeReward, era, voutMasternodePayments)) {
130197 LogPrintf (" CMNPaymentsProcessor::%s -- ERROR! Failed to get payees for block at height %s\n " , __func__, nBlockHeight);
131198 return true ;
132199 }
@@ -193,7 +260,7 @@ CAmount PlatformShare(const CAmount reward)
193260* - Other blocks are 10% lower in outgoing value, so in total, no extra coins are created
194261* - When non-superblocks are detected, the normal schedule should be maintained
195262*/
196- bool CMNPaymentsProcessor::IsBlockValueValid (const CBlock& block, const CBlockIndex* pindexPrev, const CAmount blockReward, std::string& strErrorRet, const bool check_superblock)
263+ bool CMNPaymentsProcessor::IsBlockValueValid (const CChain& active_chain, const CBlock& block, const CBlockIndex* pindexPrev, const CAmount blockReward, std::string& strErrorRet, SuperBlockCheckType check_superblock)
197264{
198265 const int nBlockHeight = pindexPrev == nullptr ? 0 : pindexPrev->nHeight + 1 ;
199266 bool isBlockRewardValueMet = (block.vtx [0 ]->GetValueOut () <= blockReward);
@@ -214,7 +281,7 @@ bool CMNPaymentsProcessor::IsBlockValueValid(const CBlock& block, const CBlockIn
214281
215282 LogPrint (BCLog::MNPAYMENTS , " block.vtx[0]->GetValueOut() %lld <= blockReward %lld\n " , block.vtx [0 ]->GetValueOut (), blockReward);
216283
217- CAmount nSuperblockMaxValue = blockReward + CSuperblock::GetPaymentsLimit (m_chainman. ActiveChain () , nBlockHeight);
284+ CAmount nSuperblockMaxValue = blockReward + CSuperblock::GetPaymentsLimit (active_chain , nBlockHeight);
218285 bool isSuperblockMaxValueMet = (block.vtx [0 ]->GetValueOut () <= nSuperblockMaxValue);
219286
220287 LogPrint (BCLog::GOBJECT , " block.vtx[0]->GetValueOut() %lld <= nSuperblockMaxValue %lld\n " , block.vtx [0 ]->GetValueOut (), nSuperblockMaxValue);
@@ -242,7 +309,7 @@ bool CMNPaymentsProcessor::IsBlockValueValid(const CBlock& block, const CBlockIn
242309 return true ;
243310 }
244311
245- if (! check_superblock) return true ;
312+ if (check_superblock == SuperBlockCheckType::NoCheck ) return true ;
246313
247314 // we are synced and possibly on a superblock now
248315
@@ -259,8 +326,8 @@ bool CMNPaymentsProcessor::IsBlockValueValid(const CBlock& block, const CBlockIn
259326 }
260327
261328 // this actually also checks for correct payees and not only amount
262- const bool is_v24{DeploymentActiveAfter (pindexPrev, m_chainman, Consensus:: DEPLOYMENT_V24 ) };
263- if (!m_superblocks.IsValidSuperblock (m_chainman. ActiveChain () , tip_mn_list, *block.vtx [0 ], nBlockHeight, blockReward, is_v24)) {
329+ const bool is_v24{check_superblock == SuperBlockCheckType::DisallowDuplicates };
330+ if (!m_superblocks.IsValidSuperblock (active_chain , tip_mn_list, *block.vtx [0 ], nBlockHeight, blockReward, is_v24)) {
264331 // triggered but invalid? that's weird
265332 LogPrintf (" CMNPaymentsProcessor::%s -- ERROR! Invalid superblock detected at height %d: %s" , __func__, nBlockHeight, block.vtx [0 ]->ToString ()); /* Continued */
266333 // should NOT allow invalid superblocks, when superblocks are enabled
@@ -272,12 +339,12 @@ bool CMNPaymentsProcessor::IsBlockValueValid(const CBlock& block, const CBlockIn
272339 return true ;
273340}
274341
275- bool CMNPaymentsProcessor::IsBlockPayeeValid (const CTransaction& txNew, const CBlockIndex* pindexPrev, const CAmount blockSubsidy, const CAmount feeReward, const bool check_superblock)
342+ bool CMNPaymentsProcessor::IsBlockPayeeValid (const CChain& active_chain, const CTransaction& txNew, const CBlockIndex* pindexPrev, const CAmount blockSubsidy, const CAmount feeReward, MnRewardEra era, SuperBlockCheckType check_superblock)
276343{
277344 const int nBlockHeight = pindexPrev == nullptr ? 0 : pindexPrev->nHeight + 1 ;
278345
279346 // Check for correct masternode payment
280- if (IsTransactionValid (txNew, pindexPrev, blockSubsidy, feeReward)) {
347+ if (IsTransactionValid (txNew, pindexPrev, blockSubsidy, feeReward, era )) {
281348 LogPrint (BCLog::MNPAYMENTS , " CMNPaymentsProcessor::%s -- Valid masternode payment at height %d: %s" , __func__, nBlockHeight, txNew.ToString ()); /* Continued */
282349 } else {
283350 LogPrintf (" CMNPaymentsProcessor::%s -- ERROR! Invalid masternode payment detected at height %d: %s" , __func__, nBlockHeight, txNew.ToString ()); /* Continued */
@@ -301,12 +368,12 @@ bool CMNPaymentsProcessor::IsBlockPayeeValid(const CTransaction& txNew, const CB
301368 }
302369
303370 // superblocks started
304- if (! check_superblock) return true ;
371+ if (check_superblock == SuperBlockCheckType::NoCheck ) return true ;
305372
306373 const auto tip_mn_list = m_dmnman.GetListAtChainTip ();
307- const bool is_v24{DeploymentActiveAfter (pindexPrev, m_chainman, Consensus:: DEPLOYMENT_V24 ) };
374+ const bool is_v24{check_superblock == SuperBlockCheckType::DisallowDuplicates };
308375 if (m_superblocks.IsSuperblockTriggered (tip_mn_list, nBlockHeight)) {
309- if (m_superblocks.IsValidSuperblock (m_chainman. ActiveChain () , tip_mn_list, txNew, nBlockHeight,
376+ if (m_superblocks.IsValidSuperblock (active_chain , tip_mn_list, txNew, nBlockHeight,
310377 blockSubsidy + feeReward, is_v24)) {
311378 LogPrint (BCLog::GOBJECT , " CMNPaymentsProcessor::%s -- Valid superblock at height %d: %s" , /* Continued */
312379 __func__, nBlockHeight, txNew.ToString ());
@@ -325,7 +392,7 @@ bool CMNPaymentsProcessor::IsBlockPayeeValid(const CTransaction& txNew, const CB
325392}
326393
327394void CMNPaymentsProcessor::FillBlockPayments (CMutableTransaction& txNew, const CBlockIndex* pindexPrev, const CAmount blockSubsidy, const CAmount feeReward,
328- std::vector<CTxOut>& voutMasternodePaymentsRet, std::vector<CTxOut>& voutSuperblockPaymentsRet)
395+ MnRewardEra era, std::vector<CTxOut>& voutMasternodePaymentsRet, std::vector<CTxOut>& voutSuperblockPaymentsRet)
329396{
330397 int nBlockHeight = pindexPrev == nullptr ? 0 : pindexPrev->nHeight + 1 ;
331398
@@ -336,7 +403,7 @@ void CMNPaymentsProcessor::FillBlockPayments(CMutableTransaction& txNew, const C
336403 m_superblocks.GetSuperblockPayments (tip_mn_list, nBlockHeight, voutSuperblockPaymentsRet);
337404 }
338405
339- if (!GetMasternodeTxOuts (pindexPrev, blockSubsidy, feeReward, voutMasternodePaymentsRet)) {
406+ if (!GetMasternodeTxOuts (pindexPrev, blockSubsidy, feeReward, era, voutMasternodePaymentsRet)) {
340407 LogPrint (BCLog::MNPAYMENTS , " CMNPaymentsProcessor::%s -- No masternode to pay (MN list probably empty)\n " , __func__);
341408 }
342409
0 commit comments