fuzz coverage

Coverage Report

Created: 2025-06-01 19:34

/Users/eugenesiegel/btc/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
517
    {
60
517
        READWRITE(VARINT(obj.nBlocks));
Line
Count
Source
156
0
#define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__))
        READWRITE(VARINT(obj.nBlocks));
Line
Count
Source
156
517
#define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__))
61
517
        READWRITE(VARINT(obj.nSize));
Line
Count
Source
156
0
#define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__))
        READWRITE(VARINT(obj.nSize));
Line
Count
Source
156
517
#define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__))
62
517
        READWRITE(VARINT(obj.nUndoSize));
Line
Count
Source
156
0
#define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__))
        READWRITE(VARINT(obj.nUndoSize));
Line
Count
Source
156
517
#define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__))
63
517
        READWRITE(VARINT(obj.nHeightFirst));
Line
Count
Source
156
0
#define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__))
        READWRITE(VARINT(obj.nHeightFirst));
Line
Count
Source
156
517
#define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__))
64
517
        READWRITE(VARINT(obj.nHeightLast));
Line
Count
Source
156
0
#define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__))
        READWRITE(VARINT(obj.nHeightLast));
Line
Count
Source
156
517
#define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__))
65
517
        READWRITE(VARINT(obj.nTimeFirst));
Line
Count
Source
156
0
#define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__))
        READWRITE(VARINT(obj.nTimeFirst));
Line
Count
Source
156
517
#define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__))
66
517
        READWRITE(VARINT(obj.nTimeLast));
Line
Count
Source
156
0
#define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__))
        READWRITE(VARINT(obj.nTimeLast));
Line
Count
Source
156
517
#define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__))
67
517
    }
Unexecuted instantiation: _ZN14CBlockFileInfo16SerializationOpsI10DataStreamS_17ActionUnserializeEEvRT0_RT_T1_
_ZN14CBlockFileInfo16SerializationOpsI10DataStreamKS_15ActionSerializeEEvRT0_RT_T1_
Line
Count
Source
59
517
    {
60
517
        READWRITE(VARINT(obj.nBlocks));
Line
Count
Source
156
517
#define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__))
61
517
        READWRITE(VARINT(obj.nSize));
Line
Count
Source
156
517
#define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__))
62
517
        READWRITE(VARINT(obj.nUndoSize));
Line
Count
Source
156
517
#define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__))
63
517
        READWRITE(VARINT(obj.nHeightFirst));
Line
Count
Source
156
517
#define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__))
64
517
        READWRITE(VARINT(obj.nHeightLast));
Line
Count
Source
156
517
#define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__))
65
517
        READWRITE(VARINT(obj.nTimeFirst));
Line
Count
Source
156
517
#define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__))
66
517
        READWRITE(VARINT(obj.nTimeLast));
Line
Count
Source
156
517
#define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__))
67
517
    }
68
69
99.9k
    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
10.0M
    {
76
10.0M
        if (nBlocks == 0 || 
nHeightFirst > nHeightIn9.99M
)
77
49.9k
            nHeightFirst = nHeightIn;
78
10.0M
        if (nBlocks == 0 || 
nTimeFirst > nTimeIn9.99M
)
79
49.9k
            nTimeFirst = nTimeIn;
80
10.0M
        nBlocks++;
81
10.0M
        if (nHeightIn > nHeightLast)
82
9.99M
            nHeightLast = nHeightIn;
83
10.0M
        if (nTimeIn > nTimeLast)
84
1.84M
            nTimeLast = nTimeIn;
85
10.0M
    }
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. 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 a spurious startup failure requiring -reindex.
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
20.1M
        : nVersion{block.nVersion},
201
20.1M
          hashMerkleRoot{block.hashMerkleRoot},
202
20.1M
          nTime{block.nTime},
203
20.1M
          nBits{block.nBits},
204
20.1M
          nNonce{block.nNonce}
205
20.1M
    {
206
20.1M
    }
207
208
    FlatFilePos GetBlockPos() const EXCLUSIVE_LOCKS_REQUIRED(::cs_main)
