mirror of
https://github.com/dashpay/dash.git
synced 2024-12-25 03:52:49 +01:00
Implement dynamic activation thresholds (#3692)
* 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 `;`
This commit is contained in:
parent
5176a26007
commit
ab8347e06b
@ -81,15 +81,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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -319,35 +325,37 @@ public:
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0001].nStartTime = 1508025600; // Oct 15th, 2017
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0001].nTimeout = 1539561600; // Oct 15th, 2018
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0001].nWindowSize = 4032;
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0001].nThreshold = 3226; // 80% of 4032
|
||||
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 = 1524477600; // Apr 23th, 2018
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_BIP147].nTimeout = 1556013600; // Apr 23th, 2019
|
||||
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("0x0000000000000000000000000000000000000000000027b81f49774e9f7fc93f"); // 1215000
|
||||
@ -513,35 +521,37 @@ public:
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0001].nStartTime = 1544655600; // Dec 13th, 2018
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0001].nTimeout = 1576191600; // Dec 13th, 2019
|
||||
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 = 1544655600; // Dec 13th, 2018
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_BIP147].nTimeout = 1576191600; // Dec 13th, 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 = 1544655600; // Dec 13th, 2018
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0003].nTimeout = 1576191600; // Dec 13th, 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 = 1584748800; // Mar 21st, 2020
|
||||
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("0x00000000000000000000000000000000000000000000000000ac720e0b2ed13d"); // 260000
|
||||
@ -679,35 +689,37 @@ public:
|
||||
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");
|
||||
@ -851,7 +863,9 @@ public:
|
||||
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");
|
||||
@ -953,9 +967,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)
|
||||
|
@ -87,7 +87,7 @@ public:
|
||||
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);
|
||||
@ -157,7 +157,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
|
||||
|
@ -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
|
||||
@ -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;
|
||||
|
23
src/init.cpp
23
src/init.cpp
@ -1353,10 +1353,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]));
|
||||
}
|
||||
@ -1367,17 +1367,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;
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ public:
|
||||
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); }
|
||||
|
@ -1925,7 +1925,7 @@ public:
|
||||
int64_t BeginTime(const Consensus::Params& params) const override { return 0; }
|
||||
int64_t EndTime(const Consensus::Params& params) const override { return std::numeric_limits<int64_t>::max(); }
|
||||
int Period(const Consensus::Params& params) const override { return params.nMinerConfirmationWindow; }
|
||||
int Threshold(const Consensus::Params& params) const override { return params.nRuleChangeActivationThreshold; }
|
||||
int Threshold(const Consensus::Params& params, int nAttempt) const override { return params.nRuleChangeActivationThreshold; }
|
||||
|
||||
bool Condition(const CBlockIndex* pindex, const Consensus::Params& params) const override
|
||||
{
|
||||
@ -4931,7 +4931,7 @@ ThresholdState VersionBitsTipState(const Consensus::Params& params, Consensus::D
|
||||
BIP9Stats VersionBitsTipStatistics(const Consensus::Params& params, Consensus::DeploymentPos pos)
|
||||
{
|
||||
LOCK(cs_main);
|
||||
return VersionBitsStatistics(chainActive.Tip(), params, pos);
|
||||
return VersionBitsStatistics(chainActive.Tip(), params, pos, versionbitscache);
|
||||
}
|
||||
|
||||
int VersionBitsTipStateSinceHeight(const Consensus::Params& params, Consensus::DeploymentPos pos)
|
||||
|
@ -46,7 +46,6 @@ const struct VBDeploymentInfo VersionBitsDeploymentInfo[Consensus::MAX_VERSION_B
|
||||
ThresholdState AbstractThresholdConditionChecker::GetStateFor(const CBlockIndex* pindexPrev, const Consensus::Params& params, ThresholdConditionCache& cache) const
|
||||
{
|
||||
int nPeriod = Period(params);
|
||||
int nThreshold = Threshold(params);
|
||||
int64_t nTimeStart = BeginTime(params);
|
||||
int64_t nTimeTimeout = EndTime(params);
|
||||
|
||||
@ -76,6 +75,13 @@ ThresholdState AbstractThresholdConditionChecker::GetStateFor(const CBlockIndex*
|
||||
assert(cache.count(pindexPrev));
|
||||
ThresholdState state = cache[pindexPrev];
|
||||
|
||||
int nStartHeight{std::numeric_limits<int>::max()};
|
||||
for (const auto& pair : cache) {
|
||||
if (pair.second == ThresholdState::STARTED && nStartHeight > pair.first->nHeight + 1) {
|
||||
nStartHeight = pair.first->nHeight + 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Now walk forward and compute the state of descendants of pindexPrev
|
||||
while (!vToCompute.empty()) {
|
||||
ThresholdState stateNext = state;
|
||||
@ -88,6 +94,7 @@ ThresholdState AbstractThresholdConditionChecker::GetStateFor(const CBlockIndex*
|
||||
stateNext = ThresholdState::FAILED;
|
||||
} else if (pindexPrev->GetMedianTimePast() >= nTimeStart) {
|
||||
stateNext = ThresholdState::STARTED;
|
||||
nStartHeight = pindexPrev->nHeight + 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -105,7 +112,9 @@ ThresholdState AbstractThresholdConditionChecker::GetStateFor(const CBlockIndex*
|
||||
}
|
||||
pindexCount = pindexCount->pprev;
|
||||
}
|
||||
if (count >= nThreshold) {
|
||||
assert(nStartHeight > 0 && nStartHeight < std::numeric_limits<int>::max());
|
||||
int nAttempt = (pindexCount->nHeight + 1 - nStartHeight) / nPeriod;
|
||||
if (count >= Threshold(params, nAttempt)) {
|
||||
stateNext = ThresholdState::LOCKED_IN;
|
||||
}
|
||||
break;
|
||||
@ -128,12 +137,12 @@ ThresholdState AbstractThresholdConditionChecker::GetStateFor(const CBlockIndex*
|
||||
}
|
||||
|
||||
// return the numerical statistics of blocks signalling the specified BIP9 condition in this current period
|
||||
BIP9Stats AbstractThresholdConditionChecker::GetStateStatisticsFor(const CBlockIndex* pindex, const Consensus::Params& params) const
|
||||
BIP9Stats AbstractThresholdConditionChecker::GetStateStatisticsFor(const CBlockIndex* pindex, const Consensus::Params& params, ThresholdConditionCache& cache) const
|
||||
{
|
||||
BIP9Stats stats = {};
|
||||
|
||||
stats.period = Period(params);
|
||||
stats.threshold = Threshold(params);
|
||||
stats.threshold = Threshold(params, 0);
|
||||
|
||||
if (pindex == nullptr)
|
||||
return stats;
|
||||
@ -142,6 +151,15 @@ BIP9Stats AbstractThresholdConditionChecker::GetStateStatisticsFor(const CBlockI
|
||||
const CBlockIndex* pindexEndOfPrevPeriod = pindex->GetAncestor(pindex->nHeight - ((pindex->nHeight + 1) % stats.period));
|
||||
stats.elapsed = pindex->nHeight - pindexEndOfPrevPeriod->nHeight;
|
||||
|
||||
// Re-calculate current threshold
|
||||
int nAttempt{0};
|
||||
const ThresholdState state = GetStateFor(pindexEndOfPrevPeriod, params, cache);
|
||||
if (state == ThresholdState::STARTED) {
|
||||
int nStartHeight = GetStateSinceHeightFor(pindexEndOfPrevPeriod, params, cache);
|
||||
nAttempt = (pindexEndOfPrevPeriod->nHeight + 1 - nStartHeight)/stats.period;
|
||||
}
|
||||
stats.threshold = Threshold(params, nAttempt);
|
||||
|
||||
// Count from current block to beginning of period
|
||||
int count = 0;
|
||||
const CBlockIndex* currentIndex = pindex;
|
||||
@ -200,7 +218,17 @@ protected:
|
||||
int64_t BeginTime(const Consensus::Params& params) const override { return params.vDeployments[id].nStartTime; }
|
||||
int64_t EndTime(const Consensus::Params& params) const override { return params.vDeployments[id].nTimeout; }
|
||||
int Period(const Consensus::Params& params) const override { return params.vDeployments[id].nWindowSize ? params.vDeployments[id].nWindowSize : params.nMinerConfirmationWindow; }
|
||||
int Threshold(const Consensus::Params& params) const override { return params.vDeployments[id].nThreshold ? params.vDeployments[id].nThreshold : params.nRuleChangeActivationThreshold; }
|
||||
int Threshold(const Consensus::Params& params, int nAttempt) const override
|
||||
{
|
||||
if (params.vDeployments[id].nThresholdStart == 0) {
|
||||
return params.nRuleChangeActivationThreshold;
|
||||
}
|
||||
if (params.vDeployments[id].nThresholdMin == 0 || params.vDeployments[id].nFalloffCoeff == 0) {
|
||||
return params.vDeployments[id].nThresholdStart;
|
||||
}
|
||||
int64_t nThresholdCalc = params.vDeployments[id].nThresholdStart - nAttempt * nAttempt * Period(params) / 100 / params.vDeployments[id].nFalloffCoeff;
|
||||
return std::max(params.vDeployments[id].nThresholdMin, nThresholdCalc);
|
||||
}
|
||||
|
||||
bool Condition(const CBlockIndex* pindex, const Consensus::Params& params) const override
|
||||
{
|
||||
@ -219,9 +247,9 @@ ThresholdState VersionBitsState(const CBlockIndex* pindexPrev, const Consensus::
|
||||
return VersionBitsConditionChecker(pos).GetStateFor(pindexPrev, params, cache.caches[pos]);
|
||||
}
|
||||
|
||||
BIP9Stats VersionBitsStatistics(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos)
|
||||
BIP9Stats VersionBitsStatistics(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos, VersionBitsCache& cache)
|
||||
{
|
||||
return VersionBitsConditionChecker(pos).GetStateStatisticsFor(pindexPrev, params);
|
||||
return VersionBitsConditionChecker(pos).GetStateStatisticsFor(pindexPrev, params, cache.caches[pos]);
|
||||
}
|
||||
|
||||
int VersionBitsStateSinceHeight(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos, VersionBitsCache& cache)
|
||||
|
@ -58,10 +58,10 @@ protected:
|
||||
virtual int64_t BeginTime(const Consensus::Params& params) const =0;
|
||||
virtual int64_t EndTime(const Consensus::Params& params) const =0;
|
||||
virtual int Period(const Consensus::Params& params) const =0;
|
||||
virtual int Threshold(const Consensus::Params& params) const =0;
|
||||
virtual int Threshold(const Consensus::Params& params, int nAttempt) const =0;
|
||||
|
||||
public:
|
||||
BIP9Stats GetStateStatisticsFor(const CBlockIndex* pindex, const Consensus::Params& params) const;
|
||||
BIP9Stats GetStateStatisticsFor(const CBlockIndex* pindex, const Consensus::Params& params, ThresholdConditionCache& cache) const;
|
||||
// Note that the functions below take a pindexPrev as input: they compute information for block B based on its parent.
|
||||
ThresholdState GetStateFor(const CBlockIndex* pindexPrev, const Consensus::Params& params, ThresholdConditionCache& cache) const;
|
||||
int GetStateSinceHeightFor(const CBlockIndex* pindexPrev, const Consensus::Params& params, ThresholdConditionCache& cache) const;
|
||||
@ -75,7 +75,7 @@ struct VersionBitsCache
|
||||
};
|
||||
|
||||
ThresholdState VersionBitsState(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos, VersionBitsCache& cache);
|
||||
BIP9Stats VersionBitsStatistics(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos);
|
||||
BIP9Stats VersionBitsStatistics(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos, VersionBitsCache& cache);
|
||||
int VersionBitsStateSinceHeight(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos, VersionBitsCache& cache);
|
||||
uint32_t VersionBitsMask(const Consensus::Params& params, Consensus::DeploymentPos pos);
|
||||
|
||||
|
@ -58,21 +58,27 @@ class BlockRewardReallocationTest(DashTestFramework):
|
||||
test_block = self.create_test_block()
|
||||
self.nodes[0].p2p.send_blocks_and_test([test_block], self.nodes[0], timeout=5)
|
||||
# generate at most 10 signaling blocks at a time
|
||||
for i in range((num_blocks - 1) // 10):
|
||||
self.bump_mocktime(10)
|
||||
self.nodes[0].generate(10)
|
||||
if num_blocks > 0:
|
||||
for i in range((num_blocks - 1) // 10):
|
||||
self.bump_mocktime(10)
|
||||
self.nodes[0].generate(10)
|
||||
self.sync_blocks()
|
||||
self.nodes[0].generate((num_blocks - 1) % 10)
|
||||
self.sync_blocks()
|
||||
self.nodes[0].generate((num_blocks - 1) % 10)
|
||||
assert_equal(get_bip9_status(self.nodes[0], 'realloc')['status'], 'started')
|
||||
self.nodes[0].generate(1)
|
||||
self.sync_blocks()
|
||||
assert_equal(get_bip9_status(self.nodes[0], 'realloc')['status'], 'started')
|
||||
bestblockhash = self.nodes[0].generate(1)[0]
|
||||
self.sync_blocks()
|
||||
self.nodes[0].getblock(bestblockhash, 1)
|
||||
if expected_lockin:
|
||||
assert_equal(get_bip9_status(self.nodes[0], 'realloc')['status'], 'locked_in')
|
||||
else:
|
||||
assert_equal(get_bip9_status(self.nodes[0], 'realloc')['status'], 'started')
|
||||
|
||||
def threshold(self, attempt):
|
||||
threshold_calc = 400 - attempt * attempt
|
||||
if threshold_calc < 300:
|
||||
return 300
|
||||
return threshold_calc
|
||||
|
||||
def run_test(self):
|
||||
self.log.info("Wait for DIP3 to activate")
|
||||
while get_bip9_status(self.nodes[0], 'dip0003')['status'] != 'active':
|
||||
@ -101,40 +107,56 @@ class BlockRewardReallocationTest(DashTestFramework):
|
||||
bi = self.nodes[0].getblockchaininfo()
|
||||
assert_equal(bi['blocks'], 499)
|
||||
assert_equal(bi['bip9_softforks']['realloc']['status'], 'started')
|
||||
assert_equal(bi['bip9_softforks']['realloc']['statistics']['threshold'], 400)
|
||||
assert_equal(bi['bip9_softforks']['realloc']['statistics']['threshold'], self.threshold(0))
|
||||
|
||||
self.signal(399, False) # 1 block short
|
||||
self.signal(400, True) # just enough to lock in
|
||||
|
||||
self.log.info("Still LOCKED_IN at height = 1498")
|
||||
self.log.info("Still STARTED but new threshold should be lower at height = 999")
|
||||
bi = self.nodes[0].getblockchaininfo()
|
||||
assert_equal(bi['blocks'], 999)
|
||||
assert_equal(bi['bip9_softforks']['realloc']['statistics']['threshold'], self.threshold(1))
|
||||
|
||||
self.signal(398, False) # 1 block short again
|
||||
|
||||
self.log.info("Still STARTED but new threshold should be even lower at height = 1499")
|
||||
bi = self.nodes[0].getblockchaininfo()
|
||||
assert_equal(bi['blocks'], 1499)
|
||||
assert_equal(bi['bip9_softforks']['realloc']['statistics']['threshold'], self.threshold(2))
|
||||
pre_locked_in_blockhash = bi['bestblockhash']
|
||||
|
||||
self.signal(396, True) # just enough to lock in
|
||||
self.log.info("Advanced to LOCKED_IN at height = 1999")
|
||||
|
||||
for i in range(49):
|
||||
self.bump_mocktime(10)
|
||||
self.nodes[0].generate(10)
|
||||
self.sync_blocks()
|
||||
self.nodes[0].generate(9)
|
||||
self.sync_blocks()
|
||||
|
||||
self.log.info("Still LOCKED_IN at height = 2498")
|
||||
bi = self.nodes[0].getblockchaininfo()
|
||||
assert_equal(bi['blocks'], 1998)
|
||||
assert_equal(bi['blocks'], 2498)
|
||||
assert_equal(bi['bip9_softforks']['realloc']['status'], 'locked_in')
|
||||
|
||||
self.log.info("Advance from LOCKED_IN to ACTIVE at height = 1999")
|
||||
self.log.info("Advance from LOCKED_IN to ACTIVE at height = 2499")
|
||||
self.nodes[0].generate(1) # activation
|
||||
bi = self.nodes[0].getblockchaininfo()
|
||||
assert_equal(bi['blocks'], 1999)
|
||||
assert_equal(bi['blocks'], 2499)
|
||||
assert_equal(bi['bip9_softforks']['realloc']['status'], 'active')
|
||||
assert_equal(bi['bip9_softforks']['realloc']['since'], 2000)
|
||||
assert_equal(bi['bip9_softforks']['realloc']['since'], 2500)
|
||||
|
||||
self.log.info("Reward split should stay ~50/50 before the first superblock after activation")
|
||||
# This applies even if reallocation was activated right at superblock height like it does here
|
||||
bt = self.nodes[0].getblocktemplate()
|
||||
assert_equal(bt['height'], 2000)
|
||||
assert_equal(bt['masternode'][0]['amount'], get_masternode_payment(bt['height'], bt['coinbasevalue'], 2000))
|
||||
assert_equal(bt['height'], 2500)
|
||||
assert_equal(bt['masternode'][0]['amount'], get_masternode_payment(bt['height'], bt['coinbasevalue'], 2500))
|
||||
self.nodes[0].generate(9)
|
||||
self.sync_blocks()
|
||||
bt = self.nodes[0].getblocktemplate()
|
||||
assert_equal(bt['masternode'][0]['amount'], get_masternode_payment(bt['height'], bt['coinbasevalue'], 2000))
|
||||
assert_equal(bt['coinbasevalue'], 17171634268)
|
||||
assert_equal(bt['masternode'][0]['amount'], 8585817128) # 0.4999999997
|
||||
assert_equal(bt['masternode'][0]['amount'], get_masternode_payment(bt['height'], bt['coinbasevalue'], 2500))
|
||||
assert_equal(bt['coinbasevalue'], 13748571607)
|
||||
assert_equal(bt['masternode'][0]['amount'], 6874285801) # 0.4999999998
|
||||
|
||||
self.log.info("Reallocation should kick-in with the superblock mined at height = 2010")
|
||||
for period in range(19): # there will be 19 adjustments, 3 superblocks long each
|
||||
@ -143,11 +165,11 @@ class BlockRewardReallocationTest(DashTestFramework):
|
||||
self.nodes[0].generate(10)
|
||||
self.sync_blocks()
|
||||
bt = self.nodes[0].getblocktemplate()
|
||||
assert_equal(bt['masternode'][0]['amount'], get_masternode_payment(bt['height'], bt['coinbasevalue'], 2000))
|
||||
assert_equal(bt['masternode'][0]['amount'], get_masternode_payment(bt['height'], bt['coinbasevalue'], 2500))
|
||||
|
||||
self.log.info("Reward split should reach ~60/40 after reallocation is done")
|
||||
assert_equal(bt['coinbasevalue'], 12766530779)
|
||||
assert_equal(bt['masternode'][0]['amount'], 7659918467) # 0.6
|
||||
assert_equal(bt['coinbasevalue'], 10221599170)
|
||||
assert_equal(bt['masternode'][0]['amount'], 6132959502) # 0.6
|
||||
|
||||
self.log.info("Reward split should stay ~60/40 after reallocation is done")
|
||||
for period in range(10): # check 10 next superblocks
|
||||
@ -155,9 +177,31 @@ class BlockRewardReallocationTest(DashTestFramework):
|
||||
self.nodes[0].generate(10)
|
||||
self.sync_blocks()
|
||||
bt = self.nodes[0].getblocktemplate()
|
||||
assert_equal(bt['masternode'][0]['amount'], get_masternode_payment(bt['height'], bt['coinbasevalue'], 2000))
|
||||
assert_equal(bt['coinbasevalue'], 12766530779)
|
||||
assert_equal(bt['masternode'][0]['amount'], 7659918467) # 0.6
|
||||
assert_equal(bt['masternode'][0]['amount'], get_masternode_payment(bt['height'], bt['coinbasevalue'], 2500))
|
||||
assert_equal(bt['coinbasevalue'], 9491484944)
|
||||
assert_equal(bt['masternode'][0]['amount'], 5694890966) # 0.6
|
||||
|
||||
self.log.info("Rollback the chain back to the STARTED state")
|
||||
self.mocktime = self.nodes[0].getblock(pre_locked_in_blockhash, 1)['time']
|
||||
for node in self.nodes:
|
||||
node.invalidateblock(pre_locked_in_blockhash)
|
||||
self.sync_all()
|
||||
# create and send non-signalling block
|
||||
test_block = self.create_test_block()
|
||||
self.nodes[0].p2p.send_blocks_and_test([test_block], self.nodes[0], timeout=5)
|
||||
bi = self.nodes[0].getblockchaininfo()
|
||||
assert_equal(bi['blocks'], 1499)
|
||||
assert_equal(bi['bip9_softforks']['realloc']['status'], 'started')
|
||||
assert_equal(bi['bip9_softforks']['realloc']['statistics']['threshold'], self.threshold(2))
|
||||
|
||||
self.log.info("Check thresholds reach min level and stay there")
|
||||
for i in range(8): # 7 to reach min level and 1 more to check it doesn't go lower than that
|
||||
self.signal(0, False) # no need to signal
|
||||
bi = self.nodes[0].getblockchaininfo()
|
||||
assert_equal(bi['blocks'], 1999 + i * 500)
|
||||
assert_equal(bi['bip9_softforks']['realloc']['status'], 'started')
|
||||
assert_equal(bi['bip9_softforks']['realloc']['statistics']['threshold'], self.threshold(i + 3))
|
||||
assert_equal(bi['bip9_softforks']['realloc']['statistics']['threshold'], 300)
|
||||
|
||||
if __name__ == '__main__':
|
||||
BlockRewardReallocationTest().main()
|
||||
|
@ -59,6 +59,7 @@ BASE_SCRIPTS= [
|
||||
# Scripts that are run by the travis build process.
|
||||
# Longest test should go first, to favor running tests in parallel
|
||||
'feature_dip3_deterministicmns.py', # NOTE: needs dash_hash to pass
|
||||
'feature_block_reward_reallocation.py',
|
||||
'wallet_hd.py',
|
||||
'wallet_backup.py',
|
||||
# vv Tests less than 5m vv
|
||||
@ -82,7 +83,6 @@ BASE_SCRIPTS= [
|
||||
'feature_llmq_is_retroactive.py', # NOTE: needs dash_hash to pass
|
||||
'feature_llmq_dkgerrors.py', # NOTE: needs dash_hash to pass
|
||||
'feature_dip4_coinbasemerkleroots.py', # NOTE: needs dash_hash to pass
|
||||
'feature_block_reward_reallocation.py',
|
||||
# vv Tests less than 60s vv
|
||||
'p2p_sendheaders.py', # NOTE: needs dash_hash to pass
|
||||
'wallet_zapwallettxes.py',
|
||||
|
Loading…
Reference in New Issue
Block a user