mirror of
https://github.com/dashpay/dash.git
synced 2024-12-25 03:52:49 +01:00
Merge pull request #5342 from knst/reward-reallocation
This commit is contained in:
commit
bc6360f6aa
@ -7,9 +7,8 @@
|
||||
#include <evo/assetlocktx.h>
|
||||
#include <evo/cbtx.h>
|
||||
|
||||
#include <llmq/utils.h>
|
||||
|
||||
#include <chain.h>
|
||||
#include <llmq/utils.h>
|
||||
#include <logging.h>
|
||||
#include <validation.h>
|
||||
#include <node/blockstorage.h>
|
||||
@ -19,6 +18,11 @@
|
||||
#include <memory>
|
||||
#include <stack>
|
||||
|
||||
// Forward declaration to prevent a new circular dependencies through masternode/payments.h
|
||||
namespace MasternodePayments {
|
||||
CAmount PlatformShare(const CAmount masternodeReward);
|
||||
} // namespace MasternodePayments
|
||||
|
||||
static const std::string DB_CREDITPOOL_SNAPSHOT = "cpm_S";
|
||||
|
||||
std::unique_ptr<CCreditPoolManager> creditPoolManager;
|
||||
@ -213,11 +217,17 @@ CCreditPoolManager::CCreditPoolManager(CEvoDB& _evoDb)
|
||||
|
||||
CCreditPoolDiff::CCreditPoolDiff(CCreditPool starter, const CBlockIndex *pindex, const Consensus::Params& consensusParams) :
|
||||
pool(std::move(starter)),
|
||||
pindex(pindex)
|
||||
pindex(pindex),
|
||||
params(consensusParams)
|
||||
{
|
||||
assert(pindex);
|
||||
}
|
||||
|
||||
void CCreditPoolDiff::AddRewardRealloced(const CAmount reward) {
|
||||
assert(MoneyRange(reward));
|
||||
platformReward += reward;
|
||||
}
|
||||
|
||||
bool CCreditPoolDiff::SetTarget(const CTransaction& tx, TxValidationState& state)
|
||||
{
|
||||
CCbTx cbTx;
|
||||
@ -225,9 +235,20 @@ bool CCreditPoolDiff::SetTarget(const CTransaction& tx, TxValidationState& state
|
||||
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-cbtx-payload");
|
||||
}
|
||||
|
||||
if (cbTx.nVersion == 3) {
|
||||
targetBalance = cbTx.creditPoolBalance;
|
||||
if (cbTx.nVersion != 3) return true;
|
||||
|
||||
targetBalance = cbTx.creditPoolBalance;
|
||||
|
||||
|
||||
if (!llmq::utils::IsMNRewardReallocationActive(pindex)) return true;
|
||||
|
||||
CAmount blockReward = 0;
|
||||
for (const CTxOut& txout : tx.vout) {
|
||||
blockReward += txout.nValue;
|
||||
}
|
||||
platformReward = MasternodePayments::PlatformShare(GetMasternodePayment(cbTx.nHeight, blockReward, params.BRRHeight));
|
||||
LogPrintf("CreditPool: set target to %lld with MN reward %lld\n", *targetBalance, platformReward);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -67,11 +67,13 @@ private:
|
||||
|
||||
CAmount sessionLocked{0};
|
||||
CAmount sessionUnlocked{0};
|
||||
CAmount platformReward{0};
|
||||
|
||||
// target value is used to validate CbTx. If values mismatched, block is invalid
|
||||
std::optional<CAmount> targetBalance;
|
||||
|
||||
const CBlockIndex *pindex{nullptr};
|
||||
const Consensus::Params& params;
|
||||
public:
|
||||
explicit CCreditPoolDiff(CCreditPool starter, const CBlockIndex *pindex, const Consensus::Params& consensusParams);
|
||||
|
||||
@ -82,8 +84,13 @@ public:
|
||||
*/
|
||||
bool ProcessTransaction(const CTransaction& tx, TxValidationState& state);
|
||||
|
||||
/**
|
||||
* This function should be called by miner for initialization of MasterNode reward
|
||||
*/
|
||||
void AddRewardRealloced(const CAmount reward);
|
||||
|
||||
CAmount GetTotalLocked() const {
|
||||
return pool.locked + sessionLocked - sessionUnlocked;
|
||||
return pool.locked + sessionLocked - sessionUnlocked + platformReward;
|
||||
}
|
||||
|
||||
const std::optional<CAmount>& GetTargetBalance() const {
|
||||
|
@ -728,6 +728,7 @@ bool IsMNRewardReallocationActive(const CBlockIndex* pindex)
|
||||
{
|
||||
assert(pindex);
|
||||
if (!IsV20Active(pindex)) return false;
|
||||
if (Params().NetworkIDString() == CBaseChainParams::TESTNET) return IsV20Active(pindex); // TODO remove this before re-hardforking testnet to check EHF
|
||||
|
||||
LOCK(cs_llmq_vbc);
|
||||
return VersionBitsState(pindex, Params().GetConsensus(), Consensus::DEPLOYMENT_MN_RR, llmq_versionbitscache) == ThresholdState::ACTIVE;
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include <governance/governance.h>
|
||||
#include <key_io.h>
|
||||
#include <logging.h>
|
||||
#include <llmq/utils.h>
|
||||
#include <masternode/sync.h>
|
||||
#include <primitives/block.h>
|
||||
#include <script/standard.h>
|
||||
@ -20,26 +21,34 @@
|
||||
#include <util/system.h>
|
||||
#include <validation.h>
|
||||
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
|
||||
/**
|
||||
* GetMasternodeTxOuts
|
||||
*
|
||||
* Get masternode payment tx outputs
|
||||
*/
|
||||
|
||||
static bool GetBlockTxOuts(const int nBlockHeight, const CAmount blockReward, std::vector<CTxOut>& voutMasternodePaymentsRet)
|
||||
[[nodiscard]] static bool GetBlockTxOuts(const int nBlockHeight, const CAmount blockReward, std::vector<CTxOut>& voutMasternodePaymentsRet)
|
||||
{
|
||||
voutMasternodePaymentsRet.clear();
|
||||
|
||||
CAmount masternodeReward = GetMasternodePayment(nBlockHeight, blockReward, Params().GetConsensus().BRRHeight);
|
||||
|
||||
const CBlockIndex* pindex = WITH_LOCK(cs_main, return ::ChainActive()[nBlockHeight - 1]);
|
||||
bool fMNRewardReallocated = llmq::utils::IsMNRewardReallocationActive(pindex);
|
||||
|
||||
if (fMNRewardReallocated) {
|
||||
const CAmount platformReward = MasternodePayments::PlatformShare(masternodeReward);
|
||||
masternodeReward -= platformReward;
|
||||
|
||||
assert(MoneyRange(masternodeReward));
|
||||
|
||||
LogPrint(BCLog::MNPAYMENTS, "CMasternodePayments::%s -- MN reward %lld reallocated to credit pool\n", __func__, platformReward);
|
||||
voutMasternodePaymentsRet.emplace_back(platformReward, CScript() << OP_RETURN);
|
||||
}
|
||||
|
||||
auto dmnPayee = deterministicMNManager->GetListForBlock(pindex).GetMNPayee(pindex);
|
||||
if (!dmnPayee) {
|
||||
return false;
|
||||
}
|
||||
|
||||
CAmount operatorReward = 0;
|
||||
CAmount masternodeReward = GetMasternodePayment(nBlockHeight, blockReward, Params().GetConsensus().BRRHeight);
|
||||
|
||||
if (dmnPayee->nOperatorReward != 0 && dmnPayee->pdmnState->scriptOperatorPayout != CScript()) {
|
||||
// This calculation might eventually turn out to result in 0 even if an operator reward percentage is given.
|
||||
@ -59,13 +68,18 @@ static bool GetBlockTxOuts(const int nBlockHeight, const CAmount blockReward, st
|
||||
}
|
||||
|
||||
|
||||
static bool GetMasternodeTxOuts(const int nBlockHeight, const CAmount blockReward, std::vector<CTxOut>& voutMasternodePaymentsRet)
|
||||
/**
|
||||
* GetMasternodeTxOuts
|
||||
*
|
||||
* Get masternode payment tx outputs
|
||||
*/
|
||||
[[nodiscard]] static bool GetMasternodeTxOuts(const int nBlockHeight, const CAmount blockReward, std::vector<CTxOut>& voutMasternodePaymentsRet)
|
||||
{
|
||||
// make sure it's not filled yet
|
||||
voutMasternodePaymentsRet.clear();
|
||||
|
||||
if(!GetBlockTxOuts(nBlockHeight, blockReward, voutMasternodePaymentsRet)) {
|
||||
LogPrintf("CMasternodePayments::%s -- no payee (deterministic masternode list empty)\n", __func__);
|
||||
LogPrintf("MasternodePayments::%s -- no payee (deterministic masternode list empty)\n", __func__);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -73,13 +87,13 @@ static bool GetMasternodeTxOuts(const int nBlockHeight, const CAmount blockRewar
|
||||
CTxDestination dest;
|
||||
ExtractDestination(txout.scriptPubKey, dest);
|
||||
|
||||
LogPrintf("CMasternodePayments::%s -- Masternode payment %lld to %s\n", __func__, txout.nValue, EncodeDestination(dest));
|
||||
LogPrintf("MasternodePayments::%s -- Masternode payment %lld to %s\n", __func__, txout.nValue, EncodeDestination(dest));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool IsTransactionValid(const CTransaction& txNew, const int nBlockHeight, const CAmount blockReward)
|
||||
[[nodiscard]] static bool IsTransactionValid(const CTransaction& txNew, const int nBlockHeight, const CAmount blockReward)
|
||||
{
|
||||
if (!deterministicMNManager->IsDIP3Enforced(nBlockHeight)) {
|
||||
// can't verify historical blocks here
|
||||
@ -88,7 +102,7 @@ static bool IsTransactionValid(const CTransaction& txNew, const int nBlockHeight
|
||||
|
||||
std::vector<CTxOut> voutMasternodePayments;
|
||||
if (!GetBlockTxOuts(nBlockHeight, blockReward, voutMasternodePayments)) {
|
||||
LogPrintf("CMasternodePayments::%s -- ERROR failed to get payees for block at height %s\n", __func__, nBlockHeight);
|
||||
LogPrintf("MasternodePayments::%s -- ERROR failed to get payees for block at height %s\n", __func__, nBlockHeight);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -98,7 +112,7 @@ static bool IsTransactionValid(const CTransaction& txNew, const int nBlockHeight
|
||||
CTxDestination dest;
|
||||
if (!ExtractDestination(txout.scriptPubKey, dest))
|
||||
assert(false);
|
||||
LogPrintf("CMasternodePayments::%s -- ERROR failed to find expected payee %s in block at height %s\n", __func__, EncodeDestination(dest), nBlockHeight);
|
||||
LogPrintf("MasternodePayments::%s -- ERROR failed to find expected payee %s in block at height %s\n", __func__, EncodeDestination(dest), nBlockHeight);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -147,7 +161,7 @@ static bool IsOldBudgetBlockValueValid(const CMasternodeSync& mn_sync, const CBl
|
||||
return isBlockRewardValueMet;
|
||||
}
|
||||
|
||||
namespace CMasternodePayments {
|
||||
namespace MasternodePayments {
|
||||
|
||||
/**
|
||||
* IsBlockValueValid
|
||||
@ -329,4 +343,13 @@ void FillBlockPayments(const CSporkManager& sporkManager, CGovernanceManager& go
|
||||
nBlockHeight, blockReward, voutMasternodeStr, txNew.ToString());
|
||||
}
|
||||
|
||||
} // namespace CMasternodePayments
|
||||
CAmount PlatformShare(const CAmount reward)
|
||||
{
|
||||
constexpr double platformShare = 0.375;
|
||||
const CAmount platformReward = reward * platformShare;
|
||||
assert(MoneyRange(platformReward));
|
||||
|
||||
return platformReward;
|
||||
}
|
||||
|
||||
} // namespace MasternodePayments
|
||||
|
@ -18,12 +18,12 @@ class CSporkManager;
|
||||
class CTxOut;
|
||||
class CMasternodeSync;
|
||||
|
||||
//
|
||||
// Masternode Payments Class
|
||||
// Keeps track of who should get paid for which blocks
|
||||
//
|
||||
/**
|
||||
* Masternode Payments Namespace
|
||||
* Helpers to kees track of who should get paid for which blocks
|
||||
*/
|
||||
|
||||
namespace CMasternodePayments
|
||||
namespace MasternodePayments
|
||||
{
|
||||
bool IsBlockValueValid(const CSporkManager& sporkManager, CGovernanceManager& governanceManager, const CMasternodeSync& mn_sync,
|
||||
const CBlock& block, const int nBlockHeight, const CAmount blockReward, std::string& strErrorRet);
|
||||
@ -32,6 +32,13 @@ bool IsBlockPayeeValid(const CSporkManager& sporkManager, CGovernanceManager& go
|
||||
void FillBlockPayments(const CSporkManager& sporkManager, CGovernanceManager& governanceManager,
|
||||
CMutableTransaction& txNew, const int nBlockHeight, const CAmount blockReward,
|
||||
std::vector<CTxOut>& voutMasternodePaymentsRet, std::vector<CTxOut>& voutSuperblockPaymentsRet);
|
||||
} // namespace CMasternodePayments
|
||||
|
||||
/**
|
||||
* this helper returns amount that should be reallocated to platform
|
||||
* it is calculated based on total amount of Masternode rewards (not block reward)
|
||||
*/
|
||||
CAmount PlatformShare(const CAmount masternodeReward);
|
||||
|
||||
} // namespace MasternodePayments
|
||||
|
||||
#endif // BITCOIN_MASTERNODE_PAYMENTS_H
|
||||
|
@ -231,6 +231,14 @@ std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& sc
|
||||
LogPrintf("CreateNewBlock() h[%d] CbTx failed to find best CL. Inserting null CL\n", nHeight);
|
||||
}
|
||||
assert(creditPoolDiff != std::nullopt);
|
||||
|
||||
bool fMNRewardReallocated = llmq::utils::IsMNRewardReallocationActive(pindexPrev);
|
||||
if (fMNRewardReallocated) {
|
||||
const CAmount masternodeReward = GetMasternodePayment(nHeight, blockReward, Params().GetConsensus().BRRHeight);
|
||||
const CAmount reallocedReward = MasternodePayments::PlatformShare(masternodeReward);
|
||||
LogPrint(BCLog::MNPAYMENTS, "%s: add MN reward %lld (%lld) to credit pool\n", __func__, masternodeReward, reallocedReward);
|
||||
creditPoolDiff->AddRewardRealloced(reallocedReward);
|
||||
}
|
||||
cbTx.creditPoolBalance = creditPoolDiff->GetTotalLocked();
|
||||
}
|
||||
}
|
||||
@ -240,7 +248,7 @@ std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& sc
|
||||
|
||||
// Update coinbase transaction with additional info about masternode and governance payments,
|
||||
// get some info back to pass to getblocktemplate
|
||||
CMasternodePayments::FillBlockPayments(spork_manager, governance_manager, coinbaseTx, nHeight, blockReward, pblocktemplate->voutMasternodePayments, pblocktemplate->voutSuperblockPayments);
|
||||
MasternodePayments::FillBlockPayments(spork_manager, governance_manager, coinbaseTx, nHeight, blockReward, pblocktemplate->voutMasternodePayments, pblocktemplate->voutSuperblockPayments);
|
||||
|
||||
pblock->vtx[0] = MakeTransactionRef(std::move(coinbaseTx));
|
||||
pblocktemplate->vTxFees[0] = -nFees;
|
||||
|
@ -460,7 +460,7 @@ static UniValue masternode_payments(const JSONRPCRequest& request, const Chainst
|
||||
std::vector<CTxOut> voutMasternodePayments, voutDummy;
|
||||
CMutableTransaction dummyTx;
|
||||
CAmount blockReward = nBlockFees + GetBlockSubsidy(pindex, Params().GetConsensus());
|
||||
CMasternodePayments::FillBlockPayments(*sporkManager, *governance, dummyTx, pindex->nHeight, blockReward, voutMasternodePayments, voutDummy);
|
||||
MasternodePayments::FillBlockPayments(*sporkManager, *governance, dummyTx, pindex->nHeight, blockReward, voutMasternodePayments, voutDummy);
|
||||
|
||||
UniValue blockObj(UniValue::VOBJ);
|
||||
CAmount payedPerBlock{0};
|
||||
|
@ -25,6 +25,8 @@
|
||||
#include <llmq/chainlocks.h>
|
||||
#include <llmq/context.h>
|
||||
#include <llmq/instantsend.h>
|
||||
#include <llmq/utils.h>
|
||||
#include <masternode/payments.h>
|
||||
#include <util/enumerate.h>
|
||||
#include <util/irange.h>
|
||||
|
||||
@ -201,7 +203,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(), GetBlockSubsidyInner(::ChainActive().Tip()->nBits, ::ChainActive().Height(), consensus_params), 2500);
|
||||
const CAmount 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 +214,7 @@ BOOST_FIXTURE_TEST_CASE(block_reward_reallocation, TestChainBRRBeforeActivationS
|
||||
|
||||
{
|
||||
LOCK(cs_main);
|
||||
auto masternode_payment = GetMasternodePayment(::ChainActive().Height(), GetBlockSubsidyInner(::ChainActive().Tip()->nBits, ::ChainActive().Height(), consensus_params), 2500);
|
||||
const CAmount 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 +229,7 @@ BOOST_FIXTURE_TEST_CASE(block_reward_reallocation, TestChainBRRBeforeActivationS
|
||||
CreateAndProcessBlock({}, coinbaseKey);
|
||||
}
|
||||
LOCK(cs_main);
|
||||
auto masternode_payment = GetMasternodePayment(::ChainActive().Height(), GetBlockSubsidyInner(::ChainActive().Tip()->nBits, ::ChainActive().Height(), consensus_params), 2500);
|
||||
const CAmount 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 +238,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(), GetBlockSubsidyInner(::ChainActive().Tip()->nBits, ::ChainActive().Height(), consensus_params), 2500);
|
||||
const CAmount 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,19 +252,33 @@ BOOST_FIXTURE_TEST_CASE(block_reward_reallocation, TestChainBRRBeforeActivationS
|
||||
CreateAndProcessBlock({}, coinbaseKey);
|
||||
}
|
||||
LOCK(cs_main);
|
||||
auto masternode_payment = GetMasternodePayment(::ChainActive().Height(), GetBlockSubsidyInner(::ChainActive().Tip()->nBits, ::ChainActive().Height(), consensus_params), 2500);
|
||||
|
||||
CAmount 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);
|
||||
|
||||
bool isMNRewardReallocated = llmq::utils::IsMNRewardReallocationActive(::ChainActive().Tip());
|
||||
if (isMNRewardReallocated) {
|
||||
const CAmount platform_payment = MasternodePayments::PlatformShare(masternode_payment);
|
||||
masternode_payment -= platform_payment;
|
||||
}
|
||||
size_t payment_index = isMNRewardReallocated ? 1 : 0;
|
||||
|
||||
BOOST_CHECK_EQUAL(pblocktemplate->voutMasternodePayments[payment_index].nValue, masternode_payment);
|
||||
}
|
||||
|
||||
{
|
||||
{ // At this moment Masternode reward should be reallocated to platform
|
||||
// Reward split should reach ~60/40 after reallocation is done
|
||||
LOCK(cs_main);
|
||||
auto masternode_payment = GetMasternodePayment(::ChainActive().Height(), GetBlockSubsidyInner(::ChainActive().Tip()->nBits, ::ChainActive().Height(), consensus_params), 2500);
|
||||
CAmount masternode_payment = GetMasternodePayment(::ChainActive().Height(), GetBlockSubsidyInner(::ChainActive().Tip()->nBits, ::ChainActive().Height(), consensus_params), 2500);
|
||||
const CAmount platform_payment = MasternodePayments::PlatformShare(masternode_payment);
|
||||
masternode_payment -= platform_payment;
|
||||
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);
|
||||
BOOST_CHECK_EQUAL(pblocktemplate->voutMasternodePayments[0].nValue, 5694890966); // 0.6
|
||||
|
||||
BOOST_CHECK(llmq::utils::IsMNRewardReallocationActive(::ChainActive().Tip()));
|
||||
|
||||
BOOST_CHECK_EQUAL(pblocktemplate->voutMasternodePayments[1].nValue, masternode_payment);
|
||||
BOOST_CHECK_EQUAL(pblocktemplate->voutMasternodePayments[1].nValue, 3559306854); // 0.6
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2413,7 +2413,7 @@ bool CChainState::ConnectBlock(const CBlock& block, BlockValidationState& state,
|
||||
int64_t nTime5_2 = GetTimeMicros(); nTimeSubsidy += nTime5_2 - nTime5_1;
|
||||
LogPrint(BCLog::BENCHMARK, " - GetBlockSubsidy: %.2fms [%.2fs (%.2fms/blk)]\n", MILLI * (nTime5_2 - nTime5_1), nTimeSubsidy * MICRO, nTimeSubsidy * MILLI / nBlocksTotal);
|
||||
|
||||
if (!CMasternodePayments::IsBlockValueValid(*sporkManager, *governance, *::masternodeSync, block, pindex->nHeight, blockReward, strError)) {
|
||||
if (!MasternodePayments::IsBlockValueValid(*sporkManager, *governance, *::masternodeSync, block, pindex->nHeight, blockReward, strError)) {
|
||||
// NOTE: Do not punish, the node might be missing governance data
|
||||
LogPrintf("ERROR: ConnectBlock(DASH): %s\n", strError);
|
||||
return state.Invalid(BlockValidationResult::BLOCK_RESULT_UNSET, "bad-cb-amount");
|
||||
@ -2422,7 +2422,7 @@ bool CChainState::ConnectBlock(const CBlock& block, BlockValidationState& state,
|
||||
int64_t nTime5_3 = GetTimeMicros(); nTimeValueValid += nTime5_3 - nTime5_2;
|
||||
LogPrint(BCLog::BENCHMARK, " - IsBlockValueValid: %.2fms [%.2fs (%.2fms/blk)]\n", MILLI * (nTime5_3 - nTime5_2), nTimeValueValid * MICRO, nTimeValueValid * MILLI / nBlocksTotal);
|
||||
|
||||
if (!CMasternodePayments::IsBlockPayeeValid(*sporkManager, *governance, *block.vtx[0], pindex->nHeight, blockReward)) {
|
||||
if (!MasternodePayments::IsBlockPayeeValid(*sporkManager, *governance, *block.vtx[0], pindex->nHeight, blockReward)) {
|
||||
// NOTE: Do not punish, the node might be missing governance data
|
||||
LogPrintf("ERROR: ConnectBlock(DASH): couldn't find masternode or superblock payments\n");
|
||||
return state.Invalid(BlockValidationResult::BLOCK_RESULT_UNSET, "bad-cb-payee");
|
||||
|
@ -288,6 +288,7 @@ class AssetLocksTest(DashTestFramework):
|
||||
self.mine_quorum()
|
||||
self.validate_credit_pool_balance(locked_1)
|
||||
|
||||
|
||||
self.log.info("Testing asset unlock...")
|
||||
|
||||
self.log.info("Generating several txes by same quorum....")
|
||||
@ -300,7 +301,7 @@ class AssetLocksTest(DashTestFramework):
|
||||
asset_unlock_tx_duplicate_index = copy.deepcopy(asset_unlock_tx)
|
||||
# modify this tx with duplicated index to make a hash of tx different, otherwise tx would be refused too early
|
||||
asset_unlock_tx_duplicate_index.vout[0].nValue += COIN
|
||||
too_late_height = node.getblock(node.getbestblockhash())["height"] + 48
|
||||
too_late_height = node.getblockcount() + 48
|
||||
|
||||
self.check_mempool_result(tx=asset_unlock_tx, result_expected={'allowed': True})
|
||||
self.check_mempool_result(tx=asset_unlock_tx_too_big_fee,
|
||||
@ -345,7 +346,7 @@ class AssetLocksTest(DashTestFramework):
|
||||
self.validate_credit_pool_balance(locked_1 - 2 * COIN)
|
||||
|
||||
self.log.info("Generating many blocks to make quorum far behind (even still active)...")
|
||||
self.slowly_generate_batch(too_late_height - node.getblock(node.getbestblockhash())["height"] - 1)
|
||||
self.slowly_generate_batch(too_late_height - node.getblockcount() - 1)
|
||||
self.check_mempool_result(tx=asset_unlock_tx_too_late, result_expected={'allowed': True})
|
||||
node.generate(1)
|
||||
self.sync_all()
|
||||
@ -495,5 +496,33 @@ class AssetLocksTest(DashTestFramework):
|
||||
assert_equal(new_total, self.get_credit_pool_balance())
|
||||
self.check_mempool_size()
|
||||
|
||||
self.activate_mn_rr(expected_activation_height=3090)
|
||||
self.log.info(f'height: {node.getblockcount()} credit: {self.get_credit_pool_balance()}')
|
||||
bt = node.getblocktemplate()
|
||||
platform_reward = bt['masternode'][0]['amount']
|
||||
assert_equal(bt['masternode'][0]['script'], '6a') # empty OP_RETURN
|
||||
owner_reward = bt['masternode'][1]['amount']
|
||||
operator_reward = bt['masternode'][2]['amount'] if len(bt['masternode']) == 3 else 0
|
||||
all_mn_rewards = platform_reward + owner_reward + operator_reward
|
||||
assert_equal(all_mn_rewards, bt['coinbasevalue'] * 0.6) # 60/40 mn/miner reward split
|
||||
assert_equal(platform_reward, int(all_mn_rewards * 0.375)) # 0.375 platform share
|
||||
assert_equal(platform_reward, 2299859813)
|
||||
assert_equal(new_total, self.get_credit_pool_balance())
|
||||
node.generate(1)
|
||||
self.sync_all()
|
||||
new_total += platform_reward
|
||||
assert_equal(new_total, self.get_credit_pool_balance())
|
||||
|
||||
coin = coins.pop()
|
||||
self.send_tx(self.create_assetlock(coin, COIN, pubkey))
|
||||
new_total += platform_reward + COIN
|
||||
node.generate(1)
|
||||
self.sync_all()
|
||||
# part of fee is going to master node reward
|
||||
# these 2 conditions need to check a range
|
||||
assert_greater_than(self.get_credit_pool_balance(), new_total)
|
||||
assert_greater_than(new_total + tiny_amount, self.get_credit_pool_balance())
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
AssetLocksTest().main()
|
||||
|
@ -1092,6 +1092,7 @@ class DashTestFramework(BitcoinTestFramework):
|
||||
|
||||
def activate_v20(self, expected_activation_height=None):
|
||||
self.activate_by_name('v20', expected_activation_height)
|
||||
|
||||
def activate_mn_rr(self, expected_activation_height=None):
|
||||
self.activate_by_name('mn_rr', expected_activation_height)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user