209
50.8k
    {
210
50.8k
        AssertLockHeld(::cs_main);
Line
Count
Source
142
50.8k
#define AssertLockHeld(cs) AssertLockHeldInternal(#cs, __FILE__, __LINE__, &cs)
211
50.8k
        FlatFilePos ret;
212
50.8k
        if (nStatus & BLOCK_HAVE_DATA) {
213
50.8k
            ret.nFile = nFile;
214
50.8k
            ret.nPos = nDataPos;
215
50.8k
        }
216
50.8k
        return ret;
217
50.8k
    }
218
219
    FlatFilePos GetUndoPos() const EXCLUSIVE_LOCKS_REQUIRED(::cs_main)
220
9.99M
    {
221
9.99M
        AssertLockHeld(::cs_main);
Line
Count
Source
142
9.99M
#define AssertLockHeld(cs) AssertLockHeldInternal(#cs, __FILE__, __LINE__, &cs)
222
9.99M
        FlatFilePos ret;
223
9.99M
        if (nStatus & BLOCK_HAVE_UNDO) {
224
55
            ret.nFile = nFile;
225
55
            ret.nPos = nUndoPos;
226
55
        }
227
9.99M
        return ret;
228
9.99M
    }
229
230
    CBlockHeader GetBlockHeader() const
231
81
    {
232
81
        CBlockHeader block;
233
81
        block.nVersion = nVersion;
234
81
        if (pprev)
235
81
            block.hashPrevBlock = pprev->GetBlockHash();
236
81
        block.hashMerkleRoot = hashMerkleRoot;
237
81
        block.nTime = nTime;
238
81
        block.nBits = nBits;
239
81
        block.nNonce = nNonce;
240
81
        return block;
241
81
    }
242
243
    uint256 GetBlockHash() const
244
141M
    {
245
141M
        assert(phashBlock != nullptr);
246
141M
        return *phashBlock;
247
141M
    }
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
9.23G
    bool HaveNumChainTxs() const { return m_chain_tx_count != 0; }
260
261
    NodeSeconds Time() const
262
70.5M
    {
263
70.5M
        return NodeSeconds{std::chrono::seconds{nTime}};
264
70.5M
    }
265
266
    int64_t GetBlockTime() const
267
813M
    {
268
813M
        return (int64_t)nTime;
269
813M
    }
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
70.2M
    {
280
70.2M
        int64_t pmedian[nMedianTimeSpan];
281
70.2M
        int64_t* pbegin = &pmedian[nMedianTimeSpan];
282
70.2M
        int64_t* pend = &pmedian[nMedianTimeSpan];
283
284
70.2M
        const CBlockIndex* pindex = this;
285
823M
        for (int i = 0; i < nMedianTimeSpan && 
pindex757M
;
i++, pindex = pindex->pprev753M
)
286
753M
            *(--pbegin) = pindex->GetBlockTime();
287
288
70.2M
        std::sort(pbegin, pend);
289
70.2M
        return pbegin[(pend - pbegin) / 2];
290
70.2M
    }
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
20.0M
    {
298
20.0M
        AssertLockHeld(::cs_main);
Line
Count
Source
142
20.0M
#define AssertLockHeld(cs) AssertLockHeldInternal(#cs, __FILE__, __LINE__, &cs)
299
20.0M
        assert(!(nUpTo & ~BLOCK_VALID_MASK)); // Only validity flags allowed.
300
20.0M
        if (nStatus & BLOCK_FAILED_MASK)
301
0
            return false;
302
20.0M
        return ((nStatus & BLOCK_VALID_MASK) >= nUpTo);
303
20.0M
    }
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
30.0M
    {
309
30.0M
        AssertLockHeld(::cs_main);
Line
Count
Source
142
30.0M
#define AssertLockHeld(cs) AssertLockHeldInternal(#cs, __FILE__, __LINE__, &cs)
310
30.0M
        assert(!(nUpTo & ~BLOCK_VALID_MASK)); // Only validity flags allowed.
311
30.0M
        if (nStatus & BLOCK_FAILED_MASK) 
return false0
;
312
313
30.0M
        if ((nStatus & BLOCK_VALID_MASK) < nUpTo) {
314
30.0M
            nStatus = (nStatus & ~BLOCK_VALID_MASK) | nUpTo;
315
30.0M
            return true;
316
30.0M
        }
317
0
        return false;
318
30.0M
    }
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
104k
    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
104k
    explicit CDiskBlockIndex(const CBlockIndex* pindex) : CBlockIndex(*pindex)
373
104k
    {
374
104k
        hashPrev = (pprev ? 
pprev->GetBlockHash()104k
:
uint256()517
);
375
104k
    }
