Bitcoin ABC 0.31.0
P2P Digital Currency
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
blockindex.cpp
Go to the documentation of this file.
1// Copyright (c) 2009-2020 The Bitcoin 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 <blockindex.h>
6#include <logging.h>
7#include <tinyformat.h>
8#include <util/check.h>
9
13static inline int InvertLowestOne(int n) {
14 return n & (n - 1);
15}
16
18static inline int GetSkipHeight(int height) {
19 if (height < 2) {
20 return 0;
21 }
22
23 // Determine which height to jump back to. Any number strictly lower than
24 // height is acceptable, but the following expression seems to perform well
25 // in simulations (max 110 steps to go back up to 2**18 blocks).
26 return (height & 1) ? InvertLowestOne(InvertLowestOne(height - 1)) + 1
27 : InvertLowestOne(height);
28}
29
30std::string CBlockIndex::ToString() const {
31 return strprintf(
32 "CBlockIndex(pprev=%p, nHeight=%d, merkle=%s, hashBlock=%s)", pprev,
34}
35
37 nChainTx = 0;
38}
39
40void CBlockIndex::MaybeResetChainStats(bool is_snapshot_base_block) {
41 // Typically nChainTx will be 0 at this point, but it can be nonzero if this
42 // is a pruned block which is being downloaded again, or if this is an
43 // assumeutxo snapshot block which has a hardcoded nChainTx value from the
44 // snapshot metadata. If the pindex is not the snapshot block and the
45 // nChainTx value is not zero, assert that value is actually correct.
46 unsigned int correct_value = nTx + (pprev ? pprev->nChainTx : 0);
47 if (!Assume(nChainTx == 0 || nChainTx == correct_value ||
48 is_snapshot_base_block)) {
49 LogPrintf("Internal bug detected: block %d has unexpected nChainTx %i "
50 "that should be %i. Please report this issue here: %s\n",
51 nHeight, nChainTx, correct_value, PACKAGE_BUGREPORT);
53 }
54}
55
57 unsigned int correct_value = nTx + (pprev ? pprev->nChainTx : 0);
58 // Before setting nChainTx, assert that it is 0 or already set to
59 // the correct value. This assert will fail after receiving the
60 // assumeutxo snapshot block if assumeutxo snapshot metadata has an
61 // incorrect hardcoded AssumeutxoData::nChainTx value.
62 if (!Assume(nChainTx == 0 || nChainTx == correct_value)) {
63 LogPrintf("Internal bug detected: block %d has unexpected nChainTx %i "
64 "that should be %i. Please report this issue here: %s\n",
65 nHeight, nChainTx, correct_value, PACKAGE_BUGREPORT);
66 }
67
68 if (pprev == nullptr || pprev->nChainTx > 0) {
69 nChainTx = correct_value;
70 return true;
71 }
72
73 return false;
74}
75
76const CBlockIndex *CBlockIndex::GetAncestor(int height) const {
77 if (height > nHeight || height < 0) {
78 return nullptr;
79 }
80
81 const CBlockIndex *pindexWalk = this;
82 int heightWalk = nHeight;
83 while (heightWalk > height) {
84 int heightSkip = GetSkipHeight(heightWalk);
85 int heightSkipPrev = GetSkipHeight(heightWalk - 1);
86 if (pindexWalk->pskip != nullptr &&
87 (heightSkip == height ||
88 (heightSkip > height && !(heightSkipPrev < heightSkip - 2 &&
89 heightSkipPrev >= height)))) {
90 // Only follow pskip if pprev->pskip isn't better than pskip->pprev.
91 pindexWalk = pindexWalk->pskip;
92 heightWalk = heightSkip;
93 } else {
94 assert(pindexWalk->pprev);
95 pindexWalk = pindexWalk->pprev;
96 heightWalk--;
97 }
98 }
99 return pindexWalk;
100}
101
103 return const_cast<CBlockIndex *>(
104 const_cast<const CBlockIndex *>(this)->GetAncestor(height));
105}
106
108 if (pprev) {
110 }
111}
static int GetSkipHeight(int height)
Compute what height to jump back to with the CBlockIndex::pskip pointer.
Definition: blockindex.cpp:18
static int InvertLowestOne(int n)
Turn the lowest '1' bit in the binary representation of a number into a '0'.
Definition: blockindex.cpp:13
#define Assume(val)
Assume is the identity function.
Definition: check.h:97
The block chain is a tree shaped structure starting with the genesis block at the root,...
Definition: blockindex.h:25
uint256 hashMerkleRoot
Definition: blockindex.h:75
void ResetChainStats()
Reset chain tx stats.
Definition: blockindex.cpp:36
std::string ToString() const
Definition: blockindex.cpp:30
CBlockIndex * pprev
pointer to the index of the predecessor of this block
Definition: blockindex.h:32
void BuildSkip()
Build the skiplist pointer for this entry.
Definition: blockindex.cpp:107
void MaybeResetChainStats(bool is_snapshot_base_block)
Reset chain tx stats and log a warning if the block is not the snapshot block, and the nChainTx value...
Definition: blockindex.cpp:40
bool UpdateChainStats()
Update chain tx stats and return True if this block is the genesis block or all parents have their tx...
Definition: blockindex.cpp:56
CBlockIndex * pskip
pointer to the index of some further predecessor of this block
Definition: blockindex.h:35
unsigned int nTx
Number of transactions in this block.
Definition: blockindex.h:55
CBlockIndex * GetAncestor(int height)
Efficiently find an ancestor of this block.
Definition: blockindex.cpp:102
BlockHash GetBlockHash() const
Definition: blockindex.h:130
int nHeight
height of the entry in the chain. The genesis block has height 0
Definition: blockindex.h:38
unsigned int nChainTx
(memory only) Number of transactions in the chain up to and including this block.
Definition: blockindex.h:68
std::string ToString() const
Definition: uint256.h:80
#define LogPrintf(...)
Definition: logging.h:227
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1202
assert(!tx.IsCoinBase())