text: // Copyright (c) 2009-2010 Satoshi Nakamoto
  // Copyright (c) 2009-2014 The Bitcoin developers
  // Copyright (c) 2016-2019 The PIVX developers
  // Copyright (c) 2018-2020 The Kabberry developers
  // Distributed under the MIT software license, see the accompanying
  // file COPYING or http://www.opensource.org/licenses/mit-license.php.
  
  #include "chain.h"
  
  
  /**
   * CChain implementation
   */
  void CChain::SetTip(CBlockIndex* pindex)
  {
      if (pindex == NULL) {
          vChain.clear();
          return;
      }
      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;
  }
  
  uint256 CBlockIndex::GetBlockTrust() const
  {
      uint256 bnTarget;
      bnTarget.SetCompact(nBits);
      if (bnTarget <= 0)
          return 0;
  
      if (IsProofOfStake()) {
          // Return trust score as usual
          return (uint256(1) << 256) / (bnTarget + 1);
      } else {
          // Calculate work amount for block
          uint256 bnPoWTrust = ((~uint256(0) >> 20) / (bnTarget + 1));
          return bnPoWTrust > 1 ? bnPoWTrust : 1;
      }
  }