376
377
    SERIALIZE_METHODS(CDiskBlockIndex, obj)
378
104k
    {
379
104k
        LOCK(::cs_main);
Line
Count
Source
257
0
#define LOCK(cs) UniqueLock UNIQUE_NAME(criticalblock)(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__)
Line
Count
Source
11
0
#define UNIQUE_NAME(name) PASTE2(name, __COUNTER__)
Line
Count
Source
9
0
#define PASTE2(x, y) PASTE(x, y)
Line
Count
Source
8
0
#define PASTE(x, y) x ## y
        LOCK(::cs_main);
Line
Count
Source
257
104k
#define LOCK(cs) UniqueLock UNIQUE_NAME(criticalblock)(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__)
Line
Count
Source
11
104k
#define UNIQUE_NAME(name) PASTE2(name, __COUNTER__)
Line
Count
Source
9
104k
#define PASTE2(x, y) PASTE(x, y)
Line
Count
Source
8
104k
#define PASTE(x, y) x ## y
380
104k
        int _nVersion = DUMMY_VERSION;
381
104k
        READWRITE(VARINT_MODE(_nVersion, VarIntMode::NONNEGATIVE_SIGNED));
Line
Count
Source
156
0
#define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__))
        READWRITE(VARINT_MODE(_nVersion, VarIntMode::NONNEGATIVE_SIGNED));
Line
Count
Source
156
104k
#define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__))
382
383
104k
        READWRITE(VARINT_MODE(obj.nHeight, VarIntMode::NONNEGATIVE_SIGNED));
Line
Count
Source
156
0
#define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__))
        READWRITE(VARINT_MODE(obj.nHeight, VarIntMode::NONNEGATIVE_SIGNED));
Line
Count
Source
156
104k
#define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__))
384
104k
        READWRITE(VARINT(obj.nStatus));
Line
Count
Source
156
0
#define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__))
        READWRITE(VARINT(obj.nStatus));
Line
Count
Source
156
104k
#define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__))
385
104k
        READWRITE(VARINT(obj.nTx));
Line
Count
Source
156
0
#define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__))
        READWRITE(VARINT(obj.nTx));
Line
Count
Source
156
104k
#define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__))
386
104k
        if (obj.nStatus & (BLOCK_HAVE_DATA | BLOCK_HAVE_UNDO)) 
READWRITE104k
(VARINT_MODE(obj.nFile, VarIntMode::NONNEGATIVE_SIGNED));
Line
Count
Source
156
0
#define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__))
        if (obj.nStatus & (BLOCK_HAVE_DATA | BLOCK_HAVE_UNDO)) 
READWRITE104k
(VARINT_MODE(obj.nFile, VarIntMode::NONNEGATIVE_SIGNED));
Line
Count
Source
156
104k
#define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__))
387
104k
        if (obj.nStatus & BLOCK_HAVE_DATA) 
READWRITE104k
(VARINT(obj.nDataPos));
Line
Count
Source
156
0
#define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__))
        if (obj.nStatus & BLOCK_HAVE_DATA) 
READWRITE104k
(VARINT(obj.nDataPos));
Line
Count
Source
156
104k
#define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__))
388
104k
        if (obj.nStatus & BLOCK_HAVE_UNDO) 
READWRITE103k
(VARINT(obj.nUndoPos));
Line
Count
Source
156
0
#define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__))
        if (obj.nStatus & BLOCK_HAVE_UNDO) 
READWRITE103k
(VARINT(obj.nUndoPos));
Line
Count
Source
156
103k
#define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__))
389
390
        // block header
391
104k
        READWRITE(obj.nVersion);
Line
Count
Source
156
0
#define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__))
        READWRITE(obj.nVersion);
Line
Count
Source
156
104k
#define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__))
392
104k
        READWRITE(obj.hashPrev);
Line
Count
Source
156
0
#define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__))
        READWRITE(obj.hashPrev);
Line
Count
Source
156
104k
#define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__))
393
104k
        READWRITE(obj.hashMerkleRoot);
Line
Count
Source
156
0
#define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__))
        READWRITE(obj.hashMerkleRoot);
Line
Count
Source
156
104k
#define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__))
394
104k
        READWRITE(obj.nTime);
Line
Count
Source
156
0
#define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__))
        READWRITE(obj.nTime);
Line
Count
Source
156
104k
#define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__))
395
104k
        READWRITE(obj.nBits);
Line
Count
Source
156
0
#define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__))
        READWRITE(obj.nBits);
Line
Count
Source
156
104k
#define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__))
396
104k
        READWRITE(obj.nNonce);
Line
Count
Source
156
0
#define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__))
        READWRITE(obj.nNonce);
Line
Count
Source
156
104k
#define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__))
397
104k
    }
