Skip to content

Commit

Permalink
Implement dynamic activation thresholds (#3692)
Browse files Browse the repository at this point in the history
* Implement dynamic activation thresholds

* fix

* Revert unrelated changes

* Clarify switching to/staying in LOCKED_IN state

* Fix signal function to work correctly with num_blocks=0

* Add simplified threshold calculation and use it in tests

* Check that thresholds are decreasing, reach the min level and stay there

* Drop `;`
  • Loading branch information
UdjinM6 authored and charlesrocket committed Sep 29, 2020
1 parent 9be3e97 commit 5c9d2cf
Show file tree
Hide file tree
Showing 10 changed files with 172 additions and 73 deletions.
56 changes: 35 additions & 21 deletions src/chainparams.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,15 +83,21 @@ static CBlock CreateGenesisBlock(uint32_t nTime, uint32_t nNonce, uint32_t nBits
}


void CChainParams::UpdateVersionBitsParameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout, int64_t nWindowSize, int64_t nThreshold)
void CChainParams::UpdateVersionBitsParameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout, int64_t nWindowSize, int64_t nThresholdStart, int64_t nThresholdMin, int64_t nFalloffCoeff)
{
consensus.vDeployments[d].nStartTime = nStartTime;
consensus.vDeployments[d].nTimeout = nTimeout;
if (nWindowSize != -1) {
consensus.vDeployments[d].nWindowSize = nWindowSize;
}
if (nThreshold != -1) {
consensus.vDeployments[d].nThreshold = nThreshold;
if (nThresholdStart != -1) {
consensus.vDeployments[d].nThresholdStart = nThresholdStart;
}
if (nThresholdMin != -1) {
consensus.vDeployments[d].nThresholdMin = nThresholdMin;
}
if (nFalloffCoeff != -1) {
consensus.vDeployments[d].nFalloffCoeff = nFalloffCoeff;
}
}

Expand Down Expand Up @@ -321,35 +327,37 @@ class CMainParams : public CChainParams {
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0001].nStartTime = 1508025600;
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0001].nTimeout = 1539561600;
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0001].nWindowSize = 4032;
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0001].nThreshold = 3226;
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0001].nThresholdStart = 3226; // 80% of 4032

// Deployment of BIP147
consensus.vDeployments[Consensus::DEPLOYMENT_BIP147].bit = 2;
consensus.vDeployments[Consensus::DEPLOYMENT_BIP147].nStartTime = 1531094400;
consensus.vDeployments[Consensus::DEPLOYMENT_BIP147].nTimeout = 1562630400;
consensus.vDeployments[Consensus::DEPLOYMENT_BIP147].nWindowSize = 4032;
consensus.vDeployments[Consensus::DEPLOYMENT_BIP147].nThreshold = 3226; // 80% of 4032
consensus.vDeployments[Consensus::DEPLOYMENT_BIP147].nThresholdStart = 3226; // 80% of 4032

// Deployment of DIP0003
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0003].bit = 3;
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0003].nStartTime = 1546300800; // Jan 1st, 2019
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0003].nTimeout = 1577836800; // Jan 1st, 2020
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0003].nWindowSize = 4032;
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0003].nThreshold = 3226; // 80% of 4032
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0003].nThresholdStart = 3226; // 80% of 4032

// Deployment of DIP0008
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0008].bit = 4;
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0008].nStartTime = 1557878400; // May 15th, 2019
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0008].nTimeout = 1589500800; // May 15th, 2020
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0008].nWindowSize = 4032;
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0008].nThreshold = 3226; // 80% of 4032
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0008].nThresholdStart = 3226; // 80% of 4032

