chain.cpp 2.41 KB
Newer Older
1
2
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin developers
3
// Distributed under the MIT software license, see the accompanying
4
5
6
7
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "chain.h"

8
9
#include "main.h"

10
11
using namespace std;

12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
/* Moved here from the header, because we need auxpow and the logic
   becomes more involved.  */
CBlockHeader CBlockIndex::GetBlockHeader() const
{
    CBlockHeader block;

    /* The CBlockIndex object's block header is missing the auxpow.
       So if this is an auxpow block, read it from disk instead.  We only
       have to read the actual *header*, not the full block.  */
    if (nVersion.IsAuxpow())
    {
        ReadBlockHeaderFromDisk(block, this);
        return block;
    }

    block.nVersion       = nVersion;
    if (pprev)
        block.hashPrevBlock = pprev->GetBlockHash();
    block.hashMerkleRoot = hashMerkleRoot;
    block.nTime          = nTime;
    block.nBits          = nBits;
    block.nNonce         = nNonce;
    return block;
}

37
38
39
/**
 * CChain implementation
 */
21E14's avatar
21E14 committed
40
void CChain::SetTip(CBlockIndex *pindex) {
41
42
    if (pindex == NULL) {
        vChain.clear();
21E14's avatar
21E14 committed
43
        return;
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
    }
    vChain.resize(pindex->nHeight + 1);
    while (pindex && vChain[pindex->nHeight] != pindex) {
        vChain[pindex->nHeight] = pindex;
        pindex = pindex->pprev;
    }
}

CBlockLocator CChain::GetLocator(const CBlockIndex *pindex) const {
    int nStep = 1;
    std::vector<uint256> vHave;
    vHave.reserve(32);

    if (!pindex)
        pindex = Tip();
    while (pindex) {
        vHave.push_back(pindex->GetBlockHash());
        // Stop when we have added the genesis block.
        if (pindex->nHeight == 0)
            break;
        // Exponentially larger steps back, plus the genesis block.
        int nHeight = std::max(pindex->nHeight - nStep, 0);
        if (Contains(pindex)) {
            // Use O(1) CChain index if possible.
            pindex = (*this)[nHeight];
        } else {
            // Otherwise, use O(log n) skiplist.
            pindex = pindex->GetAncestor(nHeight);
        }
        if (vHave.size() > 10)
            nStep *= 2;
    }

    return CBlockLocator(vHave);
}

const CBlockIndex *CChain::FindFork(const CBlockIndex *pindex) const {
    if (pindex->nHeight > Height())
        pindex = pindex->GetAncestor(Height());
    while (pindex && !Contains(pindex))
        pindex = pindex->pprev;
    return pindex;
}