Skip to content

Commit

Permalink
Update the difficulty adjustment algorithm
Browse files Browse the repository at this point in the history
change block period to 1 min and correctly implement the
  • Loading branch information
xiaohanzhu committed Sep 5, 2019
1 parent ee49330 commit 02dd9c1
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 6 deletions.
12 changes: 6 additions & 6 deletions src/chainparams.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ class CMainParams : public CChainParams {
// one hour (in seconds)
// nPowTargetTimespan / nPowTargetSpacing = 30 blocks per adjustment

consensus.nZawyLwmaAveragingWindow = 45;
consensus.nZawyLwmaAveragingWindow = 120;

//TBD. change block time to 2mins. (13772/5) Why changing nPowTargetSpacing is not enough?
consensus.nZawyLwmaAdjustedWeightLegacy = 2754; //13772;
Expand All @@ -96,7 +96,7 @@ class CMainParams : public CChainParams {
consensus.BTCMaxFutureBlockTime = 12 * 2 * 60; // 24 mins

consensus.nPowTargetTimespan = 1 * 60 * 60; // one hour adjustment time
consensus.nPowTargetSpacing = 2 * 60; // two minute block time
consensus.nPowTargetSpacing = 1 * 60; // one minute block time
consensus.fPowAllowMinDifficultyBlocks = false;
consensus.fPowNoRetargeting = false;
consensus.nRuleChangeActivationThreshold = 1916; // 95% of 2016
Expand Down Expand Up @@ -193,7 +193,7 @@ class CTestNetParams : public CChainParams {
consensus.powLimit = uint256S("00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff");

// adjust slide window
consensus.nZawyLwmaAveragingWindow = 45;
consensus.nZawyLwmaAveragingWindow = 120;
consensus.nZawyLwmaAdjustedWeightLegacy = 13632;
consensus.nZawyLwmaAdjustedWeight = 13772;
consensus.nZawyLwmaMinDenominatorLegacy = 3;
Expand All @@ -202,7 +202,7 @@ class CTestNetParams : public CChainParams {
consensus.BTCMaxFutureBlockTime = 7 * 10 * 60; // 70 mins

consensus.nPowTargetTimespan = 14 * 24 * 60 * 60; // two weeks
consensus.nPowTargetSpacing = 2 * 60;
consensus.nPowTargetSpacing = 1 * 60;
consensus.fPowAllowMinDifficultyBlocks = true;
consensus.fPowNoRetargeting = false;
consensus.nRuleChangeActivationThreshold = 1512; // 75% for testchains
Expand Down Expand Up @@ -291,7 +291,7 @@ class CRegTestParams : public CChainParams {
consensus.powLimit = uint256S("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");


consensus.nZawyLwmaAveragingWindow = 45;
consensus.nZawyLwmaAveragingWindow = 120;
consensus.nZawyLwmaAdjustedWeightLegacy = 13772;
consensus.nZawyLwmaAdjustedWeight = 13772;
consensus.nZawyLwmaMinDenominatorLegacy = 10;
Expand All @@ -300,7 +300,7 @@ class CRegTestParams : public CChainParams {
consensus.BTCMaxFutureBlockTime = 7 * 10 * 60; // 70 mins

consensus.nPowTargetTimespan = 14 * 24 * 60 * 60; // two weeks
consensus.nPowTargetSpacing = 2 * 60;
consensus.nPowTargetSpacing = 1 * 60;
consensus.fPowAllowMinDifficultyBlocks = true;
consensus.fPowNoRetargeting = true;
consensus.nRuleChangeActivationThreshold = 108; // 75% for testchains
Expand Down
78 changes: 78 additions & 0 deletions src/pow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,84 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead
return LwmaCalculateNextWorkRequired(pindexLast, params);
}

// LWMA-1 for BTC/Zcash clones
// LWMA has the best response*stability. It rises slowly & drops fast when needed.
// Copyright (c) 2017-2018 The Bitcoin Gold developers
// Copyright (c) 2018-2019 Zawy
// Copyright (c) 2018 iamstenman (Microbitcoin)
// MIT License
// Algorithm by Zawy, a modification of WT-144 by Tom Harding
// For any changes, patches, updates, etc see
// https://github.com/zawy12/difficulty-algorithms/issues/3#issuecomment-442129791
// FTL should be lowered to about N*T/20.
// FTL in BTC clones is MAX_FUTURE_BLOCK_TIME in chain.h.
// FTL in Ignition, Numus, and others can be found in main.h as DRIFT.
// FTL in Zcash & Dash clones need to change the 2*60*60 here:
// if (block.GetBlockTime() > nAdjustedTime + 2 * 60 * 60)
// which is around line 3700 in main.cpp in ZEC and validation.cpp in Dash
// If your coin uses network time instead of node local time, lowering FTL < about 125% of the
// "revert to node time" rule (70 minutes in BCH, ZEC, & BTC) allows 33% Sybil attack,
// so revert rule must be ~ FTL/2 instead of 70 minutes. See:
// https://github.com/zcash/zcash/issues/4021

unsigned int Lwma3CalculateNextWorkRequired(const CBlockIndex* pindexLast, const Consensus::Params& params)
{
const int64_t T = params.nPowTargetSpacing;

// For T=600, 300, 150 use approximately N=60, 90, 120
const int64_t N = params.nZawyLwmaAveragingWindow;

// Define a k that will be used to get a proper average after weighting the solvetimes.
const int64_t k = N * (N + 1) * T / 2;

const int64_t height = pindexLast->nHeight;
const arith_uint256 powLimit = UintToArith256(params.powLimit);

// New coins should just give away first N blocks before using this algorithm.
if (height < N) { return powLimit.GetCompact(); }

arith_uint256 avgTarget, nextTarget;
int64_t thisTimestamp, previousTimestamp;
int64_t sumWeightedSolvetimes = 0, j = 0;

const CBlockIndex* blockPreviousTimestamp = pindexLast->GetAncestor(height - N);
previousTimestamp = blockPreviousTimestamp->GetBlockTime();

// Loop through N most recent blocks.
for (int64_t i = height - N + 1; i <= height; i++) {
const CBlockIndex* block = pindexLast->GetAncestor(i);

// Prevent solvetimes from being negative in a safe way. It must be done like this.
// In particular, do not attempt anything like if(solvetime < 0) {solvetime=0;}
// The +1 ensures new coins do not calculate nextTarget = 0.
thisTimestamp = (block->GetBlockTime() > previousTimestamp) ?
block->GetBlockTime() : previousTimestamp + 1;

// A 6*T limit will prevent large drops in difficulty from long solvetimes.
// int64_t solvetime = std::min(6 * T, thisTimestamp - previousTimestamp);
int64_t solvetime = thisTimestamp - previousTimestamp;

// The following is part of "preventing negative solvetimes".
previousTimestamp = thisTimestamp;

// Give linearly higher weight to more recent solvetimes.
j++;
sumWeightedSolvetimes += solvetime * j;

arith_uint256 target;
target.SetCompact(block->nBits);
avgTarget += target / N / k; // Dividing by k here prevents an overflow below.
}
// Desired equation in next line was nextTarget = avgTarget * sumWeightSolvetimes / k
// but 1/k was moved to line above to prevent overflow in new coins

nextTarget = avgTarget * sumWeightedSolvetimes;

if (nextTarget > powLimit) { nextTarget = powLimit; }

return nextTarget.GetCompact();
}


unsigned int LwmaCalculateNextWorkRequired(const CBlockIndex* pindexLast, const Consensus::Params& params)
{
Expand Down
1 change: 1 addition & 0 deletions src/pow.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class uint256;

unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params&);
unsigned int CalculateNextWorkRequired(const CBlockIndex* pindexLast, int64_t nFirstBlockTime, const Consensus::Params&);
unsigned int Lwma3CalculateNextWorkRequired(const CBlockIndex* pindexLast, const Consensus::Params& params);
unsigned int LwmaCalculateNextWorkRequired(const CBlockIndex* pindexLast, const Consensus::Params& params);

/** Check whether a block hash satisfies the proof-of-work requirement specified by nBits */
Expand Down

0 comments on commit 02dd9c1

Please sign in to comment.