Branch data Line data Source code
1 : : // Copyright (c) 2017-2022 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 <boost/test/unit_test.hpp>
6 : :
7 : : #include <chain.h>
8 : : #include <node/blockstorage.h>
9 : : #include <rpc/blockchain.h>
10 : : #include <sync.h>
11 : : #include <test/util/setup_common.h>
12 : : #include <util/string.h>
13 : :
14 : : #include <cstdlib>
15 : :
16 : : using util::ToString;
17 : :
18 : : /* Equality between doubles is imprecise. Comparison should be done
19 : : * with a small threshold of tolerance, rather than exact equality.
20 : : */
21 : 5 : static bool DoubleEquals(double a, double b, double epsilon)
22 : : {
23 : 5 : return std::abs(a - b) < epsilon;
24 : : }
25 : :
26 : 5 : static CBlockIndex* CreateBlockIndexWithNbits(uint32_t nbits)
27 : : {
28 : 5 : CBlockIndex* block_index = new CBlockIndex();
29 : 5 : block_index->nHeight = 46367;
30 : 5 : block_index->nTime = 1269211443;
31 : 5 : block_index->nBits = nbits;
32 : 5 : return block_index;
33 : : }
34 : :
35 : 5 : static void RejectDifficultyMismatch(double difficulty, double expected_difficulty) {
36 [ + - + - : 15 : BOOST_CHECK_MESSAGE(
+ - + - ]
37 : : DoubleEquals(difficulty, expected_difficulty, 0.00001),
38 : : "Difficulty was " + ToString(difficulty)
39 : : + " but was expected to be " + ToString(expected_difficulty));
40 : 5 : }
41 : :
42 : : /* Given a BlockIndex with the provided nbits,
43 : : * verify that the expected difficulty results.
44 : : */
45 : 5 : static void TestDifficulty(uint32_t nbits, double expected_difficulty)
46 : : {
47 : 5 : CBlockIndex* block_index = CreateBlockIndexWithNbits(nbits);
48 : 5 : double difficulty = GetDifficulty(*block_index);
49 [ + - ]: 5 : delete block_index;
50 : :
51 : 5 : RejectDifficultyMismatch(difficulty, expected_difficulty);
52 : 5 : }
53 : :
54 : : BOOST_FIXTURE_TEST_SUITE(blockchain_tests, BasicTestingSetup)
55 : :
56 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(get_difficulty_for_very_low_target)
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- ]
57 : : {
58 : 1 : TestDifficulty(0x1f111111, 0.000001);
59 : 1 : }
60 : :
61 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(get_difficulty_for_low_target)
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- ]
62 : : {
63 : 1 : TestDifficulty(0x1ef88f6f, 0.000016);
64 : 1 : }
65 : :
66 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(get_difficulty_for_mid_target)
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- ]
67 : : {
68 : 1 : TestDifficulty(0x1df88f6f, 0.004023);
69 : 1 : }
70 : :
71 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(get_difficulty_for_high_target)
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- ]
72 : : {
73 : 1 : TestDifficulty(0x1cf88f6f, 1.029916);
74 : 1 : }
75 : :
76 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(get_difficulty_for_very_high_target)
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- ]
77 : : {
78 : 1 : TestDifficulty(0x12345678, 5913134931067755359633408.0);
79 : 1 : }
80 : :
81 : : //! Prune chain from height down to genesis block and check that
82 : : //! GetPruneHeight returns the correct value
83 : 3 : static void CheckGetPruneHeight(node::BlockManager& blockman, CChain& chain, int height) EXCLUSIVE_LOCKS_REQUIRED(::cs_main)
84 : : {
85 : 3 : AssertLockHeld(::cs_main);
86 : :
87 : : // Emulate pruning all blocks from `height` down to the genesis block
88 : : // by unsetting the `BLOCK_HAVE_DATA` flag from `nStatus`
89 [ + - + - : 206 : for (CBlockIndex* it{chain[height]}; it != nullptr && it->nHeight > 0; it = it->pprev) {
+ + ]
90 : 200 : it->nStatus &= ~BLOCK_HAVE_DATA;
91 : : }
92 : :
93 : 3 : const auto prune_height{GetPruneHeight(blockman, chain)};
94 [ + - ]: 6 : BOOST_REQUIRE(prune_height.has_value());
95 [ + - ]: 3 : BOOST_CHECK_EQUAL(*prune_height, height);
96 : 3 : }
97 : :
98 [ + - + - : 7 : BOOST_FIXTURE_TEST_CASE(get_prune_height, TestChain100Setup)
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- ]
99 : : {
100 : 1 : LOCK(::cs_main);
101 [ + - ]: 1 : auto& chain = m_node.chainman->ActiveChain();
102 [ + - ]: 1 : auto& blockman = m_node.chainman->m_blockman;
103 : :
104 : : // Fresh chain of 100 blocks without any pruned blocks, so std::nullopt should be returned
105 [ + - + - : 2 : BOOST_CHECK(!GetPruneHeight(blockman, chain).has_value());
+ - + - ]
106 : :
107 : : // Start pruning
108 [ + - ]: 1 : CheckGetPruneHeight(blockman, chain, 1);
109 [ + - ]: 1 : CheckGetPruneHeight(blockman, chain, 99);
110 [ + - ]: 1 : CheckGetPruneHeight(blockman, chain, 100);
111 : 1 : }
112 : :
113 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(num_chain_tx_max)
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- ]
114 : : {
115 : 1 : CBlockIndex block_index{};
116 : 1 : block_index.m_chain_tx_count = std::numeric_limits<uint64_t>::max();
117 [ + - ]: 1 : BOOST_CHECK_EQUAL(block_index.m_chain_tx_count, std::numeric_limits<uint64_t>::max());
118 : 1 : }
119 : :
120 : : BOOST_AUTO_TEST_SUITE_END()
|