@@ -274,6 +274,10 @@ struct CNodeState {
274274 bool fPreferredDownload ;
275275 // ! Whether this peer wants invs or headers (when possible) for block announcements.
276276 bool fPreferHeaders ;
277+ // ! Whether this peer wants invs or cmpctblocks (when possible) for block announcements.
278+ bool fPreferHeaderAndIDs ;
279+ // ! Whether this peer will send us cmpctblocks if we request them
280+ bool fProvidesHeaderAndIDs ;
277281
278282 CNodeState () {
279283 fCurrentlyConnected = false ;
@@ -290,6 +294,8 @@ struct CNodeState {
290294 nBlocksInFlightValidHeaders = 0 ;
291295 fPreferredDownload = false ;
292296 fPreferHeaders = false ;
297+ fPreferHeaderAndIDs = false ;
298+ fProvidesHeaderAndIDs = false ;
293299 }
294300};
295301
@@ -4454,7 +4460,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
44544460 boost::this_thread::interruption_point ();
44554461 it++;
44564462
4457- if (inv.type == MSG_BLOCK || inv.type == MSG_FILTERED_BLOCK)
4463+ if (inv.type == MSG_BLOCK || inv.type == MSG_FILTERED_BLOCK || inv. type == MSG_CMPCT_BLOCK )
44584464 {
44594465 bool send = false ;
44604466 BlockMap::iterator mi = mapBlockIndex.find (inv.hash );
@@ -4496,7 +4502,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
44964502 assert (!" cannot load block from disk" );
44974503 if (inv.type == MSG_BLOCK)
44984504 pfrom->PushMessage (NetMsgType::BLOCK, block);
4499- else // MSG_FILTERED_BLOCK)
4505+ else if (inv. type == MSG_FILTERED_BLOCK)
45004506 {
45014507 LOCK (pfrom->cs_filter );
45024508 if (pfrom->pfilter )
@@ -4516,6 +4522,18 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
45164522 // else
45174523 // no response
45184524 }
4525+ else if (inv.type == MSG_CMPCT_BLOCK)
4526+ {
4527+ // If a peer is asking for old blocks, we're almost guaranteed
4528+ // they wont have a useful mempool to match against a compact block,
4529+ // and we dont feel like constructing the object for them, so
4530+ // instead we respond with the full, non-compact block.
4531+ if (mi->second ->nHeight >= chainActive.Height () - 10 ) {
4532+ CBlockHeaderAndShortTxIDs cmpctblock (block);
4533+ pfrom->PushMessage (NetMsgType::CMPCTBLOCK, cmpctblock);
4534+ } else
4535+ pfrom->PushMessage (NetMsgType::BLOCK, block);
4536+ }
45194537
45204538 // Trigger the peer node to send a getblocks request for the next batch of inventory
45214539 if (inv.hash == pfrom->hashContinue )
@@ -4839,6 +4857,18 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
48394857 State (pfrom->GetId ())->fPreferHeaders = true ;
48404858 }
48414859
4860+ else if (strCommand == NetMsgType::SENDCMPCT)
4861+ {
4862+ bool fAnnounceUsingCMPCTBLOCK = false ;
4863+ uint64_t nCMPCTBLOCKVersion = 1 ;
4864+ vRecv >> fAnnounceUsingCMPCTBLOCK >> nCMPCTBLOCKVersion;
4865+ if (nCMPCTBLOCKVersion == 1 ) {
4866+ LOCK (cs_main);
4867+ State (pfrom->GetId ())->fProvidesHeaderAndIDs = true ;
4868+ State (pfrom->GetId ())->fPreferHeaderAndIDs = fAnnounceUsingCMPCTBLOCK ;
4869+ }
4870+ }
4871+
48424872
48434873 else if (strCommand == NetMsgType::INV)
48444874 {
@@ -4982,6 +5012,39 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
49825012 }
49835013
49845014
5015+ else if (strCommand == NetMsgType::GETBLOCKTXN)
5016+ {
5017+ BlockTransactionsRequest req;
5018+ vRecv >> req;
5019+
5020+ BlockMap::iterator it = mapBlockIndex.find (req.blockhash );
5021+ if (it == mapBlockIndex.end () || !(it->second ->nStatus & BLOCK_HAVE_DATA)) {
5022+ Misbehaving (pfrom->GetId (), 100 );
5023+ LogPrintf (" Peer %d sent us a getblocktxn for a block we don't have" , pfrom->id );
5024+ return true ;
5025+ }
5026+
5027+ if (it->second ->nHeight < chainActive.Height () - 10 ) {
5028+ LogPrint (" net" , " Peer %d sent us a getblocktxn for a block > 10 deep" , pfrom->id );
5029+ return true ;
5030+ }
5031+
5032+ CBlock block;
5033+ assert (ReadBlockFromDisk (block, it->second , chainparams.GetConsensus ()));
5034+
5035+ BlockTransactions resp (req);
5036+ for (size_t i = 0 ; i < req.indexes .size (); i++) {
5037+ if (req.indexes [i] >= block.vtx .size ()) {
5038+ Misbehaving (pfrom->GetId (), 100 );
5039+ LogPrintf (" Peer %d sent us a getblocktxn with out-of-bounds tx indices" , pfrom->id );
5040+ return true ;
5041+ }
5042+ resp.txn [i] = block.vtx [req.indexes [i]];
5043+ }
5044+ pfrom->PushMessage (NetMsgType::BLOCKTXN, resp);
5045+ }
5046+
5047+
49855048 else if (strCommand == NetMsgType::GETHEADERS)
49865049 {
49875050 CBlockLocator locator;
@@ -5824,7 +5887,9 @@ bool SendMessages(CNode* pto)
58245887 // add all to the inv queue.
58255888 LOCK (pto->cs_inventory );
58265889 vector<CBlock> vHeaders;
5827- bool fRevertToInv = (!state.fPreferHeaders || pto->vBlockHashesToAnnounce .size () > MAX_BLOCKS_TO_ANNOUNCE);
5890+ bool fRevertToInv = ((!state.fPreferHeaders &&
5891+ (!state.fPreferHeaderAndIDs || pto->vBlockHashesToAnnounce .size () > 1 )) ||
5892+ pto->vBlockHashesToAnnounce .size () > MAX_BLOCKS_TO_ANNOUNCE);
58285893 CBlockIndex *pBestIndex = NULL ; // last header queued for delivery
58295894 ProcessBlockAvailability (pto->id ); // ensure pindexBestKnownBlock is up-to-date
58305895
@@ -5876,6 +5941,33 @@ bool SendMessages(CNode* pto)
58765941 }
58775942 }
58785943 }
5944+ if (!fRevertToInv && !vHeaders.empty ()) {
5945+ if (vHeaders.size () == 1 && state.fPreferHeaderAndIDs ) {
5946+ // We only send up to 1 block as header-and-ids, as otherwise
5947+ // probably means we're doing an initial-ish-sync or they're slow
5948+ LogPrint (" net" , " %s sending header-and-ids %s to peer %d\n " , __func__,
5949+ vHeaders.front ().GetHash ().ToString (), pto->id );
5950+ // TODO: Shouldn't need to reload block from disk, but requires refactor
5951+ CBlock block;
5952+ assert (ReadBlockFromDisk (block, pBestIndex, consensusParams));
5953+ CBlockHeaderAndShortTxIDs cmpctblock (block);
5954+ pto->PushMessage (NetMsgType::CMPCTBLOCK, cmpctblock);
5955+ state.pindexBestHeaderSent = pBestIndex;
5956+ } else if (state.fPreferHeaders ) {
5957+ if (vHeaders.size () > 1 ) {
5958+ LogPrint (" net" , " %s: %u headers, range (%s, %s), to peer=%d\n " , __func__,
5959+ vHeaders.size (),
5960+ vHeaders.front ().GetHash ().ToString (),
5961+ vHeaders.back ().GetHash ().ToString (), pto->id );
5962+ } else {
5963+ LogPrint (" net" , " %s: sending header %s to peer=%d\n " , __func__,
5964+ vHeaders.front ().GetHash ().ToString (), pto->id );
5965+ }
5966+ pto->PushMessage (NetMsgType::HEADERS, vHeaders);
5967+ state.pindexBestHeaderSent = pBestIndex;
5968+ } else
5969+ fRevertToInv = true ;
5970+ }
58795971 if (fRevertToInv ) {
58805972 // If falling back to using an inv, just try to inv the tip.
58815973 // The last entry in vBlockHashesToAnnounce was our tip at some point
@@ -5901,18 +5993,6 @@ bool SendMessages(CNode* pto)
59015993 pto->id , hashToAnnounce.ToString ());
59025994 }
59035995 }
5904- } else if (!vHeaders.empty ()) {
5905- if (vHeaders.size () > 1 ) {
5906- LogPrint (" net" , " %s: %u headers, range (%s, %s), to peer=%d\n " , __func__,
5907- vHeaders.size (),
5908- vHeaders.front ().GetHash ().ToString (),
5909- vHeaders.back ().GetHash ().ToString (), pto->id );
5910- } else {
5911- LogPrint (" net" , " %s: sending header %s to peer=%d\n " , __func__,
5912- vHeaders.front ().GetHash ().ToString (), pto->id );
5913- }
5914- pto->PushMessage (NetMsgType::HEADERS, vHeaders);
5915- state.pindexBestHeaderSent = pBestIndex;
59165996 }
59175997 pto->vBlockHashesToAnnounce .clear ();
59185998 }
0 commit comments