message: Speed up getchaintips.
diff: @@ -747,17 +747,30 @@ UniValue getchaintips(const UniValue& params, bool fHelp)
  LOCK(cs_main);
  - /* Build up a list of chain tips. We start with the list of all
  - known blocks, and successively remove blocks that appear as pprev
  - of another block. */
  + /*
  + * Idea: the set of chain tips is chainActive.tip, plus orphan blocks which do not have another orphan building off of them.
  + * Algorithm:
  + * - Make one pass through mapBlockIndex, picking out the orphan blocks, and also storing a set of the orphan block's pprev pointers.
  + * - Iterate through the orphan blocks. If the block isn't pointed to by another orphan, it is a chain tip.
  + * - add chainActive.Tip()
  + */
  std::set<const CBlockIndex*, CompareBlocksByHeight> setTips;
  - BOOST_FOREACH(const PAIRTYPE(const uint256, CBlockIndex*)& item, mapBlockIndex)
  - setTips.insert(item.second);
  + std::set<const CBlockIndex*> setOrphans;
  + std::set<const CBlockIndex*> setPrevs;
  +
  BOOST_FOREACH(const PAIRTYPE(const uint256, CBlockIndex*)& item, mapBlockIndex)
  {
  - const CBlockIndex* pprev = item.second->pprev;
  - if (pprev)
  - setTips.erase(pprev);
  + if (!chainActive.Contains(item.second)) {
  + setOrphans.insert(item.second);
  + setPrevs.insert(item.second->pprev);
  + }
  + }
  +
  + for (std::set<const CBlockIndex*>::iterator it = setOrphans.begin(); it != setOrphans.end(); ++it)
  + {
  + if (setPrevs.erase(*it) == 0) {
  + setTips.insert(*it);
  + }
  }
  // Always report the currently active tip.
  