Skip to content

Commit

Permalink
Change difficulty adjust period (#378)
Browse files Browse the repository at this point in the history
  • Loading branch information
Bushstar authored May 12, 2021
1 parent 6428ac0 commit a2210fa
Show file tree
Hide file tree
Showing 7 changed files with 34 additions and 30 deletions.
2 changes: 1 addition & 1 deletion src/bench/duplicate_inputs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
12 changes: 4 additions & 8 deletions src/chainparams.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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)
Expand Down
3 changes: 2 additions & 1 deletion src/consensus/params.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,17 +113,18 @@ struct Params {
struct PoS {
uint256 diffLimit;
int64_t nTargetTimespan;
int64_t nTargetTimespanV2;
int64_t nTargetSpacing;
int64_t nStakeMinAge;
int64_t nStakeMaxAge;
bool fAllowMinDifficultyBlocks;
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;

Expand Down
4 changes: 2 additions & 2 deletions src/miner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -314,7 +314,7 @@ std::unique_ptr<CBlockTemplate> 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]);
Expand Down
37 changes: 22 additions & 15 deletions src/pos.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,54 +88,61 @@ 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;
const auto& nTargetTimespan = eunos ? params.nTargetTimespanV2 : params.nTargetTimespan;
if (nActualTimespan < nTargetTimespan/4)
nActualTimespan = nTargetTimespan/4;
if (nActualTimespan > nTargetTimespan*4)
nActualTimespan = nTargetTimespan*4;

// Retarget
const arith_uint256 bnDiffLimit = UintToArith256(params.diffLimit);
arith_uint256 bnNew;
bnNew.SetCompact(pindexLast->nBits);
bnNew *= nActualTimespan;
bnNew /= params.nTargetTimespan;
bnNew /= nTargetTimespan;

if (bnNew > bnDiffLimit)
bnNew = bnDiffLimit;

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;
}
Expand All @@ -144,12 +151,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<std::string> SignPosBlock(std::shared_ptr<CBlock> pblock, const CKey &key) {
Expand Down
4 changes: 2 additions & 2 deletions src/pos.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<std::string> SignPosBlock(std::shared_ptr<CBlock> pblock, const CKey &key);

Expand Down
2 changes: 1 addition & 1 deletion src/validation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit a2210fa

Please sign in to comment.