Coverage Report

Created: 2024-08-21 05:08

/workdir/bitcoin/src/chain.h
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
#ifndef BITCOIN_CHAIN_H
7
#define BITCOIN_CHAIN_H
8
9
#include <arith_uint256.h>
10
#include <consensus/params.h>
11
#include <flatfile.h>
12
#include <kernel/cs_main.h>
13
#include <primitives/block.h>
14
#include <serialize.h>
15
#include <sync.h>
16
#include <uint256.h>
17
#include <util/time.h>
18
19
#include <algorithm>
20
#include <cassert>
21
#include <cstdint>
22
#include <string>
23
#include <vector>
24
25
/**
26
 * Maximum amount of time that a block timestamp is allowed to exceed the
27
 * current time before the block will be accepted.
28
 */
29
static constexpr int64_t MAX_FUTURE_BLOCK_TIME = 2 * 60 * 60;
30
31
/**
32
 * Timestamp window used as a grace period by code that compares external
33
 * timestamps (such as timestamps passed to RPCs, or wallet key creation times)
34
 * to block timestamps. This should be set at least as high as
35
 * MAX_FUTURE_BLOCK_TIME.
36
 */
37
static constexpr int64_t TIMESTAMP_WINDOW = MAX_FUTURE_BLOCK_TIME;
38
39
/**
40
 * Maximum gap between node time and block time used
41
 * for the "Catching up..." mode in GUI.
42
 *
43
 * Ref: https://github.com/bitcoin/bitcoin/pull/1026
44
 */
