Coverage Report

Created: 2024-08-21 05:08

/workdir/bitcoin/src/pow.cpp
Line
Count
Source (jump to first uncovered line)
1
// Copyright (c) 2009-2010 Satoshi Nakamoto
2
// Copyright (c) 2009-2022 The Bitcoin Core developers
3
// Distributed under the MIT software license, see the accompanying
4
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
5
6
#include <pow.h>
7
8
#include <arith_uint256.h>
9
#include <chain.h>
10
#include <primitives/block.h>
11
#include <uint256.h>
12
13
unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params& params)
14
6.84k
{
15
6.84k
    assert(pindexLast != nullptr);
16
6.84k
    unsigned int nProofOfWorkLimit = UintToArith256(params.powLimit).GetCompact();
17
18
    // Only change once per difficulty adjustment interval
19
6.84k
    if ((pindexLast->nHeight+1) % params.DifficultyAdjustmentInterval() != 0)
  Branch (19:9): [True: 6.84k, False: 0]
20
6.84k
    {
21
6.84k
        if (params.fPowAllowMinDifficultyBlocks)
  Branch (21:13): [True: 0, False: 6.84k]
22
0
        {
23
            // Special difficulty rule for testnet:
24
            // If the new block's timestamp is more than 2* 10 minutes
25
            // then allow mining of a min-difficulty block.
26
0
            if (pblock->GetBlockTime() > pindexLast->GetBlockTime() + params.nPowTargetSpacing*2)
  Branch (26:17): [True: 0, False: 0]
27
0
                return nProofOfWorkLimit;
28
0
            else
29
0
            {
30
                // Return the last non-special-min-difficulty-rules-block
31
0
                const CBlockIndex* pindex = pindexLast;
32
0
                while (pindex->pprev && pindex->nHeight % params.DifficultyAdjustmentInterval() != 0 && pindex->nBits == nProofOfWorkLimit)
  Branch (32:24): [True: 0, False: 0]
  Branch (32:41): [True: 0, False: 0]
  Branch (32:105): [True: 0, False: 0]
33
0
                    pindex = pindex->pprev;
34
0
                return pindex->nBits;
35
0
            }
36
0
        }
37
6.84k
        return pindexLast->nBits;
38
6.84k
    }
39
40
    // Go back by what we want to be 14 days worth of blocks
41
0
    int nHeightFirst = pindexLast->nHeight - (params.DifficultyAdjustmentInterval()-1);
42
0
    assert(nHeightFirst >= 0);
43
0
    const CBlockIndex* pindexFirst = pindexLast->GetAncestor(nHeightFirst);
44
0
    assert(pindexFirst);
45
46
0
    return CalculateNextWorkRequired(pindexLast, pindexFirst->GetBlockTime(), params);
47
0
}
48
49
unsigned int CalculateNextWorkRequired(const CBlockIndex* pindexLast, int64_t nFirstBlockTime, const Consensus::Params& params)
50
0
{
51
0
    if (params.fPowNoRetargeting)
  Branch (51:9): [True: 0, False: 0]
52
0
        return pindexLast->nBits;
53
54
    // Limit adjustment step
55
0
    int64_t nActualTimespan = pindexLast->GetBlockTime() - nFirstBlockTime;
56
0
    if (nActualTimespan < params.nPowTargetTimespan/4)
  Branch (56:9): [True: 0, False: 0]
57
0
        nActualTimespan = params.nPowTargetTimespan/4;
58
0
    if (nActualTimespan > params.nPowTargetTimespan*4)
  Branch (58:9): [True: 0, False: 0]
59
0
        nActualTimespan = params.nPowTargetTimespan*4;
60
61
    // Retarget
62
0
    const arith_uint256 bnPowLimit = UintToArith256(params.powLimit);
63
0
    arith_uint256 bnNew;
64
65
    // Special difficulty rule for Testnet4
66
0
    if (params.enforce_BIP94) {
  Branch (66:9): [True: 0, False: 0]
67
        // Here we use the first block of the difficulty period. This way
68
        // the real difficulty is always preserved in the first block as
69
        // it is not allowed to use the min-difficulty exception.
70
0
        int nHeightFirst = pindexLast->nHeight - (params.DifficultyAdjustmentInterval()-1);
71
0
        const CBlockIndex* pindexFirst = pindexLast->GetAncestor(nHeightFirst);
72
0
        bnNew.SetCompact(pindexFirst->nBits);
73
0
    } else {
74
0
        bnNew.SetCompact(pindexLast->nBits);
75
0
    }
76
77
0
    bnNew *= nActualTimespan;
78
0
    bnNew /= params.nPowTargetTimespan;
79
80
0
    if (bnNew > bnPowLimit)
  Branch (80:9): [True: 0, False: 0]
81
0
        bnNew = bnPowLimit;
82
83
0
    return bnNew.GetCompact();
84
0
}
85
86
// Check that on difficulty adjustments, the new difficulty does not increase
87
// or decrease beyond the permitted limits.
88
bool PermittedDifficultyTransition(const Consensus::Params& params, int64_t height, uint32_t old_nbits, uint32_t new_nbits)
89
25.9k
{
90
25.9k
    if (params.fPowAllowMinDifficultyBlocks) return true;
  Branch (90:9): [True: 0, False: 25.9k]
91
92
25.9k
    if (height % params.DifficultyAdjustmentInterval() == 0) {
  Branch (92:9): [True: 0, False: 25.9k]
93
0
        int64_t smallest_timespan = params.nPowTargetTimespan/4;
94
0
        int64_t largest_timespan = params.nPowTargetTimespan*4;
95
96
0
        const arith_uint256 pow_limit = UintToArith256(params.powLimit);
97
0
        arith_uint256 observed_new_target;
98
0
        observed_new_target.SetCompact(new_nbits);
99
100
        // Calculate the largest difficulty value possible:
101
0
        arith_uint256 largest_difficulty_target;
102
0
        largest_difficulty_target.SetCompact(old_nbits);
103
0
        largest_difficulty_target *= largest_timespan;
104
0
        largest_difficulty_target /= params.nPowTargetTimespan;
105
106
0
        if (largest_difficulty_target > pow_limit) {
  Branch (106:13): [True: 0, False: 0]
107
0
            largest_difficulty_target = pow_limit;
108
0
        }
109
110
        // Round and then compare this new calculated value to what is
111
        // observed.
112
0
        arith_uint256 maximum_new_target;
113
0
        maximum_new_target.SetCompact(largest_difficulty_target.GetCompact());
114
0
        if (maximum_new_target < observed_new_target) return false;
  Branch (114:13): [True: 0, False: 0]
115
116
        // Calculate the smallest difficulty value possible:
117
0
        arith_uint256 smallest_difficulty_target;
118
0
        smallest_difficulty_target.SetCompact(old_nbits);
119
0
        smallest_difficulty_target *= smallest_timespan;
120
0
        smallest_difficulty_target /= params.nPowTargetTimespan;
121
122
0
        if (smallest_difficulty_target > pow_limit) {
  Branch (122:13): [True: 0, False: 0]
123
0
            smallest_difficulty_target = pow_limit;
124
0
        }
125
126
        // Round and then compare this new calculated value to what is
127
        // observed.
128
0
        arith_uint256 minimum_new_target;
129
0
        minimum_new_target.SetCompact(smallest_difficulty_target.GetCompact());
130
0
        if (minimum_new_target > observed_new_target) return false;
  Branch (130:13): [True: 0, False: 0]
131
25.9k
    } else if (old_nbits != new_nbits) {
  Branch (131:16): [True: 139, False: 25.8k]
132
139
        return false;
133
139
    }
134
25.8k
    return true;
135
25.9k
}
136
137
// Bypasses the actual proof of work check during fuzz testing with a simplified validation checking whether
138
// the most signficant bit of the last byte of the hash is set.
139
bool CheckProofOfWork(uint256 hash, unsigned int nBits, const Consensus::Params& params)
140
194k
{
141
194k
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
142
194k
    return (hash.data()[31] & 0x80) == 0;
143
#else
144
    return CheckProofOfWorkImpl(hash, nBits, params);
145
#endif
146
194k
}
147
148
bool CheckProofOfWorkImpl(uint256 hash, unsigned int nBits, const Consensus::Params& params)
149
0
{
150
0
    bool fNegative;
151
0
    bool fOverflow;
152
0
    arith_uint256 bnTarget;
153
154
0
    bnTarget.SetCompact(nBits, &fNegative, &fOverflow);
155
156
    // Check range
157
0
    if (fNegative || bnTarget == 0 || fOverflow || bnTarget > UintToArith256(params.powLimit))
  Branch (157:9): [True: 0, False: 0]
  Branch (157:9): [True: 0, False: 0]
  Branch (157:22): [True: 0, False: 0]
  Branch (157:39): [True: 0, False: 0]
  Branch (157:52): [True: 0, False: 0]
158
0
        return false;
159
160
    // Check proof of work matches claimed amount
161
0
    if (UintToArith256(hash) > bnTarget)
  Branch (161:9): [True: 0, False: 0]
162
0
        return false;
163
164
0
    return true;
165
0
}