Bitcoin Core 31.0.0
P2P Digital Currency
Loading...
Searching...
No Matches
fees.cpp
Go to the documentation of this file.
1// Copyright (c) 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#include <core_io.h>
8#include <node/context.h>
9#include <policy/feerate.h>
11#include <rpc/protocol.h>
12#include <rpc/request.h>
13#include <rpc/server.h>
14#include <rpc/server_util.h>
15#include <rpc/util.h>
16#include <txmempool.h>
17#include <univalue.h>
18#include <util/fees.h>
19#include <validationinterface.h>
20
21#include <algorithm>
22#include <array>
23#include <cmath>
24#include <string>
25#include <string_view>
26
31
33{
34 return RPCHelpMan{
35 "estimatesmartfee",
36 "Estimates the approximate fee per kilobyte needed for a transaction to begin\n"
37 "confirmation within conf_target blocks if possible and return the number of blocks\n"
38 "for which the estimate is valid. Uses virtual transaction size as defined\n"
39 "in BIP 141 (witness data is discounted).\n",
40 {
41 {"conf_target", RPCArg::Type::NUM, RPCArg::Optional::NO, "Confirmation target in blocks (1 - 1008)"},
42 {"estimate_mode", RPCArg::Type::STR, RPCArg::Default{"economical"}, "The fee estimate mode.\n"
43 + FeeModesDetail(std::string("default mode will be used"))},
44 },
47 {
48 {RPCResult::Type::NUM, "feerate", /*optional=*/true, "estimate fee rate in " + CURRENCY_UNIT + "/kvB (only present if no errors were encountered)"},
49 {RPCResult::Type::ARR, "errors", /*optional=*/true, "Errors encountered during processing (if there are any)",
50 {
51 {RPCResult::Type::STR, "", "error"},
52 }},
53 {RPCResult::Type::NUM, "blocks", "block number where estimate was found\n"
54 "The request target will be clamped between 2 and the highest target\n"
55 "fee estimation is able to return based on how long it has been running.\n"
56 "An error is returned if not enough transactions and blocks\n"
57 "have been observed to make an estimate for any number of blocks."},
58 }},
60 HelpExampleCli("estimatesmartfee", "6") +
61 HelpExampleRpc("estimatesmartfee", "6")
62 },
63 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
64 {
65 CBlockPolicyEstimator& fee_estimator = EnsureAnyFeeEstimator(request.context);
66 const NodeContext& node = EnsureAnyNodeContext(request.context);
67 const CTxMemPool& mempool = EnsureMemPool(node);
68
69 CHECK_NONFATAL(mempool.m_opts.signals)->SyncWithValidationInterfaceQueue();
71 unsigned int conf_target = ParseConfirmTarget(request.params[0], max_target);
73 if (!FeeModeFromString(self.Arg<std::string_view>("estimate_mode"), fee_mode)) {
74 throw JSONRPCError(RPC_INVALID_PARAMETER, InvalidEstimateModeErrorMessage());
75 }
76
82 if (feeRate != CFeeRate(0)) {
84 CFeeRate min_relay_feerate{mempool.m_opts.min_relay_feerate};
85 feeRate = std::max({feeRate, min_mempool_feerate, min_relay_feerate});
86 result.pushKV("feerate", ValueFromAmount(feeRate.GetFeePerK()));
87 } else {
88 errors.push_back("Insufficient data or no feerate found");
89 result.pushKV("errors", std::move(errors));
90 }
91 result.pushKV("blocks", feeCalc.returnedTarget);
92 return result;
93 },
94 };
95}
96
98{
99 return RPCHelpMan{
100 "estimaterawfee",
101 "WARNING: This interface is unstable and may disappear or change!\n"
102 "\nWARNING: This is an advanced API call that is tightly coupled to the specific\n"
103 "implementation of fee estimation. The parameters it can be called with\n"
104 "and the results it returns will change if the internal implementation changes.\n"
105 "\nEstimates the approximate fee per kilobyte needed for a transaction to begin\n"
106 "confirmation within conf_target blocks if possible. Uses virtual transaction size as\n"
107 "defined in BIP 141 (witness data is discounted).\n",
108 {
109 {"conf_target", RPCArg::Type::NUM, RPCArg::Optional::NO, "Confirmation target in blocks (1 - 1008)"},
110 {"threshold", RPCArg::Type::NUM, RPCArg::Default{0.95}, "The proportion of transactions in a given feerate range that must have been\n"
111 "confirmed within conf_target in order to consider those feerates as high enough and proceed to check\n"
112 "lower buckets."},
113 },
114 RPCResult{
115 RPCResult::Type::OBJ, "", "Results are returned for any horizon which tracks blocks up to the confirmation target",
116 {
117 {RPCResult::Type::OBJ, "short", /*optional=*/true, "estimate for short time horizon",
118 {
119 {RPCResult::Type::NUM, "feerate", /*optional=*/true, "estimate fee rate in " + CURRENCY_UNIT + "/kvB"},
120 {RPCResult::Type::NUM, "decay", "exponential decay (per block) for historical moving average of confirmation data"},
121 {RPCResult::Type::NUM, "scale", "The resolution of confirmation targets at this time horizon"},
122 {RPCResult::Type::OBJ, "pass", /*optional=*/true, "information about the lowest range of feerates to succeed in meeting the threshold",
123 {
124 {RPCResult::Type::NUM, "startrange", "start of feerate range"},
125 {RPCResult::Type::NUM, "endrange", "end of feerate range"},
126 {RPCResult::Type::NUM, "withintarget", "number of txs over history horizon in the feerate range that were confirmed within target"},
127 {RPCResult::Type::NUM, "totalconfirmed", "number of txs over history horizon in the feerate range that were confirmed at any point"},
128 {RPCResult::Type::NUM, "inmempool", "current number of txs in mempool in the feerate range unconfirmed for at least target blocks"},
129 {RPCResult::Type::NUM, "leftmempool", "number of txs over history horizon in the feerate range that left mempool unconfirmed after target"},
130 }},
131 {RPCResult::Type::OBJ, "fail", /*optional=*/true, "information about the highest range of feerates to fail to meet the threshold",
132 {
133 {RPCResult::Type::ELISION, "", ""},
134 }},
135 {RPCResult::Type::ARR, "errors", /*optional=*/true, "Errors encountered during processing (if there are any)",
136 {
137 {RPCResult::Type::STR, "error", ""},
138 }},
139 }},
140 {RPCResult::Type::OBJ, "medium", /*optional=*/true, "estimate for medium time horizon",
141 {
142 {RPCResult::Type::ELISION, "", ""},
143 }},
144 {RPCResult::Type::OBJ, "long", /*optional=*/true, "estimate for long time horizon",
145 {
146 {RPCResult::Type::ELISION, "", ""},
147 }},
148 }},
150 HelpExampleCli("estimaterawfee", "6 0.9")
151 },
152 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
153 {
154 CBlockPolicyEstimator& fee_estimator = EnsureAnyFeeEstimator(request.context);
155 const NodeContext& node = EnsureAnyNodeContext(request.context);
156
157 CHECK_NONFATAL(node.validation_signals)->SyncWithValidationInterfaceQueue();
159 unsigned int conf_target = ParseConfirmTarget(request.params[0], max_target);
160 double threshold = 0.95;
161 if (!request.params[1].isNull()) {
162 threshold = request.params[1].get_real();
163 }
165 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid threshold");
166 }
167
168 UniValue result(UniValue::VOBJ);
169
172 EstimationResult buckets;
173
174 // Only output results for horizons which track the target
175 if (conf_target > fee_estimator.HighestTargetTracked(horizon)) continue;
176
177 feeRate = fee_estimator.estimateRawFee(conf_target, threshold, horizon, &buckets);
181 passbucket.pushKV("startrange", round(buckets.pass.start));
182 passbucket.pushKV("endrange", round(buckets.pass.end));
183 passbucket.pushKV("withintarget", round(buckets.pass.withinTarget * 100.0) / 100.0);
184 passbucket.pushKV("totalconfirmed", round(buckets.pass.totalConfirmed * 100.0) / 100.0);
185 passbucket.pushKV("inmempool", round(buckets.pass.inMempool * 100.0) / 100.0);
186 passbucket.pushKV("leftmempool", round(buckets.pass.leftMempool * 100.0) / 100.0);
188 failbucket.pushKV("startrange", round(buckets.fail.start));
189 failbucket.pushKV("endrange", round(buckets.fail.end));
190 failbucket.pushKV("withintarget", round(buckets.fail.withinTarget * 100.0) / 100.0);
191 failbucket.pushKV("totalconfirmed", round(buckets.fail.totalConfirmed * 100.0) / 100.0);
192 failbucket.pushKV("inmempool", round(buckets.fail.inMempool * 100.0) / 100.0);
193 failbucket.pushKV("leftmempool", round(buckets.fail.leftMempool * 100.0) / 100.0);
194
195 // CFeeRate(0) is used to indicate error as a return value from estimateRawFee
196 if (feeRate != CFeeRate(0)) {
197 horizon_result.pushKV("feerate", ValueFromAmount(feeRate.GetFeePerK()));
198 horizon_result.pushKV("decay", buckets.decay);
199 horizon_result.pushKV("scale", buckets.scale);
200 horizon_result.pushKV("pass", std::move(passbucket));
201 // buckets.fail.start == -1 indicates that all buckets passed, there is no fail bucket to output
202 if (buckets.fail.start != -1) horizon_result.pushKV("fail", std::move(failbucket));
203 } else {
204 // Output only information that is still meaningful in the event of error
205 horizon_result.pushKV("decay", buckets.decay);
206 horizon_result.pushKV("scale", buckets.scale);
207 horizon_result.pushKV("fail", std::move(failbucket));
208 errors.push_back("Insufficient data or no feerate found which meets threshold");
209 horizon_result.pushKV("errors", std::move(errors));
210 }
212 }
213 return result;
214 },
215 };
216}
217
219{
220 static const CRPCCommand commands[]{
221 {"util", &estimatesmartfee},
222 {"hidden", &estimaterawfee},
223 };
224 for (const auto& c : commands) {
225 t.appendCommand(c.name, &c);
226 }
227}
std::string StringForFeeEstimateHorizon(FeeEstimateHorizon horizon)
static constexpr auto ALL_FEE_ESTIMATE_HORIZONS
#define CHECK_NONFATAL(condition)
Identity function.
Definition check.h:109
The BlockPolicyEstimator is used for estimating the feerate needed for a transaction to be included i...
virtual CFeeRate estimateSmartFee(int confTarget, FeeCalculation *feeCalc, bool conservative) const EXCLUSIVE_LOCKS_REQUIRED(!m_cs_fee_estimator)
Estimate feerate needed to get be included in a block within confTarget blocks.
virtual unsigned int HighestTargetTracked(FeeEstimateHorizon horizon) const EXCLUSIVE_LOCKS_REQUIRED(!m_cs_fee_estimator)
Calculation of highest target that estimates are tracked for.
CFeeRate estimateRawFee(int confTarget, double successThreshold, FeeEstimateHorizon horizon, EstimationResult *result=nullptr) const EXCLUSIVE_LOCKS_REQUIRED(!m_cs_fee_estimator)
Return a specific fee estimate calculation with a given success threshold and time horizon,...
Fee rate in satoshis per virtualbyte: CAmount / vB the feerate is represented internally as FeeFrac.
Definition feerate.h:32
RPC command dispatcher.
Definition server.h:87
CTxMemPool stores valid-according-to-the-current-best-chain transactions that may be included in the ...
Definition txmempool.h:187
CFeeRate GetMinFee(size_t sizelimit) const
const Options m_opts
Definition txmempool.h:303
void pushKV(std::string key, UniValue val)
Definition univalue.cpp:125
UniValue ValueFromAmount(const CAmount amount)
Definition core_io.cpp:285
const std::string CURRENCY_UNIT
Definition feerate.h:19
is a home for simple string functions returning descriptive messages that are used in RPC and GUI int...
std::string FeeModesDetail(std::string default_info)
Definition messages.cpp:74
bool FeeModeFromString(std::string_view mode_string, FeeEstimateMode &fee_estimate_mode)
Definition messages.cpp:93
std::string InvalidEstimateModeErrorMessage()
Definition messages.cpp:88
UniValue JSONRPCError(int code, const std::string &message)
Definition request.cpp:70
static RPCHelpMan estimatesmartfee()
Definition fees.cpp:32
void RegisterFeeRPCCommands(CRPCTable &t)
Definition fees.cpp:218
static RPCHelpMan estimaterawfee()
Definition fees.cpp:97
@ RPC_INVALID_PARAMETER
Invalid, missing or duplicate parameter.
Definition protocol.h:44
std::string HelpExampleCli(const std::string &methodname, const std::string &args)
Definition util.cpp:183
std::string HelpExampleRpc(const std::string &methodname, const std::string &args)
Definition util.cpp:201
unsigned int ParseConfirmTarget(const UniValue &value, unsigned int max_target)
Parse a confirm target option and raise an RPC error if it is invalid.
Definition util.cpp:369
NodeContext & EnsureAnyNodeContext(const std::any &context)
CTxMemPool & EnsureMemPool(const NodeContext &node)
CBlockPolicyEstimator & EnsureAnyFeeEstimator(const std::any &context)
@ NO
Required arg.
@ ELISION
Special type to denote elision (...)
ValidationSignals * signals
CFeeRate min_relay_feerate
A fee rate smaller than this is considered zero fee (for relaying, mining and transaction creation)
NodeContext struct containing references to chain state and connection state.
Definition context.h:56
FeeEstimateMode
Definition fees.h:9
@ CONSERVATIVE
Force estimateSmartFee to use conservative estimates.
constexpr auto Ticks(Dur2 d)
Helper to count the seconds of a duration/time_point.
Definition time.h:73