Coverage Report

Created: 2024-10-21 15:10

/root/bitcoin/src/kernel/mempool_entry.h
Line
Count
Source (jump to first uncovered line)
1
// Copyright (c) 2009-2022 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_KERNEL_MEMPOOL_ENTRY_H
6
#define BITCOIN_KERNEL_MEMPOOL_ENTRY_H
7
8
#include <consensus/amount.h>
9
#include <consensus/validation.h>
10
#include <core_memusage.h>
11
#include <policy/policy.h>
12
#include <policy/settings.h>
13
#include <primitives/transaction.h>
14
#include <util/epochguard.h>
15
#include <util/overflow.h>
16
17
#include <chrono>
18
#include <functional>
19
#include <memory>
20
#include <set>
21
#include <stddef.h>
22
#include <stdint.h>
23
24
class CBlockIndex;
25
26
struct LockPoints {
27
    // Will be set to the blockchain height and median time past
28
    // values that would be necessary to satisfy all relative locktime
29
    // constraints (BIP68) of this tx given our view of block chain history
30
    int height{0};
31
    int64_t time{0};
32
    // As long as the current chain descends from the highest height block
33
    // containing one of the inputs used in the calculation, then the cached
34
    // values are still valid even after a reorg.
35
    CBlockIndex* maxInputBlock{nullptr};
36
};
37
38
struct CompareIteratorByHash {
39
    // SFINAE for T where T is either a pointer type (e.g., a txiter) or a reference_wrapper<T>
40
    // (e.g. a wrapped CTxMemPoolEntry&)
41
    template <typename T>
42
    bool operator()(const std::reference_wrapper<T>& a, const std::reference_wrapper<T>& b) const
43
0
    {
44
0
        return a.get().GetTx().GetHash() < b.get().GetTx().GetHash();
45
0
    }
46
    template <typename T>
47
    bool operator()(const T& a, const T& b) const
48
0
    {
49
0
        return a->GetTx().GetHash() < b->GetTx().GetHash();
50
0
    }
51
};
52
53
/** \class CTxMemPoolEntry
54
 *
55
 * CTxMemPoolEntry stores data about the corresponding transaction, as well
56
 * as data about all in-mempool transactions that depend on the transaction
57
 * ("descendant" transactions).
58
 *
59
 * When a new entry is added to the mempool, we update the descendant state
60
 * (m_count_with_descendants, nSizeWithDescendants, and nModFeesWithDescendants) for
61
 * all ancestors of the newly added transaction.
62
 *
63
 */
