diff --git a/src/bench/duplicate_inputs.cpp b/src/bench/duplicate_inputs.cpp index c7628139cba..35950837196 100644 --- a/src/bench/duplicate_inputs.cpp +++ b/src/bench/duplicate_inputs.cpp @@ -30,7 +30,7 @@ static void DuplicateInputs(benchmark::State& state) LOCK(cs_main); CBlockIndex* pindexPrev = ::ChainActive().Tip(); assert(pindexPrev != nullptr); - block.nBits = pos::GetNextWorkRequired(pindexPrev, &block, chainparams.GetConsensus().pos); + block.nBits = pos::GetNextWorkRequired(pindexPrev, &block, chainparams.GetConsensus()); // block.nNonce = 0; auto nHeight = pindexPrev->nHeight + 1; diff --git a/src/chainparams.cpp b/src/chainparams.cpp index d4ca1342a4b..eaa134fe288 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -131,13 +131,12 @@ class CMainParams : public CChainParams { // consensus.pos.nTargetSpacing = 10 * 60; // 10 minutes consensus.pos.nTargetTimespan = 5 * 60; // 5 min == 10 blocks consensus.pos.nTargetSpacing = 30; // seconds + consensus.pos.nTargetTimespanV2 = 1008 * consensus.pos.nTargetSpacing; // 1008 blocks consensus.pos.nStakeMinAge = 0; consensus.pos.nStakeMaxAge = 14 * 24 * 60 * 60; // Two weeks consensus.pos.fAllowMinDifficultyBlocks = false; // only for regtest consensus.pos.fNoRetargeting = false; // only for regtest - consensus.pos.coinstakeMaturity = 100; - consensus.pos.allowMintingWithoutPeers = false; // don't mint if no peers connected consensus.CSVHeight = 1; // 000000000000000004a1b34462cb8aeebd5799177f7a29cf28f2d1961716b5b5 @@ -343,13 +342,12 @@ class CTestNetParams : public CChainParams { // consensus.pos.nTargetSpacing = 10 * 60; // 10 minutes consensus.pos.nTargetTimespan = 5 * 60; // 5 min == 10 blocks consensus.pos.nTargetSpacing = 30; + consensus.pos.nTargetTimespanV2 = 1008 * consensus.pos.nTargetSpacing; // 1008 blocks consensus.pos.nStakeMinAge = 0; consensus.pos.nStakeMaxAge = 14 * 24 * 60 * 60; // Two weeks consensus.pos.fAllowMinDifficultyBlocks = false; consensus.pos.fNoRetargeting = false; // only for regtest - consensus.pos.coinstakeMaturity = 100; - consensus.pos.allowMintingWithoutPeers = true; consensus.CSVHeight = 1; // 00000000025e930139bac5c6c31a403776da130831ab85be56578f3fa75369bb @@ -514,13 +512,12 @@ class CDevNetParams : public CChainParams { consensus.pos.diffLimit = uint256S("00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); consensus.pos.nTargetTimespan = 5 * 60; // 5 min == 10 blocks consensus.pos.nTargetSpacing = 30; + consensus.pos.nTargetTimespanV2 = 1008 * consensus.pos.nTargetSpacing; // 1008 blocks consensus.pos.nStakeMinAge = 0; consensus.pos.nStakeMaxAge = 14 * 24 * 60 * 60; // Two weeks consensus.pos.fAllowMinDifficultyBlocks = false; consensus.pos.fNoRetargeting = false; // only for regtest - consensus.pos.coinstakeMaturity = 100; - consensus.pos.allowMintingWithoutPeers = true; consensus.CSVHeight = 1; @@ -678,14 +675,13 @@ class CRegTestParams : public CChainParams { consensus.pos.diffLimit = uint256S("00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); consensus.pos.nTargetTimespan = 14 * 24 * 60 * 60; // two weeks + consensus.pos.nTargetTimespanV2 = 14 * 24 * 60 * 60; // two weeks consensus.pos.nTargetSpacing = 10 * 60; // 10 minutes consensus.pos.nStakeMinAge = 0; consensus.pos.nStakeMaxAge = 14 * 24 * 60 * 60; // Two weeks consensus.pos.fAllowMinDifficultyBlocks = true; // only for regtest consensus.pos.fNoRetargeting = true; // only for regtest - consensus.pos.coinstakeMaturity = 100; - consensus.pos.allowMintingWithoutPeers = true; // don't mint if no peers connected consensus.CSVHeight = 432; // CSV activated on regtest (Used in rpc activation tests) diff --git a/src/consensus/params.h b/src/consensus/params.h index e1f927f35a5..f4e801a9eaf 100644 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -113,6 +113,7 @@ struct Params { struct PoS { uint256 diffLimit; int64_t nTargetTimespan; + int64_t nTargetTimespanV2; int64_t nTargetSpacing; int64_t nStakeMinAge; int64_t nStakeMaxAge; @@ -120,10 +121,10 @@ struct Params { bool fNoRetargeting; int64_t DifficultyAdjustmentInterval() const { return nTargetTimespan / nTargetSpacing; } + int64_t DifficultyAdjustmentIntervalV2() const { return nTargetTimespanV2 / nTargetSpacing; } arith_uint256 interestAtoms = arith_uint256{10000000000000000ull}; bool allowMintingWithoutPeers; - int coinstakeMaturity = 500; }; PoS pos; diff --git a/src/miner.cpp b/src/miner.cpp index f87b778c3b3..a20dd14f6d6 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -44,7 +44,7 @@ int64_t UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParam // Updating time can change work required on testnet: if (consensusParams.pos.fAllowMinDifficultyBlocks) - pblock->nBits = pos::GetNextWorkRequired(pindexPrev, pblock, consensusParams.pos); + pblock->nBits = pos::GetNextWorkRequired(pindexPrev, pblock, consensusParams); return nNewTime - nOldTime; } @@ -314,7 +314,7 @@ std::unique_ptr BlockAssembler::CreateNewBlock(const CScript& sc // Fill in header pblock->hashPrevBlock = pindexPrev->GetBlockHash(); UpdateTime(pblock, consensus, pindexPrev); - pblock->nBits = pos::GetNextWorkRequired(pindexPrev, pblock, consensus.pos); + pblock->nBits = pos::GetNextWorkRequired(pindexPrev, pblock, consensus); pblock->stakeModifier = pos::ComputeStakeModifier(pindexPrev->stakeModifier, myIDs->first); pblocktemplate->vTxSigOpsCost[0] = WITNESS_SCALE_FACTOR * GetLegacySigOpCount(*pblock->vtx[0]); diff --git a/src/pos.cpp b/src/pos.cpp index e8fe3047138..ee1059f223f 100644 --- a/src/pos.cpp +++ b/src/pos.cpp @@ -88,24 +88,35 @@ bool CheckProofOfStake(const CBlockHeader& blockHeader, const CBlockIndex* pinde return CheckStakeModifier(pindexPrev, blockHeader) && ContextualCheckProofOfStake(blockHeader, params, mnView); } -unsigned int CalculateNextWorkRequired(const CBlockIndex* pindexLast, int64_t nFirstBlockTime, const Consensus::Params::PoS& params) +unsigned int CalculateNextWorkRequired(const CBlockIndex* pindexLast, int64_t nFirstBlockTime, const Consensus::Params::PoS& params, bool eunos) { if (params.fNoRetargeting) return pindexLast->nBits; // Limit adjustment step int64_t nActualTimespan = pindexLast->GetBlockTime() - nFirstBlockTime; - if (nActualTimespan < params.nTargetTimespan/4) - nActualTimespan = params.nTargetTimespan/4; - if (nActualTimespan > params.nTargetTimespan*4) - nActualTimespan = params.nTargetTimespan*4; + if (eunos) { + if (nActualTimespan < params.nTargetTimespanV2/4) + nActualTimespan = params.nTargetTimespanV2/4; + if (nActualTimespan > params.nTargetTimespanV2*4) + nActualTimespan = params.nTargetTimespanV2*4; + } else { + if (nActualTimespan < params.nTargetTimespan/4) + nActualTimespan = params.nTargetTimespan/4; + if (nActualTimespan > params.nTargetTimespan*4) + nActualTimespan = params.nTargetTimespan*4; + } // Retarget const arith_uint256 bnDiffLimit = UintToArith256(params.diffLimit); arith_uint256 bnNew; bnNew.SetCompact(pindexLast->nBits); bnNew *= nActualTimespan; - bnNew /= params.nTargetTimespan; + if (eunos) { + bnNew /= params.nTargetTimespanV2; + } else { + bnNew /= params.nTargetTimespan; + } if (bnNew > bnDiffLimit) bnNew = bnDiffLimit; @@ -113,29 +124,35 @@ unsigned int CalculateNextWorkRequired(const CBlockIndex* pindexLast, int64_t nF return bnNew.GetCompact(); } -unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params::PoS& params) +unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params& params) { assert(pindexLast != nullptr); - if (params.fNoRetargeting) + if (params.pos.fNoRetargeting) return pindexLast->nBits; - unsigned int nProofOfWorkLimit = UintToArith256(params.diffLimit).GetCompact(); + unsigned int nProofOfWorkLimit = UintToArith256(params.pos.diffLimit).GetCompact(); + + int nHeight{pindexLast->nHeight + 1}; + bool eunos{nHeight > params.EunosHeight}; + const auto interval = eunos ? params.pos.DifficultyAdjustmentIntervalV2() : params.pos.DifficultyAdjustmentInterval(); + bool skipChange = eunos ? (nHeight - params.EunosHeight) % interval != 0 : nHeight % interval != 0; // Only change once per difficulty adjustment interval - if ((pindexLast->nHeight+1) % params.DifficultyAdjustmentInterval() != 0) + if (skipChange) { - if (params.fAllowMinDifficultyBlocks) + // Regtest only + if (params.pos.fAllowMinDifficultyBlocks) { // Special difficulty rule for testnet: // If the new block's timestamp is more than 2* 10 minutes // then allow mining of a min-difficulty block. - if (pblock->GetBlockTime() > pindexLast->GetBlockTime() + params.nTargetSpacing*2) + if (pblock->GetBlockTime() > pindexLast->GetBlockTime() + params.pos.nTargetSpacing*2) return nProofOfWorkLimit; else { // Return the last non-special-min-difficulty-rules-block const CBlockIndex* pindex = pindexLast; - while (pindex->pprev && pindex->nHeight % params.DifficultyAdjustmentInterval() != 0 && pindex->nBits == nProofOfWorkLimit) + while (pindex->pprev && pindex->nHeight % params.pos.DifficultyAdjustmentInterval() != 0 && pindex->nBits == nProofOfWorkLimit) pindex = pindex->pprev; return pindex->nBits; } @@ -144,12 +161,12 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead } // Go back by what we want to be 14 days worth of blocks - int nHeightFirst = pindexLast->nHeight - (params.DifficultyAdjustmentInterval()-1); + int nHeightFirst = pindexLast->nHeight - (interval - 1); assert(nHeightFirst >= 0); const CBlockIndex* pindexFirst = pindexLast->GetAncestor(nHeightFirst); assert(pindexFirst); - return pos::CalculateNextWorkRequired(pindexLast, pindexFirst->GetBlockTime(), params); + return pos::CalculateNextWorkRequired(pindexLast, pindexFirst->GetBlockTime(), params.pos, eunos); } boost::optional SignPosBlock(std::shared_ptr pblock, const CKey &key) { diff --git a/src/pos.h b/src/pos.h index 4bdfdfb4384..e855be5e128 100644 --- a/src/pos.h +++ b/src/pos.h @@ -33,9 +33,9 @@ namespace pos { /// Check kernel hash target and coinstake signature. Check that block coinstakeTx matches header bool CheckProofOfStake(const CBlockHeader& blockHeader, const CBlockIndex* pindexPrev, const Consensus::Params& params, CCustomCSView* mnView); - unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params::PoS& params); + unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params& params); - unsigned int CalculateNextWorkRequired(const CBlockIndex* pindexLast, int64_t nFirstBlockTime, const Consensus::Params::PoS& params); + unsigned int CalculateNextWorkRequired(const CBlockIndex* pindexLast, int64_t nFirstBlockTime, const Consensus::Params::PoS& params, bool eunos = false); boost::optional SignPosBlock(std::shared_ptr pblock, const CKey &key); diff --git a/src/validation.cpp b/src/validation.cpp index 6f3ea48dfc2..d30e1ad34cd 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -4074,7 +4074,7 @@ static bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationSta // Check proof of work const Consensus::Params& consensusParams = params.GetConsensus(); - if (block.nBits != pos::GetNextWorkRequired(pindexPrev, &block, consensusParams.pos)) + if (block.nBits != pos::GetNextWorkRequired(pindexPrev, &block, consensusParams)) return state.Invalid(ValidationInvalidReason::BLOCK_INVALID_HEADER, false, REJECT_INVALID, "bad-diffbits", "incorrect proof of work"); // Check against checkpoints