Coverage Report

Created: 2026-08-14 20:23

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/tmp/bitcoin/src/common/messages.cpp
Line
Count
Source
1
// Copyright (c) 2009-2010 Satoshi Nakamoto
2
// Copyright (c) 2009-present The Bitcoin Core developers
3
// Distributed under the MIT software license, see the accompanying
4
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
5
6
#include <common/messages.h>
7
8
#include <common/types.h>
9
#include <node/types.h>
10
#include <policy/fees/block_policy_estimator.h>
11
#include <tinyformat.h>
12
#include <util/check.h>
13
#include <util/fees.h>
14
#include <util/strencodings.h>
15
#include <util/string.h>
16
#include <util/translation.h>
17
18
#include <map>
19
#include <string>
20
#include <string_view>
21
#include <utility>
22
#include <vector>
23
24
using node::TransactionError;
25
using util::Join;
26
27
namespace common {
28
std::string StringForFeeReason(FeeReason reason)
29
3.60k
{
30
3.60k
    static const std::map<FeeReason, std::string> fee_reason_strings = {
31
3.60k
        {FeeReason::NONE, "None"},
32
3.60k
        {FeeReason::HALF_ESTIMATE, "Half Target 60% Threshold"},
33
3.60k
        {FeeReason::FULL_ESTIMATE, "Target 85% Threshold"},
34
3.60k
        {FeeReason::DOUBLE_ESTIMATE, "Double Target 95% Threshold"},
35
3.60k
        {FeeReason::CONSERVATIVE, "Conservative Double Target longer horizon"},
36
3.60k
        {FeeReason::MEMPOOL_MIN, "Mempool Min Fee"},
37
3.60k
        {FeeReason::FALLBACK, "Fallback fee"},
38
3.60k
        {FeeReason::REQUIRED, "Minimum Required Fee"},
39
3.60k
    };
40
3.60k
    auto reason_string = fee_reason_strings.find(reason);
41
42
3.60k
    if (reason_string == fee_reason_strings.end()) return "Unknown";
43
44
3.60k
    return reason_string->second;
45
3.60k
}
46
47
const std::vector<std::pair<std::string, FeeEstimateMode>>& FeeModeMap()
48
27.6k
{
49
27.6k
    static const std::vector<std::pair<std::string, FeeEstimateMode>> FEE_MODES = {
50
27.6k
        {"unset", FeeEstimateMode::UNSET},
51
27.6k
        {"economical", FeeEstimateMode::ECONOMICAL},
52
27.6k
        {"conservative", FeeEstimateMode::CONSERVATIVE},
53
27.6k
    };
54
27.6k
    return FEE_MODES;
55
27.6k
}
56
57
std::string FeeModeInfo(const std::pair<std::string, FeeEstimateMode>& mode, std::string& default_info)
58
41.0k
{
59
41.0k
    switch (mode.second) {
60
13.6k
        case FeeEstimateMode::UNSET:
61
13.6k
            return strprintf("%s means no mode set (%s). \n", mode.first, default_info);
62
13.6k
        case FeeEstimateMode::ECONOMICAL:
63
13.6k
            return strprintf("%s estimates use a shorter time horizon, making them more\n"
64
13.6k
                   "responsive to short-term drops in the prevailing fee market. This mode\n"
65
13.6k
                   "potentially returns a lower fee rate estimate.\n", mode.first);
66
13.6k
        case FeeEstimateMode::CONSERVATIVE:
67
13.6k
            return strprintf("%s estimates use a longer time horizon, making them\n"
68
13.6k
                   "less responsive to short-term drops in the prevailing fee market. This mode\n"
69
13.6k
                   "potentially returns a higher fee rate estimate.\n", mode.first);
70
41.0k
    } // no default case, so the compiler can warn about missing cases
71
41.0k
    assert(false);
72
0
}
73
74
std::string FeeModesDetail(std::string default_info)
75
13.6k
{
76
13.6k
    std::string info;
77
41.0k
    for (const auto& fee_mode : FeeModeMap()) {
78
41.0k
        info += FeeModeInfo(fee_mode, default_info);
79
41.0k
    }
80
13.6k
    return strprintf("%s \n%s", FeeModes(", "), info);
81
13.6k
}
82
83
std::string FeeModes(const std::string& delimiter)
84
13.7k
{
85
41.1k
    return Join(FeeModeMap(), delimiter, [&](const std::pair<std::string, FeeEstimateMode>& i) { return i.first; });
86
13.7k
}
87
88
std::string InvalidEstimateModeErrorMessage()
89
28
{
90
28
    return "Invalid estimate_mode parameter, must be one of: \"" + FeeModes("\", \"") + "\"";
91
28
}
92
93
bool FeeModeFromString(std::string_view mode_string, FeeEstimateMode& fee_estimate_mode)
94
231
{
95
231
    auto searchkey = ToUpper(mode_string);
96
498
    for (const auto& pair : FeeModeMap()) {
97
498
        if (ToUpper(pair.first) == searchkey) {
98
203
            fee_estimate_mode = pair.second;
99
203
            return true;
100
203
        }
101
498
    }
102
28
    return false;
103
231
}
104
105
bilingual_str PSBTErrorString(PSBTError err)
106
15
{
107
15
    switch (err) {
108
0
        case PSBTError::MISSING_INPUTS:
109
0
            return Untranslated("Inputs missing or spent");
110
14
        case PSBTError::SIGHASH_MISMATCH:
111
14
            return Untranslated("Specified sighash value does not match value stored in PSBT");
112
1
        case PSBTError::EXTERNAL_SIGNER_NOT_FOUND:
113
1
            return Untranslated("External signer not found");
114
0
        case PSBTError::EXTERNAL_SIGNER_FAILED:
115
0
            return Untranslated("External signer failed to sign");
116
0
        case PSBTError::UNSUPPORTED:
117
0
            return Untranslated("Signer does not support PSBT");
118
0
        case PSBTError::INCOMPLETE:
119
0
            return Untranslated("Input needs additional signatures or other data");
120
0
        case PSBTError::INVALID_TX:
121
0
            return Untranslated("The transaction cannot be valid");
122
0
        case PSBTError::OK:
123
0
            return Untranslated("No errors");
124
15
    } // no default case, so the compiler can warn about missing cases
125
15
    assert(false);
126
0
}
127
128
bilingual_str TransactionErrorString(const TransactionError err)
129
35
{
130
35
    switch (err) {
131
0
        case TransactionError::OK:
132
0
            return Untranslated("No error");
133
0
        case TransactionError::MISSING_INPUTS:
134
0
            return Untranslated("Inputs missing or spent");
135
3
        case TransactionError::ALREADY_IN_UTXO_SET:
136
3
            return Untranslated("Transaction outputs already in utxo set");
137
0
        case TransactionError::MEMPOOL_REJECTED:
138
0
            return Untranslated("Transaction rejected by mempool");
139
0
        case TransactionError::MEMPOOL_ERROR:
140
0
            return Untranslated("Mempool internal error");
141
22
        case TransactionError::MAX_FEE_EXCEEDED:
142
22
            return Untranslated("Fee exceeds maximum configured by user (e.g. -maxtxfee, maxfeerate)");
143
5
        case TransactionError::MAX_BURN_EXCEEDED:
144
5
            return Untranslated("Unspendable output exceeds maximum configured by user (maxburnamount)");
145
0
        case TransactionError::INVALID_PACKAGE:
146
0
            return Untranslated("Transaction rejected due to invalid package");
147
5
        case TransactionError::PRIVATE_BROADCAST_FULL:
148
5
            return Untranslated("Private broadcast queue is full");
149
35
    } // no default case, so the compiler can warn about missing cases
150
35
    assert(false);
151
0
}
152
153
bilingual_str ResolveErrMsg(const std::string& optname, const std::string& strBind)
154
3
{
155
3
    return strprintf(_("Cannot resolve -%s address: '%s'"), optname, strBind);
156
3
}
157
158
bilingual_str InvalidPortErrMsg(const std::string& optname, const std::string& invalid_value)
159
13
{
160
13
    return strprintf(_("Invalid port specified in %s: '%s'"), optname, invalid_value);
161
13
}
162
163
bilingual_str AmountHighWarn(const std::string& optname)
164
7
{
165
7
    return strprintf(_("%s is set very high!"), optname);
166
7
}
167
168
bilingual_str AmountErrMsg(const std::string& optname, const std::string& strValue)
169
0
{
170
0
    return strprintf(_("Invalid amount for -%s=<amount>: '%s'"), optname, strValue);
171
0
}
172
} // namespace common