LCOV - code coverage report
Current view: top level - src/test - dynamic_activation_thresholds_tests.cpp (source / functions) Hit Total Coverage
Test: test_dash_coverage.info Lines: 82 82 100.0 %
Date: 2026-06-25 07:23:51 Functions: 92 92 100.0 %

          Line data    Source code
       1             : // Copyright (c) 2021-2025 The Dash Core developers
       2             : // Distributed under the MIT software license, see the accompanying
       3             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       4             : 
       5             : #include <test/util/setup_common.h>
       6             : 
       7             : #include <chainparams.h>
       8             : #include <deploymentstatus.h>
       9             : #include <node/miner.h>
      10             : #include <validation.h>
      11             : #include <versionbits.h>
      12             : 
      13             : #include <boost/test/unit_test.hpp>
      14             : 
      15             : using node::BlockAssembler;
      16             : 
      17             : const auto deployment_id = Consensus::DEPLOYMENT_TESTDUMMY;
      18             : constexpr int window{100}, th_start{80}, th_end{60};
      19             : 
      20         180 : static constexpr int threshold(int attempt)
      21             : {
      22             :     // An implementation of VersionBitsConditionChecker::Threshold()
      23         180 :     int threshold_calc = th_start - attempt * attempt * window / 100 / 5;
      24         180 :     if (threshold_calc < th_end) {
      25           6 :         return th_end;
      26             :     }
      27         174 :     return threshold_calc;
      28         180 : }
      29             : 
      30             : struct TestChainDATSetup : public TestChainSetup
      31             : {
      32          12 :     TestChainDATSetup() :
      33          12 :         TestChainSetup(window - 2, CBaseChainParams::REGTEST, {"-vbparams=testdummy:0:999999999999:0:100:80:60:5:0"}) {}
      34             : 
      35          90 :     void signal(int num_blocks, bool expected_lockin)
      36             :     {
      37          90 :         const auto& consensus_params = Params().GetConsensus();
      38          90 :         CScript coinbasePubKey = GetScriptForRawPubKey(coinbaseKey.GetPubKey());
      39             :         // Mine non-signalling blocks
      40          90 :         gArgs.ForceSetArg("-blockversion", "536870912");
      41        2392 :         for (int i = 0; i < window - num_blocks; ++i) {
      42        2302 :             CreateAndProcessBlock({}, coinbasePubKey);
      43        2302 :         }
      44          90 :         gArgs.ForceRemoveArg("blockversion");
      45          90 :         if (num_blocks > 0) {
      46             :             // Mine signalling blocks
      47        6788 :             for (int i = 0; i < num_blocks; ++i) {
      48        6698 :                 CreateAndProcessBlock({}, coinbasePubKey);
      49        6698 :             }
      50          90 :         }
      51          90 :         LOCK(cs_main);
      52          90 :         if (expected_lockin) {
      53          12 :             BOOST_CHECK_EQUAL(m_node.chainman->m_versionbitscache.State(m_node.chainman->ActiveChain().Tip(),
      54             :                                                                         consensus_params, deployment_id),
      55             :                               ThresholdState::LOCKED_IN);
      56          12 :         } else {
      57          78 :             BOOST_CHECK_EQUAL(m_node.chainman->m_versionbitscache.State(m_node.chainman->ActiveChain().Tip(),
      58             :                                                                         consensus_params, deployment_id),
      59             :                               ThresholdState::STARTED);
      60             :         }
      61          90 :     }
      62             : 
      63          12 :     void test(int activation_index, bool check_activation_at_min)
      64             :     {
      65          12 :         const auto& consensus_params = Params().GetConsensus();
      66          12 :         CScript coinbasePubKey = GetScriptForRawPubKey(coinbaseKey.GetPubKey());
      67             : 
      68             :         {
      69          12 :             LOCK(cs_main);
      70          12 :             BOOST_CHECK_EQUAL(m_node.chainman->ActiveChain().Height(), window - 2);
      71          12 :             BOOST_CHECK_EQUAL(m_node.chainman->m_versionbitscache.State(m_node.chainman->ActiveChain().Tip(),
      72             :                                                                         consensus_params, deployment_id),
      73             :                               ThresholdState::DEFINED);
      74          12 :         }
      75             : 
      76          12 :         CreateAndProcessBlock({}, coinbasePubKey);
      77             : 
      78             :         {
      79          12 :             LOCK(cs_main);
      80             :             // Advance from DEFINED to STARTED at height = window - 1
      81          12 :             BOOST_CHECK_EQUAL(m_node.chainman->ActiveChain().Height(), window - 1);
      82          12 :             BOOST_CHECK_EQUAL(m_node.chainman->m_versionbitscache.State(m_node.chainman->ActiveChain().Tip(),
      83             :                                                                         consensus_params, deployment_id),
      84             :                               ThresholdState::STARTED);
      85          12 :             BOOST_CHECK_EQUAL(m_node.chainman->m_versionbitscache
      86             :                                   .Statistics(m_node.chainman->ActiveChain().Tip(), consensus_params, deployment_id)
      87             :                                   .threshold,
      88             :                               threshold(0));
      89             :             // Next block should be signaling by default
      90          12 :             const auto pblocktemplate = BlockAssembler(m_node.chainman->ActiveChainstate(), m_node, m_node.mempool.get(), Params()).CreateNewBlock(coinbasePubKey);
      91          12 :             const uint32_t bitmask = ((uint32_t)1) << consensus_params.vDeployments[deployment_id].bit;
      92          12 :             BOOST_CHECK_EQUAL(m_node.chainman->ActiveChain().Tip()->nVersion & bitmask, 0);
      93          12 :             BOOST_CHECK_EQUAL(pblocktemplate->block.nVersion & bitmask, bitmask);
      94          12 :         }
      95             : 
      96             :         // Reach activation_index level
      97          90 :         for (int i = 0; i < activation_index; ++i) {
      98          78 :             signal(threshold(i) - 1, false); // 1 block short
      99             : 
     100             :             {
     101             :                 // Still STARTED but with a (potentially) new threshold
     102          78 :                 LOCK(cs_main);
     103          78 :                 BOOST_CHECK_EQUAL(m_node.chainman->ActiveChain().Height(), window * (i + 2) - 1);
     104          78 :                 BOOST_CHECK_EQUAL(m_node.chainman->m_versionbitscache.State(m_node.chainman->ActiveChain().Tip(),
     105             :                                                                             consensus_params, deployment_id),
     106             :                                   ThresholdState::STARTED);
     107          78 :                 const auto vbts = m_node.chainman->m_versionbitscache.Statistics(m_node.chainman->ActiveChain().Tip(),
     108          78 :                                                                                  consensus_params, deployment_id);
     109          78 :                 BOOST_CHECK_EQUAL(vbts.threshold, threshold(i + 1));
     110          78 :                 BOOST_CHECK(vbts.threshold <= th_start);
     111          78 :                 BOOST_CHECK(vbts.threshold >= th_end);
     112          78 :             }
     113          78 :         }
     114          24 :         if (LOCK(cs_main); check_activation_at_min) {
     115           3 :             BOOST_CHECK_EQUAL(m_node.chainman->m_versionbitscache
     116             :                                   .Statistics(m_node.chainman->ActiveChain().Tip(), consensus_params, deployment_id)
     117             :                                   .threshold,
     118             :                               th_end);
     119           3 :         } else {
     120           9 :             BOOST_CHECK(m_node.chainman->m_versionbitscache
     121             :                             .Statistics(m_node.chainman->ActiveChain().Tip(), consensus_params, deployment_id)
     122             :                             .threshold > th_end);
     123             :         }
     124             : 
     125             :         // activate
     126          12 :         signal(threshold(activation_index), true);
     127        1212 :         for (int i = 0; i < window; ++i) {
     128        1200 :             CreateAndProcessBlock({}, coinbasePubKey);
     129        1200 :         }
     130             :         {
     131          12 :             LOCK(cs_main);
     132          12 :             BOOST_CHECK_EQUAL(m_node.chainman->m_versionbitscache.State(m_node.chainman->ActiveChain().Tip(),
     133             :                                                                         consensus_params, deployment_id),
     134             :                               ThresholdState::ACTIVE);
     135          12 :         }
     136             : 
     137          12 :     }
     138             : };
     139             : 
     140             : 
     141         146 : BOOST_AUTO_TEST_SUITE(dynamic_activation_thresholds_tests)
     142             : 
     143             : #define TEST(INDEX, activate_at_min_level)  BOOST_FIXTURE_TEST_CASE(activate_at_##INDEX##_level, TestChainDATSetup) \
     144             : { \
     145             :     test(INDEX, activate_at_min_level); \
     146             : }
     147             : 
     148         148 : TEST(1, false)
     149         148 : TEST(2, false)
     150         148 : TEST(3, false)
     151         148 : TEST(4, false)
     152         148 : TEST(5, false)
     153         148 : TEST(6, false)
     154         148 : TEST(7, false)
     155         148 : TEST(8, false)
     156         148 : TEST(9, false)
     157         148 : TEST(10, true)
     158         148 : TEST(11, true)
     159         148 : TEST(12, true)
     160             : 
     161         146 : BOOST_AUTO_TEST_SUITE_END()

Generated by: LCOV version 1.16