chain.cpp raw

   1  // Copyright (c) 2009-2010 Satoshi Nakamoto
   2  // Copyright (c) 2009-2022 The Limenka 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 <chain.h>
   7  #include <tinyformat.h>
   8  #include <util/time.h>
   9  
  10  std::string CBlockFileInfo::ToString() const
  11  {
  12      return strprintf("CBlockFileInfo(blocks=%u, size=%u, heights=%u...%u, time=%s...%s)", nBlocks, nSize, nHeightFirst, nHeightLast, FormatISO8601Date(nTimeFirst), FormatISO8601Date(nTimeLast));
  13  }
  14  
  15  std::string CBlockIndex::ToString() const
  16  {
  17      return strprintf("CBlockIndex(pprev=%p, nHeight=%d, merkle=%s, hashBlock=%s)",
  18                       pprev, nHeight, hashMerkleRoot.ToString(), GetBlockHash().ToString());
  19  }
  20  
  21  void CChain::SetTip(CBlockIndex& block)
  22  {
  23      CBlockIndex* pindex = &block;
  24      vChain.resize(pindex->nHeight + 1);
  25      while (pindex && vChain[pindex->nHeight] != pindex) {
  26          vChain[pindex->nHeight] = pindex;
  27          pindex = pindex->pprev;
  28      }
  29  }
  30  
  31  std::vector<uint256> LocatorEntries(const CBlockIndex* index)
  32  {
  33      int step = 1;
  34      std::vector<uint256> have;
  35      if (index == nullptr) return have;
  36  
  37      have.reserve(32);
  38      while (index) {
  39          have.emplace_back(index->GetBlockHash());
  40          if (index->nHeight == 0) break;
  41          // Exponentially larger steps back, plus the genesis block.
  42          int height = std::max(index->nHeight - step, 0);
  43          // Use skiplist.
  44          index = index->GetAncestor(height);
  45          if (have.size() > 10) step *= 2;
  46      }
  47      return have;
  48  }
  49  
  50  CBlockLocator GetLocator(const CBlockIndex* index)
  51  {
  52      return CBlockLocator{LocatorEntries(index)};
  53  }
  54  
  55  CBlockLocator CChain::GetLocator() const
  56  {
  57      return ::GetLocator(Tip());
  58  }
  59  
  60  const CBlockIndex *CChain::FindFork(const CBlockIndex *pindex) const {
  61      if (pindex == nullptr) {
  62          return nullptr;
  63      }
  64      if (pindex->nHeight > Height())
  65          pindex = pindex->GetAncestor(Height());
  66      while (pindex && !Contains(pindex))
  67          pindex = pindex->pprev;
  68      return pindex;
  69  }
  70  
  71  CBlockIndex* CChain::FindEarliestAtLeast(int64_t nTime, int height) const
  72  {
  73      std::pair<int64_t, int> blockparams = std::make_pair(nTime, height);
  74      std::vector<CBlockIndex*>::const_iterator lower = std::lower_bound(vChain.begin(), vChain.end(), blockparams,
  75          [](CBlockIndex* pBlock, const std::pair<int64_t, int>& blockparams) -> bool { return pBlock->GetBlockTimeMax() < blockparams.first || pBlock->nHeight < blockparams.second; });
  76      return (lower == vChain.end() ? nullptr : *lower);
  77  }
  78  
  79  /** Turn the lowest '1' bit in the binary representation of a number into a '0'. */
  80  int static inline InvertLowestOne(int n) { return n & (n - 1); }
  81  
  82  /** Compute what height to jump back to with the CBlockIndex::pskip pointer. */
  83  int static inline GetSkipHeight(int height) {
  84      if (height < 2)
  85          return 0;
  86  
  87      // Determine which height to jump back to. Any number strictly lower than height is acceptable,
  88      // but the following expression seems to perform well in simulations (max 110 steps to go back
  89      // up to 2**18 blocks).
  90      return (height & 1) ? InvertLowestOne(InvertLowestOne(height - 1)) + 1 : InvertLowestOne(height);
  91  }
  92  
  93  const CBlockIndex* CBlockIndex::GetAncestor(int height) const
  94  {
  95      if (height > nHeight || height < 0) {
  96          return nullptr;
  97      }
  98  
  99      const CBlockIndex* pindexWalk = this;
 100      int heightWalk = nHeight;
 101      while (heightWalk > height) {
 102          int heightSkip = GetSkipHeight(heightWalk);
 103          int heightSkipPrev = GetSkipHeight(heightWalk - 1);
 104          if (pindexWalk->pskip != nullptr &&
 105              (heightSkip == height ||
 106               (heightSkip > height && !(heightSkipPrev < heightSkip - 2 &&
 107                                         heightSkipPrev >= height)))) {
 108              // Only follow pskip if pprev->pskip isn't better than pskip->pprev.
 109              pindexWalk = pindexWalk->pskip;
 110              heightWalk = heightSkip;
 111          } else {
 112              assert(pindexWalk->pprev);
 113              pindexWalk = pindexWalk->pprev;
 114              heightWalk--;
 115          }
 116      }
 117      return pindexWalk;
 118  }
 119  
 120  CBlockIndex* CBlockIndex::GetAncestor(int height)
 121  {
 122      return const_cast<CBlockIndex*>(static_cast<const CBlockIndex*>(this)->GetAncestor(height));
 123  }
 124  
 125  void CBlockIndex::BuildSkip()
 126  {
 127      if (pprev)
 128          pskip = pprev->GetAncestor(GetSkipHeight(nHeight));
 129  }
 130  
 131  arith_uint256 GetBlockProof(const CBlockIndex& block)
 132  {
 133      arith_uint256 bnTarget;
 134      bool fNegative;
 135      bool fOverflow;
 136      bnTarget.SetCompact(block.nBits, &fNegative, &fOverflow);
 137      if (fNegative || fOverflow || bnTarget == 0)
 138          return 0;
 139      // We need to compute 2**256 / (bnTarget+1), but we can't represent 2**256
 140      // as it's too large for an arith_uint256. However, as 2**256 is at least as large
 141      // as bnTarget+1, it is equal to ((2**256 - bnTarget - 1) / (bnTarget+1)) + 1,
 142      // or ~bnTarget / (bnTarget+1) + 1.
 143      return (~bnTarget / (bnTarget + 1)) + 1;
 144  }
 145  
 146  int64_t GetBlockProofEquivalentTime(const CBlockIndex& to, const CBlockIndex& from, const CBlockIndex& tip, const Consensus::Params& params)
 147  {
 148      arith_uint256 r;
 149      int sign = 1;
 150      if (to.nChainWork > from.nChainWork) {
 151          r = to.nChainWork - from.nChainWork;
 152      } else {
 153          r = from.nChainWork - to.nChainWork;
 154          sign = -1;
 155      }
 156      r = r * arith_uint256(params.nPowTargetSpacing) / GetBlockProof(tip);
 157      if (r.bits() > 63) {
 158          return sign * std::numeric_limits<int64_t>::max();
 159      }
 160      return sign * int64_t(r.GetLow64());
 161  }
 162  
 163  /** Find the last common ancestor two blocks have.
 164   *  Both pa and pb must be non-nullptr. */
 165  const CBlockIndex* LastCommonAncestor(const CBlockIndex* pa, const CBlockIndex* pb) {
 166      if (pa->nHeight > pb->nHeight) {
 167          pa = pa->GetAncestor(pb->nHeight);
 168      } else if (pb->nHeight > pa->nHeight) {
 169          pb = pb->GetAncestor(pa->nHeight);
 170      }
 171  
 172      while (pa != pb && pa && pb) {
 173          pa = pa->pprev;
 174          pb = pb->pprev;
 175      }
 176  
 177      // Eventually all chain branches meet at the genesis block.
 178      assert(pa == pb);
 179      return pa;
 180  }
 181