From 829d345c7d2cd3f96c11d416520fd5248f42d8e9 Mon Sep 17 00:00:00 2001 From: Peter Shugalev Date: Thu, 29 Aug 2024 13:00:10 +0200 Subject: [PATCH 1/9] Change of emission rules --- src/chainparams.cpp | 5 +++ src/consensus/params.h | 11 ++++++ src/validation.cpp | 76 +++++++++++++++++++++++------------------- 3 files changed, 57 insertions(+), 35 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index fd8a90dbbd..ac14ccfc67 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -528,6 +528,11 @@ class CTestNetParams : public CChainParams { consensus.stage3DevelopmentFundAddress = "TWDxLLKsFp6qcV1LL4U2uNmW4HwMcapmMU"; consensus.stage3CommunityFundAddress = "TCkC4uoErEyCB4MK3d6ouyJELoXnuyqe9L"; + consensus.stage4CommunityFundShare = 10; + consensus.stage4DevelopmentFundShare = 15; + consensus.stage4MasternodeShare = 70; + consensus.tailEmissionBlockSubsidy = 4 * COIN; // real value would be 1 FIRO (because of two halvings due to different block times) + consensus.nStartBlacklist = 0; consensus.nStartDuplicationCheck = 0; consensus.nMajorityEnforceBlockUpgrade = 51; diff --git a/src/consensus/params.h b/src/consensus/params.h index 1db0a6ac3c..4f05375cd5 100644 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -163,6 +163,17 @@ struct Params { /** percentage of block subsidy going to masternode */ int stage3MasternodeShare; + /** parameters for coinbase payment distribution after stage three (aka stage 4) */ + /** percentage of block subsidy going to developer fund */ + int stage4DevelopmentFundShare; + /** percentage of block subsidy going to community fund */ + int stage4CommunityFundShare; + /** percentage of block subsidy going to masternode */ + int stage4MasternodeShare; + + /** tail emission (after stage 4) */ + int tailEmissionBlockSubsidy; + int nStartDuplicationCheck; int nStartBlacklist; diff --git a/src/validation.cpp b/src/validation.cpp index abcb55e0ff..2b82972c0b 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -1931,13 +1931,15 @@ CAmount GetBlockSubsidyWithMTPFlag(int nHeight, const Consensus::Params &consens else halvings = (nHeight - consensusParams.nSubsidyHalvingSecond) / consensusParams.nSubsidyHalvingInterval + 2; - // Force block reward to zero when right shift is undefined. - if (halvings >= 64) - return 0; - CAmount nSubsidy = 50 * COIN; - nSubsidy >>= halvings; - + if (halvings > 2) + nSubsidy = consensusParams.tailEmissionBlockSubsidy; // 1 coin tail emission + else if (halvings == 2) + // stage 4 + nSubsidy = 25*COIN; + else + nSubsidy >>= halvings; + if (nHeight > 0 && fMTP) nSubsidy /= consensusParams.nMTPRewardReduction; @@ -1956,7 +1958,9 @@ CAmount GetBlockSubsidy(int nHeight, const Consensus::Params &consensusParams, i CAmount GetMasternodePayment(int nHeight, int nTime, CAmount blockValue) { const Consensus::Params ¶ms = Params().GetConsensus(); - if (nTime >= params.stage3StartTime) + if (nHeight >= params.stage4MasternodeShare) + return blockValue*params.stage4MasternodeShare/100; + else if (nTime >= params.stage3StartTime) return blockValue*params.stage3MasternodeShare/100; else if (nHeight >= params.nSubsidyHalvingFirst) return blockValue*params.stage2ZnodeShare/100; @@ -4835,35 +4839,37 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, const Co } if (nHeight >= consensusParams.nSubsidyHalvingFirst) { - if (nHeight < consensusParams.nSubsidyHalvingSecond) { - if (block.nTime >= consensusParams.stage3StartTime) { - CScript devPayoutScript = GetScriptForDestination(CBitcoinAddress(consensusParams.stage3DevelopmentFundAddress).Get()); - CAmount devPayoutValue = (GetBlockSubsidy(nHeight, consensusParams, block.nTime) * consensusParams.stage3DevelopmentFundShare) / 100; - CScript communityPayoutScript = GetScriptForDestination(CBitcoinAddress(consensusParams.stage3CommunityFundAddress).Get()); - CAmount communityPayoutValue = (GetBlockSubsidy(nHeight, consensusParams, block.nTime) * consensusParams.stage3CommunityFundShare) / 100; - - bool devFound = false, communityFound = false; - for (const CTxOut &txout: block.vtx[0]->vout) { - if (txout.scriptPubKey == devPayoutScript && txout.nValue == devPayoutValue) - devFound = true; - else if (txout.scriptPubKey == communityPayoutScript && txout.nValue == communityPayoutValue) - communityFound = true; - } - if (!devFound || !communityFound) - return state.Invalid(false, state.GetRejectCode(), state.GetRejectReason(), "Stage 3 developer/community reward check failed"); - } - else { - // "stage 2" interval between first and second halvings - CScript devPayoutScript = GetScriptForDestination(CBitcoinAddress(consensusParams.stage2DevelopmentFundAddress).Get()); - CAmount devPayoutValue = (GetBlockSubsidy(nHeight, consensusParams, block.nTime) * consensusParams.stage2DevelopmentFundShare) / 100; - bool found = false; - for (const CTxOut &txout: block.vtx[0]->vout) { - if ((found = txout.scriptPubKey == devPayoutScript && txout.nValue == devPayoutValue) == true) - break; - } - if (!found) - return state.Invalid(false, state.GetRejectCode(), state.GetRejectReason(), "Stage 2 developer reward check failed"); + if (block.nTime >= consensusParams.stage3StartTime) { + bool fStage4 = nHeight >= consensusParams.nSubsidyHalvingSecond; + int devPayoutShare = fStage4 ? consensusParams.stage4DevelopmentFundShare : consensusParams.stage3DevelopmentFundShare; + int communityPayoutShare = fStage4 ? consensusParams.stage4CommunityFundShare : consensusParams.stage3CommunityFundShare; + + CScript devPayoutScript = GetScriptForDestination(CBitcoinAddress(consensusParams.stage3DevelopmentFundAddress).Get()); + CAmount devPayoutValue = (GetBlockSubsidy(nHeight, consensusParams, block.nTime) * devPayoutShare) / 100; + CScript communityPayoutScript = GetScriptForDestination(CBitcoinAddress(consensusParams.stage3CommunityFundAddress).Get()); + CAmount communityPayoutValue = (GetBlockSubsidy(nHeight, consensusParams, block.nTime) * communityPayoutShare) / 100; + + bool devFound = false, communityFound = false; + for (const CTxOut &txout: block.vtx[0]->vout) { + if (txout.scriptPubKey == devPayoutScript && txout.nValue == devPayoutValue) + devFound = true; + else if (txout.scriptPubKey == communityPayoutScript && txout.nValue == communityPayoutValue) + communityFound = true; + } + if (!devFound || !communityFound) + return state.Invalid(false, state.GetRejectCode(), state.GetRejectReason(), "Stage 3 developer/community reward check failed"); + } + else { + // "stage 2" interval between first and second halvings + CScript devPayoutScript = GetScriptForDestination(CBitcoinAddress(consensusParams.stage2DevelopmentFundAddress).Get()); + CAmount devPayoutValue = (GetBlockSubsidy(nHeight, consensusParams, block.nTime) * consensusParams.stage2DevelopmentFundShare) / 100; + bool found = false; + for (const CTxOut &txout: block.vtx[0]->vout) { + if ((found = txout.scriptPubKey == devPayoutScript && txout.nValue == devPayoutValue) == true) + break; } + if (!found) + return state.Invalid(false, state.GetRejectCode(), state.GetRejectReason(), "Stage 2 developer reward check failed"); } } else if (!CheckZerocoinFoundersInputs(*block.vtx[0], state, consensusParams, nHeight, block.IsMTP())) { From 7527d32c00813184796ef3a629a1ec7953e0e8f5 Mon Sep 17 00:00:00 2001 From: Peter Shugalev Date: Sun, 1 Sep 2024 17:06:42 +0200 Subject: [PATCH 2/9] Fixes for testnet --- src/chainparams.cpp | 23 +++++++++++++++++++++-- src/consensus/params.h | 2 ++ src/miner.cpp | 30 +++++++++++++++++++++--------- src/validation.cpp | 28 +++++++++++++--------------- 4 files changed, 57 insertions(+), 26 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index ac14ccfc67..5412bc8b17 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -206,6 +206,12 @@ class CMainParams : public CChainParams { consensus.stage3DevelopmentFundAddress = "aLgRaYSFk6iVw2FqY1oei8Tdn2aTsGPVmP"; consensus.stage3CommunityFundAddress = "aFA2TbqG9cnhhzX5Yny2pBJRK5EaEqLCH7"; + consensus.stage4StartBlock = consensus.nSubsidyHalvingSecond; + consensus.stage4CommunityFundShare = 10; + consensus.stage4DevelopmentFundShare = 15; + consensus.stage4MasternodeShare = 70; + consensus.tailEmissionBlockSubsidy = 4 * COIN; // real value would be 1 FIRO (because of two halvings due to different block times) + consensus.nStartBlacklist = 293990; consensus.nStartDuplicationCheck = 293526; @@ -528,6 +534,7 @@ class CTestNetParams : public CChainParams { consensus.stage3DevelopmentFundAddress = "TWDxLLKsFp6qcV1LL4U2uNmW4HwMcapmMU"; consensus.stage3CommunityFundAddress = "TCkC4uoErEyCB4MK3d6ouyJELoXnuyqe9L"; + consensus.stage4StartBlock = 168500; consensus.stage4CommunityFundShare = 10; consensus.stage4DevelopmentFundShare = 15; consensus.stage4MasternodeShare = 70; @@ -794,7 +801,7 @@ class CDevNetParams : public CChainParams { consensus.chainType = Consensus::chainDevnet; consensus.nSubsidyHalvingFirst = 1; - consensus.nSubsidyHalvingSecond = 100000; + consensus.nSubsidyHalvingSecond = 3500; consensus.nSubsidyHalvingInterval = 100000; consensus.nSubsidyHalvingStopBlock = 1000000; @@ -810,6 +817,12 @@ class CDevNetParams : public CChainParams { consensus.stage3DevelopmentFundAddress = "TfvbHyGTo8hexoKBBS8fz9Gq7g9VZQQpcg"; consensus.stage3CommunityFundAddress = "TgoL9nh8vDTz7UB5WkBbknBksBdUaD9qbT"; + consensus.stage4StartBlock = consensus.nSubsidyHalvingSecond; + consensus.stage4CommunityFundShare = 10; + consensus.stage4DevelopmentFundShare = 15; + consensus.stage4MasternodeShare = 70; + consensus.tailEmissionBlockSubsidy = 4 * COIN; // real value would be 1 FIRO (because of two halvings due to different block times) + consensus.nStartBlacklist = 0; consensus.nStartDuplicationCheck = 0; consensus.nMajorityEnforceBlockUpgrade = 51; @@ -1044,13 +1057,19 @@ class CRegTestParams : public CChainParams { consensus.stage2ZnodeShare = 35; consensus.stage3StartTime = INT_MAX; - consensus.stage3StartBlock = 0; + consensus.stage3StartBlock = 2000; consensus.stage3DevelopmentFundShare = 15; consensus.stage3CommunityFundShare = 10; consensus.stage3MasternodeShare = 50; consensus.stage3DevelopmentFundAddress = "TGEGf26GwyUBE2P2o2beBAfE9Y438dCp5t"; // private key cMrz8Df36VR9TvZjtvSqLPhUQR7pcpkXRXaLNYUxfkKsRuCzHpAN consensus.stage3CommunityFundAddress = "TJmPzeJF4DECrBwUftc265U7rTPxKmpa4F"; // private key cTyPWqTMM1CgT5qy3K3LSgC1H6Q2RHvnXZHvjWtKB4vq9qXqKmMu + consensus.stage4StartBlock = consensus.nSubsidyHalvingSecond; + consensus.stage4CommunityFundShare = 15; + consensus.stage4DevelopmentFundShare = 25; + consensus.stage4MasternodeShare = 50; + consensus.tailEmissionBlockSubsidy = 4 * COIN; // real value would be 1 FIRO (because of two halvings due to different block times) + consensus.nMajorityEnforceBlockUpgrade = 750; consensus.nMajorityRejectBlockOutdated = 950; consensus.nMajorityWindow = 1000; diff --git a/src/consensus/params.h b/src/consensus/params.h index 4f05375cd5..59cb05c490 100644 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -164,6 +164,8 @@ struct Params { int stage3MasternodeShare; /** parameters for coinbase payment distribution after stage three (aka stage 4) */ + /** start time of stage 4 (usually the same as nSubsidyHalvingSecond)*/ + int stage4StartBlock; /** percentage of block subsidy going to developer fund */ int stage4DevelopmentFundShare; /** percentage of block subsidy going to community fund */ diff --git a/src/miner.cpp b/src/miner.cpp index 492cb3477b..f41d9b52a4 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -192,7 +192,7 @@ std::unique_ptr BlockAssembler::CreateNewBlock(const CScript& sc pblock->nTime = GetAdjustedTime(); bool fMTP = (pblock->nTime >= params.nMTPSwitchTime); - bool fShorterBlockDistance = (pblock->nTime >= params.stage3StartTime); + bool fShorterBlockDistance = nHeight >= params.stage3StartBlock; const int64_t nMedianTimePast = pindexPrev->GetMedianTimePast(); pblock->nVersion = ComputeBlockVersion(pindexPrev, chainparams.GetConsensus()) | (fMTP ? 0x1000 : 0); @@ -835,19 +835,31 @@ void BlockAssembler::FillFoundersReward(CMutableTransaction &coinbaseTx, bool fM if (fShorterBlockDistance) coin /= 2; - if (nHeight >= params.nSubsidyHalvingFirst && nHeight < params.nSubsidyHalvingSecond) { + if ((nHeight >= params.nSubsidyHalvingFirst && nHeight < params.nSubsidyHalvingSecond) || nHeight >= params.stage4StartBlock) { if (fShorterBlockDistance) { - // Stage 3 + bool fStage3 = nHeight < params.nSubsidyHalvingSecond; + bool fStage4 = nHeight >= params.stage4StartBlock; + CAmount devPayoutValue = 0, communityPayoutValue = 0; CScript devPayoutScript = GetScriptForDestination(CBitcoinAddress(params.stage3DevelopmentFundAddress).Get()); - CAmount devPayoutValue = (GetBlockSubsidyWithMTPFlag(nHeight, params, fMTP, true) * params.stage3DevelopmentFundShare) / 100; CScript communityPayoutScript = GetScriptForDestination(CBitcoinAddress(params.stage3CommunityFundAddress).Get()); - CAmount communityPayoutValue = (GetBlockSubsidyWithMTPFlag(nHeight, params, fMTP, true) * params.stage3CommunityFundShare) / 100; - coinbaseTx.vout[0].nValue -= devPayoutValue; - coinbaseTx.vout.push_back(CTxOut(devPayoutValue, devPayoutScript)); + // There is no dev/community payout for testnet for some time + if (fStage3 || fStage4) { + int devShare = fStage3 ? params.stage3DevelopmentFundShare : params.stage4DevelopmentFundShare; + int communityShare = fStage3 ? params.stage3CommunityFundShare : params.stage4CommunityFundShare; + devPayoutValue = (GetBlockSubsidyWithMTPFlag(nHeight, params, fMTP, true) * devShare) / 100; + communityPayoutValue = (GetBlockSubsidyWithMTPFlag(nHeight, params, fMTP, true) * communityShare) / 100; + } - coinbaseTx.vout[0].nValue -= communityPayoutValue; - coinbaseTx.vout.push_back(CTxOut(communityPayoutValue, communityPayoutScript)); + if (devPayoutValue != 0) { + coinbaseTx.vout[0].nValue -= devPayoutValue; + coinbaseTx.vout.push_back(CTxOut(devPayoutValue, devPayoutScript)); + } + + if (communityPayoutValue != 0) { + coinbaseTx.vout[0].nValue -= communityPayoutValue; + coinbaseTx.vout.push_back(CTxOut(communityPayoutValue, communityPayoutScript)); + } } else { // Stage 2 diff --git a/src/validation.cpp b/src/validation.cpp index 2b82972c0b..f7dc045d72 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -1923,22 +1923,18 @@ CAmount GetBlockSubsidyWithMTPFlag(int nHeight, const Consensus::Params &consens if (nHeight >= consensusParams.nSubsidyHalvingStopBlock) return 0; - int halvings; + CAmount nSubsidy; + if (nHeight < consensusParams.nSubsidyHalvingFirst) - halvings = 0; + nSubsidy = 50 * COIN; else if (nHeight < consensusParams.nSubsidyHalvingSecond) - halvings = 1; + nSubsidy = 25 * COIN; + else if (nHeight < consensusParams.stage4StartBlock) + nSubsidy = 25 * COIN / 2; + else if (nHeight < consensusParams.stage4StartBlock + consensusParams.nSubsidyHalvingInterval) + nSubsidy = 25 * COIN; else - halvings = (nHeight - consensusParams.nSubsidyHalvingSecond) / consensusParams.nSubsidyHalvingInterval + 2; - - CAmount nSubsidy = 50 * COIN; - if (halvings > 2) nSubsidy = consensusParams.tailEmissionBlockSubsidy; // 1 coin tail emission - else if (halvings == 2) - // stage 4 - nSubsidy = 25*COIN; - else - nSubsidy >>= halvings; if (nHeight > 0 && fMTP) nSubsidy /= consensusParams.nMTPRewardReduction; @@ -1952,7 +1948,7 @@ CAmount GetBlockSubsidyWithMTPFlag(int nHeight, const Consensus::Params &consens CAmount GetBlockSubsidy(int nHeight, const Consensus::Params &consensusParams, int nTime) { return GetBlockSubsidyWithMTPFlag(nHeight, consensusParams, nTime >= (int)consensusParams.nMTPSwitchTime, - nTime >= (int)consensusParams.stage3StartTime); + nHeight >= (int)consensusParams.stage3StartBlock); } CAmount GetMasternodePayment(int nHeight, int nTime, CAmount blockValue) @@ -1960,7 +1956,9 @@ CAmount GetMasternodePayment(int nHeight, int nTime, CAmount blockValue) const Consensus::Params ¶ms = Params().GetConsensus(); if (nHeight >= params.stage4MasternodeShare) return blockValue*params.stage4MasternodeShare/100; - else if (nTime >= params.stage3StartTime) + else if (nHeight >= params.nSubsidyHalvingSecond) + return blockValue/2; + else if (nHeight >= params.stage3StartBlock) return blockValue*params.stage3MasternodeShare/100; else if (nHeight >= params.nSubsidyHalvingFirst) return blockValue*params.stage2ZnodeShare/100; @@ -4839,7 +4837,7 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, const Co } if (nHeight >= consensusParams.nSubsidyHalvingFirst) { - if (block.nTime >= consensusParams.stage3StartTime) { + if (nHeight >= consensusParams.stage3StartBlock) { bool fStage4 = nHeight >= consensusParams.nSubsidyHalvingSecond; int devPayoutShare = fStage4 ? consensusParams.stage4DevelopmentFundShare : consensusParams.stage3DevelopmentFundShare; int communityPayoutShare = fStage4 ? consensusParams.stage4CommunityFundShare : consensusParams.stage3CommunityFundShare; From cf1edca5f37e06fa4120063da7ea111baa2ebd93 Mon Sep 17 00:00:00 2001 From: Peter Shugalev Date: Sun, 1 Sep 2024 18:06:53 +0200 Subject: [PATCH 3/9] Cleaning up code and tests --- src/chainparams.cpp | 4 --- src/consensus/params.h | 2 -- src/test/firsthalving_tests.cpp | 2 -- src/test/main_tests.cpp | 53 ++++----------------------------- src/validation.cpp | 5 ---- 5 files changed, 6 insertions(+), 60 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 5412bc8b17..031c9a746c 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -192,7 +192,6 @@ class CMainParams : public CChainParams { consensus.nSubsidyHalvingFirst = 302438; consensus.nSubsidyHalvingSecond = AdjustEndingBlockNumberAfterSubsidyHalving(302438, 420000, 486221); // =958655 consensus.nSubsidyHalvingInterval = 420000*2; - consensus.nSubsidyHalvingStopBlock = AdjustEndingBlockNumberAfterSubsidyHalving(0, 3646849, 486221); // =6807477 consensus.stage2DevelopmentFundShare = 15; consensus.stage2ZnodeShare = 35; @@ -520,7 +519,6 @@ class CTestNetParams : public CChainParams { consensus.nSubsidyHalvingFirst = 12000; consensus.nSubsidyHalvingSecond = 150000; consensus.nSubsidyHalvingInterval = 150000; - consensus.nSubsidyHalvingStopBlock = 1000000; consensus.stage2DevelopmentFundShare = 15; consensus.stage2ZnodeShare = 35; @@ -803,7 +801,6 @@ class CDevNetParams : public CChainParams { consensus.nSubsidyHalvingFirst = 1; consensus.nSubsidyHalvingSecond = 3500; consensus.nSubsidyHalvingInterval = 100000; - consensus.nSubsidyHalvingStopBlock = 1000000; consensus.stage2DevelopmentFundShare = 15; consensus.stage2ZnodeShare = 35; @@ -1049,7 +1046,6 @@ class CRegTestParams : public CChainParams { consensus.nSubsidyHalvingFirst = 1500; consensus.nSubsidyHalvingSecond = 2500; consensus.nSubsidyHalvingInterval = 1000; - consensus.nSubsidyHalvingStopBlock = 10000; consensus.nStartBlacklist = 0; consensus.nStartDuplicationCheck = 0; diff --git a/src/consensus/params.h b/src/consensus/params.h index 59cb05c490..a2c7e48d8c 100644 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -136,8 +136,6 @@ struct Params { int nSubsidyHalvingSecond; /** Subsequent subsidy halving intervals */ int nSubsidyHalvingInterval; - /** Stop subsidy at this block number */ - int nSubsidyHalvingStopBlock; /** parameters for coinbase payment distribution between first halving and stage 3 (aka stage 2) */ /** P2PKH or P2SH address for developer funds */ diff --git a/src/test/firsthalving_tests.cpp b/src/test/firsthalving_tests.cpp index e3d8b4e56c..e7059a0319 100644 --- a/src/test/firsthalving_tests.cpp +++ b/src/test/firsthalving_tests.cpp @@ -156,7 +156,6 @@ BOOST_FIXTURE_TEST_CASE(devpayout, TestChainDIP3BeforeActivationSetup) consensusParams.stage3StartTime = INT_MAX; consensusParams.nSubsidyHalvingSecond = 620; consensusParams.nSubsidyHalvingInterval = 10; - consensusParams.nSubsidyHalvingStopBlock = 1000; CScript devPayoutScript = GenerateRandomAddress(); CTxDestination devPayoutDest{CScriptID(devPayoutScript)}; @@ -305,7 +304,6 @@ BOOST_FIXTURE_TEST_CASE(devpayoutverification, TestChainDIP3BeforeActivationSetu consensusParams.nSubsidyHalvingFirst = 600; consensusParams.nSubsidyHalvingSecond = 610; consensusParams.nSubsidyHalvingInterval = 10; - consensusParams.nSubsidyHalvingStopBlock = 1000; // skip to block 600 for (int i=498; i<600; i++) diff --git a/src/test/main_tests.cpp b/src/test/main_tests.cpp index f4352ed396..6a3d6230a5 100644 --- a/src/test/main_tests.cpp +++ b/src/test/main_tests.cpp @@ -21,19 +21,13 @@ static void TestBlockSubsidyHalvings(const Consensus::Params& consensusParams) BOOST_CHECK_EQUAL(GetBlockSubsidy(1, consensusParams, consensusParams.nMTPSwitchTime-1000), nInitialSubsidy); nInitialSubsidy /= consensusParams.nMTPRewardReduction; BOOST_CHECK_EQUAL(GetBlockSubsidy(2, consensusParams, consensusParams.nMTPSwitchTime), nInitialSubsidy); + CAmount baseSubsidy = nInitialSubsidy; - CAmount nPreviousSubsidy = nInitialSubsidy; - for (int nHalvings = 1; nHalvings < maxHalvings; nHalvings++) { - int nHeight = consensusParams.nSubsidyHalvingFirst + (nHalvings-1) * consensusParams.nSubsidyHalvingInterval; - if (nHeight >= consensusParams.nSubsidyHalvingStopBlock) - break; - CAmount nSubsidy = GetBlockSubsidy(nHeight, consensusParams, consensusParams.nMTPSwitchTime); - BOOST_CHECK(nSubsidy <= nInitialSubsidy); - if(nHeight > 0) - BOOST_CHECK_EQUAL(nSubsidy, nPreviousSubsidy / 2); - nPreviousSubsidy = nPreviousSubsidy / 2; - } - BOOST_CHECK_EQUAL(GetBlockSubsidy(consensusParams.nSubsidyHalvingStopBlock, consensusParams), 0); + BOOST_CHECK_EQUAL(GetBlockSubsidy(consensusParams.nSubsidyHalvingFirst, consensusParams, consensusParams.nMTPSwitchTime), baseSubsidy/2); + BOOST_CHECK_EQUAL(GetBlockSubsidy(consensusParams.stage3StartBlock, consensusParams, consensusParams.stage3StartTime), baseSubsidy/4); + BOOST_CHECK_EQUAL(GetBlockSubsidy(consensusParams.nSubsidyHalvingSecond, consensusParams, consensusParams.stage3StartTime), baseSubsidy/4); + BOOST_CHECK_EQUAL(GetBlockSubsidy(consensusParams.nSubsidyHalvingSecond + consensusParams.nSubsidyHalvingInterval, + consensusParams, consensusParams.stage3StartTime), consensusParams.tailEmissionBlockSubsidy/consensusParams.nMTPRewardReduction/2); } BOOST_AUTO_TEST_CASE(block_subsidy_test) @@ -42,41 +36,6 @@ BOOST_AUTO_TEST_CASE(block_subsidy_test) //TestBlockSubsidyHalvings(1000); // Just another interval } -BOOST_AUTO_TEST_CASE(subsidy_limit_test) -{ - Consensus::Params consensusParams = Params(CBaseChainParams::MAIN).GetConsensus(); - CAmount nSum = 0; - int lastHalving = (consensusParams.nSubsidyHalvingStopBlock - consensusParams.nSubsidyHalvingSecond)/consensusParams.nSubsidyHalvingInterval; - int lastHalvingBlock = consensusParams.nSubsidyHalvingSecond + lastHalving*consensusParams.nSubsidyHalvingInterval; - - int step = 1; - - for(int nHeight = 0; nHeight < 14000000; nHeight += step) - { - if (nHeight == consensusParams.nSubsidyHalvingSecond) - step = 1000; - else if (nHeight == lastHalvingBlock) - step = 1; - else if (nHeight == consensusParams.nSubsidyHalvingStopBlock) - step = 10000; - - int nTime; - if (nHeight < consensusParams.nMTPStartBlock) - nTime = consensusParams.nMTPSwitchTime-1000; - else if (nHeight < consensusParams.stage3StartBlock) - nTime = consensusParams.stage3StartTime-1000; - else - nTime = consensusParams.stage3StartTime; - CAmount nSubsidy = GetBlockSubsidy(nHeight, consensusParams, nTime); - if (nHeight == 0) - nSubsidy = 50*COIN; - BOOST_CHECK(nSubsidy <= 50 * COIN); - nSum += nSubsidy * step; - BOOST_CHECK(MoneyRange(nSum)); - } - BOOST_CHECK_EQUAL(nSum, 2095751200767464ULL); -} - bool ReturnFalse() { return false; } bool ReturnTrue() { return true; } diff --git a/src/validation.cpp b/src/validation.cpp index f7dc045d72..49c5bd79a3 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -1918,11 +1918,6 @@ CAmount GetBlockSubsidyWithMTPFlag(int nHeight, const Consensus::Params &consens if (nHeight == 0) return 0; - // Subsidy is cut in half after nSubsidyHalvingFirst block, then after nSubsidyHalvingSecond, then every nSubsidyHalvingInterval blocks. - // After block nSubsidyHalvingStopBlock there will be no subsidy at all - if (nHeight >= consensusParams.nSubsidyHalvingStopBlock) - return 0; - CAmount nSubsidy; if (nHeight < consensusParams.nSubsidyHalvingFirst) From 5f4ea11386e2cd5f119f705a0a866ca526af4da2 Mon Sep 17 00:00:00 2001 From: Peter Shugalev Date: Sun, 1 Sep 2024 18:59:28 +0200 Subject: [PATCH 4/9] Workaround for current devnet bugs --- src/chainparams.cpp | 2 +- src/validation.cpp | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 031c9a746c..1fe414fa1f 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -807,7 +807,7 @@ class CDevNetParams : public CChainParams { consensus.stage2DevelopmentFundAddress = "Tq99tes2sRbQ1yNUJPJ7BforYnKcitgwWq"; consensus.stage3StartTime = 1653382800; - consensus.stage3StartBlock = 1514; + consensus.stage3StartBlock = 1514; // this is incorrect value but we have to leave it for now consensus.stage3DevelopmentFundShare = 15; consensus.stage3CommunityFundShare = 10; consensus.stage3MasternodeShare = 50; diff --git a/src/validation.cpp b/src/validation.cpp index 49c5bd79a3..292ef44bd3 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -1943,17 +1943,17 @@ CAmount GetBlockSubsidyWithMTPFlag(int nHeight, const Consensus::Params &consens CAmount GetBlockSubsidy(int nHeight, const Consensus::Params &consensusParams, int nTime) { return GetBlockSubsidyWithMTPFlag(nHeight, consensusParams, nTime >= (int)consensusParams.nMTPSwitchTime, - nHeight >= (int)consensusParams.stage3StartBlock); + nTime >= (int)consensusParams.stage3StartTime); } CAmount GetMasternodePayment(int nHeight, int nTime, CAmount blockValue) { const Consensus::Params ¶ms = Params().GetConsensus(); - if (nHeight >= params.stage4MasternodeShare) + if (nHeight >= params.stage4StartBlock) return blockValue*params.stage4MasternodeShare/100; else if (nHeight >= params.nSubsidyHalvingSecond) return blockValue/2; - else if (nHeight >= params.stage3StartBlock) + else if (nTime >= params.stage3StartTime) return blockValue*params.stage3MasternodeShare/100; else if (nHeight >= params.nSubsidyHalvingFirst) return blockValue*params.stage2ZnodeShare/100; @@ -4832,7 +4832,7 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, const Co } if (nHeight >= consensusParams.nSubsidyHalvingFirst) { - if (nHeight >= consensusParams.stage3StartBlock) { + if (block.nTime >= consensusParams.stage3StartTime) { bool fStage4 = nHeight >= consensusParams.nSubsidyHalvingSecond; int devPayoutShare = fStage4 ? consensusParams.stage4DevelopmentFundShare : consensusParams.stage3DevelopmentFundShare; int communityPayoutShare = fStage4 ? consensusParams.stage4CommunityFundShare : consensusParams.stage3CommunityFundShare; From 327c3e84ebdc515cf838cd40d7f6793494f4137d Mon Sep 17 00:00:00 2001 From: Peter Shugalev Date: Sun, 1 Sep 2024 19:52:47 +0200 Subject: [PATCH 5/9] Workaround for testnet --- src/validation.cpp | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/src/validation.cpp b/src/validation.cpp index 292ef44bd3..5cba58e368 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -4833,24 +4833,29 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, const Co if (nHeight >= consensusParams.nSubsidyHalvingFirst) { if (block.nTime >= consensusParams.stage3StartTime) { - bool fStage4 = nHeight >= consensusParams.nSubsidyHalvingSecond; - int devPayoutShare = fStage4 ? consensusParams.stage4DevelopmentFundShare : consensusParams.stage3DevelopmentFundShare; - int communityPayoutShare = fStage4 ? consensusParams.stage4CommunityFundShare : consensusParams.stage3CommunityFundShare; - + bool fStage3 = nHeight < consensusParams.nSubsidyHalvingSecond; + bool fStage4 = nHeight >= consensusParams.stage4StartBlock; + CAmount devPayoutValue = 0, communityPayoutValue = 0; CScript devPayoutScript = GetScriptForDestination(CBitcoinAddress(consensusParams.stage3DevelopmentFundAddress).Get()); - CAmount devPayoutValue = (GetBlockSubsidy(nHeight, consensusParams, block.nTime) * devPayoutShare) / 100; CScript communityPayoutScript = GetScriptForDestination(CBitcoinAddress(consensusParams.stage3CommunityFundAddress).Get()); - CAmount communityPayoutValue = (GetBlockSubsidy(nHeight, consensusParams, block.nTime) * communityPayoutShare) / 100; - bool devFound = false, communityFound = false; - for (const CTxOut &txout: block.vtx[0]->vout) { - if (txout.scriptPubKey == devPayoutScript && txout.nValue == devPayoutValue) - devFound = true; - else if (txout.scriptPubKey == communityPayoutScript && txout.nValue == communityPayoutValue) - communityFound = true; + // There is no dev/community payout for testnet for some time + if (fStage3 || fStage4) { + int devShare = fStage3 ? consensusParams.stage3DevelopmentFundShare : consensusParams.stage4DevelopmentFundShare; + int communityShare = fStage3 ? consensusParams.stage3CommunityFundShare : consensusParams.stage4CommunityFundShare; + devPayoutValue = (GetBlockSubsidy(nHeight, consensusParams, block.nTime) * devShare) / 100; + communityPayoutValue = (GetBlockSubsidy(nHeight, consensusParams, block.nTime) * communityShare) / 100; + + bool devFound = false, communityFound = false; + for (const CTxOut &txout: block.vtx[0]->vout) { + if (txout.scriptPubKey == devPayoutScript && txout.nValue == devPayoutValue) + devFound = true; + else if (txout.scriptPubKey == communityPayoutScript && txout.nValue == communityPayoutValue) + communityFound = true; + } + if (!devFound || !communityFound) + return state.Invalid(false, state.GetRejectCode(), state.GetRejectReason(), "Stage 3 developer/community reward check failed"); } - if (!devFound || !communityFound) - return state.Invalid(false, state.GetRejectCode(), state.GetRejectReason(), "Stage 3 developer/community reward check failed"); } else { // "stage 2" interval between first and second halvings From dfede8fe136983b3209093fe5c4940e013b2338e Mon Sep 17 00:00:00 2001 From: Peter Shugalev Date: Sun, 1 Sep 2024 20:07:12 +0200 Subject: [PATCH 6/9] Devnet parameter tweak --- src/chainparams.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 1fe414fa1f..8a5d9fc168 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -799,8 +799,8 @@ class CDevNetParams : public CChainParams { consensus.chainType = Consensus::chainDevnet; consensus.nSubsidyHalvingFirst = 1; - consensus.nSubsidyHalvingSecond = 3500; - consensus.nSubsidyHalvingInterval = 100000; + consensus.nSubsidyHalvingSecond = 3000; + consensus.nSubsidyHalvingInterval = 10000; consensus.stage2DevelopmentFundShare = 15; consensus.stage2ZnodeShare = 35; From 7a4cdb3a87a70335ece34d979880bbf4db9fb9c4 Mon Sep 17 00:00:00 2001 From: levonpetrosyan93 Date: Mon, 2 Sep 2024 02:54:30 +0400 Subject: [PATCH 7/9] Sigma pool closed --- src/consensus/consensus.h | 1 + src/lelantus.cpp | 7 +++++++ src/validation.cpp | 5 +++++ src/wallet/lelantusjoinsplitbuilder.cpp | 3 +++ 4 files changed, 16 insertions(+) diff --git a/src/consensus/consensus.h b/src/consensus/consensus.h index 1ae4e59f92..1371a0d07e 100644 --- a/src/consensus/consensus.h +++ b/src/consensus/consensus.h @@ -36,6 +36,7 @@ static const unsigned int MAX_BLOCK_BASE_SIZE = 2000000; static const int64_t MAX_BLOCK_SIGOPS_COST = 400000; /** The maximum allowed size of version 3 extra payload */ static const unsigned int MAX_TX_EXTRA_PAYLOAD = 150000; +static const unsigned int NEW_MAX_TX_EXTRA_PAYLOAD = 230000; /** Coinbase transaction outputs can only be spent after this number of new blocks (network rule) */ static const int COINBASE_MATURITY = 100; diff --git a/src/lelantus.cpp b/src/lelantus.cpp index 95e45e2fab..af4fd8ffd7 100644 --- a/src/lelantus.cpp +++ b/src/lelantus.cpp @@ -421,6 +421,13 @@ bool CheckLelantusJoinSplitTransaction( "CTransaction::CheckLelantusJoinSplitTransaction() : Error: incorrect joinsplit transaction verion"); } + if (joinsplit->isSigmaToLelantus() && height >= params.stage4StartBlock) { + return state.DoS(100, + false, + NSEQUENCE_INCORRECT, + "CTransaction::CheckLelantusJoinSplitTransaction() : Sigma pool already closed."); + } + uint256 txHashForMetadata; // Obtain the hash of the transaction sans the zerocoin part diff --git a/src/validation.cpp b/src/validation.cpp index 5cba58e368..656d640b4e 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -964,6 +964,11 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C const std::vector &ids = joinsplit->getCoinGroupIds(); const std::vector& serials = joinsplit->getCoinSerialNumbers(); + if (joinsplit->isSigmaToLelantus() && chainActive.Height() >= consensus.stage4StartBlock) { + return state.DoS(100, error("Sigma pool already closed."), + REJECT_INVALID, "txn-invalid-lelantus-joinsplit"); + } + if (serials.size() != ids.size()) return state.Invalid(false, REJECT_CONFLICT, "txn-invalid-lelantus-joinsplit"); diff --git a/src/wallet/lelantusjoinsplitbuilder.cpp b/src/wallet/lelantusjoinsplitbuilder.cpp index eba439524c..c6ef7363eb 100644 --- a/src/wallet/lelantusjoinsplitbuilder.cpp +++ b/src/wallet/lelantusjoinsplitbuilder.cpp @@ -193,6 +193,9 @@ CWalletTx LelantusJoinSplitBuilder::Build( std::vector denomChanges; try { + if (chainActive.Height() >= Params().GetConsensus().stage4StartBlock) + throw std::runtime_error(_("Sigma pool already closed.")); + CAmount availableBalance(0); for (auto coin : sigmaCoins) { availableBalance += coin.get_denomination_value(); From 0fdb02fb9e5f1706e44d4875eb838560c6f87c93 Mon Sep 17 00:00:00 2001 From: levonpetrosyan93 Date: Mon, 2 Sep 2024 03:24:35 +0400 Subject: [PATCH 8/9] Extra payload size limit increased --- src/validation.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/validation.cpp b/src/validation.cpp index 656d640b4e..cbc8b6b258 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -662,7 +662,7 @@ bool CheckTransaction(const CTransaction &tx, CValidationState &state, bool fChe // Size limits (this doesn't take the witness into account, as that hasn't been checked for malleability) if (::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) > MAX_BLOCK_BASE_SIZE) return state.DoS(100, false, REJECT_INVALID, "bad-txns-oversize"); - if (tx.vExtraPayload.size() > MAX_TX_EXTRA_PAYLOAD) + if ((tx.vExtraPayload.size() > MAX_TX_EXTRA_PAYLOAD && nHeight < ::Params().GetConsensus().stage4StartBlock) || tx.vExtraPayload.size() > NEW_MAX_TX_EXTRA_PAYLOAD) return state.DoS(100, false, REJECT_INVALID, "bad-txns-payload-oversize"); // Check for negative or overflow output values From 29666c7719e239d2bc4bc4e9bba96b84eb2abb84 Mon Sep 17 00:00:00 2001 From: Peter Shugalev Date: Mon, 2 Sep 2024 12:10:47 +0200 Subject: [PATCH 9/9] Changed HF block for testnet --- src/chainparams.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 8a5d9fc168..67558159cf 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -532,7 +532,7 @@ class CTestNetParams : public CChainParams { consensus.stage3DevelopmentFundAddress = "TWDxLLKsFp6qcV1LL4U2uNmW4HwMcapmMU"; consensus.stage3CommunityFundAddress = "TCkC4uoErEyCB4MK3d6ouyJELoXnuyqe9L"; - consensus.stage4StartBlock = 168500; + consensus.stage4StartBlock = 167500; consensus.stage4CommunityFundShare = 10; consensus.stage4DevelopmentFundShare = 15; consensus.stage4MasternodeShare = 70;