Merge pull request #948 from sipa/unstuck
authorGavin Andresen <gavinandresen@gmail.com>
Wed, 21 Mar 2012 19:16:28 +0000 (12:16 -0700)
committerGavin Andresen <gavinandresen@gmail.com>
Wed, 21 Mar 2012 19:16:28 +0000 (12:16 -0700)
Prevent stuck block download in large reorganisations

1  2 
src/main.cpp

diff --combined src/main.cpp
@@@ -1382,9 -1382,6 +1382,9 @@@ bool static Reorganize(CTxDB& txdb, CBl
          vConnect.push_back(pindex);
      reverse(vConnect.begin(), vConnect.end());
  
 +    printf("REORGANIZE: Disconnect %i blocks; %s..%s\n", vDisconnect.size(), pfork->GetBlockHash().ToString().substr(0,20).c_str(), pindexBest->GetBlockHash().ToString().substr(0,20).c_str());
 +    printf("REORGANIZE: Connect %i blocks; %s..%s\n", vConnect.size(), pfork->GetBlockHash().ToString().substr(0,20).c_str(), pindexNew->GetBlockHash().ToString().substr(0,20).c_str());
 +
      // Disconnect shorter branch
      vector<CTransaction> vResurrect;
      BOOST_FOREACH(CBlockIndex* pindex, vDisconnect)
          if (!block.ReadFromDisk(pindex))
              return error("Reorganize() : ReadFromDisk for disconnect failed");
          if (!block.DisconnectBlock(txdb, pindex))
 -            return error("Reorganize() : DisconnectBlock failed");
 +            return error("Reorganize() : DisconnectBlock %s failed", pindex->GetBlockHash().ToString().substr(0,20).c_str());
  
          // Queue memory transactions to resurrect
          BOOST_FOREACH(const CTransaction& tx, block.vtx)
          {
              // Invalid block
              txdb.TxnAbort();
 -            return error("Reorganize() : ConnectBlock failed");
 +            return error("Reorganize() : ConnectBlock %s failed", pindex->GetBlockHash().ToString().substr(0,20).c_str());
          }
  
          // Queue memory transactions to delete
      BOOST_FOREACH(CTransaction& tx, vDelete)
          tx.RemoveFromMemoryPool();
  
 -    printf("REORGANIZE: Disconnected %i blocks; %s..%s\n", vDisconnect.size(), pfork->GetBlockHash().ToString().substr(0,20).c_str(), pindexBest->GetBlockHash().ToString().substr(0,20).c_str());
 -    printf("REORGANIZE: Connected %i blocks; %s..%s\n", vConnect.size(), pfork->GetBlockHash().ToString().substr(0,20).c_str(), pindexNew->GetBlockHash().ToString().substr(0,20).c_str());
 +    printf("REORGANIZE: done\n");
  
      return true;
  }
@@@ -2359,8 -2357,10 +2359,10 @@@ bool static ProcessMessage(CNode* pfrom
          }
  
          CTxDB txdb("r");
-         BOOST_FOREACH(const CInv& inv, vInv)
+         for (int nInv = 0; nInv < vInv.size(); nInv++)
          {
+             const CInv &inv = vInv[nInv];
              if (fShutdown)
                  return true;
              pfrom->AddInventoryKnown(inv);
              if (fDebug)
                  printf("  got inventory: %s  %s\n", inv.ToString().c_str(), fAlreadyHave ? "have" : "new");
  
-             if (!fAlreadyHave)
+             // 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))
                  pfrom->AskFor(inv);
-             else if (inv.type == MSG_BLOCK && mapOrphanBlocks.count(inv.hash))
+             if (inv.type == MSG_BLOCK && mapOrphanBlocks.count(inv.hash))
                  pfrom->PushGetBlocks(pindexBest, GetOrphanRoot(mapOrphanBlocks[inv.hash]));
  
              // Track requests for our stuff