Skip to content

Commit 6274a57

Browse files
committed
merge bitcoin#20799: Only support version 2 compact blocks
1 parent f4ce573 commit 6274a57

File tree

2 files changed

+96
-120
lines changed

2 files changed

+96
-120
lines changed

src/net_processing.cpp

Lines changed: 67 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,8 @@ static constexpr double MAX_ADDR_RATE_PER_SECOND{0.1};
183183
* based increments won't go above this, but the MAX_ADDR_TO_SEND increment following GETADDR
184184
* is exempt from this limit). */
185185
static constexpr size_t MAX_ADDR_PROCESSING_TOKEN_BUCKET{MAX_ADDR_TO_SEND};
186+
/** The compactblocks version we support. See BIP 152. */
187+
static constexpr uint64_t CMPCTBLOCKS_VERSION{1};
186188

187189
struct COrphanTx {
188190
// When modifying, adapt the copy of this definition in tests/DoS_tests.
@@ -777,15 +779,10 @@ struct CNodeState {
777779
bool fPreferHeaders{false};
778780
//! Whether this peer wants invs or compressed headers (when possible) for block announcements.
779781
bool fPreferHeadersCompressed{false};
780-
//! Whether this peer wants invs or cmpctblocks (when possible) for block announcements.
781-
bool fPreferHeaderAndIDs{false};
782-
//! Whether this peer will send us cmpctblocks if we request them
783-
bool fProvidesHeaderAndIDs{false};
784-
/**
785-
* If we've announced last version to this peer: whether the peer sends last version in cmpctblocks/blocktxns,
786-
* otherwise: whether this peer sends non-last version in cmpctblocks/blocktxns.
787-
*/
788-
bool fSupportsDesiredCmpctVersion{false};
782+
/** Whether this peer wants invs or cmpctblocks (when possible) for block announcements. */
783+
bool m_requested_hb_cmpctblocks{false};
784+
/** Whether this peer will send us cmpctblocks if we request them. */
785+
bool m_provides_cmpctblocks{false};
789786

790787
/** State used to enforce CHAIN_SYNC_TIMEOUT and EXTRA_PEER_CHECK_INTERVAL logic.
791788
*
@@ -1059,54 +1056,52 @@ void PeerManagerImpl::MaybeSetPeerAsAnnouncingHeaderAndIDs(NodeId nodeid)
10591056
if (m_ignore_incoming_txs) return;
10601057

10611058
CNodeState* nodestate = State(nodeid);
1062-
if (!nodestate || !nodestate->fSupportsDesiredCmpctVersion) {
1063-
// Never ask from peers who can't provide desired version.
1059+
if (!nodestate || !nodestate->m_provides_cmpctblocks) {
1060+
// Don't request compact blocks if the peer has not signalled support
10641061
return;
10651062
}
1066-
if (nodestate->fProvidesHeaderAndIDs) {
1067-
int num_outbound_hb_peers = 0;
1068-
for (std::list<NodeId>::iterator it = lNodesAnnouncingHeaderAndIDs.begin(); it != lNodesAnnouncingHeaderAndIDs.end(); it++) {
1069-
if (*it == nodeid) {
1070-
lNodesAnnouncingHeaderAndIDs.erase(it);
1071-
lNodesAnnouncingHeaderAndIDs.push_back(nodeid);
1072-
return;
1073-
}
1074-
CNodeState *state = State(*it);
1075-
if (state != nullptr && !state->m_is_inbound) ++num_outbound_hb_peers;
1076-
}
1077-
if (nodestate->m_is_inbound) {
1078-
// If we're adding an inbound HB peer, make sure we're not removing
1079-
// our last outbound HB peer in the process.
1080-
if (lNodesAnnouncingHeaderAndIDs.size() >= 3 && num_outbound_hb_peers == 1) {
1081-
CNodeState *remove_node = State(lNodesAnnouncingHeaderAndIDs.front());
1082-
if (remove_node != nullptr && !remove_node->m_is_inbound) {
1083-
// Put the HB outbound peer in the second slot, so that it
1084-
// doesn't get removed.
1085-
std::swap(lNodesAnnouncingHeaderAndIDs.front(), *std::next(lNodesAnnouncingHeaderAndIDs.begin()));
1086-
}
1087-
}
1063+
1064+
int num_outbound_hb_peers = 0;
1065+
for (std::list<NodeId>::iterator it = lNodesAnnouncingHeaderAndIDs.begin(); it != lNodesAnnouncingHeaderAndIDs.end(); it++) {
1066+
if (*it == nodeid) {
1067+
lNodesAnnouncingHeaderAndIDs.erase(it);
1068+
lNodesAnnouncingHeaderAndIDs.push_back(nodeid);
1069+
return;
10881070
}
1089-
m_connman.ForNode(nodeid, [this](CNode* pfrom){
1090-
LockAssertion lock(::cs_main);
1091-
uint64_t nCMPCTBLOCKVersion = 1;
1092-
if (lNodesAnnouncingHeaderAndIDs.size() >= 3) {
1093-
// As per BIP152, we only get 3 of our peers to announce
1094-
// blocks using compact encodings.
1095-
m_connman.ForNode(lNodesAnnouncingHeaderAndIDs.front(), [this, nCMPCTBLOCKVersion](CNode* pnodeStop){
1096-
m_connman.PushMessage(pnodeStop, CNetMsgMaker(pnodeStop->GetCommonVersion()).Make(NetMsgType::SENDCMPCT, /*fAnnounceUsingCMPCTBLOCK=*/false, nCMPCTBLOCKVersion));
1097-
// save BIP152 bandwidth state: we select peer to be low-bandwidth
1098-
pnodeStop->m_bip152_highbandwidth_to = false;
1099-
return true;
1100-
});
1101-
lNodesAnnouncingHeaderAndIDs.pop_front();
1071+
CNodeState *state = State(*it);
1072+
if (state != nullptr && !state->m_is_inbound) ++num_outbound_hb_peers;
1073+
}
1074+
if (nodestate->m_is_inbound) {
1075+
// If we're adding an inbound HB peer, make sure we're not removing
1076+
// our last outbound HB peer in the process.
1077+
if (lNodesAnnouncingHeaderAndIDs.size() >= 3 && num_outbound_hb_peers == 1) {
1078+
CNodeState *remove_node = State(lNodesAnnouncingHeaderAndIDs.front());
1079+
if (remove_node != nullptr && !remove_node->m_is_inbound) {
1080+
// Put the HB outbound peer in the second slot, so that it
1081+
// doesn't get removed.
1082+
std::swap(lNodesAnnouncingHeaderAndIDs.front(), *std::next(lNodesAnnouncingHeaderAndIDs.begin()));
11021083
}
1103-
m_connman.PushMessage(pfrom, CNetMsgMaker(pfrom->GetCommonVersion()).Make(NetMsgType::SENDCMPCT, /*fAnnounceUsingCMPCTBLOCK=*/true, nCMPCTBLOCKVersion));
1104-
// save BIP152 bandwidth state: we select peer to be high-bandwidth
1105-
pfrom->m_bip152_highbandwidth_to = true;
1106-
lNodesAnnouncingHeaderAndIDs.push_back(pfrom->GetId());
1107-
return true;
1108-
});
1084+
}
11091085
}
1086+
m_connman.ForNode(nodeid, [this](CNode* pfrom) EXCLUSIVE_LOCKS_REQUIRED(::cs_main) {
1087+
AssertLockHeld(::cs_main);
1088+
if (lNodesAnnouncingHeaderAndIDs.size() >= 3) {
1089+
// As per BIP152, we only get 3 of our peers to announce
1090+
// blocks using compact encodings.
1091+
m_connman.ForNode(lNodesAnnouncingHeaderAndIDs.front(), [this](CNode* pnodeStop){
1092+
m_connman.PushMessage(pnodeStop, CNetMsgMaker(pnodeStop->GetCommonVersion()).Make(NetMsgType::SENDCMPCT, /*high_bandwidth=*/false, /*version=*/CMPCTBLOCKS_VERSION));
1093+
// save BIP152 bandwidth state: we select peer to be low-bandwidth
1094+
pnodeStop->m_bip152_highbandwidth_to = false;
1095+
return true;
1096+
});
1097+
lNodesAnnouncingHeaderAndIDs.pop_front();
1098+
}
1099+
m_connman.PushMessage(pfrom, CNetMsgMaker(pfrom->GetCommonVersion()).Make(NetMsgType::SENDCMPCT, /*high_bandwidth=*/true, /*version=*/CMPCTBLOCKS_VERSION));
1100+
// save BIP152 bandwidth state: we select peer to be high-bandwidth
1101+
pfrom->m_bip152_highbandwidth_to = true;
1102+
lNodesAnnouncingHeaderAndIDs.push_back(pfrom->GetId());
1103+
return true;
1104+
});
11101105
}
11111106

