@@ -1782,6 +1782,11 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
1782
1782
}
1783
1783
}
1784
1784
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
+
1785
1790
LOCK (cs_main);
1786
1791
// If AcceptBlockHeader returned true, it set pindex
1787
1792
assert (pindex);
@@ -1870,6 +1875,23 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
1870
1875
req.blockhash = pindex->GetBlockHash ();
1871
1876
connman.PushMessage (pfrom, msgMaker.Make (NetMsgType::GETBLOCKTXN, req));
1872
1877
}
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
+ }
1873
1895
}
1874
1896
} else {
1875
1897
if (fAlreadyInFlight ) {
@@ -1889,6 +1911,29 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
1889
1911
return ProcessMessage (pfrom, NetMsgType::HEADERS, vHeadersMsg, nTimeReceived, chainparams, connman);
1890
1912
}
1891
1913
}
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
+
1892
1937
}
1893
1938
1894
1939
else if (strCommand == NetMsgType::BLOCKTXN && !fImporting && !fReindex ) // Ignore blocks received while importing
0 commit comments