Bitcoin Core Fuzz Coverage Report

Coverage Report

Created: 2026-03-24 13:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/root/bitcoin/src/private_broadcast.cpp
Line
Count
Source
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
bool PrivateBroadcast::Add(const CTransactionRef& tx)
15
    EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
16
0
{
17
0
    LOCK(m_mutex);
Line
Count
Source
266
0
#define LOCK(cs) UniqueLock UNIQUE_NAME(criticalblock)(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__)
Line
Count
Source
11
0
#define UNIQUE_NAME(name) PASTE2(name, __COUNTER__)
Line
Count
Source
9
0
#define PASTE2(x, y) PASTE(x, y)
Line
Count
Source
8
0
#define PASTE(x, y) x ## y
18
0
    const bool inserted{m_transactions.try_emplace(tx).second};
19
0
    return inserted;
20
0
}
21
22
std::optional<size_t> PrivateBroadcast::Remove(const CTransactionRef& tx)
23
    EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
24
0
{
25
0
    LOCK(m_mutex);
Line
Count
Source
266
0
#define LOCK(cs) UniqueLock UNIQUE_NAME(criticalblock)(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__)
Line
Count
Source
11
0
#define UNIQUE_NAME(name) PASTE2(name, __COUNTER__)
Line
Count
Source
9
0
#define PASTE2(x, y) PASTE(x, y)
Line
Count
Source
8
0
#define PASTE(x, y) x ## y
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
0
    }
31
0
    return std::nullopt;
32
0
}
33
34
std::optional<CTransactionRef> PrivateBroadcast::PickTxForSend(const NodeId& will_send_to_nodeid, const CService& will_send_to_address)
35
    EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
36
0
{
37
0
    LOCK(m_mutex);
Line
Count
Source
266
0
#define LOCK(cs) UniqueLock UNIQUE_NAME(criticalblock)(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__)
Line
Count
Source
11
0
#define UNIQUE_NAME(name) PASTE2(name, __COUNTER__)
Line
Count
Source
9
0
#define PASTE2(x, y) PASTE(x, y)
Line
Count
Source
8
0
#define PASTE(x, y) x ## y
38
39
0
    const auto it{std::ranges::max_element(
40
0
            m_transactions,
41
0
            [](const auto& a, const auto& b) { return a < b; },
42
0
            [](const auto& el) { return DerivePriority(el.second); })};
43
44
0
    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
0
    }
49
50
0
    return std::nullopt;
51
0
}
52
53
std::optional<CTransactionRef> PrivateBroadcast::GetTxForNode(const NodeId& nodeid)
54
    EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
55
0
{
56
0
    LOCK(m_mutex);
Line
Count
Source
266
0
#define LOCK(cs) UniqueLock UNIQUE_NAME(criticalblock)(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__)
Line
Count
Source
11
0
#define UNIQUE_NAME(name) PASTE2(name, __COUNTER__)
Line
Count
Source
9
0
#define PASTE2(x, y) PASTE(x, y)
Line
Count
Source
8
0
#define PASTE(x, y) x ## y
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
0
    }
61
0
    return std::nullopt;
62
0
}
63
64
void PrivateBroadcast::NodeConfirmedReception(const NodeId& nodeid)
65
    EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
66
0
{
67
0
    LOCK(m_mutex);
Line
Count
Source
266
0
#define LOCK(cs) UniqueLock UNIQUE_NAME(criticalblock)(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__)
Line
Count
Source
11
0
#define UNIQUE_NAME(name) PASTE2(name, __COUNTER__)
Line
Count
Source
9
0
#define PASTE2(x, y) PASTE(x, y)
Line
Count
Source
8
0
#define PASTE(x, y) x ## y
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
0
    }
72
0
}
73
74
bool PrivateBroadcast::DidNodeConfirmReception(const NodeId& nodeid)
75
    EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
76
0
{
77
0
    LOCK(m_mutex);
Line
Count
Source
266
0
#define LOCK(cs) UniqueLock UNIQUE_NAME(criticalblock)(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__)
Line
Count
Source
11
0
#define UNIQUE_NAME(name) PASTE2(name, __COUNTER__)
Line
Count
Source
9
0
#define PASTE2(x, y) PASTE(x, y)
Line
Count
Source
8
0
#define PASTE(x, y) x ## y
78
0
    const auto tx_and_status{GetSendStatusByNode(nodeid)};
79
0
    if (tx_and_status.has_value()) {
80
0
        return tx_and_status.value().send_status.confirmed.has_value();
81
0
    }
82
0
    return false;
83
0
}
84
85
bool PrivateBroadcast::HavePendingTransactions()
86
    EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
87
0
{
88
0
    LOCK(m_mutex);
Line
Count
Source
266
0
#define LOCK(cs) UniqueLock UNIQUE_NAME(criticalblock)(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__)
Line
Count
Source
11
0
#define UNIQUE_NAME(name) PASTE2(name, __COUNTER__)
Line
Count
Source
9
0
#define PASTE2(x, y) PASTE(x, y)
Line
Count
Source
8
0
#define PASTE(x, y) x ## y
89
0
    return !m_transactions.empty();
90
0
}
91
92
std::vector<CTransactionRef> PrivateBroadcast::GetStale() const
93
    EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
94
0
{
95
0
    LOCK(m_mutex);
Line
Count
Source
266
0
#define LOCK(cs) UniqueLock UNIQUE_NAME(criticalblock)(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__)
Line
Count
Source
11
0
#define UNIQUE_NAME(name) PASTE2(name, __COUNTER__)
Line
Count
Source
9
0
#define PASTE2(x, y) PASTE(x, y)
Line
Count
Source
8
0
#define PASTE(x, y) x ## y
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
0
        }
103
0
    }
104
0
    return stale;
105
0
}
106
107
std::vector<PrivateBroadcast::TxBroadcastInfo> PrivateBroadcast::GetBroadcastInfo() const
108
    EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
109
0
{
110
0
    LOCK(m_mutex);
Line
Count
Source
266
0
#define LOCK(cs) UniqueLock UNIQUE_NAME(criticalblock)(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__)
Line
Count
Source
11
0
#define UNIQUE_NAME(name) PASTE2(name, __COUNTER__)
Line
Count
Source
9
0
#define PASTE2(x, y) PASTE(x, y)
Line
Count
Source
8
0
#define PASTE(x, y) x ## y
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
0
        }
120
0
        entries.emplace_back(TxBroadcastInfo{.tx = tx, .peers = std::move(peers)});
121
0
    }
122
123
0
    return entries;
124
0
}
125
126
PrivateBroadcast::Priority PrivateBroadcast::DerivePriority(const std::vector<SendStatus>& sent_to)
127
0
{
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
0
        }
136
0
    }
137
0
    return p;
138
0
}
139
140
std::optional<PrivateBroadcast::TxAndSendStatusForNode> PrivateBroadcast::GetSendStatusByNode(const NodeId& nodeid)
141
    EXCLUSIVE_LOCKS_REQUIRED(m_mutex)
142
0
{
143
0
    AssertLockHeld(m_mutex);
Line
Count
Source
142
0
#define AssertLockHeld(cs) AssertLockHeldInternal(#cs, __FILE__, __LINE__, &cs)
144
0
    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
0
            }
149
0
        }
150
0
    }
151
0
    return std::nullopt;
152
0
}