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