aboutsummaryrefslogtreecommitdiff
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
parent38d15d8b427904a936a4fb4b8ac390bd637e1638 (diff)
parentf9b15a4fc94cdd4b535a2f7b1eccc04332367d00 (diff)
Merge pull request #3083 from sipa/chainlocator
CBlockLocator improvements & move to core
-rw-r--r--src/core.h34
-rw-r--r--src/db.h2
-rw-r--r--src/init.cpp8
-rw-r--r--src/main.cpp123
-rw-r--r--src/main.h59
-rw-r--r--src/rpcwallet.cpp4
6 files changed, 86 insertions, 144 deletions
diff --git a/src/core.h b/src/core.h
index ce21acd59e..9ee8b2edce 100644
--- a/src/core.h
+++ b/src/core.h
@@ -661,4 +661,38 @@ public:
void print() const;
};
+
+/** Describes a place in the block chain to another node such that if the
+ * other node doesn't have the same branch, it can find a recent common trunk.
+ * The further back it is, the further before the fork it may be.
+ */
+struct CBlockLocator
+{
+ std::vector<uint256> vHave;
+
+ CBlockLocator() {}
+
+ CBlockLocator(const std::vector<uint256>& vHaveIn)
+ {
+ vHave = vHaveIn;
+ }
+
+ IMPLEMENT_SERIALIZE
+ (
+ if (!(nType & SER_GETHASH))
+ READWRITE(nVersion);
+ READWRITE(vHave);
+ )
+
+ void SetNull()
+ {
+ vHave.clear();
+ }
+
+ bool IsNull()
+ {
+ return vHave.empty();
+ }
+};
+
#endif
diff --git a/src/db.h b/src/db.h
index b3f269f3da..8736031da4 100644
--- a/src/db.h
+++ b/src/db.h
@@ -16,7 +16,7 @@
#include <db_cxx.h>
class CAddrMan;
-class CBlockLocator;
+struct CBlockLocator;
class CDiskBlockIndex;
class CMasterKey;
class COutPoint;
diff --git a/src/init.cpp b/src/init.cpp
index dcd65198c3..fce5992255 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -116,7 +116,7 @@ void Shutdown()
{
LOCK(cs_main);
if (pwalletMain)
- pwalletMain->SetBestChain(CBlockLocator(chainActive.Tip()));
+ pwalletMain->SetBestChain(chainActive.GetLocator());
if (pblocktree)
pblocktree->Flush();
if (pcoinsTip)
@@ -912,7 +912,7 @@ bool AppInit2(boost::thread_group& threadGroup)
strErrors << _("Cannot write default address") << "\n";
}
- pwalletMain->SetBestChain(CBlockLocator(chainActive.Tip()));
+ pwalletMain->SetBestChain(chainActive.GetLocator());
}
LogPrintf("%s", strErrors.str().c_str());
@@ -928,7 +928,7 @@ bool AppInit2(boost::thread_group& threadGroup)
CWalletDB walletdb(strWalletFile);
CBlockLocator locator;
if (walletdb.ReadBestBlock(locator))
- pindexRescan = locator.GetBlockIndex();
+ pindexRescan = chainActive.FindFork(locator);
else
pindexRescan = chainActive.Genesis();
}
@@ -939,7 +939,7 @@ bool AppInit2(boost::thread_group& threadGroup)
nStart = GetTimeMillis();
pwalletMain->ScanForWalletTransactions(pindexRescan, true);
LogPrintf(" rescan %15"PRI64d"ms\n", GetTimeMillis() - nStart);
- pwalletMain->SetBestChain(CBlockLocator(chainActive.Tip()));
+ pwalletMain->SetBestChain(chainActive.GetLocator());
nWalletDBUpdated++;
}
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);
}
diff --git a/src/main.h b/src/main.h
index 46d629044a..fc60ccc0b5 100644
--- a/src/main.h
+++ b/src/main.h
@@ -1033,6 +1033,12 @@ public:
/** Set/initialize a chain with a given tip. Returns the forking point. */
CBlockIndex *SetTip(CBlockIndex *pindex);
+
+ /** Return a CBlockLocator that refers to a block in this chain (by default the tip). */
+ CBlockLocator GetLocator(const CBlockIndex *pindex = NULL) const;
+
+ /** Find the last common block between this chain and a locator. */
+ CBlockIndex *FindFork(const CBlockLocator &locator) const;
};
/** The currently-connected chain of blocks. */
@@ -1040,59 +1046,6 @@ extern CChain chainActive;
-/** Describes a place in the block chain to another node such that if the
- * other node doesn't have the same branch, it can find a recent common trunk.
- * The further back it is, the further before the fork it may be.
- */
-class CBlockLocator
-{
-protected:
- std::vector<uint256> vHave;
-public:
- CBlockLocator() {}
-
- explicit CBlockLocator(const CBlockIndex* pindex)
- {
- Set(pindex);
- }
-
- explicit CBlockLocator(uint256 hashBlock);
-
- CBlockLocator(const std::vector<uint256>& vHaveIn)
- {
- vHave = vHaveIn;
- }
-
- IMPLEMENT_SERIALIZE
- (
- if (!(nType & SER_GETHASH))
- READWRITE(nVersion);
- READWRITE(vHave);
- )
-
- void SetNull()
- {
- vHave.clear();
- }
-
- bool IsNull()
- {
- return vHave.empty();
- }
-
- /** Given a block initialises the locator to that point in the chain. */
- void Set(const CBlockIndex* pindex);
- /** Returns the distance in blocks this locator is from our chain head. */
- int GetDistanceBack();
- /** Returns the first best-chain block the locator contains. */
- CBlockIndex* GetBlockIndex();
- /** Returns the hash of the first best chain block the locator contains. */
- uint256 GetBlockHash();
- /** Returns the height of the first best chain block the locator has. */
- int GetHeight();
-};
-
-
diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp
index 433cc8b735..f7341f7b69 100644
--- a/src/rpcwallet.cpp
+++ b/src/rpcwallet.cpp
@@ -1169,7 +1169,9 @@ Value listsinceblock(const Array& params, bool fHelp)
uint256 blockId = 0;
blockId.SetHex(params[0].get_str());
- pindex = CBlockLocator(blockId).GetBlockIndex();
+ std::map<uint256, CBlockIndex*>::iterator it = mapBlockIndex.find(blockId);
+ if (it != mapBlockIndex.end())
+ pindex = it->second;
}
if (params.size() > 1)