11121107
bool PeerManagerImpl::TipMayBeStale()
@@ -2024,9 +2019,7 @@ void PeerManagerImpl::NewPoWValidBlock(const CBlockIndex *pindex, const std::sha
20242019
CNodeState &state = *State(pnode->GetId());
20252020
// If the peer has, or we announced to them the previous block already,
20262021
// but we don't think they have this one, go ahead and announce it
2027-
if (state.fPreferHeaderAndIDs &&
2028-
!PeerHasHeader(&state, pindex) && PeerHasHeader(&state, pindex->pprev)) {
2029-
2022+
if (state.m_requested_hb_cmpctblocks && !PeerHasHeader(&state, pindex) && PeerHasHeader(&state, pindex->pprev)) {
20302023
LogPrint(BCLog::NET, "%s sending header-and-ids %s to peer=%d\n", "PeerManager::NewPoWValidBlock",
20312024
hashBlock.ToString(), pnode->GetId());
20322025
m_connman.PushMessage(pnode, msgMaker.Make(NetMsgType::CMPCTBLOCK, *pcmpctblock));
@@ -2757,7 +2750,6 @@ void PeerManagerImpl::SendBlockTransactions(CNode& pfrom, const CBlock& block, c
27572750
}
27582751
resp.txn[i] = block.vtx[req.indexes[i]];
27592752
}
2760-
LOCK(cs_main);
27612753
CNetMsgMaker msgMaker(pfrom.GetCommonVersion());
27622754
m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::BLOCKTXN, resp));
27632755
}
@@ -2904,7 +2896,7 @@ void PeerManagerImpl::ProcessHeadersMessage(CNode& pfrom, const Peer& peer,
29042896
}
29052897
if (vGetData.size() > 0) {
29062898
if (!m_ignore_incoming_txs &&
2907-
nodestate->fSupportsDesiredCmpctVersion &&
2899+
nodestate->m_provides_cmpctblocks &&
29082900
vGetData.size() == 1 &&
29092901
mapBlocksInFlight.size() == 1 &&
29102902
pindexLast->pprev->IsValid(BLOCK_VALID_CHAIN)) {
@@ -3533,14 +3525,12 @@ void PeerManagerImpl::ProcessMessage(
35333525
m_connman.PushMessage(&pfrom, msgMaker.Make((pfrom.nServices & NODE_HEADERS_COMPRESSED) ? NetMsgType::SENDHEADERS2 : NetMsgType::SENDHEADERS));
35343526

35353527
if (pfrom.CanRelay()) {
3536-
// Tell our peer we are willing to provide version-1 cmpctblocks
3528+
// Tell our peer we are willing to provide version 1 cmpctblocks.
35373529
// However, we do not request new block announcements using
35383530
// cmpctblock messages.
35393531
// We send this to non-NODE NETWORK peers as well, because
35403532
// they may wish to request compact blocks from us
3541-
bool fAnnounceUsingCMPCTBLOCK = false;
3542-
uint64_t nCMPCTBLOCKVersion = 1;
3543-
m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::SENDCMPCT, fAnnounceUsingCMPCTBLOCK, nCMPCTBLOCKVersion));
3533+
m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::SENDCMPCT, /*high_bandwidth=*/false, /*version=*/CMPCTBLOCKS_VERSION));
35443534
}
35453535