// Deployment of Block Reward Reallocation
consensus.vDeployments[Consensus::DEPLOYMENT_REALLOC].bit = 5;
consensus.vDeployments[Consensus::DEPLOYMENT_REALLOC].nStartTime = 1601510400; // Oct 1st, 2020
consensus.vDeployments[Consensus::DEPLOYMENT_REALLOC].nTimeout = 1633046400; // Oct 1st, 2021
consensus.vDeployments[Consensus::DEPLOYMENT_REALLOC].nWindowSize = 4032;
consensus.vDeployments[Consensus::DEPLOYMENT_REALLOC].nThreshold = 3226; // 80% of 4032
consensus.vDeployments[Consensus::DEPLOYMENT_REALLOC].nThresholdStart = 3226; // 80% of 4032
consensus.vDeployments[Consensus::DEPLOYMENT_REALLOC].nThresholdMin = 2420; // 60% of 4032
consensus.vDeployments[Consensus::DEPLOYMENT_REALLOC].nFalloffCoeff = 5; // this corresponds to 10 periods

// The best chain should have at least this much work.
consensus.nMinimumChainWork = uint256S("0x000000000000000000000000000000000000000000000057d1699af8ff34e377"); // 507186
Expand Down Expand Up @@ -519,35 +527,37 @@ class CTestNetParams : public CChainParams {
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0001].nStartTime = 1580489212; // Jan 31st, 2020
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0001].nTimeout = 1612082538; // Jan 31st, 2021
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0001].nWindowSize = 100;
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0001].nThreshold = 50; // 50% of 100
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0001].nThresholdStart = 50; // 50% of 100

// Deployment of BIP147
consensus.vDeployments[Consensus::DEPLOYMENT_BIP147].bit = 2;
consensus.vDeployments[Consensus::DEPLOYMENT_BIP147].nStartTime = 1580489212; // Jan 31st, 2020
consensus.vDeployments[Consensus::DEPLOYMENT_BIP147].nTimeout = 1612082538; // Jan 31st, 2021
consensus.vDeployments[Consensus::DEPLOYMENT_BIP147].nWindowSize = 100;
consensus.vDeployments[Consensus::DEPLOYMENT_BIP147].nThreshold = 50; // 50% of 100
consensus.vDeployments[Consensus::DEPLOYMENT_BIP147].nThresholdStart = 50; // 50% of 100

// Deployment of DIP0003
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0003].bit = 3;
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0003].nStartTime = 1580489212; // Jan 31st, 2020
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0003].nTimeout = 1612082538; // Jan 31sr, 2021
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0003].nWindowSize = 100;
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0003].nThreshold = 50; // 50% of 100
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0003].nThresholdStart = 50; // 50% of 100

// Deployment of DIP0008
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0008].bit = 4;
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0008].nStartTime = 1584088938; // Mar 13th, 2020
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0008].nTimeout = 1615624938; // Mar 13th, 2021
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0008].nWindowSize = 100;
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0008].nThreshold = 50; // 50% of 100
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0008].nThresholdStart = 50; // 50% of 100

// Deployment of Block Reward Reallocation
consensus.vDeployments[Consensus::DEPLOYMENT_REALLOC].bit = 5;
consensus.vDeployments[Consensus::DEPLOYMENT_REALLOC].nStartTime = 1598918400; // Sep 1st, 2020
consensus.vDeployments[Consensus::DEPLOYMENT_REALLOC].nTimeout = 1630454400; // Sep 1st, 2021
consensus.vDeployments[Consensus::DEPLOYMENT_REALLOC].nWindowSize = 100;
consensus.vDeployments[Consensus::DEPLOYMENT_REALLOC].nThreshold = 50; // 50% of 100
consensus.vDeployments[Consensus::DEPLOYMENT_REALLOC].nThresholdStart = 80; // 80% of 100
consensus.vDeployments[Consensus::DEPLOYMENT_REALLOC].nThresholdMin = 60; // 60% of 100
consensus.vDeployments[Consensus::DEPLOYMENT_REALLOC].nFalloffCoeff = 5; // this corresponds to 10 periods

// The best chain should have at least this much work.
consensus.nMinimumChainWork = uint256S("0x000000000000000000000000000000000000000000000000000001a10897feeb"); // 28049
Expand Down Expand Up @@ -694,35 +704,37 @@ class CDevNetParams : public CChainParams {
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0001].nStartTime = 1505692800; // Sep 18th, 2017
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0001].nTimeout = 1537228800; // Sep 18th, 2018
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0001].nWindowSize = 100;
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0001].nThreshold = 50; // 50% of 100
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0001].nThresholdStart = 50; // 50% of 100

