LCOV - code coverage report
Current view: top level - src - private_broadcast.h (source / functions) Coverage Total Hit
Test: total_coverage.info Lines: 100.0 % 9 9
Test Date: 2026-01-13 05:19:40 Functions: 100.0 % 1 1
Branches: 66.7 % 6 4

             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                 :             : #ifndef BITCOIN_PRIVATE_BROADCAST_H
       6                 :             : #define BITCOIN_PRIVATE_BROADCAST_H
       7                 :             : 
       8                 :             : #include <net.h>
       9                 :             : #include <primitives/transaction.h>
      10                 :             : #include <primitives/transaction_identifier.h>
      11                 :             : #include <sync.h>
      12                 :             : #include <threadsafety.h>
      13                 :             : #include <util/time.h>
      14                 :             : 
      15                 :             : #include <optional>
      16                 :             : #include <tuple>
      17                 :             : #include <unordered_map>
      18                 :             : #include <vector>
      19                 :             : 
      20                 :             : /**
      21                 :             :  * Store a list of transactions to be broadcast privately. Supports the following operations:
      22                 :             :  * - Add a new transaction
      23                 :             :  * - Remove a transaction
      24                 :             :  * - Pick a transaction for sending to one recipient
      25                 :             :  * - Query which transaction has been picked for sending to a given recipient node
      26                 :             :  * - Mark that a given recipient node has confirmed receipt of a transaction
      27                 :             :  * - Query whether a given recipient node has confirmed reception
      28                 :             :  * - Query whether any transactions that need sending are currently on the list
      29                 :             :  */
      30         [ +  + ]:        1222 : class PrivateBroadcast
      31                 :             : {
      32                 :             : public:
      33                 :             :     /**
      34                 :             :      * Add a transaction to the storage.
      35                 :             :      * @param[in] tx The transaction to add.
      36                 :             :      * @retval true The transaction was added.
      37                 :             :      * @retval false The transaction was already present.
      38                 :             :      */
      39                 :             :     bool Add(const CTransactionRef& tx)
      40                 :             :         EXCLUSIVE_LOCKS_REQUIRED(!m_mutex);
      41                 :             : 
      42                 :             :     /**
      43                 :             :      * Forget a transaction.
      44                 :             :      * @param[in] tx Transaction to forget.
      45                 :             :      * @retval !nullopt The number of times the transaction was sent and confirmed
      46                 :             :      * by the recipient (if the transaction existed and was removed).
      47                 :             :      * @retval nullopt The transaction was not in the storage.
      48                 :             :      */
      49                 :             :     std::optional<size_t> Remove(const CTransactionRef& tx)
      50                 :             :         EXCLUSIVE_LOCKS_REQUIRED(!m_mutex);
      51                 :             : 
      52                 :             :     /**
      53                 :             :      * Pick the transaction with the fewest send attempts, and confirmations,
      54                 :             :      * and oldest send/confirm times.
      55                 :             :      * @param[in] will_send_to_nodeid Will remember that the returned transaction
      56                 :             :      * was picked for sending to this node.
      57                 :             :      * @return Most urgent transaction or nullopt if there are no transactions.
      58                 :             :      */
      59                 :             :     std::optional<CTransactionRef> PickTxForSend(const NodeId& will_send_to_nodeid)
      60                 :             :         EXCLUSIVE_LOCKS_REQUIRED(!m_mutex);
      61                 :             : 
      62                 :             :     /**
      63                 :             :      * Get the transaction that was picked for sending to a given node by PickTxForSend().
      64                 :             :      * @param[in] nodeid Node to which a transaction is being (or was) sent.
      65                 :             :      * @return Transaction or nullopt if the nodeid is unknown.
      66                 :             :      */
      67                 :             :     std::optional<CTransactionRef> GetTxForNode(const NodeId& nodeid)
      68                 :             :         EXCLUSIVE_LOCKS_REQUIRED(!m_mutex);
      69                 :             : 
      70                 :             :     /**
      71                 :             :      * Mark that the node has confirmed reception of the transaction we sent it by
      72                 :             :      * responding with `PONG` to our `PING` message.
      73                 :             :      * @param[in] nodeid Node that we sent a transaction to.
      74                 :             :      */
      75                 :             :     void NodeConfirmedReception(const NodeId& nodeid)
      76                 :             :         EXCLUSIVE_LOCKS_REQUIRED(!m_mutex);
      77                 :             : 
      78                 :             :     /**
      79                 :             :      * Check if the node has confirmed reception of the transaction.
      80                 :             :      * @retval true Node has confirmed, `NodeConfirmedReception()` has been called.
      81                 :             :      * @retval false Node has not confirmed, `NodeConfirmedReception()` has not been called.
      82                 :             :      */
      83                 :             :     bool DidNodeConfirmReception(const NodeId& nodeid)
      84                 :             :         EXCLUSIVE_LOCKS_REQUIRED(!m_mutex);
      85                 :             : 
      86                 :             :     /**
      87                 :             :      * Check if there are transactions that need to be broadcast.
      88                 :             :      */
      89                 :             :     bool HavePendingTransactions()
      90                 :             :         EXCLUSIVE_LOCKS_REQUIRED(!m_mutex);
      91                 :             : 
      92                 :             :     /**
      93                 :             :      * Get the transactions that have not been broadcast recently.
      94                 :             :      */
      95                 :             :     std::vector<CTransactionRef> GetStale() const
      96                 :             :         EXCLUSIVE_LOCKS_REQUIRED(!m_mutex);
      97                 :             : 
      98                 :             : private:
      99                 :             :     /// Status of a transaction sent to a given node.
     100                 :             :     struct SendStatus {
     101                 :             :         const NodeId nodeid; /// Node to which the transaction will be sent (or was sent).
     102                 :             :         const NodeClock::time_point picked; ///< When was the transaction picked for sending to the node.
     103                 :             :         std::optional<NodeClock::time_point> confirmed; ///< When was the transaction reception confirmed by the node (by PONG).
     104                 :             : 
     105                 :          12 :         SendStatus(const NodeId& nodeid, const NodeClock::time_point& picked) : nodeid{nodeid}, picked{picked} {}
     106                 :             :     };
     107                 :             : 
     108                 :             :     /// Cumulative stats from all the send attempts for a transaction. Used to prioritize transactions.
     109                 :             :     struct Priority {
     110                 :             :         size_t num_picked{0}; ///< Number of times the transaction was picked for sending.
     111                 :             :         NodeClock::time_point last_picked{}; ///< The most recent time when the transaction was picked for sending.
     112                 :             :         size_t num_confirmed{0}; ///< Number of nodes that have confirmed reception of a transaction (by PONG).
     113                 :             :         NodeClock::time_point last_confirmed{}; ///< The most recent time when the transaction was confirmed.
     114                 :             : 
     115                 :           5 :         auto operator<=>(const Priority& other) const
     116                 :             :         {
     117                 :             :             // Invert `other` and `this` in the comparison because smaller num_picked, num_confirmed or
     118                 :             :             // earlier times mean greater priority. In other words, if this.num_picked < other.num_picked
     119                 :             :             // then this > other.
     120                 :           5 :             return std::tie(other.num_picked, other.num_confirmed, other.last_picked, other.last_confirmed) <=>
     121                 :           5 :                    std::tie(num_picked, num_confirmed, last_picked, last_confirmed);
     122                 :             :         }
     123                 :             :     };
     124                 :             : 
     125                 :             :     /// A pair of a transaction and a sent status for a given node. Convenience return type of GetSendStatusByNode().
     126                 :             :     struct TxAndSendStatusForNode {
     127                 :             :         const CTransactionRef& tx;
     128                 :             :         SendStatus& send_status;
     129                 :             :     };
     130                 :             : 
     131                 :             :     // No need for salted hasher because we are going to store just a bunch of locally originating transactions.
     132                 :             : 
     133                 :             :     struct CTransactionRefHash {
     134                 :       16138 :         size_t operator()(const CTransactionRef& tx) const
     135                 :             :         {
     136         [ +  + ]:       16138 :             return static_cast<size_t>(tx->GetWitnessHash().ToUint256().GetUint64(0));
     137                 :             :         }
     138                 :             :     };
     139                 :             : 
     140                 :             :     struct CTransactionRefComp {
     141                 :           6 :         bool operator()(const CTransactionRef& a, const CTransactionRef& b) const
     142                 :             :         {
     143         [ -  - ]:           6 :             return a->GetWitnessHash() == b->GetWitnessHash(); // If wtxid equals, then txid also equals.
     144                 :             :         }
     145                 :             :     };
     146                 :             : 
     147                 :             :     /**
     148                 :             :      * Derive the sending priority of a transaction.
     149                 :             :      * @param[in] sent_to List of nodes that the transaction has been sent to.
     150                 :             :      */
     151                 :             :     static Priority DerivePriority(const std::vector<SendStatus>& sent_to);
     152                 :             : 
     153                 :             :     /**
     154                 :             :      * Find which transaction we sent to a given node (marked by PickTxForSend()).
     155                 :             :      * @return That transaction together with the send status or nullopt if we did not
     156                 :             :      * send any transaction to the given node.
     157                 :             :      */
     158                 :             :     std::optional<TxAndSendStatusForNode> GetSendStatusByNode(const NodeId& nodeid)
     159                 :             :         EXCLUSIVE_LOCKS_REQUIRED(m_mutex);
     160                 :             : 
     161                 :             :     mutable Mutex m_mutex;
     162                 :             :     std::unordered_map<CTransactionRef, std::vector<SendStatus>, CTransactionRefHash, CTransactionRefComp>
     163                 :             :         m_transactions GUARDED_BY(m_mutex);
     164                 :             : };
     165                 :             : 
     166                 :             : #endif // BITCOIN_PRIVATE_BROADCAST_H
        

Generated by: LCOV version 2.0-1