35463536
if (!fBlocksOnly) {
@@ -3570,18 +3560,19 @@ void PeerManagerImpl::ProcessMessage(
35703560
}
35713561

35723562
if (msg_type == NetMsgType::SENDCMPCT) {
3573-
bool fAnnounceUsingCMPCTBLOCK = false;
3574-
uint64_t nCMPCTBLOCKVersion = 1;
3575-
vRecv >> fAnnounceUsingCMPCTBLOCK >> nCMPCTBLOCKVersion;
3576-
if (nCMPCTBLOCKVersion == 1) {
3577-
LOCK(cs_main);
3578-
State(pfrom.GetId())->fProvidesHeaderAndIDs = true;
3579-
State(pfrom.GetId())->fPreferHeaderAndIDs = fAnnounceUsingCMPCTBLOCK;
3580-
State(pfrom.GetId())->fSupportsDesiredCmpctVersion = true;
3581-
// save whether peer selects us as BIP152 high-bandwidth peer
3582-
// (receiving sendcmpct(1) signals high-bandwidth, sendcmpct(0) low-bandwidth)
3583-
pfrom.m_bip152_highbandwidth_from = fAnnounceUsingCMPCTBLOCK;
3584-
}
3563+
bool sendcmpct_hb{false};
3564+
uint64_t sendcmpct_version{0};
3565+
vRecv >> sendcmpct_hb >> sendcmpct_version;
3566+
3567+
if (sendcmpct_version != CMPCTBLOCKS_VERSION) return;
3568+
3569+
LOCK(cs_main);
3570+
CNodeState *nodestate = State(pfrom.GetId());
3571+
nodestate->m_provides_cmpctblocks = true;
3572+
nodestate->m_requested_hb_cmpctblocks = sendcmpct_hb;
3573+
// save whether peer selects us as BIP152 high-bandwidth peer
3574+
// (receiving sendcmpct(1) signals high-bandwidth, sendcmpct(0) low-bandwidth)
3575+
pfrom.m_bip152_highbandwidth_from = sendcmpct_hb;
35853576
return;
35863577
}
35873578

@@ -3976,9 +3967,7 @@ void PeerManagerImpl::ProcessMessage(
39763967
// expensive disk reads, because it will require the peer to
39773968
// actually receive all the data read from disk over the network.
39783969
LogPrint(BCLog::NET, "Peer %d sent us a getblocktxn for a block > %i deep\n", pfrom.GetId(), MAX_BLOCKTXN_DEPTH);
3979-
CInv inv;
3980-
WITH_LOCK(cs_main, inv.type = MSG_BLOCK);
3981-
inv.hash = req.blockhash;
3970+
CInv inv{MSG_BLOCK, req.blockhash};
39823971
WITH_LOCK(peer->m_getdata_requests_mutex, peer->m_getdata_requests.push_back(inv));
39833972
// The message processing loop will go around again (without pausing) and we'll respond then (without cs_main)
39843973
return;
@@ -5449,7 +5438,7 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
54495438
LOCK(peer->m_block_inv_mutex);
54505439
std::vector<CBlock> vHeaders;
54515440
bool fRevertToInv = ((!state.fPreferHeaders && !state.fPreferHeadersCompressed &&
5452-
(!state.fPreferHeaderAndIDs || peer->m_blocks_for_headers_relay.size() > 1)) ||
5441+
(!state.m_requested_hb_cmpctblocks || peer->m_blocks_for_headers_relay.size() > 1)) ||
54535442
peer->m_blocks_for_headers_relay.size() > MAX_BLOCKS_TO_ANNOUNCE);
54545443
const CBlockIndex *pBestIndex = nullptr; // last header queued for delivery
54555444
ProcessBlockAvailability(pto->GetId()); // ensure pindexBestKnownBlock is up-to-date
@@ -5511,7 +5500,7 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
55115500
}
55125501
}
55135502
if (!fRevertToInv && !vHeaders.empty()) {
5514-
if (vHeaders.size() == 1 && state.fPreferHeaderAndIDs) {
5503+
if (vHeaders.size() == 1 && state.m_requested_hb_cmpctblocks) {
55155504
// We only send up to 1 block as header-and-ids, as otherwise
55165505
// probably means we're doing an initial-ish-sync or they're slow
55175506
LogPrint(BCLog::NET, "%s sending header-and-ids %s to peer=%d\n", __func__,

0 commit comments

Comments
 (0)