// Deployment of BIP147
consensus.vDeployments[Consensus::DEPLOYMENT_BIP147].bit = 2;
consensus.vDeployments[Consensus::DEPLOYMENT_BIP147].nStartTime = 1517792400; // Feb 5th, 2018
consensus.vDeployments[Consensus::DEPLOYMENT_BIP147].nTimeout = 1549328400; // Feb 5th, 2019
consensus.vDeployments[Consensus::DEPLOYMENT_BIP147].nWindowSize = 100;
consensus.vDeployments[Consensus::DEPLOYMENT_BIP147].nThreshold = 50; // 50% of 100
consensus.vDeployments[Consensus::DEPLOYMENT_BIP147].nThresholdStart = 50; // 50% of 100

// Deployment of DIP0003
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0003].bit = 3;
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0003].nStartTime = 1535752800; // Sep 1st, 2018
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0003].nTimeout = 1567288800; // Sep 1st, 2019
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0003].nWindowSize = 100;
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0003].nThreshold = 50; // 50% of 100
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0003].nThresholdStart = 50; // 50% of 100

// Deployment of DIP0008
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0008].bit = 4;
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0008].nStartTime = 1553126400; // Mar 21st, 2019
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0008].nTimeout = 1900281600; // Mar 21st, 2030
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0008].nWindowSize = 100;
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0008].nThreshold = 50; // 50% of 100
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0008].nThresholdStart = 50; // 50% of 100

// Deployment of Block Reward Reallocation
consensus.vDeployments[Consensus::DEPLOYMENT_REALLOC].bit = 5;
consensus.vDeployments[Consensus::DEPLOYMENT_REALLOC].nStartTime = 1598918400; // Sep 1st, 2020
consensus.vDeployments[Consensus::DEPLOYMENT_REALLOC].nTimeout = 1900281600; // Mar 21st, 2030
consensus.vDeployments[Consensus::DEPLOYMENT_REALLOC].nWindowSize = 100;
consensus.vDeployments[Consensus::DEPLOYMENT_REALLOC].nThreshold = 50; // 50% of 100
consensus.vDeployments[Consensus::DEPLOYMENT_REALLOC].nThresholdStart = 80; // 80% of 100
consensus.vDeployments[Consensus::DEPLOYMENT_REALLOC].nThresholdMin = 60; // 60% of 100
consensus.vDeployments[Consensus::DEPLOYMENT_REALLOC].nFalloffCoeff = 5; // this corresponds to 10 periods

// The best chain should have at least this much work.
consensus.nMinimumChainWork = uint256S("0x000000000000000000000000000000000000000000000000000000000000000");
Expand Down Expand Up @@ -866,7 +878,9 @@ class CRegTestParams : public CChainParams {
consensus.vDeployments[Consensus::DEPLOYMENT_REALLOC].nStartTime = 0;
consensus.vDeployments[Consensus::DEPLOYMENT_REALLOC].nTimeout = 999999999999ULL;
consensus.vDeployments[Consensus::DEPLOYMENT_REALLOC].nWindowSize = 500;
consensus.vDeployments[Consensus::DEPLOYMENT_REALLOC].nThreshold = 400; // 80%
consensus.vDeployments[Consensus::DEPLOYMENT_REALLOC].nThresholdStart = 400; // 80%
consensus.vDeployments[Consensus::DEPLOYMENT_REALLOC].nThresholdMin = 300; // 60%
consensus.vDeployments[Consensus::DEPLOYMENT_REALLOC].nFalloffCoeff = 5;

// The best chain should have at least this much work.
consensus.nMinimumChainWork = uint256S("0x00");
Expand Down Expand Up @@ -968,9 +982,9 @@ void SelectParams(const std::string& network)
globalChainParams = CreateChainParams(network);
}

void UpdateVersionBitsParameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout, int64_t nWindowSize, int64_t nThreshold)
void UpdateVersionBitsParameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout, int64_t nWindowSize, int64_t nThresholdStart, int64_t nThresholdMin, int64_t nFalloffCoeff)
{
globalChainParams->UpdateVersionBitsParameters(d, nStartTime, nTimeout, nWindowSize, nThreshold);
globalChainParams->UpdateVersionBitsParameters(d, nStartTime, nTimeout, nWindowSize, nThresholdStart, nThresholdMin, nFalloffCoeff);
}

void UpdateDIP3Parameters(int nActivationHeight, int nEnforcementHeight)
Expand Down
4 changes: 2 additions & 2 deletions src/chainparams.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ class CChainParams
const std::vector<SeedSpec6>& FixedSeeds() const { return vFixedSeeds; }
const CCheckpointData& Checkpoints() const { return checkpointData; }
const ChainTxData& TxData() const { return chainTxData; }
void UpdateVersionBitsParameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout, int64_t nWindowSize, int64_t nThreshold);
void UpdateVersionBitsParameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout, int64_t nWindowSize, int64_t nThresholdStart, int64_t nThresholdMin, int64_t nFalloffCoeff);
void UpdateDIP3Parameters(int nActivationHeight, int nEnforcementHeight);
void UpdateBudgetParameters(int nMasternodePaymentsStartBlock, int nBudgetPaymentsStartBlock, int nSuperblockStartBlock);
void UpdateSubsidyAndDiffParams(int nMinimumDifficultyBlocks, int nHighSubsidyBlocks, int nHighSubsidyFactor);
Expand Down Expand Up @@ -151,7 +151,7 @@ void SelectParams(const std::string& chain);
/**
* Allows modifying the Version Bits regtest parameters.
*/
void UpdateVersionBitsParameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout, int64_t nWindowSize, int64_t nThreshold);
void UpdateVersionBitsParameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout, int64_t nWindowSize, int64_t nThresholdStart, int64_t nThresholdMin, int64_t nFalloffCoeff);

/**
* Allows modifying the DIP3 activation and enforcement height
Expand Down
10 changes: 7 additions & 3 deletions src/consensus/params.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,12 @@ struct BIP9Deployment {
int64_t nTimeout;
/** The number of past blocks (including the block under consideration) to be taken into account for locking in a fork. */
int64_t nWindowSize{0};
/** A number of blocks, in the range of 1..nWindowSize, which must signal for a fork in order to lock it in. */
int64_t nThreshold{0};
/** A starting number of blocks, in the range of 1..nWindowSize, which must signal for a fork in order to lock it in. */
int64_t nThresholdStart{0};
/** A minimum number of blocks, in the range of 1..nWindowSize, which must signal for a fork in order to lock it in. */
int64_t nThresholdMin{0};
/** A coefficient which adjusts the speed a required number of signaling blocks is decreasing from nThresholdStart to nThresholdMin at with each period. */
int64_t nFalloffCoeff{0};
};

