@@ -274,6 +274,10 @@ struct CNodeState {
274
274
bool fPreferredDownload ;
275
275
// ! Whether this peer wants invs or headers (when possible) for block announcements.
276
276
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 ;
277
281
278
282
CNodeState () {
279
283
fCurrentlyConnected = false ;
@@ -290,6 +294,8 @@ struct CNodeState {
290
294
nBlocksInFlightValidHeaders = 0 ;
291
295
fPreferredDownload = false ;
292
296
fPreferHeaders = false ;
297
+ fPreferHeaderAndIDs = false ;
298
+ fProvidesHeaderAndIDs = false ;
293
299
}
294
300
};
295
301
@@ -4454,7 +4460,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
4454
4460
boost::this_thread::interruption_point ();
4455
4461
it++;
4456
4462
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 )
4458
4464
{
4459
4465
bool send = false ;
4460
4466
BlockMap::iterator mi = mapBlockIndex.find (inv.hash );
@@ -4496,7 +4502,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
4496
4502
assert (!" cannot load block from disk" );
4497
4503
if (inv.type == MSG_BLOCK)
4498
4504
pfrom->PushMessage (NetMsgType::BLOCK, block);
4499
- else // MSG_FILTERED_BLOCK)
4505
+ else if (inv. type == MSG_FILTERED_BLOCK)
4500
4506
{
4501
4507
LOCK (pfrom->cs_filter );
4502
4508
if (pfrom->pfilter )
@@ -4516,6 +4522,18 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
4516
4522
// else
4517
4523
// no response
4518
4524
}
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
+ }
4519
4537
4520
4538
// Trigger the peer node to send a getblocks request for the next batch of inventory
4521
4539
if (inv.hash == pfrom->hashContinue )
@@ -4839,6 +4857,18 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
4839
4857
State (pfrom->GetId ())->fPreferHeaders = true ;
4840
4858
}
4841
4859
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
+
4842
4872
4843
4873
else if (strCommand == NetMsgType::INV)
4844
4874
{
@@ -4982,6 +5012,39 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
4982
5012
}
4983
5013
4984
5014
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
+
4985
5048
else if (strCommand == NetMsgType::GETHEADERS)
4986
5049
{
4987
5050
CBlockLocator locator;
@@ -5824,7 +5887,9 @@ bool SendMessages(CNode* pto)
5824
5887
// add all to the inv queue.
5825
5888
LOCK (pto->cs_inventory );
5826
5889
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);
5828
5893
CBlockIndex *pBestIndex = NULL ; // last header queued for delivery
5829
5894
ProcessBlockAvailability (pto->id ); // ensure pindexBestKnownBlock is up-to-date
5830
5895
@@ -5876,6 +5941,33 @@ bool SendMessages(CNode* pto)
5876
5941
}
5877
5942
}
5878
5943
}
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
+ }
5879
5971
if (fRevertToInv ) {
5880
5972
// If falling back to using an inv, just try to inv the tip.
5881
5973
// The last entry in vBlockHashesToAnnounce was our tip at some point
@@ -5901,18 +5993,6 @@ bool SendMessages(CNode* pto)
5901
5993
pto->id , hashToAnnounce.ToString ());
5902
5994
}
5903
5995
}
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;
5916
5996
}
5917
5997
pto->vBlockHashesToAnnounce .clear ();
5918
5998
}
0 commit comments