Coverage Report

Created: 2025-04-14 16:24

/Users/mcomp/contrib/bitcoin/src/node/txdownloadman.h
Line
Count
Source (jump to first uncovered line)
1
// Copyright (c) 2024 The Bitcoin Core developers
2
// Distributed under the MIT software license, see the accompanying
3
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
5
#ifndef BITCOIN_NODE_TXDOWNLOADMAN_H
6
#define BITCOIN_NODE_TXDOWNLOADMAN_H
7
8
#include <net.h>
9
#include <policy/packages.h>
10
#include <txorphanage.h>
11
12
#include <cstdint>
13
#include <memory>
14
15
class CBlock;
16
class CRollingBloomFilter;
17
class CTxMemPool;
18
class GenTxid;
19
class TxRequestTracker;
20
namespace node {
21
class TxDownloadManagerImpl;
22
23
/** Maximum number of in-flight transaction requests from a peer. It is not a hard limit, but the threshold at which
24
 *  point the OVERLOADED_PEER_TX_DELAY kicks in. */
25
static constexpr int32_t MAX_PEER_TX_REQUEST_IN_FLIGHT = 100;
26
/** Maximum number of transactions to consider for requesting, per peer. It provides a reasonable DoS limit to
27
 *  per-peer memory usage spent on announcements, while covering peers continuously sending INVs at the maximum
28
 *  rate (by our own policy, see INVENTORY_BROADCAST_PER_SECOND) for several minutes, while not receiving
29
 *  the actual transaction (from any peer) in response to requests for them. */
30
static constexpr int32_t MAX_PEER_TX_ANNOUNCEMENTS = 5000;
31
/** How long to delay requesting transactions via txids, if we have wtxid-relaying peers */
32
static constexpr auto TXID_RELAY_DELAY{2s};
33
/** How long to delay requesting transactions from non-preferred peers */
34
static constexpr auto NONPREF_PEER_TX_DELAY{2s};
35
/** How long to delay requesting transactions from overloaded peers (see MAX_PEER_TX_REQUEST_IN_FLIGHT). */
36
static constexpr auto OVERLOADED_PEER_TX_DELAY{2s};
37
/** How long to wait before downloading a transaction from an additional peer */
38
static constexpr auto GETDATA_TX_INTERVAL{60s};
39
struct TxDownloadOptions {
40
    /** Read-only reference to mempool. */
41
    const CTxMemPool& m_mempool;
42
    /** RNG provided by caller. */
43
    FastRandomContext& m_rng;
44
    /** Maximum number of transactions allowed in orphanage. */
45
    const uint32_t m_max_orphan_txs;
46
    /** Instantiate TxRequestTracker as deterministic (used for tests). */
47
    bool m_deterministic_txrequest{false};
48
};
49
struct TxDownloadConnectionInfo {
50
    /** Whether this peer is preferred for transaction download. */
51
    const bool m_preferred;
52
    /** Whether this peer has Relay permissions. */
53
    const bool m_relay_permissions;
54
    /** Whether this peer supports wtxid relay. */
55
    const bool m_wtxid_relay;
56
};
57
struct PackageToValidate {
58
    Package m_txns;
59
    std::vector<NodeId> m_senders;
60
    /** Construct a 1-parent-1-child package. */
61
    explicit PackageToValidate(const CTransactionRef& parent,
62
                               const CTransactionRef& child,
63
                               NodeId parent_sender,
64
                               NodeId child_sender) :
65
0
        m_txns{parent, child},
66
0
        m_senders{parent_sender, child_sender}
67
0
    {}
68
69
    // Move ctor
70
0
    PackageToValidate(PackageToValidate&& other) : m_txns{std::move(other.m_txns)}, m_senders{std::move(other.m_senders)} {}
71
    // Copy ctor
72
0
    PackageToValidate(const PackageToValidate& other) = default;
73
74
    // Move assignment
75
0
    PackageToValidate& operator=(PackageToValidate&& other) {
76
0
        this->m_txns = std::move(other.m_txns);
77
0
        this->m_senders = std::move(other.m_senders);
78
0
        return *this;
79
0
    }
80
81
0
    std::string ToString() const {
82
0
        Assume(m_txns.size() == 2);
83
0
        return strprintf("parent %s (wtxid=%s, sender=%d) + child %s (wtxid=%s, sender=%d)",
84
0
                         m_txns.front()->GetHash().ToString(),
85
0
                         m_txns.front()->GetWitnessHash().ToString(),
86
0
                         m_senders.front(),
87
0
                         m_txns.back()->GetHash().ToString(),
88
0
                         m_txns.back()->GetWitnessHash().ToString(),
89
0
                         m_senders.back());
90
0
    }
91
};
92
struct RejectedTxTodo
93
{
94
    bool m_should_add_extra_compact_tx;
95
    std::vector<Txid> m_unique_parents;
96
    std::optional<PackageToValidate> m_package_to_validate;
97
};
98
99
100
/**
101
 * Class responsible for deciding what transactions to request and, once
102
 * downloaded, whether and how to validate them. It is also responsible for
103
 * deciding what transaction packages to validate and how to resolve orphan
104
 * transactions. Its data structures include TxRequestTracker for scheduling
105
 * requests, rolling bloom filters for remembering transactions that have
106
 * already been {accepted, rejected, confirmed}, an orphanage, and a registry of
107
 * each peer's transaction relay-related information.
108
 *
109
 * Caller needs to interact with TxDownloadManager:
110
 * - ValidationInterface callbacks.
111
 * - When a potential transaction relay peer connects or disconnects.
112
 * - When a transaction or package is accepted or rejected from mempool
113
 * - When a inv, notfound, or tx message is received
114
 * - To get instructions for which getdata messages to send
115
 *
116
 * This class is not thread-safe. Access must be synchronized using an
117
 * external mutex.
118
 */
119
class TxDownloadManager {
120
    const std::unique_ptr<TxDownloadManagerImpl> m_impl;
121
122
public:
123
    explicit TxDownloadManager(const TxDownloadOptions& options);
124
    ~TxDownloadManager();
125
126
    // Responses to chain events. TxDownloadManager is not an actual client of ValidationInterface, these are called through PeerManager.
127
    void ActiveTipChange();
128
    void BlockConnected(const std::shared_ptr<const CBlock>& pblock);
129
    void BlockDisconnected();
130
131
    /** Creates a new PeerInfo. Saves the connection info to calculate tx announcement delays later. */
132
    void ConnectedPeer(NodeId nodeid, const TxDownloadConnectionInfo& info);
133
134
    /** Deletes all txrequest announcements and orphans for a given peer. */
135
    void DisconnectedPeer(NodeId nodeid);
136
137
    /** Consider adding this tx hash to txrequest. Should be called whenever a new inv has been received.
138
     * Also called internally when a transaction is missing parents so that we can request them.
139
     * Returns true if this was a dropped inv (p2p_inv=true and we already have the tx), false otherwise. */
140
    bool AddTxAnnouncement(NodeId peer, const GenTxid& gtxid, std::chrono::microseconds now);
141
142
    /** Get getdata requests to send. */
143
    std::vector<GenTxid> GetRequestsToSend(NodeId nodeid, std::chrono::microseconds current_time);
144
145
    /** Should be called when a notfound for a tx has been received. */
146
    void ReceivedNotFound(NodeId nodeid, const std::vector<uint256>& txhashes);
147
148
    /** Respond to successful transaction submission to mempool */
149
    void MempoolAcceptedTx(const CTransactionRef& tx);
150
151
    /** Respond to transaction rejected from mempool */
152
    RejectedTxTodo MempoolRejectedTx(const CTransactionRef& ptx, const TxValidationState& state, NodeId nodeid, bool first_time_failure);
153
154
    /** Respond to package rejected from mempool */
155
    void MempoolRejectedPackage(const Package& package);
156
157
    /** Marks a tx as ReceivedResponse in txrequest and checks whether AlreadyHaveTx.
158
     * Return a bool indicating whether this tx should be validated. If false, optionally, a
159
     * PackageToValidate. */
160
    std::pair<bool, std::optional<PackageToValidate>> ReceivedTx(NodeId nodeid, const CTransactionRef& ptx);
161
162
    /** Whether there are any orphans to reconsider for this peer. */
163
    bool HaveMoreWork(NodeId nodeid) const;
164
165
    /** Returns next orphan tx to consider, or nullptr if none exist. */
166
    CTransactionRef GetTxToReconsider(NodeId nodeid);
167
168
    /** Check that all data structures are empty. */
169
    void CheckIsEmpty() const;
170
171
    /** Check that all data structures that track per-peer information have nothing for this peer. */
172
    void CheckIsEmpty(NodeId nodeid) const;
173
174
    /** Wrapper for TxOrphanage::GetOrphanTransactions */
175
    std::vector<TxOrphanage::OrphanTxBase> GetOrphanTransactions() const;
176
};
177
} // namespace node
178
#endif // BITCOIN_NODE_TXDOWNLOADMAN_H