LCOV - code coverage report
Current view: top level - src - private_broadcast.cpp (source / functions) Coverage Total Hit
Test: fuzz_coverage.info Lines: 97.8 % 92 90
Test Date: 2026-07-21 06:28:42 Functions: 100.0 % 11 11
Branches: 69.6 % 92 64

             Branch data     Line data    Source code
       1                 :             : // Copyright (c) 2023-present The Bitcoin Core developers
       2                 :             : // Distributed under the MIT software license, see the accompanying
       3                 :             : // file COPYING or https://opensource.org/license/mit/.
       4                 :             : 
       5                 :             : #include <private_broadcast.h>
       6                 :             : 
       7                 :             : #include <util/check.h>
       8                 :             : 
       9                 :             : #include <algorithm>
      10                 :             : 
      11                 :             : 
      12                 :        8582 : PrivateBroadcast::AddResult PrivateBroadcast::Add(const CTransactionRef& tx)
      13                 :             :     EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
      14                 :             : {
      15                 :        8582 :     LOCK(m_mutex);
      16                 :             :     // Re-adding an already-tracked transaction is a no-op regardless of the cap.
      17         [ +  + ]:        8582 :     if (m_transactions.contains(tx)) return AddResult::AlreadyPresent;
      18                 :             : 
      19         [ +  + ]:        5810 :     if (m_transactions.size() >= m_max_transactions) return AddResult::QueueFull;
      20                 :             : 
      21         [ +  - ]:        5039 :     m_transactions.try_emplace(tx);
      22                 :             :     return AddResult::Added;
      23                 :        8582 : }
      24                 :             : 
      25                 :        8314 : std::optional<size_t> PrivateBroadcast::Remove(const CTransactionRef& tx)
      26                 :             :     EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
      27                 :             : {
      28                 :        8314 :     LOCK(m_mutex);
      29                 :        8314 :     const auto handle{m_transactions.extract(tx)};
      30         [ +  + ]:        8314 :     if (handle) {
      31         [ +  - ]:        4157 :         const auto p{DerivePriority(handle.mapped().send_statuses)};
      32                 :        4157 :         return p.num_confirmed;
      33                 :             :     }
      34                 :        4157 :     return std::nullopt;
      35         [ +  - ]:       16628 : }
      36                 :             : 
      37                 :       21331 : std::optional<CTransactionRef> PrivateBroadcast::PickTxForSend(const NodeId& will_send_to_nodeid, const CService& will_send_to_address)
      38                 :             :     EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
      39                 :             : {
      40                 :       21331 :     LOCK(m_mutex);
      41                 :             : 
      42   [ +  -  -  + ]:       21331 :     if (GetSendStatusByNode(will_send_to_nodeid).has_value()) { // nodeid reuse, shouldn't send >1 tx to a given node
      43         [ #  # ]:           0 :         Assume(false);
      44                 :           0 :         return std::nullopt;
      45                 :             :     }
      46                 :             : 
      47                 :       21331 :     const auto it{std::ranges::max_element(
      48         [ +  - ]:       21331 :             m_transactions,
      49                 :       15621 :             [](const auto& a, const auto& b) { return a < b; },
      50                 :       15621 :             [](const auto& el) { return DerivePriority(el.second.send_statuses); })};
      51                 :             : 
      52         [ +  + ]:       21331 :     if (it != m_transactions.end()) {
      53                 :       13056 :         auto& [tx, state]{*it};
      54         [ +  - ]:       13056 :         state.send_statuses.emplace_back(will_send_to_nodeid, will_send_to_address, NodeClock::now());
      55                 :       13056 :         return tx;
      56                 :             :     }
      57                 :             : 
      58                 :        8275 :     return std::nullopt;
      59                 :       21331 : }
      60                 :             : 
      61                 :       41251 : std::optional<CTransactionRef> PrivateBroadcast::GetTxForNode(const NodeId& nodeid)
      62                 :             :     EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
      63                 :             : {
      64                 :       41251 :     LOCK(m_mutex);
      65         [ +  - ]:       41251 :     const auto tx_and_status{GetSendStatusByNode(nodeid)};
      66         [ +  + ]:       41251 :     if (tx_and_status.has_value()) {
      67                 :       18420 :         return tx_and_status.value().tx;
      68                 :             :     }
      69                 :       22831 :     return std::nullopt;
      70                 :       41251 : }
      71                 :             : 
      72                 :        7071 : void PrivateBroadcast::NodeConfirmedReception(const NodeId& nodeid)
      73                 :             :     EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
      74                 :             : {
      75                 :        7071 :     LOCK(m_mutex);
      76         [ +  - ]:        7071 :     const auto tx_and_status{GetSendStatusByNode(nodeid)};
      77         [ +  + ]:        7071 :     if (tx_and_status.has_value()) {
      78   [ +  +  +  - ]:        9796 :         tx_and_status.value().send_status.confirmed = NodeClock::now();
      79                 :             :     }
      80                 :        7071 : }
      81                 :             : 
      82                 :       23561 : bool PrivateBroadcast::DidNodeConfirmReception(const NodeId& nodeid)
      83                 :             :     EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
      84                 :             : {
      85                 :       23561 :     LOCK(m_mutex);
      86         [ +  - ]:       23561 :     const auto tx_and_status{GetSendStatusByNode(nodeid)};
      87         [ +  + ]:       23561 :     if (tx_and_status.has_value()) {
      88                 :        1281 :         return tx_and_status.value().send_status.confirmed.has_value();
      89                 :             :     }
      90                 :             :     return false;
      91                 :       23561 : }
      92                 :             : 
      93                 :        2020 : bool PrivateBroadcast::HavePendingTransactions()
      94                 :             :     EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
      95                 :             : {
      96                 :        2020 :     LOCK(m_mutex);
      97         [ +  - ]:        2020 :     return !m_transactions.empty();
      98                 :        2020 : }
      99                 :             : 
     100                 :        7830 : std::vector<CTransactionRef> PrivateBroadcast::GetStale() const
     101                 :             :     EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
     102                 :             : {
     103                 :        7830 :     LOCK(m_mutex);
     104                 :        7830 :     const auto now{NodeClock::now()};
     105                 :        7830 :     std::vector<CTransactionRef> stale;
     106   [ +  +  +  - ]:       29282 :     for (const auto& [tx, state] : m_transactions) {
     107         [ +  - ]:       21452 :         const Priority p{DerivePriority(state.send_statuses)};
     108         [ +  + ]:       21452 :         if (p.num_confirmed == 0) {
     109   [ +  +  +  - ]:       18493 :             if (state.time_added < now - INITIAL_STALE_DURATION) stale.push_back(tx);
     110                 :             :         } else {
     111   [ +  +  +  - ]:        2959 :             if (p.last_confirmed < now - STALE_DURATION) stale.push_back(tx);
     112                 :             :         }
     113                 :             :     }
     114         [ +  - ]:        7830 :     return stale;
     115                 :        7830 : }
     116                 :             : 
     117                 :        1700 : std::vector<PrivateBroadcast::TxBroadcastInfo> PrivateBroadcast::GetBroadcastInfo() const
     118                 :             :     EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
     119                 :             : {
     120                 :        1700 :     LOCK(m_mutex);
     121                 :        1700 :     std::vector<TxBroadcastInfo> entries;
     122         [ +  - ]:        1700 :     entries.reserve(m_transactions.size());
     123                 :             : 
     124   [ +  +  -  + ]:        5193 :     for (const auto& [tx, state] : m_transactions) {
     125                 :        3493 :         std::vector<PeerSendInfo> peers;
     126   [ +  -  -  + ]:        3493 :         peers.reserve(state.send_statuses.size());
     127         [ +  + ]:       34263 :         for (const auto& status : state.send_statuses) {
     128         [ +  - ]:       61540 :             peers.emplace_back(PeerSendInfo{.address = status.address, .sent = status.picked, .received = status.confirmed});
     129                 :             :         }
     130   [ +  -  +  - ]:        6986 :         entries.emplace_back(TxBroadcastInfo{.tx = tx, .time_added = state.time_added, .peers = std::move(peers)});
     131                 :        3493 :     }
     132                 :             : 
     133         [ +  - ]:        1700 :     return entries;
     134                 :        1700 : }
     135                 :             : 
     136                 :       56851 : PrivateBroadcast::Priority PrivateBroadcast::DerivePriority(const std::vector<SendStatus>& sent_to)
     137                 :             : {
     138                 :       56851 :     Priority p;
     139         [ -  + ]:       56851 :     p.num_picked = sent_to.size();
     140         [ +  + ]:      544658 :     for (const auto& send_status : sent_to) {
     141                 :      487807 :         p.last_picked = std::max(p.last_picked, send_status.picked);
     142         [ +  + ]:      487807 :         if (send_status.confirmed.has_value()) {
     143                 :       57418 :             ++p.num_confirmed;
     144                 :       57418 :             p.last_confirmed = std::max(p.last_confirmed, send_status.confirmed.value());
     145                 :             :         }
     146                 :             :     }
     147                 :       56851 :     return p;
     148                 :             : }
     149                 :             : 
     150                 :       93214 : std::optional<PrivateBroadcast::TxAndSendStatusForNode> PrivateBroadcast::GetSendStatusByNode(const NodeId& nodeid)
     151                 :             :     EXCLUSIVE_LOCKS_REQUIRED(m_mutex)
     152                 :             : {
     153                 :       93214 :     AssertLockHeld(m_mutex);
     154         [ +  + ]:      240604 :     for (auto& [tx, state] : m_transactions) {
     155         [ +  + ]:     8356766 :         for (auto& send_status : state.send_statuses) {
     156         [ +  + ]:     8209376 :             if (send_status.nodeid == nodeid) {
     157                 :       22426 :                 return TxAndSendStatusForNode{.tx = tx, .send_status = send_status};
     158                 :             :             }
     159                 :             :         }
     160                 :             :     }
     161                 :       70788 :     return std::nullopt;
     162                 :             : }
        

Generated by: LCOV version 2.0-1