Line data Source code
1 : // Copyright (c) 2015-2020 The Bitcoin 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 <chain.h>
6 : #include <chainparams.h>
7 : #include <pow.h>
8 : #include <test/util/random.h>
9 : #include <test/util/setup_common.h>
10 :
11 : #include <boost/test/unit_test.hpp>
12 :
13 146 : BOOST_FIXTURE_TEST_SUITE(pow_tests, BasicTestingSetup)
14 :
15 : /* Test calculation of next difficulty target with DGW */
16 149 : BOOST_AUTO_TEST_CASE(get_next_work)
17 : {
18 1 : const auto chainParams = CreateChainParams(*m_node.args, CBaseChainParams::MAIN);
19 :
20 1 : static const std::vector<std::pair<uint32_t, uint32_t>> mainnet_data = {
21 3 : { 1408728124, 0x1b104be1U }, { 1408728332, 0x1b10e09eU }, { 1408728479, 0x1b11a33cU },
22 3 : { 1408728495, 0x1b121cf3U }, { 1408728608, 0x1b11951eU }, { 1408728744, 0x1b11abacU },
23 3 : { 1408728756, 0x1b118d9cU }, { 1408728950, 0x1b1123f9U }, { 1408729116, 0x1b1141bfU },
24 3 : { 1408729179, 0x1b110764U }, { 1408729305, 0x1b107556U }, { 1408729474, 0x1b104297U },
25 3 : { 1408729576, 0x1b1063d0U }, { 1408729587, 0x1b10e878U }, { 1408729647, 0x1b0dfaffU },
26 3 : { 1408729678, 0x1b0c9ab8U }, { 1408730179, 0x1b0c03d6U }, { 1408730862, 0x1b0dd168U },
27 3 : { 1408730914, 0x1b10b864U }, { 1408731242, 0x1b0fed89U }, { 1408731256, 0x1b113ff1U },
28 3 : { 1408732229, 0x1b10460bU }, { 1408732257, 0x1b13b83fU }, { 1408732489, 0x1b1418d4U }
29 : };
30 :
31 : // Construct a chain of block index entries
32 1 : std::list<CBlockIndex> blockidx;
33 1 : CBlockIndex* blockIndexLast{nullptr};
34 :
35 25 : for (const auto& [nTime, nBits] : mainnet_data) {
36 24 : auto& entry = blockidx.emplace_back();
37 24 : entry.nTime = nTime;
38 24 : entry.nBits = nBits;
39 24 : entry.pprev = blockIndexLast;
40 24 : blockIndexLast = &entry;
41 : }
42 1 : blockIndexLast->nHeight = 123456;
43 1 : assert(mainnet_data.size() == blockidx.size());
44 :
45 1 : CBlockHeader blockHeader;
46 1 : blockHeader.nTime = 1408732505; // Block #123457
47 1 : BOOST_CHECK_EQUAL(GetNextWorkRequired(blockIndexLast, &blockHeader, chainParams->GetConsensus()), 0x1b1441deU); // Block #123457 has 0x1b1441de
48 :
49 : // test special rules for slow blocks on devnet/testnet
50 1 : const auto chainParamsDev = CreateChainParams(*m_node.args, CBaseChainParams::DEVNET);
51 :
52 : // make sure normal rules apply
53 1 : blockHeader.nTime = 1408732505; // Block #123457
54 1 : BOOST_CHECK_EQUAL(GetNextWorkRequired(blockIndexLast, &blockHeader, chainParamsDev->GetConsensus()), 0x1b1441deU); // Block #123457 has 0x1b1441de
55 :
56 : // 10x higher target
57 1 : blockHeader.nTime = 1408733090; // Block #123457 (10m+1sec)
58 1 : BOOST_CHECK_EQUAL(GetNextWorkRequired(blockIndexLast, &blockHeader, chainParamsDev->GetConsensus()), 0x1c00c8f8U); // Block #123457 has 0x1c00c8f8
59 1 : blockHeader.nTime = 1408733689; // Block #123457 (20m)
60 1 : BOOST_CHECK_EQUAL(GetNextWorkRequired(blockIndexLast, &blockHeader, chainParamsDev->GetConsensus()), 0x1c00c8f8U); // Block #123457 has 0x1c00c8f8
61 : // lowest diff possible
62 1 : blockHeader.nTime = 1408739690; // Block #123457 (2h+1sec)
63 1 : BOOST_CHECK_EQUAL(GetNextWorkRequired(blockIndexLast, &blockHeader, chainParamsDev->GetConsensus()), 0x207fffffU); // Block #123457 has 0x207fffff
64 1 : blockHeader.nTime = 1408743289; // Block #123457 (3h)
65 1 : BOOST_CHECK_EQUAL(GetNextWorkRequired(blockIndexLast, &blockHeader, chainParamsDev->GetConsensus()), 0x207fffffU); // Block #123457 has 0x207fffff
66 1 : }
67 :
68 : /* Test the constraint on the upper bound for next work */
69 : // BOOST_AUTO_TEST_CASE(get_next_work_pow_limit)
70 : // {
71 : // const auto chainParams = CreateChainParams(*m_node.args, CBaseChainParams::MAIN);
72 :
73 : // int64_t nLastRetargetTime = 1231006505; // Block #0
74 : // CBlockIndex pindexLast;
75 : // pindexLast.nHeight = 2015;
76 : // pindexLast.nTime = 1233061996; // Block #2015
77 : // pindexLast.nBits = 0x1d00ffff;
78 : // BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime, chainParams->GetConsensus()), 0x1d00ffffU);
79 : // }
80 :
81 : /* Test the constraint on the lower bound for actual time taken */
82 : // BOOST_AUTO_TEST_CASE(get_next_work_lower_limit_actual)
83 : // {
84 : // const auto chainParams = CreateChainParams(*m_node.args, CBaseChainParams::MAIN);
85 :
86 : // int64_t nLastRetargetTime = 1279008237; // Block #66528
87 : // CBlockIndex pindexLast;
88 : // pindexLast.nHeight = 68543;
89 : // pindexLast.nTime = 1279297671; // Block #68543
90 : // pindexLast.nBits = 0x1c05a3f4;
91 : // BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime, chainParams->GetConsensus()), 0x1c0168fdU);
92 : // }
93 :
94 : /* Test the constraint on the upper bound for actual time taken */
95 : // BOOST_AUTO_TEST_CASE(get_next_work_upper_limit_actual)
96 : // {
97 : // const auto chainParams = CreateChainParams(*m_node.args, CBaseChainParams::MAIN);
98 :
99 : // int64_t nLastRetargetTime = 1263163443; // NOTE: Not an actual block time
100 : // CBlockIndex pindexLast;
101 : // pindexLast.nHeight = 46367;
102 : // pindexLast.nTime = 1269211443; // Block #46367
103 : // pindexLast.nBits = 0x1c387f6f;
104 : // BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime, chainParams->GetConsensus()), 0x1d00e1fdU);
105 : // }
106 :
107 149 : BOOST_AUTO_TEST_CASE(CheckProofOfWork_test_negative_target)
108 : {
109 1 : const auto consensus = CreateChainParams(*m_node.args, CBaseChainParams::MAIN)->GetConsensus();
110 1 : uint256 hash;
111 : unsigned int nBits;
112 1 : nBits = UintToArith256(consensus.powLimit).GetCompact(true);
113 1 : hash.SetHex("0x1");
114 1 : BOOST_CHECK(!CheckProofOfWork(hash, nBits, consensus));
115 1 : }
116 :
117 149 : BOOST_AUTO_TEST_CASE(CheckProofOfWork_test_overflow_target)
118 : {
119 1 : const auto consensus = CreateChainParams(*m_node.args, CBaseChainParams::MAIN)->GetConsensus();
120 1 : uint256 hash;
121 1 : unsigned int nBits{~0x00800000U};
122 1 : hash.SetHex("0x1");
123 1 : BOOST_CHECK(!CheckProofOfWork(hash, nBits, consensus));
124 1 : }
125 :
126 149 : BOOST_AUTO_TEST_CASE(CheckProofOfWork_test_too_easy_target)
127 : {
128 1 : const auto consensus = CreateChainParams(*m_node.args, CBaseChainParams::MAIN)->GetConsensus();
129 1 : uint256 hash;
130 : unsigned int nBits;
131 1 : arith_uint256 nBits_arith = UintToArith256(consensus.powLimit);
132 1 : nBits_arith *= 2;
133 1 : nBits = nBits_arith.GetCompact();
134 1 : hash.SetHex("0x1");
135 1 : BOOST_CHECK(!CheckProofOfWork(hash, nBits, consensus));
136 1 : }
137 :
138 149 : BOOST_AUTO_TEST_CASE(CheckProofOfWork_test_biger_hash_than_target)
139 : {
140 1 : const auto consensus = CreateChainParams(*m_node.args, CBaseChainParams::MAIN)->GetConsensus();
141 1 : uint256 hash;
142 : unsigned int nBits;
143 1 : arith_uint256 hash_arith = UintToArith256(consensus.powLimit);
144 1 : nBits = hash_arith.GetCompact();
145 1 : hash_arith *= 2; // hash > nBits
146 1 : hash = ArithToUint256(hash_arith);
147 1 : BOOST_CHECK(!CheckProofOfWork(hash, nBits, consensus));
148 1 : }
149 :
150 149 : BOOST_AUTO_TEST_CASE(CheckProofOfWork_test_zero_target)
151 : {
152 1 : const auto consensus = CreateChainParams(*m_node.args, CBaseChainParams::MAIN)->GetConsensus();
153 1 : uint256 hash;
154 : unsigned int nBits;
155 1 : arith_uint256 hash_arith{0};
156 1 : nBits = hash_arith.GetCompact();
157 1 : hash = ArithToUint256(hash_arith);
158 1 : BOOST_CHECK(!CheckProofOfWork(hash, nBits, consensus));
159 1 : }
160 :
161 149 : BOOST_AUTO_TEST_CASE(GetBlockProofEquivalentTime_test)
162 : {
163 1 : const auto chainParams = CreateChainParams(*m_node.args, CBaseChainParams::MAIN);
164 1 : std::vector<CBlockIndex> blocks(10000);
165 10001 : for (int i = 0; i < 10000; i++) {
166 10000 : blocks[i].pprev = i ? &blocks[i - 1] : nullptr;
167 10000 : blocks[i].nHeight = i;
168 10000 : blocks[i].nTime = 1269211443 + i * chainParams->GetConsensus().nPowTargetSpacing;
169 10000 : blocks[i].nBits = 0x207fffff; /* target 0x7fffff000... */
170 10000 : blocks[i].nChainWork = i ? blocks[i - 1].nChainWork + GetBlockProof(blocks[i - 1]) : arith_uint256(0);
171 10000 : }
172 :
173 1001 : for (int j = 0; j < 1000; j++) {
174 1000 : CBlockIndex *p1 = &blocks[InsecureRandRange(10000)];
175 1000 : CBlockIndex *p2 = &blocks[InsecureRandRange(10000)];
176 1000 : CBlockIndex *p3 = &blocks[InsecureRandRange(10000)];
177 :
178 1000 : int64_t tdiff = GetBlockProofEquivalentTime(*p1, *p2, *p3, chainParams->GetConsensus());
179 1000 : BOOST_CHECK_EQUAL(tdiff, p1->GetBlockTime() - p2->GetBlockTime());
180 1000 : }
181 1 : }
182 :
183 4 : void sanity_check_chainparams(const ArgsManager& args, std::string chainName)
184 : {
185 4 : const auto chainParams = CreateChainParams(args, chainName);
186 4 : const auto consensus = chainParams->GetConsensus();
187 :
188 : // hash genesis is correct
189 4 : BOOST_CHECK_EQUAL(consensus.hashGenesisBlock, chainParams->GenesisBlock().GetHash());
190 :
191 : // target timespan is an even multiple of spacing
192 4 : BOOST_CHECK_EQUAL(consensus.nPowTargetTimespan % consensus.nPowTargetSpacing, 0);
193 :
194 : // genesis nBits is positive, doesn't overflow and is lower than powLimit
195 4 : arith_uint256 pow_compact;
196 : bool neg, over;
197 4 : pow_compact.SetCompact(chainParams->GenesisBlock().nBits, &neg, &over);
198 8 : BOOST_CHECK(!neg && pow_compact != 0);
199 4 : BOOST_CHECK(!over);
200 4 : BOOST_CHECK(UintToArith256(consensus.powLimit) >= pow_compact);
201 :
202 : // check max target * 4*nPowTargetTimespan doesn't overflow -- see pow.cpp:CalculateNextWorkRequired()
203 4 : if (!consensus.fPowNoRetargeting) {
204 3 : arith_uint256 targ_max{UintToArith256(uint256S("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"))};
205 3 : targ_max /= consensus.nPowTargetTimespan*4;
206 : // for devnets pow-no-retargeting may work as non-expected but it's a breaking change to fix it
207 : // TODO: remove this special case for devnet
208 3 : if (chainName != CBaseChainParams::DEVNET) {
209 2 : BOOST_CHECK(UintToArith256(consensus.powLimit) < targ_max);
210 2 : }
211 3 : }
212 4 : }
213 :
214 149 : BOOST_AUTO_TEST_CASE(ChainParams_MAIN_sanity)
215 : {
216 1 : sanity_check_chainparams(*m_node.args, CBaseChainParams::MAIN);
217 1 : }
218 :
219 149 : BOOST_AUTO_TEST_CASE(ChainParams_REGTEST_sanity)
220 : {
221 1 : sanity_check_chainparams(*m_node.args, CBaseChainParams::REGTEST);
222 1 : }
223 :
224 149 : BOOST_AUTO_TEST_CASE(ChainParams_TESTNET_sanity)
225 : {
226 1 : sanity_check_chainparams(*m_node.args, CBaseChainParams::TESTNET);
227 1 : }
228 :
229 149 : BOOST_AUTO_TEST_CASE(ChainParams_DEVNET_sanity)
230 : {
231 1 : gArgs.SoftSetBoolArg("-devnet", true);
232 1 : sanity_check_chainparams(*m_node.args, CBaseChainParams::DEVNET);
233 1 : gArgs.ForceRemoveArg("devnet");
234 1 : }
235 :
236 146 : BOOST_AUTO_TEST_SUITE_END()
|