Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adjustment for block numbers in consensus following faster blocks hardfork #1185

Merged
merged 5 commits into from
Jul 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 23 additions & 4 deletions src/chainparams.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,17 @@

using namespace secp_primitives;

// If some feature is enabled at block intervalStart and its duration is intervalLength halving distance between blocks
// causes the end to happen sooner in real time. This function adjusts the end block number so the approximate ending time
// is left intact
static constexpr int AdjustEndingBlockNumberAfterSubsidyHalving(int intervalStart, int intervalLength, int halvingPoint) {
if (halvingPoint < intervalStart || halvingPoint >= intervalStart + intervalLength)
// halving occurs outside of interval
return intervalStart + intervalLength;
else
return halvingPoint + (intervalStart + intervalLength - halvingPoint)*2;
}

static CBlock CreateGenesisBlock(const char *pszTimestamp, const CScript &genesisOutputScript, uint32_t nTime, uint32_t nNonce,
uint32_t nBits, int32_t nVersion, const CAmount &genesisReward,
std::vector<unsigned char> extraNonce) {
Expand Down Expand Up @@ -179,14 +190,16 @@ class CMainParams : public CChainParams {
consensus.chainType = Consensus::chainMain;

consensus.nSubsidyHalvingFirst = 302438;
consensus.nSubsidyHalvingInterval = 420000;
consensus.nSubsidyHalvingStopBlock = 3646849;
consensus.nSubsidyHalvingSecond = AdjustEndingBlockNumberAfterSubsidyHalving(302438, 420000, 486221); // =958665
consensus.nSubsidyHalvingInterval = 420000*2;
consensus.nSubsidyHalvingStopBlock = AdjustEndingBlockNumberAfterSubsidyHalving(0, 3646849, 486221); // =6807477

consensus.stage2DevelopmentFundShare = 15;
consensus.stage2ZnodeShare = 35;
consensus.stage2DevelopmentFundAddress = "aFrAVZFr8pva5mG8XKaUH8EXcFVVNxLiuB";

consensus.stage3StartTime = 1655380800; // Thursday, 16 June 2022 12:00:00 UTC
consensus.stage3StartBlock = 486221;
consensus.stage3DevelopmentFundShare = 15;
consensus.stage3CommunityFundShare = 10;
consensus.stage3MasternodeShare = 50;
Expand Down Expand Up @@ -425,7 +438,7 @@ class CMainParams : public CChainParams {

consensus.evoSporkKeyID = "a78fERshquPsTv2TuKMSsxTeKom56uBwLP";
consensus.nEvoSporkStartBlock = ZC_LELANTUS_STARTING_BLOCK;
consensus.nEvoSporkStopBlock = ZC_LELANTUS_STARTING_BLOCK + 2*24*12*365; // two years after lelantus
consensus.nEvoSporkStopBlock = AdjustEndingBlockNumberAfterSubsidyHalving(ZC_LELANTUS_STARTING_BLOCK, 2*24*12*365, 486221); // =608035, two years after lelantus
consensus.nEvoSporkStopBlockExtensionVersion = 140903;
consensus.nEvoSporkStopBlockPrevious = ZC_LELANTUS_STARTING_BLOCK + 1*24*12*365; // one year after lelantus
consensus.nEvoSporkStopBlockExtensionGracefulPeriod = 24*12*14; // two weeks
Expand Down Expand Up @@ -490,6 +503,7 @@ class CTestNetParams : public CChainParams {
consensus.chainType = Consensus::chainTestnet;

consensus.nSubsidyHalvingFirst = 12000;
consensus.nSubsidyHalvingSecond = 150000;
consensus.nSubsidyHalvingInterval = 150000;
consensus.nSubsidyHalvingStopBlock = 1000000;

Expand All @@ -498,6 +512,7 @@ class CTestNetParams : public CChainParams {
consensus.stage2DevelopmentFundAddress = "TUuKypsbbnHHmZ2auC2BBWfaP1oTEnxjK2";

consensus.stage3StartTime = 1653409800; // May 24th 2022 04:30 UTC
consensus.stage3StartBlock = 84459;
consensus.stage3DevelopmentFundShare = 15;
consensus.stage3CommunityFundShare = 10;
consensus.stage3MasternodeShare = 50;
Expand Down Expand Up @@ -753,6 +768,7 @@ class CDevNetParams : public CChainParams {
consensus.chainType = Consensus::chainDevnet;

consensus.nSubsidyHalvingFirst = 120;
consensus.nSubsidyHalvingSecond = 100000;
consensus.nSubsidyHalvingInterval = 100000;
consensus.nSubsidyHalvingStopBlock = 1000000;

Expand All @@ -761,6 +777,7 @@ class CDevNetParams : public CChainParams {
consensus.stage2DevelopmentFundAddress = "TixHByoJ21dmx5xfMAXTVC4V7k53U7RncU";

consensus.stage3StartTime = 1653382800;
consensus.stage3StartBlock = 1514;
consensus.stage3DevelopmentFundShare = 15;
consensus.stage3CommunityFundShare = 10;
consensus.stage3MasternodeShare = 50;
Expand Down Expand Up @@ -979,6 +996,7 @@ class CRegTestParams : public CChainParams {

// To be changed for specific tests
consensus.nSubsidyHalvingFirst = 1500;
consensus.nSubsidyHalvingSecond = 2500;
consensus.nSubsidyHalvingInterval = 1000;
consensus.nSubsidyHalvingStopBlock = 10000;

Expand All @@ -987,7 +1005,8 @@ class CRegTestParams : public CChainParams {
consensus.stage2DevelopmentFundShare = 15;
consensus.stage2ZnodeShare = 35;

consensus.stage3StartTime = INT_MAX; // Thursday, 16 June 2022 12:00:00 UTC
consensus.stage3StartTime = INT_MAX;
consensus.stage3StartBlock = 0;
consensus.stage3DevelopmentFundShare = 15;
consensus.stage3CommunityFundShare = 10;
consensus.stage3MasternodeShare = 50;
Expand Down
4 changes: 4 additions & 0 deletions src/consensus/params.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,8 @@ struct Params {
uint256 hashGenesisBlock;
/** First subsidy halving */
int nSubsidyHalvingFirst;
/** Second subsidy halving */
int nSubsidyHalvingSecond;
/** Subsequent subsidy halving intervals */
int nSubsidyHalvingInterval;
/** Stop subsidy at this block number */
Expand All @@ -148,6 +150,8 @@ struct Params {
/** parameters for coinbase payment distribution after stage two and before second halving (aka stage 3) */
/** start time of stage 3 */
int stage3StartTime;
/** starting block number of stage 3 (zero if unknown) */
int stage3StartBlock;
/** P2PKH or P2SH address for developer funds */
std::string stage3DevelopmentFundAddress;
/** P2PKH or P2SH address for community funds */
Expand Down
2 changes: 1 addition & 1 deletion src/miner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -807,7 +807,7 @@ void BlockAssembler::FillFoundersReward(CMutableTransaction &coinbaseTx, bool fM
if (fShorterBlockDistance)
coin /= 2;

if (nHeight >= params.nSubsidyHalvingFirst && nHeight < params.nSubsidyHalvingFirst + params.nSubsidyHalvingInterval) {
if (nHeight >= params.nSubsidyHalvingFirst && nHeight < params.nSubsidyHalvingSecond) {
if (fShorterBlockDistance) {
// Stage 3
CScript devPayoutScript = GetScriptForDestination(CBitcoinAddress(params.stage3DevelopmentFundAddress).Get());
Expand Down
4 changes: 2 additions & 2 deletions src/net_processing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1443,9 +1443,9 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
if (!vRecv.empty()) {
vRecv >> LIMITED_STRING(strSubVer, MAX_SUBVERSION_LENGTH);
cleanSubVer = SanitizeString(strSubVer);
int parsedVersion[4];
int parsedVersion[4] = {0, 0, 0, 0};
if (sscanf(cleanSubVer.c_str(), "/Satoshi:%2d.%2d.%2d.%2d/",
&parsedVersion[0], &parsedVersion[1], &parsedVersion[2], &parsedVersion[3]) == 4) {
&parsedVersion[0], &parsedVersion[1], &parsedVersion[2], &parsedVersion[3]) >= 2) {
int peerClientVersion = parsedVersion[0]*1000000 + parsedVersion[1]*10000 + parsedVersion[2]*100 + parsedVersion[3];
if (peerClientVersion < MIN_FIRO_CLIENT_VERSION) {
connman.PushMessage(pfrom, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::REJECT, strCommand, REJECT_OBSOLETE, "This version is banned from the network"));
Expand Down
28 changes: 17 additions & 11 deletions src/pow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,25 +109,31 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead
return (exponent << 24) | base;
}

if (pblock->nTime < params.stage3StartTime + BlocksTargetSpacing*PastBlocksMax*3) {
uint32_t numberOfStage3Blocks = pindexLast->nHeight;

if (params.stage3StartBlock != 0) {
// we know the first stage3 block
numberOfStage3Blocks = pindexLast->nHeight - params.stage3StartBlock + 1;
}
else if (pblock->nTime < params.stage3StartTime + BlocksTargetSpacing*PastBlocksMax*3) {
// transition to stage3 happened recently, look for the last block before the transition
const CBlockIndex *pindex = pindexLast;
while (pindex && pindex->nTime >= params.stage3StartTime)
pindex = pindex->pprev;

if (pindex) {
uint32_t numberOfStage3Blocks = pindexLast->nHeight - pindex->nHeight;
if (numberOfStage3Blocks < params.DifficultyAdjustmentInterval(true)/2)
// do not retarget if too few stage3 blocks
return pindexLast->nBits;

PastBlocksMin = std::min(PastBlocksMin, numberOfStage3Blocks);
PastBlocksMax = std::min(PastBlocksMax, numberOfStage3Blocks);
}
if (pindex)
numberOfStage3Blocks = pindexLast->nHeight - pindex->nHeight;
}

if (numberOfStage3Blocks < params.DifficultyAdjustmentInterval(true)/2)
// do not retarget if too few stage3 blocks
return pindexLast->nBits;

PastBlocksMin = std::min(PastBlocksMin, numberOfStage3Blocks);
PastBlocksMax = std::min(PastBlocksMax, numberOfStage3Blocks);
}
else if (pblock->IsProgPow()) {
uint32_t numberOfPPBlocks = 0;
uint32_t numberOfPPBlocks = pindexLast->nHeight;

if (params.nPPBlockNumber != 0) {
// we know the first ProgPow block
Expand Down
31 changes: 27 additions & 4 deletions src/test/firsthalving_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,8 @@ BOOST_FIXTURE_TEST_CASE(devpayout, TestChainDIP3BeforeActivationSetup)

consensusParams.nSubsidyHalvingFirst = 600;
consensusParams.stage3StartTime = INT_MAX;
consensusParams.nSubsidyHalvingInterval = 20;
consensusParams.nSubsidyHalvingSecond = 620;
consensusParams.nSubsidyHalvingInterval = 10;
consensusParams.nSubsidyHalvingStopBlock = 1000;

CScript devPayoutScript = GenerateRandomAddress();
Expand Down Expand Up @@ -252,13 +253,34 @@ BOOST_FIXTURE_TEST_CASE(devpayout, TestChainDIP3BeforeActivationSetup)
BOOST_ASSERT(block.vtx[0]->GetValueOut() == 25*COIN/2);
}

for (int i=620; i<630; i++) {
CBlock block = CreateAndProcessBlock({}, coinbaseKey);
deterministicMNManager->UpdatedBlockTip(chainActive.Tip());

CAmount nValue;
auto dmnPayout = FindPayoutDmn(block, nValue);

BOOST_ASSERT(dmnPayout != nullptr && nValue == 3125*COIN/1000); // 3.125 (6.25*0.5)

// there should be no more payment to devs fund
for (const CTxOut &txout: block.vtx[0]->vout) {
BOOST_ASSERT(txout.scriptPubKey != GetScriptForDestination(CBitcoinAddress(consensusParams.stage2DevelopmentFundAddress).Get()));
}

// miner's reward should be 6.25-3.125 = 3.125
BOOST_ASSERT(block.vtx[0]->vout[0].nValue == 3125*COIN/1000);
// should be only 2 vouts in coinbase
BOOST_ASSERT(block.vtx[0]->vout.size() == 2);
}

// the third halving should occur at block 630
CBlock block = CreateAndProcessBlock({}, coinbaseKey);
deterministicMNManager->UpdatedBlockTip(chainActive.Tip());

CAmount nValue;
auto dmnPayout = FindPayoutDmn(block, nValue);

BOOST_ASSERT(dmnPayout != nullptr && nValue == 3125*COIN/1000); // (25/4*0.5)
BOOST_ASSERT(dmnPayout != nullptr && nValue == 3125*COIN/1000/2); // 3.125/2 (3.125*0.5)

// there should be no more payment to devs/community funds fund
for (const CTxOut &txout: block.vtx[0]->vout) {
Expand All @@ -267,8 +289,8 @@ BOOST_FIXTURE_TEST_CASE(devpayout, TestChainDIP3BeforeActivationSetup)
txout.scriptPubKey != GetScriptForDestination(CBitcoinAddress(consensusParams.stage3CommunityFundAddress).Get()));
}

// miner's reward should be 3.125
BOOST_ASSERT(block.vtx[0]->vout[0].nValue == 3125*COIN/1000);
// miner's reward should be 3.125/2
BOOST_ASSERT(block.vtx[0]->vout[0].nValue == 3125*COIN/1000/2);
// should be only 2 vouts in coinbase
BOOST_ASSERT(block.vtx[0]->vout.size() == 2);

Expand All @@ -281,6 +303,7 @@ BOOST_FIXTURE_TEST_CASE(devpayoutverification, TestChainDIP3BeforeActivationSetu
Consensus::Params consensusParamsBackup = consensusParams;

consensusParams.nSubsidyHalvingFirst = 600;
consensusParams.nSubsidyHalvingSecond = 610;
consensusParams.nSubsidyHalvingInterval = 10;
consensusParams.nSubsidyHalvingStopBlock = 1000;

Expand Down
18 changes: 12 additions & 6 deletions src/test/main_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,29 +46,35 @@ BOOST_AUTO_TEST_CASE(subsidy_limit_test)
{
Consensus::Params consensusParams = Params(CBaseChainParams::MAIN).GetConsensus();
CAmount nSum = 0;
const int nMTPFirstBlock = 117564;
int lastHalving = (consensusParams.nSubsidyHalvingStopBlock - consensusParams.nSubsidyHalvingFirst)/consensusParams.nSubsidyHalvingInterval;
int lastHalvingBlock = consensusParams.nSubsidyHalvingFirst + lastHalving*consensusParams.nSubsidyHalvingInterval;
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.nSubsidyHalvingFirst)
if (nHeight == consensusParams.nSubsidyHalvingSecond)
step = 1000;
else if (nHeight == lastHalvingBlock)
step = 1;
else if (nHeight == consensusParams.nSubsidyHalvingStopBlock)
step = 10000;

CAmount nSubsidy = GetBlockSubsidy(nHeight, consensusParams, nHeight<nMTPFirstBlock ? consensusParams.nMTPSwitchTime-1000 : consensusParams.nMTPSwitchTime);
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, 2095751201171875ULL);
BOOST_CHECK_EQUAL(nSum, 2095751200767464ULL);
}

bool ReturnFalse() { return false; }
Expand Down
14 changes: 11 additions & 3 deletions src/validation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1717,11 +1717,19 @@ CAmount GetBlockSubsidyWithMTPFlag(int nHeight, const Consensus::Params &consens
if (nHeight == 0)
return 0;

// Subsidy is cut in half after nSubsidyHalvingFirst block, then every nSubsidyHalvingInterval blocks.
// 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;
int halvings = nHeight < consensusParams.nSubsidyHalvingFirst ? 0 : (nHeight - consensusParams.nSubsidyHalvingFirst) / consensusParams.nSubsidyHalvingInterval + 1;

int halvings;
if (nHeight < consensusParams.nSubsidyHalvingFirst)
halvings = 0;
else if (nHeight < consensusParams.nSubsidyHalvingSecond)
halvings = 1;
else
halvings = (nHeight - consensusParams.nSubsidyHalvingSecond) / consensusParams.nSubsidyHalvingInterval + 2;

// Force block reward to zero when right shift is undefined.
if (halvings >= 64)
return 0;
Expand Down Expand Up @@ -4576,7 +4584,7 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, const Co
}

if (nHeight >= consensusParams.nSubsidyHalvingFirst) {
if (nHeight < consensusParams.nSubsidyHalvingFirst + consensusParams.nSubsidyHalvingInterval) {
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;
Expand Down
2 changes: 1 addition & 1 deletion src/version.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ static const int SHORT_IDS_BLOCKS_VERSION = 90013;
static const int INVALID_CB_NO_BAN_VERSION = 90013;

//! minimum version of official client to connect to
static const int MIN_FIRO_CLIENT_VERSION = 140900; // 0.14.9.0
static const int MIN_FIRO_CLIENT_VERSION = 141000; // 0.14.10.0

//! introduction of DIP3/deterministic masternodes
static const int DMN_PROTO_VERSION = 90030;
Expand Down