@@ -1782,6 +1782,11 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
17821782 }
17831783 }
17841784
1785+ // Keep a CBlock for "optimistic" compactblock reconstructions (see
1786+ // below)
1787+ std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
1788+ bool fBlockReconstructed = false ;
1789+
17851790 LOCK (cs_main);
17861791 // If AcceptBlockHeader returned true, it set pindex
17871792 assert (pindex);
@@ -1870,6 +1875,23 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
18701875 req.blockhash = pindex->GetBlockHash ();
18711876 connman.PushMessage (pfrom, msgMaker.Make (NetMsgType::GETBLOCKTXN, req));
18721877 }
1878+ } else {
1879+ // This block is either already in flight from a different
1880+ // peer, or this peer has too many blocks outstanding to
1881+ // download from.
1882+ // Optimistically try to reconstruct anyway since we might be
1883+ // able to without any round trips.
1884+ PartiallyDownloadedBlock tempBlock (&mempool);
1885+ ReadStatus status = tempBlock.InitData (cmpctblock);
1886+ if (status != READ_STATUS_OK) {
1887+ // TODO: don't ignore failures
1888+ return true ;
1889+ }
1890+ std::vector<CTransactionRef> dummy;
1891+ status = tempBlock.FillBlock (*pblock, dummy);
1892+ if (status == READ_STATUS_OK) {
1893+ fBlockReconstructed = true ;
1894+ }
18731895 }
18741896 } else {
18751897 if (fAlreadyInFlight ) {
@@ -1889,6 +1911,29 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
18891911 return ProcessMessage (pfrom, NetMsgType::HEADERS, vHeadersMsg, nTimeReceived, chainparams, connman);
18901912 }
18911913 }
1914+
1915+ if (fBlockReconstructed ) {
1916+ // If we got here, we were able to optimistically reconstruct a
1917+ // block that is in flight from some other peer.
1918+ {
1919+ LOCK (cs_main);
1920+ mapBlockSource.emplace (pblock->GetHash (), std::make_pair (pfrom->GetId (), false ));
1921+ }
1922+ bool fNewBlock = false ;
1923+ ProcessNewBlock (chainparams, pblock, true , &fNewBlock );
1924+ if (fNewBlock )
1925+ pfrom->nLastBlockTime = GetTime ();
1926+
1927+ LOCK (cs_main); // hold cs_main for CBlockIndex::IsValid()
1928+ if (pindex->IsValid (BLOCK_VALID_TRANSACTIONS)) {
1929+ // Clear download state for this block, which is in
1930+ // process from some other peer. We do this after calling
1931+ // ProcessNewBlock so that a malleated cmpctblock announcement
1932+ // can't be used to interfere with block relay.
1933+ MarkBlockAsReceived (pblock->GetHash ());
1934+ }
1935+ }
1936+
18921937 }
18931938
18941939 else if (strCommand == NetMsgType::BLOCKTXN && !fImporting && !fReindex ) // Ignore blocks received while importing
0 commit comments