aboutsummaryrefslogtreecommitdiff
path: root/src/main.cpp
diff options
context:
space:
mode:
authorGavin Andresen <gavinandresen@gmail.com>2013-10-15 16:31:46 -0700
committerGavin Andresen <gavinandresen@gmail.com>2013-10-15 16:31:46 -0700
commit9e70bff67a581e62a77c40ec5dd3900c62fb86ba (patch)
treed495796c3608c5e3eba2f0c3734474e8395ff641 /src/main.cpp
parent38d15d8b427904a936a4fb4b8ac390bd637e1638 (diff)
parentf9b15a4fc94cdd4b535a2f7b1eccc04332367d00 (diff)
Merge pull request #3083 from sipa/chainlocator
CBlockLocator improvements & move to core
Diffstat (limited to 'src/main.cpp')
-rw-r--r--src/main.cpp123
1 files changed, 38 insertions, 85 deletions
diff --git a/src/main.cpp b/src/main.cpp
index 477bc74fae..215a7ba620 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -190,105 +190,61 @@ void UnregisterNodeSignals(CNodeSignals& nodeSignals)
//////////////////////////////////////////////////////////////////////////////
//
-// CBlockLocator implementation
+// CChain implementation
//
-CBlockLocator::CBlockLocator(uint256 hashBlock)
-{
- std::map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock);
- if (mi != mapBlockIndex.end())
- Set((*mi).second);
+CBlockIndex *CChain::SetTip(CBlockIndex *pindex) {
+ if (pindex == NULL) {
+ vChain.clear();
+ return NULL;
+ }
+ vChain.resize(pindex->nHeight + 1);
+ while (pindex && vChain[pindex->nHeight] != pindex) {
+ vChain[pindex->nHeight] = pindex;
+ pindex = pindex->pprev;
+ }
+ return pindex;
}
-void CBlockLocator::Set(const CBlockIndex* pindex)
-{
- vHave.clear();
+CBlockLocator CChain::GetLocator(const CBlockIndex *pindex) const {
int nStep = 1;
- while (pindex)
- {
- vHave.push_back(pindex->GetBlockHash());
+ std::vector<uint256> vHave;
+ vHave.reserve(32);
- // Exponentially larger steps back
- for (int i = 0; pindex && i < nStep; i++)
+ 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);
+ // In case pindex is not in this chain, iterate pindex->pprev to find blocks.
+ while (pindex->nHeight > nHeight && !Contains(pindex))
pindex = pindex->pprev;
+ // If pindex is in this chain, use direct height-based access.
+ if (pindex->nHeight > nHeight)
+ pindex = (*this)[nHeight];
if (vHave.size() > 10)
nStep *= 2;
}
- vHave.push_back(Params().HashGenesisBlock());
-}
-int CBlockLocator::GetDistanceBack()
-{
- // Retrace how far back it was in the sender's branch
- int nDistance = 0;
- int nStep = 1;
- BOOST_FOREACH(const uint256& hash, vHave)
- {
- std::map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hash);
- if (mi != mapBlockIndex.end())
- {
- CBlockIndex* pindex = (*mi).second;
- if (chainActive.Contains(pindex))
- return nDistance;
- }
- nDistance += nStep;
- if (nDistance > 10)
- nStep *= 2;
- }
- return nDistance;
+ return CBlockLocator(vHave);
}
-CBlockIndex *CBlockLocator::GetBlockIndex()
-{
+CBlockIndex *CChain::FindFork(const CBlockLocator &locator) const {
// Find the first block the caller has in the main chain
- BOOST_FOREACH(const uint256& hash, vHave)
- {
+ BOOST_FOREACH(const uint256& hash, locator.vHave) {
std::map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hash);
if (mi != mapBlockIndex.end())
{
CBlockIndex* pindex = (*mi).second;
- if (chainActive.Contains(pindex))
+ if (Contains(pindex))
return pindex;
}
}
- return chainActive.Genesis();
-}
-
-uint256 CBlockLocator::GetBlockHash()
-{
- // Find the first block the caller has in the main chain
- BOOST_FOREACH(const uint256& hash, vHave)
- {
- std::map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hash);
- if (mi != mapBlockIndex.end())
- {
- CBlockIndex* pindex = (*mi).second;
- if (chainActive.Contains(pindex))
- return hash;
- }
- }
- return Params().HashGenesisBlock();
-}
-
-int CBlockLocator::GetHeight()
-{
- CBlockIndex* pindex = GetBlockIndex();
- if (!pindex)
- return 0;
- return pindex->nHeight;
-}
-
-CBlockIndex *CChain::SetTip(CBlockIndex *pindex) {
- if (pindex == NULL) {
- std::vector<CBlockIndex*>().swap(vChain);
- return NULL;
- }
- vChain.resize(pindex->nHeight + 1);
- while (pindex && vChain[pindex->nHeight] != pindex) {
- vChain[pindex->nHeight] = pindex;
- pindex = pindex->pprev;
- }
- return pindex;
+ return Genesis();
}
//////////////////////////////////////////////////////////////////////////////
@@ -2156,10 +2112,7 @@ bool SetBestChain(CValidationState &state, CBlockIndex* pindexNew)
// Update best block in wallet (so we can detect restored wallets)
if ((pindexNew->nHeight % 20160) == 0 || (!fIsInitialDownload && (pindexNew->nHeight % 144) == 0))
- {
- const CBlockLocator locator(pindexNew);
- ::SetBestChain(locator);
- }
+ ::SetBestChain(chainActive.GetLocator(pindexNew));
// New best block
nTimeBestReceived = GetTime();
@@ -2525,7 +2478,7 @@ void PushGetBlocks(CNode* pnode, CBlockIndex* pindexBegin, uint256 hashEnd)
pnode->pindexLastGetBlocksBegin = pindexBegin;
pnode->hashLastGetBlocksEnd = hashEnd;
- pnode->PushMessage("getblocks", CBlockLocator(pindexBegin), hashEnd);
+ pnode->PushMessage("getblocks", chainActive.GetLocator(pindexBegin), hashEnd);
}
bool ProcessBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBlockPos *dbp)
@@ -3653,7 +3606,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
vRecv >> locator >> hashStop;
// Find the last block the caller has in the main chain
- CBlockIndex* pindex = locator.GetBlockIndex();
+ CBlockIndex* pindex = chainActive.FindFork(locator);
// Send the rest of the chain
if (pindex)
@@ -3698,7 +3651,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
else
{
// Find the last block the caller has in the main chain
- pindex = locator.GetBlockIndex();
+ pindex = chainActive.FindFork(locator);
if (pindex)
pindex = chainActive.Next(pindex);
}