45
static constexpr int64_t MAX_BLOCK_TIME_GAP = 90 * 60;
46
47
class CBlockFileInfo
48
{
49
public:
50
    unsigned int nBlocks{};      //!< number of blocks stored in file
51
    unsigned int nSize{};        //!< number of used bytes of block file
52
    unsigned int nUndoSize{};    //!< number of used bytes in the undo file
53
    unsigned int nHeightFirst{}; //!< lowest height of block in file
54
    unsigned int nHeightLast{};  //!< highest height of block in file
55
    uint64_t nTimeFirst{};       //!< earliest time of block in file
56
    uint64_t nTimeLast{};        //!< latest time of block in file
57
58
    SERIALIZE_METHODS(CBlockFileInfo, obj)
59
0
    {
60
0
        READWRITE(VARINT(obj.nBlocks));
61
0
        READWRITE(VARINT(obj.nSize));
62
0
        READWRITE(VARINT(obj.nUndoSize));
63
0
        READWRITE(VARINT(obj.nHeightFirst));
64
0
        READWRITE(VARINT(obj.nHeightLast));
65
0
        READWRITE(VARINT(obj.nTimeFirst));
66
0
        READWRITE(VARINT(obj.nTimeLast));
67
0
    }
Unexecuted instantiation: void CBlockFileInfo::SerializationOps<DataStream, CBlockFileInfo, ActionUnserialize>(CBlockFileInfo&, DataStream&, ActionUnserialize)
Unexecuted instantiation: void CBlockFileInfo::SerializationOps<DataStream, CBlockFileInfo const, ActionSerialize>(CBlockFileInfo const&, DataStream&, ActionSerialize)
68
69
0
    CBlockFileInfo() = default;
70
71
    std::string ToString() const;
72
73
    /** update statistics (does not update nSize) */
74
    void AddBlock(unsigned int nHeightIn, uint64_t nTimeIn)
75
0
    {
76
0
        if (nBlocks == 0 || nHeightFirst > nHeightIn)
  Branch (76:13): [True: 0, False: 0]
  Branch (76:29): [True: 0, False: 0]
77
0
            nHeightFirst = nHeightIn;
78
0
        if (nBlocks == 0 || nTimeFirst > nTimeIn)
  Branch (78:13): [True: 0, False: 0]
  Branch (78:29): [True: 0, False: 0]
79
0
            nTimeFirst = nTimeIn;
80
0
        nBlocks++;
81
0
        if (nHeightIn > nHeightLast)
  Branch (81:13): [True: 0, False: 0]
82
0
            nHeightLast = nHeightIn;
83
0
        if (nTimeIn > nTimeLast)
  Branch (83:13): [True: 0, False: 0]
84
0
            nTimeLast = nTimeIn;
85
0
    }
86
};
87
88
enum BlockStatus : uint32_t {
89
    //! Unused.
90
    BLOCK_VALID_UNKNOWN      =    0,
91
92
    //! Reserved (was BLOCK_VALID_HEADER).
93
    BLOCK_VALID_RESERVED     =    1,
94
95
    //! All parent headers found, difficulty matches, timestamp >= median previous, checkpoint. Implies all parents
96
    //! are also at least TREE.
97
    BLOCK_VALID_TREE         =    2,
98
99
    /**
100
     * Only first tx is coinbase, 2 <= coinbase input script length <= 100, transactions valid, no duplicate txids,
101
     * sigops, size, merkle root. Implies all parents are at least TREE but not necessarily TRANSACTIONS.
102
     *
103
     * If a block's validity is at least VALID_TRANSACTIONS, CBlockIndex::nTx will be set. If a block and all previous
104
     * blocks back to the genesis block or an assumeutxo snapshot block are at least VALID_TRANSACTIONS,
105
     * CBlockIndex::m_chain_tx_count will be set.
106
     */
107
    BLOCK_VALID_TRANSACTIONS =    3,
108
109
    //! Outputs do not overspend inputs, no double spends, coinbase output ok, no immature coinbase spends, BIP30.
110
    //! Implies all previous blocks back to the genesis block or an assumeutxo snapshot block are at least VALID_CHAIN.
111
    BLOCK_VALID_CHAIN        =    4,
112
113
    //! Scripts & signatures ok. Implies all previous blocks back to the genesis block or an assumeutxo snapshot block
114
    //! are at least VALID_SCRIPTS.
115
    BLOCK_VALID_SCRIPTS      =    5,
116
117
    //! All validity bits.
118
    BLOCK_VALID_MASK         =   BLOCK_VALID_RESERVED | BLOCK_VALID_TREE | BLOCK_VALID_TRANSACTIONS |
119
                                 BLOCK_VALID_CHAIN | BLOCK_VALID_SCRIPTS,
120
121
    BLOCK_HAVE_DATA          =    8, //!< full block available in blk*.dat
122
    BLOCK_HAVE_UNDO          =   16, //!< undo data available in rev*.dat
123
    BLOCK_HAVE_MASK          =   BLOCK_HAVE_DATA | BLOCK_HAVE_UNDO,
124
125
    BLOCK_FAILED_VALID       =   32, //!< stage after last reached validness failed
126
    BLOCK_FAILED_CHILD       =   64, //!< descends from failed block
127
    BLOCK_FAILED_MASK        =   BLOCK_FAILED_VALID | BLOCK_FAILED_CHILD,
128
129
    BLOCK_OPT_WITNESS        =   128, //!< block data in blk*.dat was received with a witness-enforcing client
130
131
    BLOCK_STATUS_RESERVED    =   256, //!< Unused flag that was previously set on assumeutxo snapshot blocks and their
132
                                      //!< ancestors before they were validated, and unset when they were validated.
133
};
134
135
/** The block chain is a tree shaped structure starting with the
136
 * genesis block at the root, with each block potentially having multiple
137
 * candidates to be the next block. A blockindex may have multiple pprev pointing
138
 * to it, but at most one of them can be part of the currently active branch.
139
 */
