Browse Source

Merge pull request #3083 from sipa/chainlocator

CBlockLocator improvements & move to core
0.10
Gavin Andresen 11 years ago
parent
commit
9e70bff67a
  1. 34
      src/core.h
  2. 2
      src/db.h
  3. 8
      src/init.cpp
  4. 123
      src/main.cpp
  5. 59
      src/main.h
  6. 4
      src/rpcwallet.cpp

34
src/core.h

@ -661,4 +661,38 @@ public: @@ -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

2
src/db.h

@ -16,7 +16,7 @@ @@ -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() @@ -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) @@ -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) @@ -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) @@ -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) @@ -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) @@ -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) @@ -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) @@ -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) @@ -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);
}

59
src/main.h

@ -1033,6 +1033,12 @@ public: @@ -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; @@ -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();
};

4
src/rpcwallet.cpp

@ -1169,7 +1169,9 @@ Value listsinceblock(const Array& params, bool fHelp) @@ -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