Before Bitcoin Core v25.0, the per-peer m_tx_inventory_to_send
sets could grow
too large to a point where sorting these sets when constructing inventory
messages would affect the node’s ability to communicate with its peers. Network
conditions in early May 2023 triggered this DoS and affected block and transaction
propagation.
This issue is considered Medium severity.
Details
As part of transaction relay, Bitcoin Core maintains a per-peer
m_tx_inventory_to_send
set with transactions that should be announced to the
peer. When constructing an inventory message for a peer, the set is sorted by
transaction dependencies and feerate to prioritize high-feerate transactions and
to avoid leaking the order the node learned about the transactions. Before
Bitcoin Core v25.0, when constructing inventory messages, relevant (still in
mempool, not yet announced to us by the peer, above the fee filter) transactions
were being drained at a rate of 7 transactions per second.
In early May 2023, increased network activity caused the sets to grow faster than they were being drained resulting in significant time spent sorting the sets in the P2P communication thread. Additionally, peers that only listen for transaction announcements but never announce any themselves (commonly referred to as “spy nodes”), amplified this by having huge sets (with transactions they already know about) that take a long time to sort. It was observed that sorting took up nearly the complete time spent in the P2P communication thread, which significantly affected block and transaction propagation as well as keeping connection with peers alive.
This was fixed in #27610 by 1) earlier removing transactions that aren’t in the mempool anymore and 2) by dynamically increasing the set drainage rate depending on the set size.
Attribution
Credit goes to Anthony Towns for working on a fix and to b10c for initially reporting and narrowing the problem down to the slow inv-to-send sorting.
Timeline
- 2023-05-02 - Problem first observed and reported
- 2023-05-11 - Fix is merged (#27610)
- 2023-05-25 - v25.0 is released
- 2024-10-09 - Public disclosure