Bitcoin Core 31.99.0
P2P Digital Currency
private_broadcast.h
Go to the documentation of this file.
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>
11#include <sync.h>
12#include <util/time.h>
13
14#include <optional>
15#include <tuple>
16#include <unordered_map>
17#include <vector>
18
30{
31public:
32
35 static constexpr auto INITIAL_STALE_DURATION{5min};
36
39 static constexpr auto STALE_DURATION{1min};
40
43 static constexpr size_t MAX_TRANSACTIONS{10'000};
44
47 explicit PrivateBroadcast(size_t max_transactions = MAX_TRANSACTIONS)
48 : m_max_transactions{max_transactions} {}
49
50 struct PeerSendInfo {
53 std::optional<NodeClock::time_point> received;
54 };
55
59 std::vector<PeerSendInfo> peers;
60 };
61
63 enum class AddResult {
65 Added,
67 AlreadyPresent,
69 QueueFull,
70 };
71
78 [[nodiscard]] AddResult Add(const CTransactionRef& tx)
80
88 std::optional<size_t> Remove(const CTransactionRef& tx)
90
102 std::optional<CTransactionRef> PickTxForSend(const NodeId& will_send_to_nodeid, const CService& will_send_to_address)
104
110 std::optional<CTransactionRef> GetTxForNode(const NodeId& nodeid)
112
118 void NodeConfirmedReception(const NodeId& nodeid)
120
126 bool DidNodeConfirmReception(const NodeId& nodeid)
128
134
138 std::vector<CTransactionRef> GetStale() const
140
144 std::vector<TxBroadcastInfo> GetBroadcastInfo() const
146
147private:
149 struct SendStatus {
157 std::optional<NodeClock::time_point> confirmed;
158
159 SendStatus(const NodeId& nodeid, const CService& address, const NodeClock::time_point& picked) : nodeid{nodeid}, address{address}, picked{picked} {}
160 };
161
163 struct Priority {
164 size_t num_picked{0};
166 size_t num_confirmed{0};
168
169 auto operator<=>(const Priority& other) const
170 {
171 // Invert `other` and `this` in the comparison because smaller num_picked, num_confirmed or
172 // earlier times mean greater priority. In other words, if this.num_picked < other.num_picked
173 // then this > other.
174 return std::tie(other.num_picked, other.num_confirmed, other.last_picked, other.last_confirmed) <=>
176 }
177 };
178
183 };
184
185 // No need for salted hasher because we are going to store just a bunch of locally originating transactions.
186
188 size_t operator()(const CTransactionRef& tx) const
189 {
190 return static_cast<size_t>(tx->GetWitnessHash().ToUint256().GetUint64(0));
191 }
192 };
193
195 bool operator()(const CTransactionRef& a, const CTransactionRef& b) const
196 {
197 return a->GetWitnessHash() == b->GetWitnessHash(); // If wtxid equals, then txid also equals.
198 }
199 };
200
205 static Priority DerivePriority(const std::vector<SendStatus>& sent_to);
206
212 std::optional<TxAndSendStatusForNode> GetSendStatusByNode(const NodeId& nodeid)
216 std::vector<SendStatus> send_statuses;
217 };
219 const size_t m_max_transactions;
220 mutable Mutex m_mutex;
221 std::unordered_map<CTransactionRef, TxSendStatus, CTransactionRefHash, CTransactionRefComp>
222 m_transactions GUARDED_BY(m_mutex);
223};
224
225#endif // BITCOIN_PRIVATE_BROADCAST_H
A combination of a network address (CNetAddr) and a (TCP) port.
Definition: netaddress.h:530
Store a list of transactions to be broadcast privately.
static Priority DerivePriority(const std::vector< SendStatus > &sent_to)
Derive the sending priority of a transaction.
void NodeConfirmedReception(const NodeId &nodeid) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Mark that the node has confirmed reception of the transaction we sent it by responding with PONG to o...
AddResult Add(const CTransactionRef &tx) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Add a transaction to the storage.
std::vector< TxBroadcastInfo > GetBroadcastInfo() const EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Get stats about all transactions currently being privately broadcast.
PrivateBroadcast(size_t max_transactions=MAX_TRANSACTIONS)
AddResult
Outcome of Add().
const size_t m_max_transactions
Cap on the number of simultaneously tracked transactions (see Add()).
bool HavePendingTransactions() EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Check if there are transactions that need to be broadcast.
bool DidNodeConfirmReception(const NodeId &nodeid) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Check if the node has confirmed reception of the transaction.
static constexpr auto STALE_DURATION
If a transaction is not received back from the network for this duration after it is broadcast,...
std::optional< size_t > Remove(const CTransactionRef &tx) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Forget a transaction.
std::optional< CTransactionRef > PickTxForSend(const NodeId &will_send_to_nodeid, const CService &will_send_to_address) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Pick the transaction with the fewest send attempts, and confirmations, and oldest send/confirm times.
static constexpr size_t MAX_TRANSACTIONS
Maximum number of transactions tracked simultaneously.
std::optional< TxAndSendStatusForNode > GetSendStatusByNode(const NodeId &nodeid) EXCLUSIVE_LOCKS_REQUIRED(m_mutex)
Find which transaction we sent to a given node (marked by PickTxForSend()).
std::optional< CTransactionRef > GetTxForNode(const NodeId &nodeid) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Get the transaction that was picked for sending to a given node by PickTxForSend().
std::vector< CTransactionRef > GetStale() const EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Get the transactions that have not been broadcast recently.
std::unordered_map< CTransactionRef, TxSendStatus, CTransactionRefHash, CTransactionRefComp > m_transactions GUARDED_BY(m_mutex)
static constexpr auto INITIAL_STALE_DURATION
If a transaction is not sent to any peer for this duration, then we consider it stale / for rebroadca...
int64_t NodeId
Definition: net.h:103
std::shared_ptr< const CTransaction > CTransactionRef
Definition: transaction.h:403
static time_point now() noexcept
Return current system time or mocked time, if set.
Definition: time.cpp:38
std::chrono::time_point< NodeClock > time_point
Definition: time.h:28
bool operator()(const CTransactionRef &a, const CTransactionRef &b) const
size_t operator()(const CTransactionRef &tx) const
std::optional< NodeClock::time_point > received
Cumulative stats from all the send attempts for a transaction. Used to prioritize transactions.
size_t num_picked
Number of times the transaction was picked for sending.
auto operator<=>(const Priority &other) const
NodeClock::time_point last_confirmed
The most recent time when the transaction was confirmed.
size_t num_confirmed
Number of nodes that have confirmed reception of a transaction (by PONG).
NodeClock::time_point last_picked
The most recent time when the transaction was picked for sending.
Status of a transaction sent to a given node.
SendStatus(const NodeId &nodeid, const CService &address, const NodeClock::time_point &picked)
std::optional< NodeClock::time_point > confirmed
When was the transaction reception confirmed by the node (by PONG).
const NodeId nodeid
Node to which the transaction will be sent (or was sent).
const NodeClock::time_point picked
When was the transaction picked for sending to the node.
const CService address
Address of the node.
A pair of a transaction and a sent status for a given node. Convenience return type of GetSendStatusB...
std::vector< PeerSendInfo > peers
std::vector< SendStatus > send_statuses
const NodeClock::time_point time_added
#define EXCLUSIVE_LOCKS_REQUIRED(...)
Definition: threadsafety.h:49