64
65
class CTxMemPoolEntry
66
{
67
public:
68
    typedef std::reference_wrapper<const CTxMemPoolEntry> CTxMemPoolEntryRef;
69
    // two aliases, should the types ever diverge
70
    typedef std::set<CTxMemPoolEntryRef, CompareIteratorByHash> Parents;
71
    typedef std::set<CTxMemPoolEntryRef, CompareIteratorByHash> Children;
72
73
private:
74
0
    CTxMemPoolEntry(const CTxMemPoolEntry&) = default;
75
    struct ExplicitCopyTag {
76
        explicit ExplicitCopyTag() = default;
77
    };
78
79
    const CTransactionRef tx;
80
    mutable Parents m_parents;
81
    mutable Children m_children;
82
    const CAmount nFee;             //!< Cached to avoid expensive parent-transaction lookups
83
    const int32_t nTxWeight;         //!< ... and avoid recomputing tx weight (also used for GetTxSize())
84
    const size_t nUsageSize;        //!< ... and total memory usage
85
    const int64_t nTime;            //!< Local time when entering the mempool
86
    const uint64_t entry_sequence;  //!< Sequence number used to determine whether this transaction is too recent for relay
87
    const unsigned int entryHeight; //!< Chain height when entering the mempool
88
    const bool spendsCoinbase;      //!< keep track of transactions that spend a coinbase
89
    const int64_t sigOpCost;        //!< Total sigop cost
90
    CAmount m_modified_fee;         //!< Used for determining the priority of the transaction for mining in a block
91
    mutable LockPoints lockPoints;  //!< Track the height and time at which tx was final
92
93
    // Information about descendants of this transaction that are in the
94
    // mempool; if we remove this transaction we must remove all of these
95
    // descendants as well.
96
    int64_t m_count_with_descendants{1}; //!< number of descendant transactions
97
    // Using int64_t instead of int32_t to avoid signed integer overflow issues.
98
    int64_t nSizeWithDescendants;      //!< ... and size
99
    CAmount nModFeesWithDescendants;   //!< ... and total fees (all including us)
100
101
    // Analogous statistics for ancestor transactions
102
    int64_t m_count_with_ancestors{1};
103
    // Using int64_t instead of int32_t to avoid signed integer overflow issues.
104
    int64_t nSizeWithAncestors;
105
    CAmount nModFeesWithAncestors;
106
    int64_t nSigOpCostWithAncestors;
107
108
public:
109
    CTxMemPoolEntry(const CTransactionRef& tx, CAmount fee,
110
                    int64_t time, unsigned int entry_height, uint64_t entry_sequence,
111
                    bool spends_coinbase,
112
                    int64_t sigops_cost, LockPoints lp)
113
0
        : tx{tx},
114
0
          nFee{fee},
115
0
          nTxWeight{GetTransactionWeight(*tx)},
116
0
          nUsageSize{RecursiveDynamicUsage(tx)},
117
0
          nTime{time},
118
0
          entry_sequence{entry_sequence},
119
0
          entryHeight{entry_height},
120
0
          spendsCoinbase{spends_coinbase},
121
0
          sigOpCost{sigops_cost},
122
0
          m_modified_fee{nFee},
123
0
          lockPoints{lp},
124
0
          nSizeWithDescendants{GetTxSize()},
125
0
          nModFeesWithDescendants{nFee},
126
0
          nSizeWithAncestors{GetTxSize()},
127
0
          nModFeesWithAncestors{nFee},
128
0
          nSigOpCostWithAncestors{sigOpCost} {}
129
130
0
    CTxMemPoolEntry(ExplicitCopyTag, const CTxMemPoolEntry& entry) : CTxMemPoolEntry(entry) {}
131
    CTxMemPoolEntry& operator=(const CTxMemPoolEntry&) = delete;
132
    CTxMemPoolEntry(CTxMemPoolEntry&&) = delete;
133
    CTxMemPoolEntry& operator=(CTxMemPoolEntry&&) = delete;
134
135
    static constexpr ExplicitCopyTag ExplicitCopy{};
136
137
0
    const CTransaction& GetTx() const { return *this->tx; }
138
0
    CTransactionRef GetSharedTx() const { return this->tx; }
139
0
    const CAmount& GetFee() const { return nFee; }
140
    int32_t GetTxSize() const
141
0
    {
142
0
        return GetVirtualTransactionSize(nTxWeight, sigOpCost, ::nBytesPerSigOp);
143
0
    }
144
0
    int32_t GetTxWeight() const { return nTxWeight; }
145
0
    std::chrono::seconds GetTime() const { return std::chrono::seconds{nTime}; }
146
0
    unsigned int GetHeight() const { return entryHeight; }
147
0
    uint64_t GetSequence() const { return entry_sequence; }
148
0
    int64_t GetSigOpCost() const { return sigOpCost; }
149
0
    CAmount GetModifiedFee() const { return m_modified_fee; }
150
0
    size_t DynamicMemoryUsage() const { return nUsageSize; }
151
0
    const LockPoints& GetLockPoints() const { return lockPoints; }
152
153
    // Adjusts the descendant state.
154
    void UpdateDescendantState(int32_t modifySize, CAmount modifyFee, int64_t modifyCount);
155
    // Adjusts the ancestor state
156
    void UpdateAncestorState(int32_t modifySize, CAmount modifyFee, int64_t modifyCount, int64_t modifySigOps);
157
    // Updates the modified fees with descendants/ancestors.
158
    void UpdateModifiedFee(CAmount fee_diff)
159
0
    {
160
0
        nModFeesWithDescendants = SaturatingAdd(nModFeesWithDescendants, fee_diff);
161
0
        nModFeesWithAncestors = SaturatingAdd(nModFeesWithAncestors, fee_diff);
162
0
        m_modified_fee = SaturatingAdd(m_modified_fee, fee_diff);
163
0
    }
164
165
    // Update the LockPoints after a reorg
166
    void UpdateLockPoints(const LockPoints& lp) const
167
0
    {
168
0
        lockPoints = lp;
169
0
    }
170
171
0
    uint64_t GetCountWithDescendants() const { return m_count_with_descendants; }
172
0
    int64_t GetSizeWithDescendants() const { return nSizeWithDescendants; }
173
0
    CAmount GetModFeesWithDescendants() const { return nModFeesWithDescendants; }
174
175
0
    bool GetSpendsCoinbase() const { return spendsCoinbase; }
176
177
0
    uint64_t GetCountWithAncestors() const { return m_count_with_ancestors; }
178
0
    int64_t GetSizeWithAncestors() const { return nSizeWithAncestors; }
179
0
    CAmount GetModFeesWithAncestors() const { return nModFeesWithAncestors; }
180
0
    int64_t GetSigOpCostWithAncestors() const { return nSigOpCostWithAncestors; }
181
182
0
    const Parents& GetMemPoolParentsConst() const { return m_parents; }
183
0
    const Children& GetMemPoolChildrenConst() const { return m_children; }
184
0
    Parents& GetMemPoolParents() const { return m_parents; }
185
0
    Children& GetMemPoolChildren() const { return m_children; }
186
187
    mutable size_t idx_randomized; //!< Index in mempool's txns_randomized
188
    mutable Epoch::Marker m_epoch_marker; //!< epoch when last touched, useful for graph algorithms
189
};
190
191
using CTxMemPoolEntryRef = CTxMemPoolEntry::CTxMemPoolEntryRef;
192
193
struct TransactionInfo {
194
    const CTransactionRef m_tx;
195
    /* The fee the transaction paid */
196
    const CAmount m_fee;
197
    /**
198
     * The virtual transaction size.
199
     *
200
     * This is a policy field which considers the sigop cost of the
201
     * transaction as well as its weight, and reinterprets it as bytes.
202
     *
203
     * It is the primary metric by which the mining algorithm selects
204
     * transactions.
205
     */
206
    const int64_t m_virtual_transaction_size;
207
    /* The block height the transaction entered the mempool */
208
    const unsigned int txHeight;
209
210
    TransactionInfo(const CTransactionRef& tx, const CAmount& fee, const int64_t vsize, const unsigned int height)
211
0
        : m_tx{tx},
212
0
          m_fee{fee},
213
0
          m_virtual_transaction_size{vsize},
214
0
          txHeight{height} {}
215
};
216
217
struct RemovedMempoolTransactionInfo {
218
    TransactionInfo info;
219
    explicit RemovedMempoolTransactionInfo(const CTxMemPoolEntry& entry)
220
0
        : info{entry.GetSharedTx(), entry.GetFee(), entry.GetTxSize(), entry.GetHeight()} {}
221
};
222
223
struct NewMempoolTransactionInfo {
224
    TransactionInfo info;
225
    /*
226
     * This boolean indicates whether the transaction was added
227
     * without enforcing mempool fee limits.
228
     */
229
    const bool m_mempool_limit_bypassed;
230
    /* This boolean indicates whether the transaction is part of a package. */
231
    const bool m_submitted_in_package;
232
    /*
233
     * This boolean indicates whether the blockchain is up to date when the
234
     * transaction is added to the mempool.
235
     */
236
    const bool m_chainstate_is_current;
237
    /* Indicates whether the transaction has unconfirmed parents. */
238
    const bool m_has_no_mempool_parents;
239
240
    explicit NewMempoolTransactionInfo(const CTransactionRef& tx, const CAmount& fee,
241
                                       const int64_t vsize, const unsigned int height,
242
                                       const bool mempool_limit_bypassed, const bool submitted_in_package,
243
                                       const bool chainstate_is_current,
244
                                       const bool has_no_mempool_parents)
245
0
        : info{tx, fee, vsize, height},
246
0
          m_mempool_limit_bypassed{mempool_limit_bypassed},
247
0
          m_submitted_in_package{submitted_in_package},
248
0
          m_chainstate_is_current{chainstate_is_current},
249
0
          m_has_no_mempool_parents{has_no_mempool_parents} {}
250
};
251
252
#endif // BITCOIN_KERNEL_MEMPOOL_ENTRY_H