diff --git a/src/bench/duplicate_inputs.cpp b/src/bench/duplicate_inputs.cpp index 4604789c5fc3..7e1a18c85ce2 100644 --- a/src/bench/duplicate_inputs.cpp +++ b/src/bench/duplicate_inputs.cpp @@ -38,7 +38,7 @@ static void DuplicateInputs(benchmark::Bench& bench) coinbaseTx.vin[0].prevout.SetNull(); coinbaseTx.vout.resize(1); coinbaseTx.vout[0].scriptPubKey = SCRIPT_PUB; - coinbaseTx.vout[0].nValue = GetBlockSubsidy(block.nBits, nHeight, chainparams.GetConsensus()); + coinbaseTx.vout[0].nValue = GetBlockSubsidyInner(block.nBits, nHeight, chainparams.GetConsensus()); coinbaseTx.vin[0].scriptSig = CScript() << nHeight << OP_0; naughtyTx.vout.resize(1); diff --git a/src/governance/classes.cpp b/src/governance/classes.cpp index 34a3e27294d8..e1e8023210dd 100644 --- a/src/governance/classes.cpp +++ b/src/governance/classes.cpp @@ -486,7 +486,7 @@ 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 nSuperblockPartOfSubsidy = GetBlockSubsidyInner(nBits, nBlockHeight - 1, consensusParams, true); CAmount nPaymentsLimit = nSuperblockPartOfSubsidy * consensusParams.nSuperblockCycle; LogPrint(BCLog::GOBJECT, "CSuperblock::GetPaymentsLimit -- Valid superblock height %d, payments max %lld\n", nBlockHeight, nPaymentsLimit); diff --git a/src/index/coinstatsindex.cpp b/src/index/coinstatsindex.cpp index 22330661329b..8321b7f17b2b 100644 --- a/src/index/coinstatsindex.cpp +++ b/src/index/coinstatsindex.cpp @@ -107,7 +107,7 @@ CoinStatsIndex::CoinStatsIndex(size_t n_cache_size, bool f_memory, bool f_wipe) bool CoinStatsIndex::WriteBlock(const CBlock& block, const CBlockIndex* pindex) { CBlockUndo block_undo; - const CAmount block_subsidy{pindex->nHeight > 0 ? GetBlockSubsidy(pindex->pprev->nBits, pindex->pprev->nHeight, Params().GetConsensus()) : Params().GenesisBlock().vtx[0]->GetValueOut()}; + const CAmount block_subsidy{GetBlockSubsidy(pindex, Params().GetConsensus())}; m_total_subsidy += block_subsidy; // Ignore genesis block @@ -394,7 +394,7 @@ bool CoinStatsIndex::ReverseBlock(const CBlock& block, const CBlockIndex* pindex CBlockUndo block_undo; std::pair read_out; - const CAmount block_subsidy{pindex->nHeight > 0 ? GetBlockSubsidy(pindex->pprev->nBits, pindex->pprev->nHeight, Params().GetConsensus()) : Params().GenesisBlock().vtx[0]->GetValueOut()}; + const CAmount block_subsidy{GetBlockSubsidy(pindex, Params().GetConsensus())}; m_total_subsidy -= block_subsidy; // Ignore genesis block diff --git a/src/miner.cpp b/src/miner.cpp index 208058230b2d..858d039fe40c 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -190,7 +190,7 @@ std::unique_ptr BlockAssembler::CreateNewBlock(const CScript& sc coinbaseTx.vout[0].scriptPubKey = scriptPubKeyIn; // NOTE: unlike in bitcoin, we need to pass PREVIOUS block height here - CAmount blockReward = nFees + GetBlockSubsidy(pindexPrev->nBits, pindexPrev->nHeight, Params().GetConsensus()); + CAmount blockReward = nFees + GetBlockSubsidyInner(pindexPrev->nBits, pindexPrev->nHeight, Params().GetConsensus()); // Compute regular coinbase transaction. coinbaseTx.vout[0].nValue = blockReward; diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index f24e968f240d..99c2766744af 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -2386,7 +2386,7 @@ static UniValue getblockstats(const JSONRPCRequest& request) ret_all.pushKV("minfeerate", (minfeerate == MAX_MONEY) ? 0 : minfeerate); ret_all.pushKV("mintxsize", mintxsize == MaxBlockSize() ? 0 : mintxsize); ret_all.pushKV("outs", outputs); - ret_all.pushKV("subsidy", pindex->pprev ? GetBlockSubsidy(pindex->pprev->nBits, pindex->pprev->nHeight, Params().GetConsensus()) : 50 * COIN); + ret_all.pushKV("subsidy", GetBlockSubsidy(pindex, Params().GetConsensus())); ret_all.pushKV("time", pindex->GetBlockTime()); ret_all.pushKV("total_out", total_out); ret_all.pushKV("total_size", total_size); diff --git a/src/rpc/masternode.cpp b/src/rpc/masternode.cpp index 63b89739420a..04adb54bebc2 100644 --- a/src/rpc/masternode.cpp +++ b/src/rpc/masternode.cpp @@ -459,7 +459,7 @@ static UniValue masternode_payments(const JSONRPCRequest& request, const Chainst std::vector voutMasternodePayments, voutDummy; CMutableTransaction dummyTx; - CAmount blockReward = nBlockFees + GetBlockSubsidy(pindex->pprev->nBits, pindex->pprev->nHeight, Params().GetConsensus()); + CAmount blockReward = nBlockFees + GetBlockSubsidy(pindex, Params().GetConsensus()); CMasternodePayments::FillBlockPayments(*sporkManager, *governance, dummyTx, pindex->nHeight, blockReward, voutMasternodePayments, voutDummy); UniValue blockObj(UniValue::VOBJ); diff --git a/src/test/block_reward_reallocation_tests.cpp b/src/test/block_reward_reallocation_tests.cpp index 0a209024cc38..13c20230b1df 100644 --- a/src/test/block_reward_reallocation_tests.cpp +++ b/src/test/block_reward_reallocation_tests.cpp @@ -201,7 +201,7 @@ BOOST_FIXTURE_TEST_CASE(block_reward_reallocation, TestChainBRRBeforeActivationS LOCK(cs_main); deterministicMNManager->UpdatedBlockTip(::ChainActive().Tip()); BOOST_ASSERT(deterministicMNManager->GetListAtChainTip().HasMN(tx.GetHash())); - auto masternode_payment = GetMasternodePayment(::ChainActive().Height(), GetBlockSubsidy(::ChainActive().Tip()->nBits, ::ChainActive().Height(), consensus_params), 2500); + auto masternode_payment = GetMasternodePayment(::ChainActive().Height(), GetBlockSubsidyInner(::ChainActive().Tip()->nBits, ::ChainActive().Height(), consensus_params), 2500); const auto pblocktemplate = BlockAssembler(*sporkManager, *governance, *m_node.llmq_ctx, *m_node.evodb, ::ChainstateActive(), *m_node.mempool, Params()).CreateNewBlock(coinbasePubKey); BOOST_CHECK_EQUAL(pblocktemplate->voutMasternodePayments[0].nValue, masternode_payment); } @@ -212,7 +212,7 @@ BOOST_FIXTURE_TEST_CASE(block_reward_reallocation, TestChainBRRBeforeActivationS { LOCK(cs_main); - auto masternode_payment = GetMasternodePayment(::ChainActive().Height(), GetBlockSubsidy(::ChainActive().Tip()->nBits, ::ChainActive().Height(), consensus_params), 2500); + auto masternode_payment = GetMasternodePayment(::ChainActive().Height(), GetBlockSubsidyInner(::ChainActive().Tip()->nBits, ::ChainActive().Height(), consensus_params), 2500); const auto pblocktemplate = BlockAssembler(*sporkManager, *governance, *m_node.llmq_ctx, *m_node.evodb, ::ChainstateActive(), *m_node.mempool, Params()).CreateNewBlock(coinbasePubKey); BOOST_CHECK_EQUAL(pblocktemplate->block.vtx[0]->GetValueOut(), 13748571607); BOOST_CHECK_EQUAL(pblocktemplate->voutMasternodePayments[0].nValue, masternode_payment); @@ -227,7 +227,7 @@ BOOST_FIXTURE_TEST_CASE(block_reward_reallocation, TestChainBRRBeforeActivationS CreateAndProcessBlock({}, coinbaseKey); } LOCK(cs_main); - auto masternode_payment = GetMasternodePayment(::ChainActive().Height(), GetBlockSubsidy(::ChainActive().Tip()->nBits, ::ChainActive().Height(), consensus_params), 2500); + auto masternode_payment = GetMasternodePayment(::ChainActive().Height(), GetBlockSubsidyInner(::ChainActive().Tip()->nBits, ::ChainActive().Height(), consensus_params), 2500); const auto pblocktemplate = BlockAssembler(*sporkManager, *governance, *m_node.llmq_ctx, *m_node.evodb, ::ChainstateActive(), *m_node.mempool, Params()).CreateNewBlock(coinbasePubKey); BOOST_CHECK_EQUAL(pblocktemplate->voutMasternodePayments[0].nValue, masternode_payment); } @@ -236,7 +236,7 @@ BOOST_FIXTURE_TEST_CASE(block_reward_reallocation, TestChainBRRBeforeActivationS { // Reward split should reach ~60/40 after reallocation is done LOCK(cs_main); - auto masternode_payment = GetMasternodePayment(::ChainActive().Height(), GetBlockSubsidy(::ChainActive().Tip()->nBits, ::ChainActive().Height(), consensus_params), 2500); + auto masternode_payment = GetMasternodePayment(::ChainActive().Height(), GetBlockSubsidyInner(::ChainActive().Tip()->nBits, ::ChainActive().Height(), consensus_params), 2500); const auto pblocktemplate = BlockAssembler(*sporkManager, *governance, *m_node.llmq_ctx, *m_node.evodb, ::ChainstateActive(), *m_node.mempool, Params()).CreateNewBlock(coinbasePubKey); BOOST_CHECK_EQUAL(pblocktemplate->block.vtx[0]->GetValueOut(), 10221599170); BOOST_CHECK_EQUAL(pblocktemplate->voutMasternodePayments[0].nValue, masternode_payment); @@ -250,7 +250,7 @@ BOOST_FIXTURE_TEST_CASE(block_reward_reallocation, TestChainBRRBeforeActivationS CreateAndProcessBlock({}, coinbaseKey); } LOCK(cs_main); - auto masternode_payment = GetMasternodePayment(::ChainActive().Height(), GetBlockSubsidy(::ChainActive().Tip()->nBits, ::ChainActive().Height(), consensus_params), 2500); + auto masternode_payment = GetMasternodePayment(::ChainActive().Height(), GetBlockSubsidyInner(::ChainActive().Tip()->nBits, ::ChainActive().Height(), consensus_params), 2500); const auto pblocktemplate = BlockAssembler(*sporkManager, *governance, *m_node.llmq_ctx, *m_node.evodb, ::ChainstateActive(), *m_node.mempool, Params()).CreateNewBlock(coinbasePubKey); BOOST_CHECK_EQUAL(pblocktemplate->voutMasternodePayments[0].nValue, masternode_payment); } @@ -258,7 +258,7 @@ BOOST_FIXTURE_TEST_CASE(block_reward_reallocation, TestChainBRRBeforeActivationS { // Reward split should reach ~60/40 after reallocation is done LOCK(cs_main); - auto masternode_payment = GetMasternodePayment(::ChainActive().Height(), GetBlockSubsidy(::ChainActive().Tip()->nBits, ::ChainActive().Height(), consensus_params), 2500); + auto masternode_payment = GetMasternodePayment(::ChainActive().Height(), GetBlockSubsidyInner(::ChainActive().Tip()->nBits, ::ChainActive().Height(), consensus_params), 2500); const auto pblocktemplate = BlockAssembler(*sporkManager, *governance, *m_node.llmq_ctx, *m_node.evodb, ::ChainstateActive(), *m_node.mempool, Params()).CreateNewBlock(coinbasePubKey); BOOST_CHECK_EQUAL(pblocktemplate->block.vtx[0]->GetValueOut(), 9491484944); BOOST_CHECK_EQUAL(pblocktemplate->voutMasternodePayments[0].nValue, masternode_payment); diff --git a/src/test/subsidy_tests.cpp b/src/test/subsidy_tests.cpp index b29cea8130db..08d9456a9131 100644 --- a/src/test/subsidy_tests.cpp +++ b/src/test/subsidy_tests.cpp @@ -22,43 +22,43 @@ BOOST_AUTO_TEST_CASE(block_subsidy_test) // details for block 4249 (subsidy returned will be for block 4250) nPrevBits = 0x1c4a47c4; nPrevHeight = 4249; - nSubsidy = GetBlockSubsidy(nPrevBits, nPrevHeight, chainParams->GetConsensus(), false); + nSubsidy = GetBlockSubsidyInner(nPrevBits, nPrevHeight, chainParams->GetConsensus(), false); BOOST_CHECK_EQUAL(nSubsidy, 50000000000ULL); // details for block 4501 (subsidy returned will be for block 4502) nPrevBits = 0x1c4a47c4; nPrevHeight = 4501; - nSubsidy = GetBlockSubsidy(nPrevBits, nPrevHeight, chainParams->GetConsensus(), false); + nSubsidy = GetBlockSubsidyInner(nPrevBits, nPrevHeight, chainParams->GetConsensus(), false); BOOST_CHECK_EQUAL(nSubsidy, 5600000000ULL); // details for block 5464 (subsidy returned will be for block 5465) nPrevBits = 0x1c29ec00; nPrevHeight = 5464; - nSubsidy = GetBlockSubsidy(nPrevBits, nPrevHeight, chainParams->GetConsensus(), false); + nSubsidy = GetBlockSubsidyInner(nPrevBits, nPrevHeight, chainParams->GetConsensus(), false); BOOST_CHECK_EQUAL(nSubsidy, 2100000000ULL); // details for block 5465 (subsidy returned will be for block 5466) nPrevBits = 0x1c29ec00; nPrevHeight = 5465; - nSubsidy = GetBlockSubsidy(nPrevBits, nPrevHeight, chainParams->GetConsensus(), false); + nSubsidy = GetBlockSubsidyInner(nPrevBits, nPrevHeight, chainParams->GetConsensus(), false); BOOST_CHECK_EQUAL(nSubsidy, 12200000000ULL); // details for block 17588 (subsidy returned will be for block 17589) nPrevBits = 0x1c08ba34; nPrevHeight = 17588; - nSubsidy = GetBlockSubsidy(nPrevBits, nPrevHeight, chainParams->GetConsensus(), false); + nSubsidy = GetBlockSubsidyInner(nPrevBits, nPrevHeight, chainParams->GetConsensus(), false); BOOST_CHECK_EQUAL(nSubsidy, 6100000000ULL); // details for block 99999 (subsidy returned will be for block 100000) nPrevBits = 0x1b10cf42; nPrevHeight = 99999; - nSubsidy = GetBlockSubsidy(nPrevBits, nPrevHeight, chainParams->GetConsensus(), false); + nSubsidy = GetBlockSubsidyInner(nPrevBits, nPrevHeight, chainParams->GetConsensus(), false); BOOST_CHECK_EQUAL(nSubsidy, 500000000ULL); // details for block 210239 (subsidy returned will be for block 210240) nPrevBits = 0x1b11548e; nPrevHeight = 210239; - nSubsidy = GetBlockSubsidy(nPrevBits, nPrevHeight, chainParams->GetConsensus(), false); + nSubsidy = GetBlockSubsidyInner(nPrevBits, nPrevHeight, chainParams->GetConsensus(), false); BOOST_CHECK_EQUAL(nSubsidy, 500000000ULL); // 1st subsidy reduction happens here @@ -66,7 +66,7 @@ BOOST_AUTO_TEST_CASE(block_subsidy_test) // details for block 210240 (subsidy returned will be for block 210241) nPrevBits = 0x1b10d50b; nPrevHeight = 210240; - nSubsidy = GetBlockSubsidy(nPrevBits, nPrevHeight, chainParams->GetConsensus(), false); + nSubsidy = GetBlockSubsidyInner(nPrevBits, nPrevHeight, chainParams->GetConsensus(), false); BOOST_CHECK_EQUAL(nSubsidy, 464285715ULL); } diff --git a/src/validation.cpp b/src/validation.cpp index 0c39f31dd2c6..5bc1e91996a2 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -1113,7 +1113,7 @@ NOTE: unlike bitcoin we are using PREVIOUS block height here, might be a good idea to change this to use prev bits but current height to avoid confusion. */ -CAmount GetBlockSubsidy(int nPrevBits, int nPrevHeight, const Consensus::Params& consensusParams, bool fSuperblockPartOnly) +CAmount GetBlockSubsidyInner(int nPrevBits, int nPrevHeight, const Consensus::Params& consensusParams, bool fSuperblockPartOnly) { double dDiff; CAmount nSubsidyBase; @@ -1163,6 +1163,12 @@ CAmount GetBlockSubsidy(int nPrevBits, int nPrevHeight, const Consensus::Params& return fSuperblockPartOnly ? nSuperblockPart : nSubsidy - nSuperblockPart; } +CAmount GetBlockSubsidy(const CBlockIndex* const pindex, const Consensus::Params& consensusParams) +{ + if (pindex->pprev == nullptr) return Params().GenesisBlock().vtx[0]->GetValueOut(); + return GetBlockSubsidyInner(pindex->pprev->nBits, pindex->pprev->nHeight, consensusParams); +} + CAmount GetMasternodePayment(int nHeight, CAmount blockValue, int nReallocActivationHeight) { CAmount ret = blockValue/5; // start at 20% @@ -2401,7 +2407,7 @@ bool CChainState::ConnectBlock(const CBlock& block, BlockValidationState& state, // DASH : MODIFIED TO CHECK MASTERNODE PAYMENTS AND SUPERBLOCKS // TODO: resync data (both ways?) and try to reprocess this block later. - CAmount blockReward = nFees + GetBlockSubsidy(pindex->pprev->nBits, pindex->pprev->nHeight, m_params.GetConsensus()); + CAmount blockReward = nFees + GetBlockSubsidy(pindex, m_params.GetConsensus()); std::string strError = ""; int64_t nTime5_2 = GetTimeMicros(); nTimeSubsidy += nTime5_2 - nTime5_1; diff --git a/src/validation.h b/src/validation.h index 518954a20bb9..37de5260a8eb 100644 --- a/src/validation.h +++ b/src/validation.h @@ -206,7 +206,15 @@ void StopScriptCheckWorkerThreads(); CTransactionRef GetTransaction(const CBlockIndex* const block_index, const CTxMemPool* const mempool, const uint256& hash, const Consensus::Params& consensusParams, uint256& hashBlock); double ConvertBitsToDouble(unsigned int nBits); -CAmount GetBlockSubsidy(int nBits, int nHeight, const Consensus::Params& consensusParams, bool fSuperblockPartOnly = false); +/** + * Due to difference in logic, the GetBlockSubsidy() has also different list of + * arguments. + * + * When pindex points to a genesis block GetBlockSubsidy() returns a pre-calculated value. + * For other blocks it calls GetBlockSubsidyInner() using nBits and nHeight of a pindex->pprev block. + */ +CAmount GetBlockSubsidyInner(int nPrevBits, int nPrevHeight, const Consensus::Params& consensusParams, bool fSuperblockPartOnly = false); +CAmount GetBlockSubsidy(const CBlockIndex* const pindex, const Consensus::Params& consensusParams); CAmount GetMasternodePayment(int nHeight, CAmount blockValue, int nReallocActivationHeight = std::numeric_limits::max() /* not activated */); /** Guess verification progress (as a fraction between 0.0=genesis and 1.0=current tip). */