aboutsummaryrefslogtreecommitdiff
path: root/src/main.cpp
diff options
context:
space:
mode:
authorPieter Wuille <pieter.wuille@gmail.com>2012-05-05 04:04:38 +0200
committerLuke Dashjr <luke-jr+git@utopios.org>2012-05-07 02:45:08 +0000
commit2403bb79bc232ea3f9a78448d0fb4ffcf385d209 (patch)
tree6837a2bd5bab98b998962bee2d1d8b80d7d7118d /src/main.cpp
parenteb3f661add15837434c286476a32e05f279a1919 (diff)
downloadbitcoin-2403bb79bc232ea3f9a78448d0fb4ffcf385d209.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.cpp16
1 files changed, 14 insertions, 2 deletions
diff --git a/src/main.cpp b/src/main.cpp
index 167e2821c0..a2fc7387fb 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -2177,6 +2177,12 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
if (vInv.size() > 50000)
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 (int nInv = 0; nInv < vInv.size(); nInv++)
{
@@ -2193,9 +2199,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