Unexecuted instantiation: _ZN15CDiskBlockIndex16SerializationOpsI10DataStreamS_17ActionUnserializeEEvRT0_RT_T1_
_ZN15CDiskBlockIndex16SerializationOpsI10DataStreamKS_15ActionSerializeEEvRT0_RT_T1_
Line
Count
Source
378
104k
    {
379
104k
        LOCK(::cs_main);
Line
Count
Source
257
104k
#define LOCK(cs) UniqueLock UNIQUE_NAME(criticalblock)(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__)
Line
Count
Source
11
104k
#define UNIQUE_NAME(name) PASTE2(name, __COUNTER__)
Line
Count
Source
9
104k
#define PASTE2(x, y) PASTE(x, y)
Line
Count
Source
8
104k
#define PASTE(x, y) x ## y
380
104k
        int _nVersion = DUMMY_VERSION;
381
104k
        READWRITE(VARINT_MODE(_nVersion, VarIntMode::NONNEGATIVE_SIGNED));
Line
Count
Source
156
104k
#define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__))
382
383
104k
        READWRITE(VARINT_MODE(obj.nHeight, VarIntMode::NONNEGATIVE_SIGNED));
Line
Count
Source
156
104k
#define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__))
384
104k
        READWRITE(VARINT(obj.nStatus));
Line
Count
Source
156
104k
#define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__))
385
104k
        READWRITE(VARINT(obj.nTx));
Line
Count
Source
156
104k
#define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__))
386
104k
        if (obj.nStatus & (BLOCK_HAVE_DATA | BLOCK_HAVE_UNDO)) 
READWRITE104k
(VARINT_MODE(obj.nFile, VarIntMode::NONNEGATIVE_SIGNED));
Line
Count
Source
156
104k
#define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__))
387
104k
        if (obj.nStatus & BLOCK_HAVE_DATA) 
READWRITE104k
(VARINT(obj.nDataPos));
Line
Count
Source
156
104k
#define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__))
388
104k
        if (obj.nStatus & BLOCK_HAVE_UNDO) 
READWRITE103k
(VARINT(obj.nUndoPos));
Line
Count
Source
156
103k
#define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__))
389
390
        // block header
391
104k
        READWRITE(obj.nVersion);
Line
Count
Source
156
104k
#define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__))
392
104k
        READWRITE(obj.hashPrev);
Line
Count
Source
156
104k
#define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__))
393
104k
        READWRITE(obj.hashMerkleRoot);
Line
Count
Source
156
104k
#define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__))
394
104k
        READWRITE(obj.nTime);
Line
Count
Source
156
104k
#define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__))
395
104k
        READWRITE(obj.nBits);
Line
Count
Source
156
104k
#define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__))
396
104k
        READWRITE(obj.nNonce);
Line
Count
Source
156
104k
#define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__))
397
104k
    }
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
30.2M
    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
60.3M
    {
429
60.3M
        return vChain.size() > 0 ? vChain[0] : 
nullptr0
;
430
60.3M
    }
431
432
    /** Returns the index entry for the tip of this chain, or nullptr if none. */
433
    CBlockIndex* Tip() const
434
6.54G
    {
435
6.54G
        return vChain.size() > 0 ? 
vChain[vChain.size() - 1]6.54G
:
nullptr449k
;
436
6.54G
    }
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
9.28G
    {
441
9.28G
        if (nHeight < 0 || nHeight >= (int)vChain.size())
442
40.2M
            return nullptr;
443
9.24G
        return vChain[nHeight];
444
9.28G
    }
445
446
    /** Efficiently check whether a block is present in this chain. */
447
    bool Contains(const CBlockIndex* pindex) const
448
6.18G
    {
449
6.18G
        return (*this)[pindex->nHeight] == pindex;
450
6.18G
    }
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))
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
160M
    {
464
160M
        return int(vChain.size()) - 1;
465
160M
    }
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