mirror of
https://github.com/dashpay/dash.git
synced 2024-12-25 20:12:57 +01:00
Merge pull request #2644 from sipa/constfindblock
Make FindBlockByHeight constant-time
This commit is contained in:
commit
d397715661
@ -3,9 +3,9 @@ index 04a8618..519429a 100644
|
|||||||
--- a/src/main.cpp
|
--- a/src/main.cpp
|
||||||
+++ b/src/main.cpp
|
+++ b/src/main.cpp
|
||||||
@@ -31,8 +31,8 @@ CTxMemPool mempool;
|
@@ -31,8 +31,8 @@ CTxMemPool mempool;
|
||||||
unsigned int nTransactionsUpdated = 0;
|
|
||||||
|
|
||||||
map<uint256, CBlockIndex*> mapBlockIndex;
|
map<uint256, CBlockIndex*> mapBlockIndex;
|
||||||
|
std::vector<CBlockIndex*> vBlockIndexByHeight;
|
||||||
-uint256 hashGenesisBlock("0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f");
|
-uint256 hashGenesisBlock("0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f");
|
||||||
-static CBigNum bnProofOfWorkLimit(~uint256(0) >> 32);
|
-static CBigNum bnProofOfWorkLimit(~uint256(0) >> 32);
|
||||||
+uint256 hashGenesisBlock("0x0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206");
|
+uint256 hashGenesisBlock("0x0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206");
|
||||||
|
54
src/main.cpp
54
src/main.cpp
@ -31,6 +31,7 @@ CTxMemPool mempool;
|
|||||||
unsigned int nTransactionsUpdated = 0;
|
unsigned int nTransactionsUpdated = 0;
|
||||||
|
|
||||||
map<uint256, CBlockIndex*> mapBlockIndex;
|
map<uint256, CBlockIndex*> mapBlockIndex;
|
||||||
|
std::vector<CBlockIndex*> vBlockIndexByHeight;
|
||||||
uint256 hashGenesisBlock("0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f");
|
uint256 hashGenesisBlock("0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f");
|
||||||
static CBigNum bnProofOfWorkLimit(~uint256(0) >> 32);
|
static CBigNum bnProofOfWorkLimit(~uint256(0) >> 32);
|
||||||
CBlockIndex* pindexGenesisBlock = NULL;
|
CBlockIndex* pindexGenesisBlock = NULL;
|
||||||
@ -1036,19 +1037,9 @@ bool GetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock
|
|||||||
static CBlockIndex* pblockindexFBBHLast;
|
static CBlockIndex* pblockindexFBBHLast;
|
||||||
CBlockIndex* FindBlockByHeight(int nHeight)
|
CBlockIndex* FindBlockByHeight(int nHeight)
|
||||||
{
|
{
|
||||||
CBlockIndex *pblockindex;
|
if (nHeight >= (int)vBlockIndexByHeight.size())
|
||||||
if (nHeight < nBestHeight / 2)
|
return NULL;
|
||||||
pblockindex = pindexGenesisBlock;
|
return vBlockIndexByHeight[nHeight];
|
||||||
else
|
|
||||||
pblockindex = pindexBest;
|
|
||||||
if (pblockindexFBBHLast && abs(nHeight - pblockindex->nHeight) > abs(nHeight - pblockindexFBBHLast->nHeight))
|
|
||||||
pblockindex = pblockindexFBBHLast;
|
|
||||||
while (pblockindex->nHeight > nHeight)
|
|
||||||
pblockindex = pblockindex->pprev;
|
|
||||||
while (pblockindex->nHeight < nHeight)
|
|
||||||
pblockindex = pblockindex->pnext;
|
|
||||||
pblockindexFBBHLast = pblockindex;
|
|
||||||
return pblockindex;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CBlock::ReadFromDisk(const CBlockIndex* pindex)
|
bool CBlock::ReadFromDisk(const CBlockIndex* pindex)
|
||||||
@ -1231,7 +1222,7 @@ void static InvalidBlockFound(CBlockIndex *pindex) {
|
|||||||
pblocktree->WriteBlockIndex(CDiskBlockIndex(pindex));
|
pblocktree->WriteBlockIndex(CDiskBlockIndex(pindex));
|
||||||
setBlockIndexValid.erase(pindex);
|
setBlockIndexValid.erase(pindex);
|
||||||
InvalidChainFound(pindex);
|
InvalidChainFound(pindex);
|
||||||
if (pindex->pnext) {
|
if (pindex->GetNextInMainChain()) {
|
||||||
CValidationState stateDummy;
|
CValidationState stateDummy;
|
||||||
ConnectBestBlock(stateDummy); // reorganise away from the failed block
|
ConnectBestBlock(stateDummy); // reorganise away from the failed block
|
||||||
}
|
}
|
||||||
@ -1271,7 +1262,7 @@ bool ConnectBestBlock(CValidationState &state) {
|
|||||||
if (pindexBest == NULL || pindexTest->nChainWork > pindexBest->nChainWork)
|
if (pindexBest == NULL || pindexTest->nChainWork > pindexBest->nChainWork)
|
||||||
vAttach.push_back(pindexTest);
|
vAttach.push_back(pindexTest);
|
||||||
|
|
||||||
if (pindexTest->pprev == NULL || pindexTest->pnext != NULL) {
|
if (pindexTest->pprev == NULL || pindexTest->GetNextInMainChain()) {
|
||||||
reverse(vAttach.begin(), vAttach.end());
|
reverse(vAttach.begin(), vAttach.end());
|
||||||
BOOST_FOREACH(CBlockIndex *pindexSwitch, vAttach) {
|
BOOST_FOREACH(CBlockIndex *pindexSwitch, vAttach) {
|
||||||
boost::this_thread::interruption_point();
|
boost::this_thread::interruption_point();
|
||||||
@ -1846,15 +1837,10 @@ bool SetBestChain(CValidationState &state, CBlockIndex* pindexNew)
|
|||||||
// At this point, all changes have been done to the database.
|
// At this point, all changes have been done to the database.
|
||||||
// Proceed by updating the memory structures.
|
// Proceed by updating the memory structures.
|
||||||
|
|
||||||
// Disconnect shorter branch
|
// Register new best chain
|
||||||
BOOST_FOREACH(CBlockIndex* pindex, vDisconnect)
|
vBlockIndexByHeight.resize(pindexNew->nHeight + 1);
|
||||||
if (pindex->pprev)
|
|
||||||
pindex->pprev->pnext = NULL;
|
|
||||||
|
|
||||||
// Connect longer branch
|
|
||||||
BOOST_FOREACH(CBlockIndex* pindex, vConnect)
|
BOOST_FOREACH(CBlockIndex* pindex, vConnect)
|
||||||
if (pindex->pprev)
|
vBlockIndexByHeight[pindex->nHeight] = pindex;
|
||||||
pindex->pprev->pnext = pindex;
|
|
||||||
|
|
||||||
// Resurrect memory transactions that were in the disconnected branch
|
// Resurrect memory transactions that were in the disconnected branch
|
||||||
BOOST_FOREACH(CTransaction& tx, vResurrect) {
|
BOOST_FOREACH(CTransaction& tx, vResurrect) {
|
||||||
@ -2587,12 +2573,12 @@ bool static LoadBlockIndexDB()
|
|||||||
nBestHeight = pindexBest->nHeight;
|
nBestHeight = pindexBest->nHeight;
|
||||||
nBestChainWork = pindexBest->nChainWork;
|
nBestChainWork = pindexBest->nChainWork;
|
||||||
|
|
||||||
// set 'next' pointers in best chain
|
// register best chain
|
||||||
CBlockIndex *pindex = pindexBest;
|
CBlockIndex *pindex = pindexBest;
|
||||||
while(pindex != NULL && pindex->pprev != NULL) {
|
vBlockIndexByHeight.resize(pindexBest->nHeight + 1);
|
||||||
CBlockIndex *pindexPrev = pindex->pprev;
|
while(pindex != NULL) {
|
||||||
pindexPrev->pnext = pindex;
|
vBlockIndexByHeight[pindex->nHeight] = pindex;
|
||||||
pindex = pindexPrev;
|
pindex = pindex->pprev;
|
||||||
}
|
}
|
||||||
printf("LoadBlockIndexDB(): hashBestChain=%s height=%d date=%s\n",
|
printf("LoadBlockIndexDB(): hashBestChain=%s height=%d date=%s\n",
|
||||||
hashBestChain.ToString().c_str(), nBestHeight,
|
hashBestChain.ToString().c_str(), nBestHeight,
|
||||||
@ -2661,7 +2647,7 @@ bool VerifyDB() {
|
|||||||
CBlockIndex *pindex = pindexState;
|
CBlockIndex *pindex = pindexState;
|
||||||
while (pindex != pindexBest) {
|
while (pindex != pindexBest) {
|
||||||
boost::this_thread::interruption_point();
|
boost::this_thread::interruption_point();
|
||||||
pindex = pindex->pnext;
|
pindex = pindex->GetNextInMainChain();
|
||||||
CBlock block;
|
CBlock block;
|
||||||
if (!block.ReadFromDisk(pindex))
|
if (!block.ReadFromDisk(pindex))
|
||||||
return error("VerifyDB() : *** block.ReadFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString().c_str());
|
return error("VerifyDB() : *** block.ReadFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString().c_str());
|
||||||
@ -2837,7 +2823,7 @@ void PrintBlockTree()
|
|||||||
vector<CBlockIndex*>& vNext = mapNext[pindex];
|
vector<CBlockIndex*>& vNext = mapNext[pindex];
|
||||||
for (unsigned int i = 0; i < vNext.size(); i++)
|
for (unsigned int i = 0; i < vNext.size(); i++)
|
||||||
{
|
{
|
||||||
if (vNext[i]->pnext)
|
if (vNext[i]->GetNextInMainChain())
|
||||||
{
|
{
|
||||||
swap(vNext[0], vNext[i]);
|
swap(vNext[0], vNext[i]);
|
||||||
break;
|
break;
|
||||||
@ -3418,10 +3404,10 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
|||||||
|
|
||||||
// Send the rest of the chain
|
// Send the rest of the chain
|
||||||
if (pindex)
|
if (pindex)
|
||||||
pindex = pindex->pnext;
|
pindex = pindex->GetNextInMainChain();
|
||||||
int nLimit = 500;
|
int nLimit = 500;
|
||||||
printf("getblocks %d to %s limit %d\n", (pindex ? pindex->nHeight : -1), hashStop.ToString().c_str(), nLimit);
|
printf("getblocks %d to %s limit %d\n", (pindex ? pindex->nHeight : -1), hashStop.ToString().c_str(), nLimit);
|
||||||
for (; pindex; pindex = pindex->pnext)
|
for (; pindex; pindex = pindex->GetNextInMainChain())
|
||||||
{
|
{
|
||||||
if (pindex->GetBlockHash() == hashStop)
|
if (pindex->GetBlockHash() == hashStop)
|
||||||
{
|
{
|
||||||
@ -3461,14 +3447,14 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
|||||||
// Find the last block the caller has in the main chain
|
// Find the last block the caller has in the main chain
|
||||||
pindex = locator.GetBlockIndex();
|
pindex = locator.GetBlockIndex();
|
||||||
if (pindex)
|
if (pindex)
|
||||||
pindex = pindex->pnext;
|
pindex = pindex->GetNextInMainChain();
|
||||||
}
|
}
|
||||||
|
|
||||||
// we must use CBlocks, as CBlockHeaders won't include the 0x00 nTx count at the end
|
// we must use CBlocks, as CBlockHeaders won't include the 0x00 nTx count at the end
|
||||||
vector<CBlock> vHeaders;
|
vector<CBlock> vHeaders;
|
||||||
int nLimit = 2000;
|
int nLimit = 2000;
|
||||||
printf("getheaders %d to %s\n", (pindex ? pindex->nHeight : -1), hashStop.ToString().c_str());
|
printf("getheaders %d to %s\n", (pindex ? pindex->nHeight : -1), hashStop.ToString().c_str());
|
||||||
for (; pindex; pindex = pindex->pnext)
|
for (; pindex; pindex = pindex->GetNextInMainChain())
|
||||||
{
|
{
|
||||||
vHeaders.push_back(pindex->GetBlockHeader());
|
vHeaders.push_back(pindex->GetBlockHeader());
|
||||||
if (--nLimit <= 0 || pindex->GetBlockHash() == hashStop)
|
if (--nLimit <= 0 || pindex->GetBlockHash() == hashStop)
|
||||||
|
24
src/main.h
24
src/main.h
@ -69,6 +69,7 @@ extern CScript COINBASE_FLAGS;
|
|||||||
|
|
||||||
extern CCriticalSection cs_main;
|
extern CCriticalSection cs_main;
|
||||||
extern std::map<uint256, CBlockIndex*> mapBlockIndex;
|
extern std::map<uint256, CBlockIndex*> mapBlockIndex;
|
||||||
|
extern std::vector<CBlockIndex*> vBlockIndexByHeight;
|
||||||
extern std::set<CBlockIndex*, CBlockIndexWorkComparator> setBlockIndexValid;
|
extern std::set<CBlockIndex*, CBlockIndexWorkComparator> setBlockIndexValid;
|
||||||
extern uint256 hashGenesisBlock;
|
extern uint256 hashGenesisBlock;
|
||||||
extern CBlockIndex* pindexGenesisBlock;
|
extern CBlockIndex* pindexGenesisBlock;
|
||||||
@ -1589,10 +1590,8 @@ enum BlockStatus {
|
|||||||
|
|
||||||
/** The block chain is a tree shaped structure starting with the
|
/** The block chain is a tree shaped structure starting with the
|
||||||
* genesis block at the root, with each block potentially having multiple
|
* genesis block at the root, with each block potentially having multiple
|
||||||
* candidates to be the next block. pprev and pnext link a path through the
|
* candidates to be the next block. A blockindex may have multiple pprev pointing
|
||||||
* main/longest chain. A blockindex may have multiple pprev pointing back
|
* to it, but at most one of them can be part of the currently active branch.
|
||||||
* to it, but pnext will only point forward to the longest branch, or will
|
|
||||||
* be null if the block is not part of the longest chain.
|
|
||||||
*/
|
*/
|
||||||
class CBlockIndex
|
class CBlockIndex
|
||||||
{
|
{
|
||||||
@ -1603,9 +1602,6 @@ public:
|
|||||||
// pointer to the index of the predecessor of this block
|
// pointer to the index of the predecessor of this block
|
||||||
CBlockIndex* pprev;
|
CBlockIndex* pprev;
|
||||||
|
|
||||||
// (memory only) pointer to the index of the *active* successor of this block
|
|
||||||
CBlockIndex* pnext;
|
|
||||||
|
|
||||||
// height of the entry in the chain. The genesis block has height 0
|
// height of the entry in the chain. The genesis block has height 0
|
||||||
int nHeight;
|
int nHeight;
|
||||||
|
|
||||||
@ -1643,7 +1639,6 @@ public:
|
|||||||
{
|
{
|
||||||
phashBlock = NULL;
|
phashBlock = NULL;
|
||||||
pprev = NULL;
|
pprev = NULL;
|
||||||
pnext = NULL;
|
|
||||||
nHeight = 0;
|
nHeight = 0;
|
||||||
nFile = 0;
|
nFile = 0;
|
||||||
nDataPos = 0;
|
nDataPos = 0;
|
||||||
@ -1664,7 +1659,6 @@ public:
|
|||||||
{
|
{
|
||||||
phashBlock = NULL;
|
phashBlock = NULL;
|
||||||
pprev = NULL;
|
pprev = NULL;
|
||||||
pnext = NULL;
|
|
||||||
nHeight = 0;
|
nHeight = 0;
|
||||||
nFile = 0;
|
nFile = 0;
|
||||||
nDataPos = 0;
|
nDataPos = 0;
|
||||||
@ -1733,7 +1727,11 @@ public:
|
|||||||
|
|
||||||
bool IsInMainChain() const
|
bool IsInMainChain() const
|
||||||
{
|
{
|
||||||
return (pnext || this == pindexBest);
|
return nHeight < (int)vBlockIndexByHeight.size() && vBlockIndexByHeight[nHeight] == this;
|
||||||
|
}
|
||||||
|
|
||||||
|
CBlockIndex *GetNextInMainChain() const {
|
||||||
|
return nHeight+1 >= (int)vBlockIndexByHeight.size() ? NULL : vBlockIndexByHeight[nHeight+1];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CheckIndex() const
|
bool CheckIndex() const
|
||||||
@ -1762,9 +1760,9 @@ public:
|
|||||||
const CBlockIndex* pindex = this;
|
const CBlockIndex* pindex = this;
|
||||||
for (int i = 0; i < nMedianTimeSpan/2; i++)
|
for (int i = 0; i < nMedianTimeSpan/2; i++)
|
||||||
{
|
{
|
||||||
if (!pindex->pnext)
|
if (!pindex->GetNextInMainChain())
|
||||||
return GetBlockTime();
|
return GetBlockTime();
|
||||||
pindex = pindex->pnext;
|
pindex = pindex->GetNextInMainChain();
|
||||||
}
|
}
|
||||||
return pindex->GetMedianTimePast();
|
return pindex->GetMedianTimePast();
|
||||||
}
|
}
|
||||||
@ -1779,7 +1777,7 @@ public:
|
|||||||
std::string ToString() const
|
std::string ToString() const
|
||||||
{
|
{
|
||||||
return strprintf("CBlockIndex(pprev=%p, pnext=%p, nHeight=%d, merkle=%s, hashBlock=%s)",
|
return strprintf("CBlockIndex(pprev=%p, pnext=%p, nHeight=%d, merkle=%s, hashBlock=%s)",
|
||||||
pprev, pnext, nHeight,
|
pprev, GetNextInMainChain(), nHeight,
|
||||||
hashMerkleRoot.ToString().c_str(),
|
hashMerkleRoot.ToString().c_str(),
|
||||||
GetBlockHash().ToString().c_str());
|
GetBlockHash().ToString().c_str());
|
||||||
}
|
}
|
||||||
|
@ -65,8 +65,9 @@ Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex)
|
|||||||
|
|
||||||
if (blockindex->pprev)
|
if (blockindex->pprev)
|
||||||
result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex()));
|
result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex()));
|
||||||
if (blockindex->pnext)
|
CBlockIndex *pnext = blockindex->GetNextInMainChain();
|
||||||
result.push_back(Pair("nextblockhash", blockindex->pnext->GetBlockHash().GetHex()));
|
if (pnext)
|
||||||
|
result.push_back(Pair("nextblockhash", pnext->GetBlockHash().GetHex()));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -779,7 +779,7 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
|
|||||||
if (AddToWalletIfInvolvingMe(tx.GetHash(), tx, &block, fUpdate))
|
if (AddToWalletIfInvolvingMe(tx.GetHash(), tx, &block, fUpdate))
|
||||||
ret++;
|
ret++;
|
||||||
}
|
}
|
||||||
pindex = pindex->pnext;
|
pindex = pindex->GetNextInMainChain();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
|
Loading…
Reference in New Issue
Block a user