Hopefully final fix for the stuck blockchain issue
Immediately issue a "getblocks", instead of a "getdata" (which will trigger the relevant "inv" to be sent anyway), and only do so when the previous set of invs led us into a known and attached part of the block tree.
This commit is contained in:
parent
790fe2e558
commit
385f730f31
1 changed files with 13 additions and 11 deletions
24
src/main.cpp
24
src/main.cpp
|
@ -2482,8 +2482,10 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
||||||
// find last block in inv vector
|
// find last block in inv vector
|
||||||
unsigned int nLastBlock = (unsigned int)(-1);
|
unsigned int nLastBlock = (unsigned int)(-1);
|
||||||
for (unsigned int nInv = 0; nInv < vInv.size(); nInv++) {
|
for (unsigned int nInv = 0; nInv < vInv.size(); nInv++) {
|
||||||
if (vInv[vInv.size() - 1 - nInv].type == MSG_BLOCK)
|
if (vInv[vInv.size() - 1 - nInv].type == MSG_BLOCK) {
|
||||||
nLastBlock = vInv.size() - 1 - nInv;
|
nLastBlock = vInv.size() - 1 - nInv;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
CTxDB txdb("r");
|
CTxDB txdb("r");
|
||||||
for (unsigned int nInv = 0; nInv < vInv.size(); nInv++)
|
for (unsigned int nInv = 0; nInv < vInv.size(); nInv++)
|
||||||
|
@ -2498,19 +2500,19 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
||||||
if (fDebug)
|
if (fDebug)
|
||||||
printf(" got inventory: %s %s\n", inv.ToString().c_str(), fAlreadyHave ? "have" : "new");
|
printf(" got inventory: %s %s\n", inv.ToString().c_str(), fAlreadyHave ? "have" : "new");
|
||||||
|
|
||||||
// Always request the last block in an inv bundle (even if we already have it), as it is the
|
|
||||||
// trigger for the other side to send further invs. If we are stuck on a (very long) side chain,
|
|
||||||
// this is necessary to connect earlier received orphan blocks to the chain again.
|
|
||||||
if (fAlreadyHave && nInv == nLastBlock) {
|
|
||||||
// bypass mapAskFor, and send request directly; it must go through.
|
|
||||||
std::vector<CInv> vGetData(1,inv);
|
|
||||||
pfrom->PushMessage("getdata", vGetData);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!fAlreadyHave)
|
if (!fAlreadyHave)
|
||||||
pfrom->AskFor(inv);
|
pfrom->AskFor(inv);
|
||||||
else if (inv.type == MSG_BLOCK && mapOrphanBlocks.count(inv.hash))
|
else if (inv.type == MSG_BLOCK && mapOrphanBlocks.count(inv.hash)) {
|
||||||
pfrom->PushGetBlocks(pindexBest, GetOrphanRoot(mapOrphanBlocks[inv.hash]));
|
pfrom->PushGetBlocks(pindexBest, GetOrphanRoot(mapOrphanBlocks[inv.hash]));
|
||||||
|
} else if (nInv == nLastBlock) {
|
||||||
|
// In case we are on a very long side-chain, it is possible that we already have
|
||||||
|
// the last block in an inv bundle sent in response to getblocks. Try to detect
|
||||||
|
// this situation and push another getblocks to continue.
|
||||||
|
std::vector<CInv> vGetData(1,inv);
|
||||||
|
pfrom->PushGetBlocks(mapBlockIndex[inv.hash], uint256(0));
|
||||||
|
if (fDebug)
|
||||||
|
printf("force request: %s\n", inv.ToString().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
// Track requests for our stuff
|
// Track requests for our stuff
|
||||||
Inventory(inv.hash);
|
Inventory(inv.hash);
|
||||||
|
|
Loading…
Reference in a new issue