diff --git a/src/chainparams.cpp b/src/chainparams.cpp index ceadb9d386..d202b81e03 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -135,6 +135,7 @@ class CMainParams : public CChainParams { g_con_elementsmode = false; g_con_blockheightinheader = false; consensus.total_valid_epochs = 0; + consensus.elements_mode = g_con_elementsmode; /** * The message start string is designed to be unlikely to occur in normal data. @@ -265,6 +266,7 @@ class CTestNetParams : public CChainParams { g_con_elementsmode = false; g_con_blockheightinheader = false; consensus.total_valid_epochs = 0; + consensus.elements_mode = g_con_elementsmode; pchMessageStart[0] = 0x0b; pchMessageStart[1] = 0x11; @@ -367,6 +369,7 @@ class CRegTestParams : public CChainParams { consensus.has_parent_chain = false; g_signed_blocks = false; g_con_elementsmode = false; + consensus.elements_mode = g_con_elementsmode; g_con_blockheightinheader = false; consensus.total_valid_epochs = 0; @@ -552,6 +555,7 @@ class CCustomParams : public CRegTestParams { // Default to true for custom chains. g_con_blockheightinheader = args.GetBoolArg("-con_blockheightinheader", true); g_con_elementsmode = args.GetBoolArg("-con_elementsmode", true); + consensus.elements_mode = g_con_elementsmode; // No subsidy for custom chains by default consensus.genesis_subsidy = args.GetArg("-con_blocksubsidy", 0); @@ -726,6 +730,7 @@ class CLiquidV1Params : public CChainParams { g_con_blockheightinheader = true; g_con_elementsmode = true; + consensus.elements_mode = g_con_elementsmode; // TODO: Pick appropriate value for this network. consensus.total_valid_epochs = 2; diff --git a/src/consensus/params.h b/src/consensus/params.h index aaf4cf1401..e4ef209bef 100644 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -108,6 +108,7 @@ struct Params { // Used to allow M-epoch-old peg-in addresses as deposits // default 1 to not break legacy chains implicitly. size_t total_valid_epochs = 1; + bool elements_mode = false; }; } // namespace Consensus diff --git a/src/versionbits.cpp b/src/versionbits.cpp index 3f297c0ebb..83b782b5b6 100644 --- a/src/versionbits.cpp +++ b/src/versionbits.cpp @@ -5,10 +5,20 @@ #include #include +// Elements: We use height, not time! +int64_t GetBIP9Time(const CBlockIndex* pindexPrev, const Consensus::Params& params) { + if (params.elements_mode) { + return pindexPrev->nHeight; + } else { + return pindexPrev->GetMedianTimePast(); + } +} + ThresholdState AbstractThresholdConditionChecker::GetStateFor(const CBlockIndex* pindexPrev, const Consensus::Params& params, ThresholdConditionCache& cache) const { int nPeriod = Period(params); int nThreshold = Threshold(params); + // ELEMENTS: We interpret this as block height, not block time! int64_t nTimeStart = BeginTime(params); int64_t nTimeTimeout = EndTime(params); @@ -30,7 +40,7 @@ ThresholdState AbstractThresholdConditionChecker::GetStateFor(const CBlockIndex* cache[pindexPrev] = ThresholdState::DEFINED; break; } - if (pindexPrev->GetMedianTimePast() < nTimeStart) { + if (GetBIP9Time(pindexPrev, params) < nTimeStart) { // Optimization: don't recompute down further, as we know every earlier block will be before the start time cache[pindexPrev] = ThresholdState::DEFINED; break; @@ -51,15 +61,15 @@ ThresholdState AbstractThresholdConditionChecker::GetStateFor(const CBlockIndex* switch (state) { case ThresholdState::DEFINED: { - if (pindexPrev->GetMedianTimePast() >= nTimeTimeout) { + if (GetBIP9Time(pindexPrev, params) >= nTimeTimeout) { stateNext = ThresholdState::FAILED; - } else if (pindexPrev->GetMedianTimePast() >= nTimeStart) { + } else if (GetBIP9Time(pindexPrev, params) >= nTimeStart) { stateNext = ThresholdState::STARTED; } break; } case ThresholdState::STARTED: { - if (pindexPrev->GetMedianTimePast() >= nTimeTimeout) { + if (GetBIP9Time(pindexPrev, params) >= nTimeTimeout) { stateNext = ThresholdState::FAILED; break; } diff --git a/test/functional/feature_dynafed.py b/test/functional/feature_dynafed.py index ea03310e5f..2ce325e380 100755 --- a/test/functional/feature_dynafed.py +++ b/test/functional/feature_dynafed.py @@ -63,7 +63,7 @@ def set_test_params(self): self.setup_clean_chain = True self.num_nodes = 2 # We want to test activation of dynafed - self.extra_args = [["-con_dyna_deploy_start=0", "-enforce_pak=1", "-con_parent_chain_signblockscript=51", "-peginconfirmationdepth=1", "-parentscriptprefix=75", "-parent_bech32_hrp=ert"] for i in range(self.num_nodes)] + self.extra_args = [["-con_dyna_deploy_start=1000", "-enforce_pak=1", "-con_parent_chain_signblockscript=51", "-peginconfirmationdepth=1", "-parentscriptprefix=75", "-parent_bech32_hrp=ert"] for i in range(self.num_nodes)] # second node will not mine transactions self.extra_args[1].append("-blocksonly=1") @@ -105,8 +105,18 @@ def test_legacy_params(self): def test_dynafed_activation(self): self.log.info("Testing dynafed versionbits activation...") + # Signaling window is in height, not time, so first block that will signal is + # at height 1008 which is evenly disible by 144(regtest bip9 window size) + # Giving funds to node 1 to avoid a transaction size blowup when sweeping later + blocks = self.nodes[0].generatetoaddress(1006, self.nodes[1].getnewaddress()) + assert_equal(self.nodes[0].getblockchaininfo()["bip9_softforks"]["dynafed"]["status"], "defined") + blocks += self.nodes[0].generatetoaddress(1, self.nodes[0].getnewaddress()) + assert_equal(self.nodes[0].getblockchaininfo()["bip9_softforks"]["dynafed"]["status"], "started") + blocks += self.nodes[0].generatetoaddress(144, self.nodes[0].getnewaddress()) + assert_equal(self.nodes[0].getblockchaininfo()["bip9_softforks"]["dynafed"]["status"], "locked_in") + # Move chain forward to activation, any new blocks will be enforced - blocks = self.nodes[0].generatetoaddress(431, self.nodes[0].getnewaddress()) + blocks += self.nodes[0].generatetoaddress(144, self.nodes[0].getnewaddress()) self.sync_all() assert_equal(self.nodes[0].getblockchaininfo()["bip9_softforks"]["dynafed"]["status"], "active")