Browse Source

Reimplement CBlockLocator's chain-related logic in CChain.

This removes a few unused CBlockLocator methods, and moves the
construction and fork-finding logic to CChain (which can do these
more efficiently, as it has a height-indexable chain available).
It also makes CBlockLocator independent from the validation code.
pull/145/head
Pieter Wuille 11 years ago
committed by Pieter Wuille
parent
commit
e4daecda0b
  1. 2
      src/db.h
  2. 8
      src/init.cpp
  3. 123
      src/main.cpp
  4. 25
      src/main.h
  5. 4
      src/rpcwallet.cpp

2
src/db.h

@ -16,7 +16,7 @@
#include <db_cxx.h>
class CAddrMan;
class CBlockLocator;
struct CBlockLocator;
class CDiskBlockIndex;
class CMasterKey;
class COutPoint;

8
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++;
}

123
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);
}

25
src/main.h

@ -22,6 +22,7 @@ class CBlock;
class CBlockIndex;
class CKeyItem;
class CReserveKey;
class CBlockLocator;
class CAddress;
class CInv;
@ -1033,6 +1034,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. */
@ -1051,13 +1058,6 @@ protected:
public:
CBlockLocator() {}
explicit CBlockLocator(const CBlockIndex* pindex)
{
Set(pindex);
}
explicit CBlockLocator(uint256 hashBlock);
CBlockLocator(const std::vector<uint256>& vHaveIn)
{
vHave = vHaveIn;
@ -1080,16 +1080,7 @@ public:
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();
friend class CChain;
};

4
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)

Loading…
Cancel
Save