diff options
author | Pieter Wuille <pieter.wuille@gmail.com> | 2012-05-05 04:04:38 +0200 |
---|---|---|
committer | Luke Dashjr <luke-jr+git@utopios.org> | 2012-05-07 04:00:49 +0000 |
commit | 60953d05c8cc6eefb0c03d1d39209bdaf54725eb (patch) | |
tree | bf8d530abe0d746754bc1d0a31e3b57499509645 /src/main.cpp | |
parent | 6bcefc1338c6e117219b56d8133a8ca0c055e210 (diff) | |
download | bitcoin-60953d05c8cc6eefb0c03d1d39209bdaf54725eb.tar.xz |
Prevent stuck download: correct solution
Pull request #948 introduced a fix for nodes stuck on a long side branch
of the main chain. The fix was non-functional however, as the additional
getdata request was created in a first step of processing, but dropped
in a second step as it was considered redundant. This commits fixes it
by sending the request directly.
Diffstat (limited to 'src/main.cpp')
-rw-r--r-- | src/main.cpp | 16 |
1 files changed, 14 insertions, 2 deletions
diff --git a/src/main.cpp b/src/main.cpp index 9b93c85caf..7e4ed1100c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2391,6 +2391,12 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) return error("message inv size() = %d", vInv.size()); } + // find last block in inv vector + unsigned int nLastBlock = (unsigned int)(-1); + for (unsigned int nInv = 0; nInv < vInv.size(); nInv++) { + if (vInv[vInv.size() - 1 - nInv].type == MSG_BLOCK) + nLastBlock = vInv.size() - 1 - nInv; + } CTxDB txdb("r"); for (unsigned int nInv = 0; nInv < vInv.size(); nInv++) { @@ -2407,9 +2413,15 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) // 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 || (inv.type == MSG_BLOCK && nInv==vInv.size()-1)) + 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) pfrom->AskFor(inv); - 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])); // Track requests for our stuff |