Skip to content

Commit

Permalink
Implement dynamic activation thresholds (dashpay#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 gades committed Mar 11, 2022
1 parent e56e002 commit 18cb9c8
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
Expand Up @@ -134,15 +134,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 @@ -369,35 +375,37 @@ class CMainParams : public CChainParams {
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0001].nStartTime = 1619222400; // April 24, 2021
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0001].nTimeout = 1672444800; // December 31, 2022
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 = 1619222400; // April 24, 2021
consensus.vDeployments[Consensus::DEPLOYMENT_BIP147].nTimeout = 1672444800; // December 31, 2022
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 = 1619222400; // April 24, 2021
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0003].nTimeout = 1672444800; // December 31, 2022
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 = 1619222400; // April 24, 2021
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0008].nTimeout = 1672444800; // December 31, 2022
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 = 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("0x00000000000000000000000000000000000000000000000000006120b78e779e");
Expand Down Expand Up @@ -554,35 +562,37 @@ class CTestNetParams : public CChainParams {
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0001].nStartTime = 1544655600; // Dec 13th, 2018
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0001].nTimeout = 1635903900; // Nov 3rd, 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 = 1619222400; // April 24, 2021
consensus.vDeployments[Consensus::DEPLOYMENT_BIP147].nTimeout = 1672444800; // December 31, 2022
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 = 1619222400; // April 24, 2021
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0003].nTimeout = 1672444800; // December 31, 2022
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 = 1619222400; // April 24, 2021
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0008].nTimeout = 1672444800; // December 31, 2022
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("0x00000000000000000000000000000000000000000000000000000013f294c61a");
Expand Down Expand Up @@ -732,35 +742,37 @@ class CDevNetParams : public CChainParams {
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0001].nStartTime = 1619222400; // April 24, 2021
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0001].nTimeout = 1672444800; // December 31, 2022
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 = 1619222400; // April 24, 2021
consensus.vDeployments[Consensus::DEPLOYMENT_BIP147].nTimeout = 1672444800; // December 31, 2022
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 = 1619222400; // April 24, 2021
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0003].nTimeout = 1672444800; // December 31, 2022
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 = 1619222400; // April 24, 2021
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0008].nTimeout = 1672444800; // December 31, 2022
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 @@ -913,7 +925,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 @@ -1027,9 +1041,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
Expand Up @@ -82,7 +82,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 @@ -153,7 +153,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
Expand Up @@ -38,8 +38,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 @@ -159,7 +163,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
Expand Up @@ -1406,10 +1406,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 @@ -1420,17 +1420,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
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

0 comments on commit 18cb9c8

Please sign in to comment.