140
class CBlockIndex
141
{
142
public:
143
    //! pointer to the hash of the block, if any. Memory is owned by this CBlockIndex
144
    const uint256* phashBlock{nullptr};
145
146
    //! pointer to the index of the predecessor of this block
147
    CBlockIndex* pprev{nullptr};
148
149
    //! pointer to the index of some further predecessor of this block
150
    CBlockIndex* pskip{nullptr};
151
152
    //! height of the entry in the chain. The genesis block has height 0
153
    int nHeight{0};
154
155
    //! Which # file this block is stored in (blk?????.dat)
156
    int nFile GUARDED_BY(::cs_main){0};
157
158
    //! Byte offset within blk?????.dat where this block's data is stored
159
    unsigned int nDataPos GUARDED_BY(::cs_main){0};
160
161
    //! Byte offset within rev?????.dat where this block's undo data is stored
162
    unsigned int nUndoPos GUARDED_BY(::cs_main){0};
163
164
    //! (memory only) Total amount of work (expected number of hashes) in the chain up to and including this block
165
    arith_uint256 nChainWork{};
166
167
    //! Number of transactions in this block. This will be nonzero if the block
168
    //! reached the VALID_TRANSACTIONS level, and zero otherwise.
169
    //! Note: in a potential headers-first mode, this number cannot be relied upon
170
    unsigned int nTx{0};
171
172
    //! (memory only) Number of transactions in the chain up to and including this block.
173
    //! This value will be non-zero if this block and all previous blocks back
174
    //! to the genesis block or an assumeutxo snapshot block have reached the
175
    //! VALID_TRANSACTIONS level.
176
    uint64_t m_chain_tx_count{0};
177
178
    //! Verification status of this block. See enum BlockStatus
179
    //!
180
    //! Note: this value is modified to show BLOCK_OPT_WITNESS during UTXO snapshot
181
    //! load to avoid the block index being spuriously rewound.
182
    //! @sa NeedsRedownload
183
    //! @sa ActivateSnapshot
184
    uint32_t nStatus GUARDED_BY(::cs_main){0};
185
186
    //! block header
187
    int32_t nVersion{0};
188
    uint256 hashMerkleRoot{};
189
    uint32_t nTime{0};
190
    uint32_t nBits{0};
191
    uint32_t nNonce{0};
192
193
    //! (memory only) Sequential id assigned to distinguish order in which blocks are received.
194
    int32_t nSequenceId{0};
195
196
    //! (memory only) Maximum nTime in the chain up to and including this block.
197
    unsigned int nTimeMax{0};
198
199
    explicit CBlockIndex(const CBlockHeader& block)
200
37.5k
        : nVersion{block.nVersion},
201
37.5k
          hashMerkleRoot{block.hashMerkleRoot},
202
37.5k
          nTime{block.nTime},
203
37.5k
          nBits{block.nBits},
204
37.5k
          nNonce{block.nNonce}
205
37.5k
    {
206
37.5k
    }
207
208
    FlatFilePos GetBlockPos() const EXCLUSIVE_LOCKS_REQUIRED(::cs_main)
209
0
    {
210
0
        AssertLockHeld(::cs_main);
211
0
        FlatFilePos ret;
212
0
        if (nStatus & BLOCK_HAVE_DATA) {
  Branch (212:13): [True: 0, False: 0]
213
0
            ret.nFile = nFile;
214
0
            ret.nPos = nDataPos;
215
0
        }
216
0
        return ret;
217
0
    }
218
219
    FlatFilePos GetUndoPos() const EXCLUSIVE_LOCKS_REQUIRED(::cs_main)
220
0
    {
221
0
        AssertLockHeld(::cs_main);
222
0
        FlatFilePos ret;
223
0
        if (nStatus & BLOCK_HAVE_UNDO) {
  Branch (223:13): [True: 0, False: 0]
224
0
            ret.nFile = nFile;
225
0
            ret.nPos = nUndoPos;
226
0
        }
227
0
        return ret;
228
0
    }
229
230
    CBlockHeader GetBlockHeader() const
231
8.73k
    {
232
8.73k
        CBlockHeader block;
233
8.73k
        block.nVersion = nVersion;
234
8.73k
        if (pprev)
  Branch (234:13): [True: 0, False: 8.73k]
235
0
            block.hashPrevBlock = pprev->GetBlockHash();
236
8.73k
        block.hashMerkleRoot = hashMerkleRoot;
237
8.73k
        block.nTime = nTime;
238
8.73k
        block.nBits = nBits;
239
8.73k
        block.nNonce = nNonce;
240
8.73k
        return block;
241
8.73k
    }
242
243
    uint256 GetBlockHash() const
244
10.8k
    {
245
10.8k
        assert(phashBlock != nullptr);
246
10.8k
        return *phashBlock;
247
10.8k
    }
248
249
    /**
250
     * Check whether this block and all previous blocks back to the genesis block or an assumeutxo snapshot block have
251
     * reached VALID_TRANSACTIONS and had transactions downloaded (and stored to disk) at some point.
252
     *
253
     * Does not imply the transactions are consensus-valid (ConnectTip might fail)
254
     * Does not imply the transactions are still stored on disk. (IsBlockPruned might return true)
255
     *
256
     * Note that this will be true for the snapshot base block, if one is loaded, since its m_chain_tx_count value will have
257
     * been set manually based on the related AssumeutxoData entry.
258
     */
259
20.5k
    bool HaveNumChainTxs() const { return m_chain_tx_count != 0; }
260
261
    NodeSeconds Time() const
262
2.32k
    {
263
2.32k
        return NodeSeconds{std::chrono::seconds{nTime}};
264
2.32k
    }
265
266
    int64_t GetBlockTime() const
267
6.76k
    {
268
6.76k
        return (int64_t)nTime;
269
6.76k
    }
270
271
    int64_t GetBlockTimeMax() const
272
0
    {
273
0
        return (int64_t)nTimeMax;
274
0
    }
275
276
    static constexpr int nMedianTimeSpan = 11;
277
278
    int64_t GetMedianTimePast() const
279
6.76k
    {
280
6.76k
        int64_t pmedian[nMedianTimeSpan];
281
6.76k
        int64_t* pbegin = &pmedian[nMedianTimeSpan];
282
6.76k
        int64_t* pend = &pmedian[nMedianTimeSpan];
283
284
6.76k
        const CBlockIndex* pindex = this;
285
13.5k
        for (int i = 0; i < nMedianTimeSpan && pindex; i++, pindex = pindex->pprev)
  Branch (285:25): [True: 13.5k, False: 0]
  Branch (285:48): [True: 6.76k, False: 6.76k]
286
6.76k
            *(--pbegin) = pindex->GetBlockTime();
287
288
6.76k
        std::sort(pbegin, pend);
289
6.76k
        return pbegin[(pend - pbegin) / 2];
290
6.76k
    }
291
292
    std::string ToString() const;
293
294
    //! Check whether this block index entry is valid up to the passed validity level.
295
    bool IsValid(enum BlockStatus nUpTo = BLOCK_VALID_TRANSACTIONS) const
296
        EXCLUSIVE_LOCKS_REQUIRED(::cs_main)
297
74
    {
298
74
        AssertLockHeld(::cs_main);
299
74
        assert(!(nUpTo & ~BLOCK_VALID_MASK)); // Only validity flags allowed.
300
74
        if (nStatus & BLOCK_FAILED_MASK)
  Branch (300:13): [True: 0, False: 74]
301
0
            return false;
302
74
        return ((nStatus & BLOCK_VALID_MASK) >= nUpTo);
303
74
    }
304
305
    //! Raise the validity level of this block index entry.
306
    //! Returns true if the validity was changed.
307
    bool RaiseValidity(enum BlockStatus nUpTo) EXCLUSIVE_LOCKS_REQUIRED(::cs_main)
308
0
    {
309
0
        AssertLockHeld(::cs_main);
310
0
        assert(!(nUpTo & ~BLOCK_VALID_MASK)); // Only validity flags allowed.
311
0
        if (nStatus & BLOCK_FAILED_MASK) return false;
  Branch (311:13): [True: 0, False: 0]
312
313
0
        if ((nStatus & BLOCK_VALID_MASK) < nUpTo) {
  Branch (313:13): [True: 0, False: 0]
314
0
            nStatus = (nStatus & ~BLOCK_VALID_MASK) | nUpTo;
315
0
            return true;
316
0
        }
317
0
        return false;
318
0
    }
319
320
    //! Build the skiplist pointer for this entry.
321
    void BuildSkip();
322
323
    //! Efficiently find an ancestor of this block.
324
    CBlockIndex* GetAncestor(int height);
325
    const CBlockIndex* GetAncestor(int height) const;
326
327
0
    CBlockIndex() = default;
328
    ~CBlockIndex() = default;
329
330
protected:
331
    //! CBlockIndex should not allow public copy construction because equality
332
    //! comparison via pointer is very common throughout the codebase, making
333
    //! use of copy a footgun. Also, use of copies do not have the benefit
334
    //! of simplifying lifetime considerations due to attributes like pprev and
335
    //! pskip, which are at risk of becoming dangling pointers in a copied
336
    //! instance.
337
    //!
338
    //! We declare these protected instead of simply deleting them so that
339
    //! CDiskBlockIndex can reuse copy construction.
340
0
    CBlockIndex(const CBlockIndex&) = default;
341
    CBlockIndex& operator=(const CBlockIndex&) = delete;
342
    CBlockIndex(CBlockIndex&&) = delete;
343
    CBlockIndex& operator=(CBlockIndex&&) = delete;
344
};
345
346
arith_uint256 GetBlockProof(const CBlockIndex& block);
347
/** Return the time it would take to redo the work difference between from and to, assuming the current hashrate corresponds to the difficulty at tip, in seconds. */
348
int64_t GetBlockProofEquivalentTime(const CBlockIndex& to, const CBlockIndex& from, const CBlockIndex& tip, const Consensus::Params&);
349
/** Find the forking point between two chain tips. */
350
const CBlockIndex* LastCommonAncestor(const CBlockIndex* pa, const CBlockIndex* pb);
351
352
353
/** Used to marshal pointers into hashes for db storage. */
354
class CDiskBlockIndex : public CBlockIndex
355
{
356
    /** Historically CBlockLocator's version field has been written to disk
357
     * streams as the client version, but the value has never been used.
358
     *
359
     * Hard-code to the highest client version ever written.
360
     * SerParams can be used if the field requires any meaning in the future.
361
     **/
362
    static constexpr int DUMMY_VERSION = 259900;
363
364
public:
365
    uint256 hashPrev;
366
367
    CDiskBlockIndex()
368
0
    {
369
0
        hashPrev = uint256();
370
0
    }
371
372
0
    explicit CDiskBlockIndex(const CBlockIndex* pindex) : CBlockIndex(*pindex)
373
0
    {
374
0
        hashPrev = (pprev ? pprev->GetBlockHash() : uint256());
  Branch (374:21): [True: 0, False: 0]
375
0
    }
376
377
    SERIALIZE_METHODS(CDiskBlockIndex, obj)
378
0
    {
379
0
        LOCK(::cs_main);
380
0
        int _nVersion = DUMMY_VERSION;
381
0
        READWRITE(VARINT_MODE(_nVersion, VarIntMode::NONNEGATIVE_SIGNED));
382
383
0
        READWRITE(VARINT_MODE(obj.nHeight, VarIntMode::NONNEGATIVE_SIGNED));
384
0
        READWRITE(VARINT(obj.nStatus));
385
0
        READWRITE(VARINT(obj.nTx));
386
0
        if (obj.nStatus & (BLOCK_HAVE_DATA | BLOCK_HAVE_UNDO)) READWRITE(VARINT_MODE(obj.nFile, VarIntMode::NONNEGATIVE_SIGNED));
  Branch (386:13): [True: 0, False: 0]
  Branch (386:13): [True: 0, False: 0]
387
0
        if (obj.nStatus & BLOCK_HAVE_DATA) READWRITE(VARINT(obj.nDataPos));
  Branch (387:13): [True: 0, False: 0]
  Branch (387:13): [True: 0, False: 0]
388
0
        if (obj.nStatus & BLOCK_HAVE_UNDO) READWRITE(VARINT(obj.nUndoPos));
  Branch (388:13): [True: 0, False: 0]
  Branch (388:13): [True: 0, False: 0]
389
390
        // block header
391
0
        READWRITE(obj.nVersion);
392
0
        READWRITE(obj.hashPrev);
393
0
        READWRITE(obj.hashMerkleRoot);
394
0
        READWRITE(obj.nTime);
395
0
        READWRITE(obj.nBits);
396
0
        READWRITE(obj.nNonce);
397
0
    }
Unexecuted instantiation: void CDiskBlockIndex::SerializationOps<DataStream, CDiskBlockIndex, ActionUnserialize>(CDiskBlockIndex&, DataStream&, ActionUnserialize)
Unexecuted instantiation: void CDiskBlockIndex::SerializationOps<DataStream, CDiskBlockIndex const, ActionSerialize>(CDiskBlockIndex const&, DataStream&, ActionSerialize)
398
399
    uint256 ConstructBlockHash() const
400
0
    {
401
0
        CBlockHeader block;
402
0
        block.nVersion = nVersion;
403
0
        block.hashPrevBlock = hashPrev;
404
0
        block.hashMerkleRoot = hashMerkleRoot;
405
0
        block.nTime = nTime;
406
0
        block.nBits = nBits;
407
0
        block.nNonce = nNonce;
408
0
        return block.GetHash();
409
0
    }
410
411
    uint256 GetBlockHash() = delete;
412
    std::string ToString() = delete;
413
};
414
415
/** An in-memory indexed chain of blocks. */
416
class CChain
417
{
418
private:
419
    std::vector<CBlockIndex*> vChain;
420
421
public:
422
6.84k
    CChain() = default;
423
    CChain(const CChain&) = delete;
424
    CChain& operator=(const CChain&) = delete;
425
426
    /** Returns the index entry for the genesis block of this chain, or nullptr if none. */
427
    CBlockIndex* Genesis() const
428
13.6k
    {
429
13.6k
        return vChain.size() > 0 ? vChain[0] : nullptr;
  Branch (429:16): [True: 13.6k, False: 0]
430
13.6k
    }
431
432
    /** Returns the index entry for the tip of this chain, or nullptr if none. */
433
    CBlockIndex* Tip() const
434
60.6k
    {
435
60.6k
        return vChain.size() > 0 ? vChain[vChain.size() - 1] : nullptr;
  Branch (435:16): [True: 60.6k, False: 0]
436
60.6k
    }
437
438
    /** Returns the index entry at a particular height in this chain, or nullptr if no such height exists. */
439
    CBlockIndex* operator[](int nHeight) const
440
27.3k
    {
441
27.3k
        if (nHeight < 0 || nHeight >= (int)vChain.size())
  Branch (441:13): [True: 0, False: 27.3k]
  Branch (441:28): [True: 6.84k, False: 20.5k]
442
6.84k
            return nullptr;
443
20.5k
        return vChain[nHeight];
444
27.3k
    }
445
446
    /** Efficiently check whether a block is present in this chain. */
447
    bool Contains(const CBlockIndex* pindex) const
448
13.6k
    {
449
13.6k
        return (*this)[pindex->nHeight] == pindex;
450
13.6k
    }
451
452
    /** Find the successor of a block in this chain, or nullptr if the given index is not found or is the tip. */
453
    CBlockIndex* Next(const CBlockIndex* pindex) const
454
0
    {
455
0
        if (Contains(pindex))
  Branch (455:13): [True: 0, False: 0]
456
0
            return (*this)[pindex->nHeight + 1];
457
0
        else
458
0
            return nullptr;
459
0
    }
460
461
    /** Return the maximal height in the chain. Is equal to chain.Tip() ? chain.Tip()->nHeight : -1. */
462
    int Height() const
463
20.5k
    {
464
20.5k
        return int(vChain.size()) - 1;
465
20.5k
    }
466
467
    /** Set/initialize a chain with a given tip. */
468
    void SetTip(CBlockIndex& block);
469
470
    /** Return a CBlockLocator that refers to the tip in of this chain. */
471
    CBlockLocator GetLocator() const;
472
473
    /** Find the last common block between this chain and a block index entry. */
474
    const CBlockIndex* FindFork(const CBlockIndex* pindex) const;
475
476
    /** Find the earliest block with timestamp equal or greater than the given time and height equal or greater than the given height. */
477
    CBlockIndex* FindEarliestAtLeast(int64_t nTime, int height) const;
478
};
479
480
/** Get a locator for a block index entry. */
481
CBlockLocator GetLocator(const CBlockIndex* index);
482
483
/** Construct a list of hash entries to put in a locator.  */
484
std::vector<uint256> LocatorEntries(const CBlockIndex* index);
485
486
#endif // BITCOIN_CHAIN_H