@@ -297,6 +297,8 @@ struct CNodeState {
297297 bool fProvidesHeaderAndIDs ;
298298 // ! Whether this peer can give us witnesses
299299 bool fHaveWitness ;
300+ // ! Whether this peer wants witnesses in cmpctblocks/blocktxns
301+ bool fWantCmpctWitness ;
300302
301303 CNodeState () {
302304 fCurrentlyConnected = false ;
@@ -317,6 +319,7 @@ struct CNodeState {
317319 fPreferHeaderAndIDs = false ;
318320 fProvidesHeaderAndIDs = false ;
319321 fHaveWitness = false ;
322+ fWantCmpctWitness = false ;
320323 }
321324};
322325
@@ -476,16 +479,16 @@ void UpdateBlockAvailability(NodeId nodeid, const uint256 &hash) {
476479}
477480
478481void MaybeSetPeerAsAnnouncingHeaderAndIDs (const CNodeState* nodestate, CNode* pfrom) {
479- if (nLocalServices & NODE_WITNESS) {
480- // Don't ever request compact blocks when segwit is enabled .
482+ if (nLocalServices & ~pfrom-> nServices & NODE_WITNESS) {
483+ // Never ask from peers who can't provide witnesses .
481484 return ;
482485 }
483486 if (nodestate->fProvidesHeaderAndIDs ) {
484487 BOOST_FOREACH (const NodeId nodeid, lNodesAnnouncingHeaderAndIDs)
485488 if (nodeid == pfrom->GetId ())
486489 return ;
487490 bool fAnnounceUsingCMPCTBLOCK = false ;
488- uint64_t nCMPCTBLOCKVersion = 1 ;
491+ uint64_t nCMPCTBLOCKVersion = (nLocalServices & NODE_WITNESS) ? 2 : 1 ;
489492 if (lNodesAnnouncingHeaderAndIDs.size () >= 3 ) {
490493 // As per BIP152, we only get 3 of our peers to announce
491494 // blocks using compact encodings.
@@ -4817,11 +4820,12 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
48174820 // they wont have a useful mempool to match against a compact block,
48184821 // and we dont feel like constructing the object for them, so
48194822 // instead we respond with the full, non-compact block.
4823+ bool fPeerWantsWitness = State (pfrom->GetId ())->fWantCmpctWitness ;
48204824 if (mi->second ->nHeight >= chainActive.Height () - 10 ) {
4821- CBlockHeaderAndShortTxIDs cmpctblock (block);
4822- pfrom->PushMessageWithFlag (SERIALIZE_TRANSACTION_NO_WITNESS, NetMsgType::CMPCTBLOCK, cmpctblock);
4825+ CBlockHeaderAndShortTxIDs cmpctblock (block, fPeerWantsWitness );
4826+ pfrom->PushMessageWithFlag (fPeerWantsWitness ? 0 : SERIALIZE_TRANSACTION_NO_WITNESS, NetMsgType::CMPCTBLOCK, cmpctblock);
48234827 } else
4824- pfrom->PushMessageWithFlag (SERIALIZE_TRANSACTION_NO_WITNESS, NetMsgType::BLOCK, block);
4828+ pfrom->PushMessageWithFlag (fPeerWantsWitness ? 0 : SERIALIZE_TRANSACTION_NO_WITNESS, NetMsgType::BLOCK, block);
48254829 }
48264830
48274831 // Trigger the peer node to send a getblocks request for the next batch of inventory
@@ -5087,13 +5091,13 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
50875091 pfrom->PushMessage (NetMsgType::SENDHEADERS);
50885092 }
50895093 if (pfrom->nVersion >= SHORT_IDS_BLOCKS_VERSION) {
5090- // Tell our peer we are willing to provide version-1 cmpctblocks
5094+ // Tell our peer we are willing to provide version 1 or 2 cmpctblocks
50915095 // However, we do not request new block announcements using
50925096 // cmpctblock messages.
50935097 // We send this to non-NODE NETWORK peers as well, because
50945098 // they may wish to request compact blocks from us
50955099 bool fAnnounceUsingCMPCTBLOCK = false ;
5096- uint64_t nCMPCTBLOCKVersion = 1 ;
5100+ uint64_t nCMPCTBLOCKVersion = (pfrom-> nServices & nLocalServices & NODE_WITNESS) ? 2 : 1 ;
50975101 pfrom->PushMessage (NetMsgType::SENDCMPCT, fAnnounceUsingCMPCTBLOCK , nCMPCTBLOCKVersion);
50985102 }
50995103 }
@@ -5173,12 +5177,13 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
51735177 else if (strCommand == NetMsgType::SENDCMPCT)
51745178 {
51755179 bool fAnnounceUsingCMPCTBLOCK = false ;
5176- uint64_t nCMPCTBLOCKVersion = 1 ;
5180+ uint64_t nCMPCTBLOCKVersion = 0 ;
51775181 vRecv >> fAnnounceUsingCMPCTBLOCK >> nCMPCTBLOCKVersion;
5178- if (nCMPCTBLOCKVersion == 1 ) {
5182+ if (nCMPCTBLOCKVersion == 1 || nCMPCTBLOCKVersion == 2 ) {
51795183 LOCK (cs_main);
5180- State (pfrom->GetId ())->fProvidesHeaderAndIDs = true ;
5184+ State (pfrom->GetId ())->fProvidesHeaderAndIDs = !(nLocalServices & NODE_WITNESS) || (nCMPCTBLOCKVersion == 2 ) ;
51815185 State (pfrom->GetId ())->fPreferHeaderAndIDs = fAnnounceUsingCMPCTBLOCK ;
5186+ State (pfrom->GetId ())->fWantCmpctWitness = (nCMPCTBLOCKVersion == 2 );
51825187 }
51835188 }
51845189
@@ -5236,7 +5241,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
52365241 nodestate->nBlocksInFlight < MAX_BLOCKS_IN_TRANSIT_PER_PEER &&
52375242 (!IsWitnessEnabled (chainActive.Tip (), chainparams.GetConsensus ()) || State (pfrom->GetId ())->fHaveWitness )) {
52385243 inv.type |= nFetchFlags;
5239- if (nodestate->fProvidesHeaderAndIDs && !(nLocalServices & NODE_WITNESS) )
5244+ if (nodestate->fProvidesHeaderAndIDs )
52405245 vToFetch.push_back (CInv (MSG_CMPCT_BLOCK, inv.hash ));
52415246 else
52425247 vToFetch.push_back (inv);
@@ -5365,7 +5370,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
53655370 }
53665371 resp.txn [i] = block.vtx [req.indexes [i]];
53675372 }
5368- pfrom->PushMessageWithFlag (SERIALIZE_TRANSACTION_NO_WITNESS, NetMsgType::BLOCKTXN, resp);
5373+ pfrom->PushMessageWithFlag (State (pfrom-> GetId ())-> fWantCmpctWitness ? 0 : SERIALIZE_TRANSACTION_NO_WITNESS, NetMsgType::BLOCKTXN, resp);
53695374 }
53705375
53715376
@@ -5625,7 +5630,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
56255630 // We requested this block for some reason, but our mempool will probably be useless
56265631 // so we just grab the block via normal getdata
56275632 std::vector<CInv> vInv (1 );
5628- vInv[0 ] = CInv (MSG_BLOCK, cmpctblock.header .GetHash ());
5633+ vInv[0 ] = CInv (MSG_BLOCK | GetFetchFlags (pfrom, pindex-> pprev , chainparams. GetConsensus ()) , cmpctblock.header .GetHash ());
56295634 pfrom->PushMessage (NetMsgType::GETDATA, vInv);
56305635 return true ;
56315636 }
@@ -5663,7 +5668,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
56635668 } else if (status == READ_STATUS_FAILED) {
56645669 // Duplicate txindexes, the block is now in-flight, so just request it
56655670 std::vector<CInv> vInv (1 );
5666- vInv[0 ] = CInv (MSG_BLOCK, cmpctblock.header .GetHash ());
5671+ vInv[0 ] = CInv (MSG_BLOCK | GetFetchFlags (pfrom, pindex-> pprev , chainparams. GetConsensus ()) , cmpctblock.header .GetHash ());
56675672 pfrom->PushMessage (NetMsgType::GETDATA, vInv);
56685673 return true ;
56695674 }
@@ -5690,7 +5695,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
56905695 // We requested this block, but its far into the future, so our
56915696 // mempool will probably be useless - request the block normally
56925697 std::vector<CInv> vInv (1 );
5693- vInv[0 ] = CInv (MSG_BLOCK, cmpctblock.header .GetHash ());
5698+ vInv[0 ] = CInv (MSG_BLOCK | GetFetchFlags (pfrom, pindex-> pprev , chainparams. GetConsensus ()) , cmpctblock.header .GetHash ());
56945699 pfrom->PushMessage (NetMsgType::GETDATA, vInv);
56955700 return true ;
56965701 } else {
@@ -5732,7 +5737,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
57325737 } else if (status == READ_STATUS_FAILED) {
57335738 // Might have collided, fall back to getdata now :(
57345739 std::vector<CInv> invs;
5735- invs.push_back (CInv (MSG_BLOCK, resp.blockhash ));
5740+ invs.push_back (CInv (MSG_BLOCK | GetFetchFlags (pfrom, chainActive. Tip (), chainparams. GetConsensus ()) , resp.blockhash ));
57365741 pfrom->PushMessage (NetMsgType::GETDATA, invs);
57375742 } else {
57385743 CValidationState state;
@@ -5881,7 +5886,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
58815886 pindexLast->GetBlockHash ().ToString (), pindexLast->nHeight );
58825887 }
58835888 if (vGetData.size () > 0 ) {
5884- if (nodestate->fProvidesHeaderAndIDs && vGetData.size () == 1 && mapBlocksInFlight.size () == 1 && pindexLast->pprev ->IsValid (BLOCK_VALID_CHAIN) && !(nLocalServices & NODE_WITNESS) ) {
5889+ if (nodestate->fProvidesHeaderAndIDs && vGetData.size () == 1 && mapBlocksInFlight.size () == 1 && pindexLast->pprev ->IsValid (BLOCK_VALID_CHAIN)) {
58855890 // We seem to be rather well-synced, so it appears pfrom was the first to provide us
58865891 // with this block! Let's get them to announce using compact blocks in the future.
58875892 MaybeSetPeerAsAnnouncingHeaderAndIDs (nodestate, pfrom);
@@ -6504,8 +6509,8 @@ bool SendMessages(CNode* pto)
65046509 // TODO: Shouldn't need to reload block from disk, but requires refactor
65056510 CBlock block;
65066511 assert (ReadBlockFromDisk (block, pBestIndex, consensusParams));
6507- CBlockHeaderAndShortTxIDs cmpctblock (block);
6508- pto->PushMessageWithFlag (SERIALIZE_TRANSACTION_NO_WITNESS, NetMsgType::CMPCTBLOCK, cmpctblock);
6512+ CBlockHeaderAndShortTxIDs cmpctblock (block, state. fWantCmpctWitness );
6513+ pto->PushMessageWithFlag (state. fWantCmpctWitness ? 0 : SERIALIZE_TRANSACTION_NO_WITNESS, NetMsgType::CMPCTBLOCK, cmpctblock);
65096514 state.pindexBestHeaderSent = pBestIndex;
65106515 } else if (state.fPreferHeaders ) {
65116516 if (vHeaders.size () > 1 ) {
0 commit comments