enum LLMQType : uint8_t
Expand Down Expand Up @@ -158,7 +162,7 @@ struct Params {
/**
* Minimum blocks including miner confirmation of the total of nMinerConfirmationWindow blocks in a retargeting period,
* (nPowTargetTimespan / nPowTargetSpacing) which is also used for BIP9 deployments.
* Default BIP9Deployment::nThreshold value for deployments where it's not specified and for unknown deployments.
* Default BIP9Deployment::nThresholdStart value for deployments where it's not specified and for unknown deployments.
* Examples: 1916 for 95%, 1512 for testchains.
*/
uint32_t nRuleChangeActivationThreshold;
Expand Down
23 changes: 16 additions & 7 deletions src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1351,10 +1351,10 @@ bool AppInitParameterInteraction()
for (const std::string& strDeployment : gArgs.GetArgs("-vbparams")) {
std::vector<std::string> vDeploymentParams;
boost::split(vDeploymentParams, strDeployment, boost::is_any_of(":"));
if (vDeploymentParams.size() != 3 && vDeploymentParams.size() != 5) {
return InitError("Version bits parameters malformed, expecting deployment:start:end or deployment:start:end:window:threshold");
if (vDeploymentParams.size() != 3 && vDeploymentParams.size() != 5 && vDeploymentParams.size() != 7) {
return InitError("Version bits parameters malformed, expecting deployment:start:end or deployment:start:end:window:threshold or deployment:start:end:window:thresholdstart:thresholdmin:falloffcoeff");
}
int64_t nStartTime, nTimeout, nWindowSize = -1, nThreshold = -1;
int64_t nStartTime, nTimeout, nWindowSize = -1, nThresholdStart = -1, nThresholdMin = -1, nFalloffCoeff = -1;
if (!ParseInt64(vDeploymentParams[1], &nStartTime)) {
return InitError(strprintf("Invalid nStartTime (%s)", vDeploymentParams[1]));
}
Expand All @@ -1365,17 +1365,26 @@ bool AppInitParameterInteraction()
if (!ParseInt64(vDeploymentParams[3], &nWindowSize)) {
return InitError(strprintf("Invalid nWindowSize (%s)", vDeploymentParams[3]));
}
if (!ParseInt64(vDeploymentParams[4], &nThreshold)) {
return InitError(strprintf("Invalid nThreshold (%s)", vDeploymentParams[4]));
if (!ParseInt64(vDeploymentParams[4], &nThresholdStart)) {
return InitError(strprintf("Invalid nThresholdStart (%s)", vDeploymentParams[4]));
}
}
if (vDeploymentParams.size() == 7) {
if (!ParseInt64(vDeploymentParams[5], &nThresholdMin)) {
return InitError(strprintf("Invalid nThresholdMin (%s)", vDeploymentParams[5]));
}
if (!ParseInt64(vDeploymentParams[6], &nFalloffCoeff)) {
return InitError(strprintf("Invalid nFalloffCoeff (%s)", vDeploymentParams[6]));
}
}
bool found = false;
for (int j=0; j<(int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; ++j)
{
if (vDeploymentParams[0].compare(VersionBitsDeploymentInfo[j].name) == 0) {
UpdateVersionBitsParameters(Consensus::DeploymentPos(j), nStartTime, nTimeout, nWindowSize, nThreshold);
UpdateVersionBitsParameters(Consensus::DeploymentPos(j), nStartTime, nTimeout, nWindowSize, nThresholdStart, nThresholdMin, nFalloffCoeff);
found = true;
LogPrintf("Setting version bits activation parameters for %s to start=%ld, timeout=%ld, window=%ld, threshold=%ld\n", vDeploymentParams[0], nStartTime, nTimeout, nWindowSize, nThreshold);
LogPrintf("Setting version bits activation parameters for %s to start=%ld, timeout=%ld, window=%ld, thresholdstart=%ld, thresholdmin=%ld, falloffcoeff=%ld\n",
vDeploymentParams[0], nStartTime, nTimeout, nWindowSize, nThresholdStart, nThresholdMin, nFalloffCoeff);
break;
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/test/versionbits_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class TestConditionChecker : public AbstractThresholdConditionChecker
int64_t BeginTime(const Consensus::Params& params) const override { return TestTime(10000); }
int64_t EndTime(const Consensus::Params& params) const override { return TestTime(20000); }
int Period(const Consensus::Params& params) const override { return 1000; }
int Threshold(const Consensus::Params& params) const override { return 900; }
int Threshold(const Consensus::Params& params, int nAttempt) const override { return 900; }
bool Condition(const CBlockIndex* pindex, const Consensus::Params& params) const override { return (pindex->nVersion & 0x100); }

ThresholdState GetStateFor(const CBlockIndex* pindexPrev) const { return AbstractThresholdConditionChecker::GetStateFor(pindexPrev, paramsDummy, cache); }
Expand Down
Loading

0 comments on commit 5c9d2cf

Please sign in to comment.