LCOV - code coverage report
Current view: top level - src - private_broadcast.cpp (source / functions) Coverage Total Hit
Test: fuzz_coverage.info Lines: 23.0 % 87 20
Test Date: 2026-03-01 04:36:14 Functions: 36.4 % 11 4
Branches: 7.7 % 78 6

             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                 :             : #include <util/check.h>
       7                 :             : 
       8                 :             : #include <algorithm>
       9                 :             : 
      10                 :             : /// If a transaction is not received back from the network for this duration
      11                 :             : /// after it is broadcast, then we consider it stale / for rebroadcasting.
      12                 :             : static constexpr auto STALE_DURATION{1min};
      13                 :             : 
      14                 :           0 : bool PrivateBroadcast::Add(const CTransactionRef& tx)
      15                 :             :     EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
      16                 :             : {
      17                 :           0 :     LOCK(m_mutex);
      18         [ #  # ]:           0 :     const bool inserted{m_transactions.try_emplace(tx).second};
      19         [ #  # ]:           0 :     return inserted;
      20                 :           0 : }
      21                 :             : 
      22                 :           0 : std::optional<size_t> PrivateBroadcast::Remove(const CTransactionRef& tx)
      23                 :             :     EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
      24                 :             : {
      25                 :           0 :     LOCK(m_mutex);
      26                 :           0 :     const auto handle{m_transactions.extract(tx)};
      27         [ #  # ]:           0 :     if (handle) {
      28         [ #  # ]:           0 :         const auto p{DerivePriority(handle.mapped())};
      29                 :           0 :         return p.num_confirmed;
      30                 :             :     }
      31                 :           0 :     return std::nullopt;
      32         [ #  # ]:           0 : }
      33                 :             : 
      34                 :          40 : std::optional<CTransactionRef> PrivateBroadcast::PickTxForSend(const NodeId& will_send_to_nodeid, const CService& will_send_to_address)
      35                 :             :     EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
      36                 :             : {
      37                 :          40 :     LOCK(m_mutex);
      38                 :             : 
      39                 :          40 :     const auto it{std::ranges::max_element(
      40         [ +  - ]:          40 :             m_transactions,
      41                 :           0 :             [](const auto& a, const auto& b) { return a < b; },
      42                 :           0 :             [](const auto& el) { return DerivePriority(el.second); })};
      43                 :             : 
      44         [ +  - ]:          40 :     if (it != m_transactions.end()) {
      45                 :           0 :         auto& [tx, sent_to]{*it};
      46         [ #  # ]:           0 :         sent_to.emplace_back(will_send_to_nodeid, will_send_to_address, NodeClock::now());
      47                 :           0 :         return tx;
      48                 :             :     }
      49                 :             : 
      50                 :          40 :     return std::nullopt;
      51                 :          40 : }
      52                 :             : 
      53                 :           0 : std::optional<CTransactionRef> PrivateBroadcast::GetTxForNode(const NodeId& nodeid)
      54                 :             :     EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
      55                 :             : {
      56                 :           0 :     LOCK(m_mutex);
      57         [ #  # ]:           0 :     const auto tx_and_status{GetSendStatusByNode(nodeid)};
      58         [ #  # ]:           0 :     if (tx_and_status.has_value()) {
      59                 :           0 :         return tx_and_status.value().tx;
      60                 :             :     }
      61                 :           0 :     return std::nullopt;
      62                 :           0 : }
      63                 :             : 
      64                 :           0 : void PrivateBroadcast::NodeConfirmedReception(const NodeId& nodeid)
      65                 :             :     EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
      66                 :             : {
      67                 :           0 :     LOCK(m_mutex);
      68         [ #  # ]:           0 :     const auto tx_and_status{GetSendStatusByNode(nodeid)};
      69         [ #  # ]:           0 :     if (tx_and_status.has_value()) {
      70   [ #  #  #  # ]:           0 :         tx_and_status.value().send_status.confirmed = NodeClock::now();
      71                 :             :     }
      72                 :           0 : }
      73                 :             : 
      74                 :        1472 : bool PrivateBroadcast::DidNodeConfirmReception(const NodeId& nodeid)
      75                 :             :     EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
      76                 :             : {
      77                 :        1472 :     LOCK(m_mutex);
      78         [ +  - ]:        1472 :     const auto tx_and_status{GetSendStatusByNode(nodeid)};
      79         [ -  + ]:        1472 :     if (tx_and_status.has_value()) {
      80                 :           0 :         return tx_and_status.value().send_status.confirmed.has_value();
      81                 :             :     }
      82                 :             :     return false;
      83                 :        1472 : }
      84                 :             : 
      85                 :        1472 : bool PrivateBroadcast::HavePendingTransactions()
      86                 :             :     EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
      87                 :             : {
      88                 :        1472 :     LOCK(m_mutex);
      89         [ +  - ]:        1472 :     return !m_transactions.empty();
      90                 :        1472 : }
      91                 :             : 
      92                 :           0 : std::vector<CTransactionRef> PrivateBroadcast::GetStale() const
      93                 :             :     EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
      94                 :             : {
      95                 :           0 :     LOCK(m_mutex);
      96                 :           0 :     const auto stale_time{NodeClock::now() - STALE_DURATION};
      97                 :           0 :     std::vector<CTransactionRef> stale;
      98   [ #  #  #  # ]:           0 :     for (const auto& [tx, send_status] : m_transactions) {
      99         [ #  # ]:           0 :         const Priority p{DerivePriority(send_status)};
     100         [ #  # ]:           0 :         if (p.last_confirmed < stale_time) {
     101         [ #  # ]:           0 :             stale.push_back(tx);
     102                 :             :         }
     103                 :             :     }
     104         [ #  # ]:           0 :     return stale;
     105                 :           0 : }
     106                 :             : 
     107                 :           0 : std::vector<PrivateBroadcast::TxBroadcastInfo> PrivateBroadcast::GetBroadcastInfo() const
     108                 :             :     EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
     109                 :             : {
     110                 :           0 :     LOCK(m_mutex);
     111                 :           0 :     std::vector<TxBroadcastInfo> entries;
     112         [ #  # ]:           0 :     entries.reserve(m_transactions.size());
     113                 :             : 
     114   [ #  #  #  # ]:           0 :     for (const auto& [tx, sent_to] : m_transactions) {
     115                 :           0 :         std::vector<PeerSendInfo> peers;
     116   [ #  #  #  # ]:           0 :         peers.reserve(sent_to.size());
     117         [ #  # ]:           0 :         for (const auto& status : sent_to) {
     118         [ #  # ]:           0 :             peers.emplace_back(PeerSendInfo{.address = status.address, .sent = status.picked, .received = status.confirmed});
     119                 :             :         }
     120   [ #  #  #  # ]:           0 :         entries.emplace_back(TxBroadcastInfo{.tx = tx, .peers = std::move(peers)});
     121                 :           0 :     }
     122                 :             : 
     123         [ #  # ]:           0 :     return entries;
     124                 :           0 : }
     125                 :             : 
     126                 :           0 : PrivateBroadcast::Priority PrivateBroadcast::DerivePriority(const std::vector<SendStatus>& sent_to)
     127                 :             : {
     128                 :           0 :     Priority p;
     129         [ #  # ]:           0 :     p.num_picked = sent_to.size();
     130         [ #  # ]:           0 :     for (const auto& send_status : sent_to) {
     131                 :           0 :         p.last_picked = std::max(p.last_picked, send_status.picked);
     132         [ #  # ]:           0 :         if (send_status.confirmed.has_value()) {
     133                 :           0 :             ++p.num_confirmed;
     134                 :           0 :             p.last_confirmed = std::max(p.last_confirmed, send_status.confirmed.value());
     135                 :             :         }
     136                 :             :     }
     137                 :           0 :     return p;
     138                 :             : }
     139                 :             : 
     140                 :        1472 : std::optional<PrivateBroadcast::TxAndSendStatusForNode> PrivateBroadcast::GetSendStatusByNode(const NodeId& nodeid)
     141                 :             :     EXCLUSIVE_LOCKS_REQUIRED(m_mutex)
     142                 :             : {
     143                 :        1472 :     AssertLockHeld(m_mutex);
     144         [ +  - ]:        1472 :     for (auto& [tx, sent_to] : m_transactions) {
     145         [ #  # ]:           0 :         for (auto& send_status : sent_to) {
     146         [ #  # ]:           0 :             if (send_status.nodeid == nodeid) {
     147                 :           0 :                 return TxAndSendStatusForNode{.tx = tx, .send_status = send_status};
     148                 :             :             }
     149                 :             :         }
     150                 :             :     }
     151                 :        1472 :     return std::nullopt;
     152                 :             : }
        

Generated by: LCOV version 2.0-1