During IBD it is possible that a malicious peer sends unsolicited compact-block messages to reset its m_stalling_since
state. This requires two or more malicious peer connections and can happen with the following steps:
- Malicious peer A sends a headers message that contains height
h+1
. The node requests blockh+1
from peer A. - Malicious peer B sends a headers message that contains heights
{h+1, h+2, ..., h+1024}
. The node requestsMAX_BLOCKS_IN_TRANSIT_PER_PEER
blocks from B. Peer B does not need to reply with any of these blocks. - Honest peer C sends a headers message that contains heights
{h+1, h+2, ..., h+1024}
. The node will request blocks continuing from where it last requested from peer B. - Peer A sends a compact-block for
h+2
with non-empty but bogusshorttxids
.- The target node will attempt to process the compact-block since it is within two blocks of
h
. TheCanDirectFetch
logic is also skipped here as the block is already in-flight with peer B. - Since the
shorttxids
field is bogus, execution hits this branch and callsRemoveBlockRequest
. This will resetm_stalling_since
even though peer A hasn’t actually provided a block. - This can be repeated by peer A to reset
m_stalling_since
before the timeout triggers. The peer should eventually be disconnected (unless it gives the block) after the larger block download timeout of ~10minutes+ depending on the number of downloading peers which could be numerous in IBD.
- The target node will attempt to process the compact-block since it is within two blocks of
I think this scenario is a bit contrived since it requires two (or more?) malicious peers whom are requested subsequent blocks, but it illustrates that:
- resetting
m_stalling_since
in this case is a bug - compact-blocks can be received unsolicited even in IBD. The block must be currently in-flight and must be one of the two blocks above the target node’s tip.
Here is a branch that demonstrates this with a functional test: https://github.com/Crypt-iQ/bitcoin/tree/ibd_cmpct