-
Notifications
You must be signed in to change notification settings - Fork 37.7k
p2p: Drop unsolicited CMPCTBLOCK from non-HB peer #32606
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
p2p: Drop unsolicited CMPCTBLOCK from non-HB peer #32606
Conversation
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. Code Coverage & BenchmarksFor details see: https://corecheck.dev/bitcoin/bitcoin/pulls/32606. ReviewsSee the guideline for information on the review process.
If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update. ConflictsReviewers, this pull request conflicts with the following ones:
If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first. |
Concept ACK. BIP152 is marked as Final but perhaps could be clarified on this point. |
Concept ACK. LLM linter's punctuation advice seems right to me. :) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Concept ACK
In the commit message:
"making it only possible for peers selected as high bandwidth to discover a node's
mempool" is a bit too strong, since mempools are discoverable, just not transactions that were added to them after the last inv to the peer.
Processing unsolicited CMPCTBLOCK's from a peer that has not been marked high bandwidth is not well-specified behavior in BIP-0152, in fact the BIP seems to imply that it is not permitted: "[...] method is not useful for compact blocks because `cmpctblock` blocks can be sent unsolicitedly in high-bandwidth mode" See https://github.com/bitcoin/bips/blob/master/bip-0152.mediawiki#separate-version-for-segregated-witness This partially mitigates a mempool leak described in [bitcoin#28272](bitcoin#28272), but that particular issue will persist for peers that have been selected as high bandwidth. This also mitigates potential DoS / bandwidth-wasting / abusive behavior that is discussed in the comments of bitcoin#28272.
28086e7
to
1fc95e0
Compare
Rebased to address @ajtowns and @mzumsande feedback. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK 1fc95e0
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My main concern here is if this disables a FIBRE future; FIBRE apparently used unsolicited compact blocks (see: #28272 (comment)). If we are not concerned about that, then Concept ACK.
@@ -4435,6 +4435,11 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type, | |||
range_flight.first++; | |||
} | |||
|
|||
if (!requested_block_from_this_peer && !pfrom.m_bip152_highbandwidth_to) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this check is still permissive enough such that a NetMsgType::CMPCTBLOCK
message can be sent to a node in -blocksonly mode and still get processed. This would require the -blocksonly node to request the block from the peer.
Maybe something like this instead?
+ if ((!requested_block_from_this_peer && !pfrom.m_bip152_highbandwidth_to) || m_opts.ignore_incoming_txs) {
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed - even if we are in blocks-only mode we might have requested_block_from_this_peer
, but we won't be able to reconstruct a block from our barren mempool unless the block is empty (or only contains transactions we originated).
One could special-case it to account for allowing empty block reconstruction on blocks-only nodes but it feels like dead weight in the code.
In case C of the diagram at https://github.com/bitcoin/bips/blob/master/bip-0152.mediawiki#intended-protocol-flow, we might have explicitly asked for a compact block from a low bandwidth peer. But we appear to not be doing so in blocks-only mode, which makes sense:
bitcoin/src/net_processing.cpp
Lines 2780 to 2788 in 6e1a49b
if (!m_opts.ignore_incoming_txs && | |
nodestate->m_provides_cmpctblocks && | |
vGetData.size() == 1 && | |
mapBlocksInFlight.size() == 1 && | |
last_header.pprev->IsValid(BLOCK_VALID_CHAIN)) { | |
// In any case, we want to download using a compact block, not a regular one | |
vGetData[0] = CInv(MSG_CMPCT_BLOCK, vGetData[0].hash); | |
} | |
MakeAndPushMessage(pfrom, NetMsgType::GETDATA, vGetData); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One could special-case it to account for allowing empty block reconstruction on blocks-only nodes but it feels like dead weight in the code.
Yeah, I feel like the complexity isn't worth it.
|
Yup I think this means the defense is ineffective.
This is interesting, but in this case I would still consider the compact block as "requested" as the peer has updated its internal state to request the compact block. The fibre patchset is being revived and while I haven't tested it so I don't know if it breaks fibre, I would rather be cautious and only include the defense for -blocksonly nodes. |
The fact that you're enabling FIBRE on a connection can just be taken as implicitly soliciting compact blocks on that connection, so I don't think this is a problem. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Concept ACK 1fc95e0
@@ -4435,6 +4435,11 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type, | |||
range_flight.first++; | |||
} | |||
|
|||
if (!requested_block_from_this_peer && !pfrom.m_bip152_highbandwidth_to) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed - even if we are in blocks-only mode we might have requested_block_from_this_peer
, but we won't be able to reconstruct a block from our barren mempool unless the block is empty (or only contains transactions we originated).
One could special-case it to account for allowing empty block reconstruction on blocks-only nodes but it feels like dead weight in the code.
In case C of the diagram at https://github.com/bitcoin/bips/blob/master/bip-0152.mediawiki#intended-protocol-flow, we might have explicitly asked for a compact block from a low bandwidth peer. But we appear to not be doing so in blocks-only mode, which makes sense:
bitcoin/src/net_processing.cpp
Lines 2780 to 2788 in 6e1a49b
if (!m_opts.ignore_incoming_txs && | |
nodestate->m_provides_cmpctblocks && | |
vGetData.size() == 1 && | |
mapBlocksInFlight.size() == 1 && | |
last_header.pprev->IsValid(BLOCK_VALID_CHAIN)) { | |
// In any case, we want to download using a compact block, not a regular one | |
vGetData[0] = CInv(MSG_CMPCT_BLOCK, vGetData[0].hash); | |
} | |
MakeAndPushMessage(pfrom, NetMsgType::GETDATA, vGetData); |
@@ -4435,6 +4435,11 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type, | |||
range_flight.first++; | |||
} | |||
|
|||
if (!requested_block_from_this_peer && !pfrom.m_bip152_highbandwidth_to) { | |||
LogDebug(BCLog::NET, "Peer %d, not marked as high-bandwidth, sent us an unsolicited compact block!\n", pfrom.GetId()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might as well include the IP of this suspicious peer (and drop newline):
LogDebug(BCLog::NET, "Peer %d, not marked as high-bandwidth, sent us an unsolicited compact block!\n", pfrom.GetId()); | |
LogDebug(BCLog::NET, "Peer %d%s, not marked as high-bandwidth, sent us an unsolicited compact block!", pfrom.GetId(), pfrom.LogIP(fLogIPs)); |
Right, my earlier comment was wrong. I think that dropping unsolicited cmpctblock in the non -blocksonly case is kind of ineffective as pointed out by others. But I also don't have a strong opinion about it given that it doesn't affect FIBRE. |
self.generate(self.nodes[0], COINBASE_MATURITY + 1) | ||
block = self.build_block_on_tip(self.nodes[0]) | ||
|
||
self.segwit_node.send_header_for_blocks([block]) | ||
self.segwit_node.wait_for_getdata([block.sha256], timeout=30) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AttributeError: 'CBlock' object has no attribute 'sha256'
🐙 This pull request conflicts with the target branch and needs rebase. |
Processing unsolicited
CMPCTBLOCK
's from a peer that has not been marked high bandwidth is not well-specified behavior in BIP-0152, in fact the BIP seems to imply that it is not permitted:See https://github.com/bitcoin/bips/blob/master/bip-0152.mediawiki#separate-version-for-segregated-witness
This partially mitigates a mempool leak described in #28272, making it only possible for peers selected as high bandwidth to discover a node's mempool.