diff options
author | Wladimir J. van der Laan <laanwj@gmail.com> | 2016-04-19 10:44:44 +0200 |
---|---|---|
committer | Wladimir J. van der Laan <laanwj@gmail.com> | 2016-04-19 10:44:47 +0200 |
commit | 4205ad7ca2b159cc463d5a27e17e013c9dba8570 (patch) | |
tree | 4741c78076bbafe58e36efbaddd11da41d29ae9a /src/rpc | |
parent | fa9d86f8c4f4aba2c284f1db2cc8d0a1e89a9ce6 (diff) | |
parent | 87049e832d97d4f2808c0b479b21fc7b16c86934 (diff) |
Merge #7827: Speed up getchaintips.
87049e8 Speed up getchaintips. (mrbandrews)
Diffstat (limited to 'src/rpc')
-rw-r--r-- | src/rpc/blockchain.cpp | 29 |
1 files changed, 21 insertions, 8 deletions
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 88f6278b2a..5de2394e24 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -815,17 +815,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. |