mirror of
https://github.com/dashpay/dash.git
synced 2024-12-25 20:12:57 +01:00
feat: imlemented new hard-fork mechanism that uses MN Activation Height
Altough, it's still disabled because no calls of related methods after processing MnEHF tx
This commit is contained in:
parent
5e5b571be6
commit
612faa8868
@ -105,6 +105,30 @@ static CBlock FindDevNetGenesisBlock(const CBlock &prevBlock, const CAmount& rew
|
||||
assert(false);
|
||||
}
|
||||
|
||||
bool CChainParams::UpdateMNActivationParam(int nBit, int height, int64_t timePast, bool fJustCheck) const
|
||||
{
|
||||
for (int index = 0; index < Consensus::MAX_VERSION_BITS_DEPLOYMENTS; ++index) {
|
||||
if (consensus.vDeployments[index].bit == nBit) {
|
||||
auto& deployment = consensus.vDeployments[index];
|
||||
if (timePast > deployment.nTimeout) {
|
||||
LogPrintf("%s: activation by bit=%d time-outed at height=%d\n", __func__, nBit, height);
|
||||
continue;
|
||||
}
|
||||
if (deployment.nMNActivationHeight < 0) {
|
||||
LogPrintf("%s: trying to set MnEHF height=%d for non-masternode activation fork bit=%d\n", __func__, height, nBit);
|
||||
return false;
|
||||
}
|
||||
if (!fJustCheck) {
|
||||
LogPrintf("%s: set MnEHF height=%d for bit=%d successfuly while fJustCheck=%d\n", __func__, height, nBit, fJustCheck);
|
||||
deployment.nMNActivationHeight = height;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
LogPrintf("%s: not found MnEHF fork bit=%d\n", __func__, nBit);
|
||||
return false;
|
||||
}
|
||||
|
||||
void CChainParams::AddLLMQ(Consensus::LLMQType llmqType)
|
||||
{
|
||||
assert(!GetLLMQ(llmqType).has_value());
|
||||
@ -909,7 +933,7 @@ public:
|
||||
/**
|
||||
* Allows modifying the Version Bits regtest parameters.
|
||||
*/
|
||||
void UpdateVersionBitsParameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout, int64_t nWindowSize, int64_t nThresholdStart, int64_t nThresholdMin, int64_t nFalloffCoeff)
|
||||
void UpdateVersionBitsParameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout, int64_t nWindowSize, int64_t nThresholdStart, int64_t nThresholdMin, int64_t nFalloffCoeff, int64_t nMNActivationHeight)
|
||||
{
|
||||
consensus.vDeployments[d].nStartTime = nStartTime;
|
||||
consensus.vDeployments[d].nTimeout = nTimeout;
|
||||
@ -925,6 +949,9 @@ public:
|
||||
if (nFalloffCoeff != -1) {
|
||||
consensus.vDeployments[d].nFalloffCoeff = nFalloffCoeff;
|
||||
}
|
||||
if (nMNActivationHeight != -1) {
|
||||
consensus.vDeployments[d].nMNActivationHeight = nMNActivationHeight;
|
||||
}
|
||||
}
|
||||
void UpdateActivationParametersFromArgs(const ArgsManager& args);
|
||||
|
||||
@ -998,13 +1025,13 @@ void CRegTestParams::UpdateActivationParametersFromArgs(const ArgsManager& args)
|
||||
|
||||
for (const std::string& strDeployment : args.GetArgs("-vbparams")) {
|
||||
std::vector<std::string> vDeploymentParams = SplitString(strDeployment, ':');
|
||||
if (vDeploymentParams.size() != 3 && vDeploymentParams.size() != 5 && vDeploymentParams.size() != 7) {
|
||||
if (vDeploymentParams.size() != 3 && vDeploymentParams.size() != 5 && vDeploymentParams.size() != 8) {
|
||||
throw std::runtime_error("Version bits parameters malformed, expecting "
|
||||
"<deployment>:<start>:<end> or "
|
||||
"<deployment>:<start>:<end>:<window>:<threshold> or "
|
||||
"<deployment>:<start>:<end>:<window>:<thresholdstart>:<thresholdmin>:<falloffcoeff>");
|
||||
"<deployment>:<start>:<end>:<window>:<thresholdstart>:<thresholdmin>:<falloffcoeff>:<mnactivation>");
|
||||
}
|
||||
int64_t nStartTime, nTimeout, nWindowSize = -1, nThresholdStart = -1, nThresholdMin = -1, nFalloffCoeff = -1;
|
||||
int64_t nStartTime, nTimeout, nWindowSize = -1, nThresholdStart = -1, nThresholdMin = -1, nFalloffCoeff = -1, nMNActivationHeight = -1;
|
||||
if (!ParseInt64(vDeploymentParams[1], &nStartTime)) {
|
||||
throw std::runtime_error(strprintf("Invalid nStartTime (%s)", vDeploymentParams[1]));
|
||||
}
|
||||
@ -1019,21 +1046,24 @@ void CRegTestParams::UpdateActivationParametersFromArgs(const ArgsManager& args)
|
||||
throw std::runtime_error(strprintf("Invalid nThresholdStart (%s)", vDeploymentParams[4]));
|
||||
}
|
||||
}
|
||||
if (vDeploymentParams.size() == 7) {
|
||||
if (vDeploymentParams.size() == 8) {
|
||||
if (!ParseInt64(vDeploymentParams[5], &nThresholdMin)) {
|
||||
throw std::runtime_error(strprintf("Invalid nThresholdMin (%s)", vDeploymentParams[5]));
|
||||
}
|
||||
if (!ParseInt64(vDeploymentParams[6], &nFalloffCoeff)) {
|
||||
throw std::runtime_error(strprintf("Invalid nFalloffCoeff (%s)", vDeploymentParams[6]));
|
||||
}
|
||||
if (!ParseInt64(vDeploymentParams[7], &nMNActivationHeight)) {
|
||||
throw std::runtime_error(strprintf("Invalid nMNActivationHeight (%s)", vDeploymentParams[7]));
|
||||
}
|
||||
}
|
||||
bool found = false;
|
||||
for (int j=0; j < (int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; ++j) {
|
||||
if (vDeploymentParams[0] == VersionBitsDeploymentInfo[j].name) {
|
||||
UpdateVersionBitsParameters(Consensus::DeploymentPos(j), nStartTime, nTimeout, nWindowSize, nThresholdStart, nThresholdMin, nFalloffCoeff);
|
||||
UpdateVersionBitsParameters(Consensus::DeploymentPos(j), nStartTime, nTimeout, nWindowSize, nThresholdStart, nThresholdMin, nFalloffCoeff, nMNActivationHeight);
|
||||
found = true;
|
||||
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);
|
||||
LogPrintf("Setting version bits activation parameters for %s to start=%ld, timeout=%ld, window=%ld, thresholdstart=%ld, thresholdmin=%ld, falloffcoeff=%ld, mnactivationHeight=%ld\n",
|
||||
vDeploymentParams[0], nStartTime, nTimeout, nWindowSize, nThresholdStart, nThresholdMin, nFalloffCoeff, nMNActivationHeight);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -134,6 +134,7 @@ public:
|
||||
void UpdateDIP8Parameters(int nActivationHeight);
|
||||
void UpdateBudgetParameters(int nMasternodePaymentsStartBlock, int nBudgetPaymentsStartBlock, int nSuperblockStartBlock);
|
||||
void UpdateLLMQInstantSend(Consensus::LLMQType llmqType);
|
||||
bool UpdateMNActivationParam(int nBit, int height, int64_t timePast, bool fJustCheck) const;
|
||||
int PoolMinParticipants() const { return nPoolMinParticipants; }
|
||||
int PoolMaxParticipants() const { return nPoolMaxParticipants; }
|
||||
int FulfilledRequestExpireTime() const { return nFulfilledRequestExpireTime; }
|
||||
|
@ -36,9 +36,9 @@ void SetupChainParamsBaseOptions(ArgsManager& argsman)
|
||||
argsman.AddArg("-regtest", "Enter regression test mode, which uses a special chain in which blocks can be solved instantly. "
|
||||
"This is intended for regression testing tools and app development. Equivalent to -chain=regtest", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::CHAINPARAMS);
|
||||
argsman.AddArg("-testnet", "Use the test chain. Equivalent to -chain=test", ArgsManager::ALLOW_ANY, OptionsCategory::CHAINPARAMS);
|
||||
argsman.AddArg("-vbparams=<deployment>:<start>:<end>(:<window>:<threshold/thresholdstart>(:<thresholdmin>:<falloffcoeff>))",
|
||||
argsman.AddArg("-vbparams=<deployment>:<start>:<end>(:<window>:<threshold/thresholdstart>(:<thresholdmin>:<falloffcoeff>:<mnactivation>))",
|
||||
"Use given start/end times for specified version bits deployment (regtest-only). "
|
||||
"Specifying window, threshold/thresholdstart, thresholdmin and falloffcoeff is optional.", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::CHAINPARAMS);
|
||||
"Specifying window, threshold/thresholdstart, thresholdmin, falloffcoeff and mnactivation is optional.", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::CHAINPARAMS);
|
||||
|
||||
}
|
||||
|
||||
|
@ -48,6 +48,13 @@ struct BIP9Deployment {
|
||||
* process (which takes at least 3 BIP9 intervals). Only tests that specifically test the
|
||||
* behaviour during activation cannot use this. */
|
||||
static constexpr int64_t ALWAYS_ACTIVE = -1;
|
||||
|
||||
/** this value is used for forks activated by master nodes.
|
||||
* negative values means it is regular fork, no masternodes confirmation is needed.
|
||||
* 0 means that there's no approval from masternodes yet.
|
||||
* Otherwise it shows minimum height when miner's signals for this block can be assumed
|
||||
*/
|
||||
mutable int64_t nMNActivationHeight{-1};
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -34,7 +34,7 @@ static constexpr int threshold(int attempt)
|
||||
|
||||
struct TestChainDATSetup : public TestChainSetup
|
||||
{
|
||||
TestChainDATSetup() : TestChainSetup(window - 2, {"-vbparams=testdummy:0:999999999999:100:80:60:5"}) {}
|
||||
TestChainDATSetup() : TestChainSetup(window - 2, {"-vbparams=testdummy:0:999999999999:100:80:60:5:-1"}) {}
|
||||
|
||||
void signal(int num_blocks, bool expected_lockin)
|
||||
{
|
||||
|
@ -24,6 +24,7 @@ private:
|
||||
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 MasternodeBeginHeight(const Consensus::Params& params) const override { return 0; }
|
||||
int Period(const Consensus::Params& params) const override { return 1000; }
|
||||
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); }
|
||||
|
@ -1927,6 +1927,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 MasternodeBeginHeight(const Consensus::Params& params) const override { return 0; }
|
||||
int Period(const Consensus::Params& params) const override { return params.nMinerConfirmationWindow; }
|
||||
int Threshold(const Consensus::Params& params, int nAttempt) const override { return params.nRuleChangeActivationThreshold; }
|
||||
|
||||
|
@ -5,10 +5,33 @@
|
||||
#include <versionbits.h>
|
||||
#include <consensus/params.h>
|
||||
|
||||
static int calculateStartHeight(const CBlockIndex* pindexPrev, ThresholdState state, const int nPeriod, const ThresholdConditionCache& cache) {
|
||||
int nStartHeight{std::numeric_limits<int>::max()};
|
||||
|
||||
// we are interested only in state STARTED
|
||||
// For state DEFINED: it is not started yet, nothing to do
|
||||
// For states LOCKED_IN, FAILED, ACTIVE: it is too late, nothing to do
|
||||
while (state == ThresholdState::STARTED) {
|
||||
nStartHeight = std::min(pindexPrev->nHeight + 1, nStartHeight);
|
||||
|
||||
// we can walk back here because the only way for STARTED state to exist
|
||||
// in cache already is to be calculated in previous runs via "walk forward"
|
||||
// loop below starting from DEFINED state.
|
||||
pindexPrev = pindexPrev->GetAncestor(pindexPrev->nHeight - nPeriod);
|
||||
auto cache_it = cache.find(pindexPrev);
|
||||
assert(cache_it != cache.end());
|
||||
|
||||
state = cache_it->second;
|
||||
}
|
||||
|
||||
return nStartHeight;
|
||||
}
|
||||
|
||||
ThresholdState AbstractThresholdConditionChecker::GetStateFor(const CBlockIndex* pindexPrev, const Consensus::Params& params, ThresholdConditionCache& cache) const
|
||||
{
|
||||
int nPeriod = Period(params);
|
||||
int64_t nTimeStart = BeginTime(params);
|
||||
int masternodeStartHeight = MasternodeBeginHeight(params);
|
||||
int64_t nTimeTimeout = EndTime(params);
|
||||
|
||||
// Check if this deployment is always active.
|
||||
@ -29,7 +52,7 @@ ThresholdState AbstractThresholdConditionChecker::GetStateFor(const CBlockIndex*
|
||||
cache[pindexPrev] = ThresholdState::DEFINED;
|
||||
break;
|
||||
}
|
||||
if (pindexPrev->GetMedianTimePast() < nTimeStart) {
|
||||
if (pindexPrev->GetMedianTimePast() < nTimeStart || pindexPrev->nHeight < masternodeStartHeight) {
|
||||
// Optimization: don't recompute down further, as we know every earlier block will be before the start time
|
||||
cache[pindexPrev] = ThresholdState::DEFINED;
|
||||
break;
|
||||
@ -42,35 +65,7 @@ ThresholdState AbstractThresholdConditionChecker::GetStateFor(const CBlockIndex*
|
||||
assert(cache.count(pindexPrev));
|
||||
ThresholdState state = cache[pindexPrev];
|
||||
|
||||
auto pindex_search = pindexPrev;
|
||||
auto state_search = state;
|
||||
bool do_search{true};
|
||||
int nStartHeight{std::numeric_limits<int>::max()};
|
||||
while (do_search) {
|
||||
switch (state_search) {
|
||||
case ThresholdState::DEFINED: {
|
||||
// not started yet, nothinig to do
|
||||
do_search = false;
|
||||
break;
|
||||
}
|
||||
case ThresholdState::STARTED: {
|
||||
nStartHeight = std::min(nStartHeight, pindex_search->nHeight + 1);
|
||||
// we can walk back here because the only way for STARTED state to exist
|
||||
// in cache already is to be calculated in previous runs via "walk forward"
|
||||
// loop below starting from DEFINED state.
|
||||
pindex_search = pindex_search->GetAncestor(pindex_search->nHeight - nPeriod);
|
||||
state_search = cache[pindex_search];
|
||||
break;
|
||||
}
|
||||
case ThresholdState::LOCKED_IN:
|
||||
case ThresholdState::FAILED:
|
||||
case ThresholdState::ACTIVE: {
|
||||
// too late, nothing to do
|
||||
do_search = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
int nStartHeight = calculateStartHeight(pindexPrev, state, nPeriod, cache);
|
||||
|
||||
// Now walk forward and compute the state of descendants of pindexPrev
|
||||
while (!vToCompute.empty()) {
|
||||
@ -82,7 +77,7 @@ ThresholdState AbstractThresholdConditionChecker::GetStateFor(const CBlockIndex*
|
||||
case ThresholdState::DEFINED: {
|
||||
if (pindexPrev->GetMedianTimePast() >= nTimeTimeout) {
|
||||
stateNext = ThresholdState::FAILED;
|
||||
} else if (pindexPrev->GetMedianTimePast() >= nTimeStart) {
|
||||
} else if (pindexPrev->GetMedianTimePast() >= nTimeStart && pindexPrev->nHeight >= masternodeStartHeight) {
|
||||
stateNext = ThresholdState::STARTED;
|
||||
nStartHeight = pindexPrev->nHeight + 1;
|
||||
}
|
||||
@ -210,6 +205,16 @@ private:
|
||||
|
||||
protected:
|
||||
int64_t BeginTime(const Consensus::Params& params) const override { return params.vDeployments[id].nStartTime; }
|
||||
int MasternodeBeginHeight(const Consensus::Params& params) const override {
|
||||
const auto& deployment = params.vDeployments[id];
|
||||
if (deployment.nMNActivationHeight == 0) {
|
||||
return std::numeric_limits<int>::max();
|
||||
}
|
||||
if (deployment.nMNActivationHeight < 0) {
|
||||
return 0;
|
||||
}
|
||||
return deployment.nMNActivationHeight;
|
||||
}
|
||||
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, int nAttempt) const override
|
||||
|
@ -56,6 +56,7 @@ class AbstractThresholdConditionChecker {
|
||||
protected:
|
||||
virtual bool Condition(const CBlockIndex* pindex, const Consensus::Params& params) const =0;
|
||||
virtual int64_t BeginTime(const Consensus::Params& params) const =0;
|
||||
virtual int MasternodeBeginHeight(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, int nAttempt) const =0;
|
||||
|
@ -24,7 +24,7 @@ llmq_type_strings = {llmq_test: 'llmq_test', llmq_test_v17: 'llmq_test_v17'}
|
||||
|
||||
class QuorumDataRecoveryTest(DashTestFramework):
|
||||
def set_test_params(self):
|
||||
extra_args = [["-vbparams=testdummy:0:999999999999:10:8:6:5"] for _ in range(9)]
|
||||
extra_args = [["-vbparams=testdummy:0:999999999999:10:8:6:5:-1"] for _ in range(9)]
|
||||
self.set_dash_test_params(9, 7, fast_dip3_enforcement=True, extra_args=extra_args)
|
||||
self.set_dash_llmq_test_params(4, 3)
|
||||
|
||||
|
@ -17,7 +17,7 @@ class NewQuorumTypeActivationTest(BitcoinTestFramework):
|
||||
def set_test_params(self):
|
||||
self.setup_clean_chain = True
|
||||
self.num_nodes = 1
|
||||
self.extra_args = [["-vbparams=testdummy:0:999999999999:10:8:6:5"]]
|
||||
self.extra_args = [["-vbparams=testdummy:0:999999999999:10:8:6:5:-1"]]
|
||||
|
||||
def run_test(self):
|
||||
self.log.info(get_bip9_details(self.nodes[0], 'testdummy'))
|
||||
|
Loading…
Reference in New Issue
Block a user