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()
|