LCOV - code coverage report
Current view: top level - src/rpc - fees.cpp (source / functions) Coverage Total Hit
Test: test_bitcoin_coverage.info Lines: 46.9 % 179 84
Test Date: 2026-10-11 07:59:32 Functions: 100.0 % 7 7
Branches: 28.3 % 672 190

             Branch data     Line data    Source code
       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 <util/fees.h>
       7                 :             : 
       8                 :             : #include <common/messages.h>
       9                 :             : #include <core_io.h>
      10                 :             : #include <node/context.h>
      11                 :             : #include <policy/feerate.h>
      12                 :             : #include <policy/fees/block_policy_estimator.h>
      13                 :             : #include <policy/fees/estimator_man.h>
      14                 :             : #include <policy/fees/mempool_estimator.h>
      15                 :             : #include <rpc/protocol.h>
      16                 :             : #include <rpc/register.h> // IWYU pragma: associated
      17                 :             : #include <rpc/request.h>
      18                 :             : #include <rpc/server.h>
      19                 :             : #include <rpc/server_util.h>
      20                 :             : #include <rpc/util.h>
      21                 :             : #include <txmempool.h>
      22                 :             : #include <univalue.h>
      23                 :             : #include <util/check.h>
      24                 :             : #include <util/expected.h>
      25                 :             : #include <validationinterface.h>
      26                 :             : 
      27                 :             : #include <algorithm>
      28                 :             : #include <array>
      29                 :             : #include <cmath>
      30                 :             : #include <map>
      31                 :             : #include <optional>
      32                 :             : #include <string>
      33                 :             : #include <string_view>
      34                 :             : #include <utility>
      35                 :             : #include <vector>
      36                 :             : 
      37                 :             : using common::FeeModeFromString;
      38                 :             : using common::FeeModesDetail;
      39                 :             : using common::InvalidEstimateModeErrorMessage;
      40                 :             : using node::NodeContext;
      41                 :             : 
      42                 :          86 : static RPCMethod estimatesmartfee()
      43                 :             : {
      44                 :          86 :     return RPCMethod{
      45                 :          86 :         "estimatesmartfee",
      46         [ +  - ]:         172 :         "Estimates the approximate fee per kilobyte needed for a transaction to begin\n"
      47                 :             :         "confirmation within conf_target blocks if possible and return the number of blocks\n"
      48                 :             :         "for which the estimate is valid. Uses virtual transaction size as defined\n"
      49                 :             :         "in BIP 141 (witness data is discounted).\n",
      50                 :             :         {
      51   [ +  -  +  - ]:         172 :             {"conf_target", RPCArg::Type::NUM, RPCArg::Optional::NO, "Confirmation target in blocks (1 - 1008)"},
      52   [ +  -  +  - ]:         172 :             {"estimate_mode", RPCArg::Type::STR, RPCArg::Default{"economical"}, "The fee estimate mode.\n"
      53   [ +  -  +  -  :         172 :               + FeeModesDetail(std::string("default mode will be used"))},
                   +  - ]
      54   [ +  -  +  - ]:         172 :             {"options", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "",
      55                 :             :                 {
      56   [ +  -  +  - ]:         172 :                     {"fee_rate_estimator", RPCArg::Type::STR, RPCArg::Default{"auto"},
      57         [ +  - ]:         172 :                      "Selects which fee rate estimator to use.\n"
      58                 :             :                      "\"auto\" (the default) combines both estimators, returning the lower of the block policy and\n"
      59                 :             :                      "mempool fee rate estimates. If the mempool fee rate estimator cannot produce an estimate, the\n"
      60                 :             :                      "block policy fee rate estimate is returned instead. An error is returned only if the block\n"
      61                 :             :                      "policy fee rate estimate is unavailable.\n"
      62                 :             :                      "\"block_policy\" uses only the block policy fee rate estimator.\n"
      63                 :             :                      "\"mempool_policy\" uses only the mempool fee rate estimator."},
      64   [ +  -  +  - ]:         172 :                     {"verbosity", RPCArg::Type::NUM, RPCArg::Default{1},
      65         [ +  - ]:         172 :                      "1 returns feerate or errors. 2 also returns \"mempool_health_statistics\"."},
      66                 :             :                 },
      67                 :             :             },
      68                 :             :         },
      69         [ +  - ]:         172 :         RPCResult{
      70   [ +  -  +  - ]:         172 :             RPCResult::Type::OBJ, "", "",
      71                 :             :             {
      72   [ +  -  +  - ]:         172 :                 {RPCResult::Type::NUM, "feerate", /*optional=*/true, "estimate fee rate in " + CURRENCY_UNIT + "/kvB (only present if no errors were encountered)"},
      73   [ +  -  +  - ]:         172 :                 {RPCResult::Type::STR, "estimator", /*optional=*/true, "the fee estimator used to produce the result (only present for successful estimates when fee_rate_estimator is \"auto\")"},
      74   [ +  -  +  - ]:         172 :                 {RPCResult::Type::ARR, "errors", /*optional=*/true, "Errors encountered during processing (if there are any)",
      75                 :             :                     {
      76   [ +  -  +  - ]:         172 :                         {RPCResult::Type::STR, "", "error"},
      77                 :             :                     }},
      78   [ +  -  +  - ]:         172 :                 {RPCResult::Type::NUM, "blocks", "the confirmation target in blocks for the returned fee rate estimate.\n"
      79                 :             :                 "For the block policy fee rate estimator, this is the target the estimate was found at, clamped to at\n"
      80                 :             :                 "least 2 and at most the estimator's maximum usable target. For the mempool fee rate\n"
      81                 :             :                 "estimator, it is always 2."},
      82   [ +  -  +  - ]:         172 :                 {RPCResult::Type::ARR, "mempool_health_statistics", /*optional=*/true, "Health statistics for the most recently mined blocks tracked by the mempool fee rate estimator (only present when verbosity >= 2)",
      83                 :             :                     {
      84   [ +  -  +  - ]:         172 :                         {RPCResult::Type::OBJ, "", "",
      85                 :             :                             {
      86   [ +  -  +  - ]:         172 :                                 {RPCResult::Type::NUM, "block_height", "Block height"},
      87   [ +  -  +  - ]:         172 :                                 {RPCResult::Type::NUM, "block_weight", "Total weight of non-coinbase transactions in the block"},
      88   [ +  -  +  - ]:         172 :                                 {RPCResult::Type::NUM, "mempool_txs_weight", "Total weight of transactions removed from the mempool for this block"},
      89                 :             :                             }},
      90                 :             :                     }},
      91   [ +  -  +  -  :        2150 :         }},
          +  -  +  -  +  
          -  +  +  +  +  
          +  +  +  +  -  
          -  -  -  -  -  
                   -  - ]
      92                 :          86 :         RPCExamples{
      93   [ +  -  +  -  :         172 :             HelpExampleCli("estimatesmartfee", "6") +
                   +  - ]
      94   [ +  -  +  -  :         258 :             HelpExampleRpc("estimatesmartfee", "6")
             +  -  +  - ]
      95         [ +  - ]:          86 :         },
      96                 :          86 :         [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
      97                 :             :         {
      98                 :           0 :             FeeRateEstimatorManager& fee_estimator_man = EnsureAnyFeeEstimatorMan(request.context);
      99                 :           0 :             const NodeContext& node = EnsureAnyNodeContext(request.context);
     100                 :           0 :             const CTxMemPool& mempool = EnsureMemPool(node);
     101                 :             : 
     102                 :           0 :             CHECK_NONFATAL(mempool.m_opts.signals)->SyncWithValidationInterfaceQueue();
     103                 :           0 :             unsigned int max_target = fee_estimator_man.MaximumTarget();
     104                 :           0 :             unsigned int conf_target = ParseConfirmTarget(request.params[0], max_target);
     105                 :           0 :             FeeEstimateMode fee_mode;
     106         [ #  # ]:           0 :             if (!FeeModeFromString(self.Arg<std::string_view>("estimate_mode"), fee_mode)) {
     107   [ #  #  #  # ]:           0 :                 throw JSONRPCError(RPC_INVALID_PARAMETER, InvalidEstimateModeErrorMessage());
     108                 :             :             }
     109         [ #  # ]:           0 :             const UniValue options{request.params[2].isNull() ? UniValue::VOBJ : request.params[2]};
     110   [ #  #  #  #  :           0 :             RPCTypeCheckObj(options,
                   #  # ]
     111                 :             :                             {
     112         [ #  # ]:           0 :                                 {"fee_rate_estimator", UniValueType(UniValue::VSTR)},
     113         [ #  # ]:           0 :                                 {"verbosity", UniValueType(UniValue::VNUM)},
     114                 :             :                             }, /*fAllowNull=*/true, /*fStrict=*/true);
     115         [ #  # ]:           0 :             const auto parsed_fee_rate_estimator{FeeRateEstimatorTypeFromString(
     116   [ #  #  #  #  :           0 :                 options["fee_rate_estimator"].isNull() ? "auto" : options["fee_rate_estimator"].get_str())};
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                #  #  # ]
     117         [ #  # ]:           0 :             if (!parsed_fee_rate_estimator) {
     118   [ #  #  #  # ]:           0 :                 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid fee_rate_estimator parameter, must be one of: \"auto\", \"block_policy\", \"mempool_policy\"");
     119                 :             :             }
     120         [ #  # ]:           0 :             const FeeRateEstimatorType fee_rate_estimator{*parsed_fee_rate_estimator};
     121                 :           0 :             bool conservative{fee_mode == FeeEstimateMode::CONSERVATIVE};
     122   [ #  #  #  #  :           0 :             int verbosity{ParseVerbosity(options["verbosity"], /*default_verbosity=*/1, /*allow_bool=*/false)};
                   #  # ]
     123                 :           0 :             UniValue result(UniValue::VOBJ);
     124                 :           0 :             UniValue errors(UniValue::VARR);
     125         [ #  # ]:           0 :             const auto estimate{fee_estimator_man.GetFeeRateEstimate(fee_rate_estimator, conf_target, conservative)};
     126         [ #  # ]:           0 :             if (estimate) {
     127         [ #  # ]:           0 :                 const CFeeRate min_mempool_feerate{mempool.GetMinFee()};
     128                 :           0 :                 const CFeeRate min_relay_feerate{mempool.m_opts.min_relay_feerate};
     129         [ #  # ]:           0 :                 const auto fee_rate{std::max({CFeeRate(estimate->feerate), min_mempool_feerate, min_relay_feerate})};
     130   [ #  #  #  #  :           0 :                 result.pushKV("feerate", ValueFromAmount(fee_rate.GetFeePerK()));
                   #  # ]
     131                 :             :             } else {
     132   [ #  #  #  # ]:           0 :                 errors.push_back(estimate.error().reason);
     133   [ #  #  #  # ]:           0 :                 result.pushKV("errors", std::move(errors));
     134                 :             :             }
     135   [ #  #  #  # ]:           0 :             if (estimate && fee_rate_estimator == FeeRateEstimatorType::AUTO) {
     136   [ #  #  #  #  :           0 :                 result.pushKV("estimator", FeeRateEstimatorTypeToString(estimate->feerate_estimator));
             #  #  #  # ]
     137                 :             :             }
     138                 :           0 :             const FeeRateEstimation& estimation{FeeRateEstimationRef(estimate)};
     139   [ #  #  #  #  :           0 :             result.pushKV("blocks", estimation.returned_target);
                   #  # ]
     140         [ #  # ]:           0 :             if (verbosity >= 2) {
     141                 :           0 :                 UniValue mempool_health_stats(UniValue::VARR);
     142         [ #  # ]:           0 :                 const auto blocks_data = fee_estimator_man.MempoolPolicyEstimatorBlocksStats();
     143         [ #  # ]:           0 :                 for (auto it = blocks_data.rbegin(); it != blocks_data.rend(); ++it) {
     144                 :           0 :                     UniValue entry(UniValue::VOBJ);
     145   [ #  #  #  #  :           0 :                     entry.pushKV("block_height", it->m_height);
                   #  # ]
     146   [ #  #  #  #  :           0 :                     entry.pushKV("block_weight", it->m_block_weight);
                   #  # ]
     147   [ #  #  #  #  :           0 :                     entry.pushKV("mempool_txs_weight", it->m_removed_block_txs_weight);
                   #  # ]
     148         [ #  # ]:           0 :                     mempool_health_stats.push_back(std::move(entry));
     149                 :           0 :                 }
     150   [ #  #  #  # ]:           0 :                 result.pushKV("mempool_health_statistics", std::move(mempool_health_stats));
     151                 :           0 :             }
     152                 :           0 :             return result;
     153   [ #  #  #  #  :           0 :         },
             #  #  #  # ]
     154   [ +  -  +  -  :         946 :     };
          +  -  +  +  +  
             +  -  -  -  
                      - ]
     155   [ +  -  +  -  :        2580 : }
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  -  -  -  -  
             -  -  -  - ]
     156                 :             : 
     157                 :         516 : static std::vector<RPCResult> FeeRateBucketDoc(bool elide = false)
     158                 :             : {
     159                 :         516 :     auto fields = std::vector<RPCResult>{
     160   [ +  -  +  - ]:        1032 :         {RPCResult::Type::NUM, "startrange", "start of feerate range"},
     161   [ +  -  +  - ]:        1032 :         {RPCResult::Type::NUM, "endrange", "end of feerate range"},
     162   [ +  -  +  - ]:        1032 :         {RPCResult::Type::NUM, "withintarget", "number of txs over history horizon in the feerate range that were confirmed within target"},
     163   [ +  -  +  - ]:        1032 :         {RPCResult::Type::NUM, "totalconfirmed", "number of txs over history horizon in the feerate range that were confirmed at any point"},
     164   [ +  -  +  - ]:        1032 :         {RPCResult::Type::NUM, "inmempool", "current number of txs in mempool in the feerate range unconfirmed for at least target blocks"},
     165   [ +  -  +  - ]:        1032 :         {RPCResult::Type::NUM, "leftmempool", "number of txs over history horizon in the feerate range that left mempool unconfirmed after target"},
     166   [ +  -  +  +  :        7224 :     };
                   -  - ]
     167   [ +  +  +  -  :        1290 :     return elide ? ElideGroup(std::move(fields)) : fields;
          +  -  +  -  +  
                +  -  - ]
     168   [ +  -  +  -  :        6708 : }
          +  -  +  -  +  
             -  +  -  -  
                      - ]
     169                 :             : 
     170                 :         258 : static std::vector<RPCResult> FeeEstimateHorizonDoc(bool elide = false)
     171                 :             : {
     172                 :         258 :     auto fields = std::vector<RPCResult>{
     173   [ +  -  +  - ]:         516 :         {RPCResult::Type::NUM, "feerate", /*optional=*/true, "estimate fee rate in " + CURRENCY_UNIT + "/kvB"},
     174   [ +  -  +  - ]:         516 :         {RPCResult::Type::NUM, "decay", "exponential decay (per block) for historical moving average of confirmation data"},
     175   [ +  -  +  - ]:         516 :         {RPCResult::Type::NUM, "scale", "The resolution of confirmation targets at this time horizon"},
     176   [ +  -  +  -  :         516 :         {RPCResult::Type::OBJ, "pass", /*optional=*/true, "information about the lowest range of feerates to succeed in meeting the threshold", FeeRateBucketDoc()},
                   +  - ]
     177   [ +  -  +  -  :         516 :         {RPCResult::Type::OBJ, "fail", /*optional=*/true, "information about the highest range of feerates to fail to meet the threshold", FeeRateBucketDoc(/*elide=*/true)},
                   +  - ]
     178   [ +  -  +  - ]:         516 :         {RPCResult::Type::ARR, "errors", /*optional=*/true, "Errors encountered during processing (if there are any)",
     179                 :             :         {
     180   [ +  -  +  - ]:         516 :             {RPCResult::Type::STR, "", "error"},
     181                 :             :         }},
     182   [ +  -  +  -  :        3870 :     };
          +  +  +  +  -  
                -  -  - ]
     183   [ +  +  +  -  :         688 :     return elide ? ElideGroup(std::move(fields)) : fields;
          +  -  +  -  +  
                +  -  - ]
     184   [ +  -  +  -  :        3870 : }
          +  -  +  -  +  
          -  +  -  +  -  
                   -  - ]
     185                 :             : 
     186                 :          86 : static RPCMethod estimaterawfee()
     187                 :             : {
     188                 :          86 :     return RPCMethod{
     189                 :          86 :         "estimaterawfee",
     190         [ +  - ]:         172 :         "WARNING: This interface is unstable and may disappear or change!\n"
     191                 :             :         "\nWARNING: This is an advanced API call that is tightly coupled to the specific\n"
     192                 :             :         "implementation of fee estimation. The parameters it can be called with\n"
     193                 :             :         "and the results it returns will change if the internal implementation changes.\n"
     194                 :             :         "\nEstimates the approximate fee per kilobyte needed for a transaction to begin\n"
     195                 :             :         "confirmation within conf_target blocks if possible. Uses virtual transaction size as\n"
     196                 :             :         "defined in BIP 141 (witness data is discounted).\n",
     197                 :             :         {
     198   [ +  -  +  - ]:         172 :             {"conf_target", RPCArg::Type::NUM, RPCArg::Optional::NO, "Confirmation target in blocks (1 - 1008)"},
     199   [ +  -  +  -  :         258 :             {"threshold", RPCArg::Type::NUM, RPCArg::Default{0.95}, "The proportion of transactions in a given feerate range that must have been\n"
                   +  - ]
     200                 :             :             "confirmed within conf_target in order to consider those feerates as high enough and proceed to check\n"
     201                 :             :             "lower buckets."},
     202                 :             :         },
     203         [ +  - ]:         172 :         RPCResult{
     204   [ +  -  +  - ]:         172 :             RPCResult::Type::OBJ, "", "Results are returned for any horizon which tracks blocks up to the confirmation target",
     205                 :             :             {
     206   [ +  -  +  - ]:         172 :                 {RPCResult::Type::OBJ, "short", /*optional=*/true, "estimate for short time horizon",
     207         [ +  - ]:         172 :                     FeeEstimateHorizonDoc()},
     208   [ +  -  +  - ]:         172 :                 {RPCResult::Type::OBJ, "medium", /*optional=*/true, "estimate for medium time horizon",
     209         [ +  - ]:         172 :                     FeeEstimateHorizonDoc(/*elide=*/true)},
     210   [ +  -  +  - ]:         172 :                 {RPCResult::Type::OBJ, "long", /*optional=*/true, "estimate for long time horizon",
     211         [ +  - ]:         172 :                     FeeEstimateHorizonDoc(/*elide=*/true)},
     212   [ +  -  +  -  :         430 :             }},
             +  +  -  - ]
     213                 :          86 :         RPCExamples{
     214   [ +  -  +  -  :         172 :             HelpExampleCli("estimaterawfee", "6 0.9")
                   +  - ]
     215         [ +  - ]:          86 :         },
     216                 :          86 :         [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
     217                 :             :         {
     218                 :           0 :             FeeRateEstimatorManager& fee_estimator_man = EnsureAnyFeeEstimatorMan(request.context);
     219                 :           0 :             const NodeContext& node = EnsureAnyNodeContext(request.context);
     220                 :             : 
     221                 :           0 :             CHECK_NONFATAL(node.validation_signals)->SyncWithValidationInterfaceQueue();
     222                 :           0 :             unsigned int max_target = fee_estimator_man.MaximumTarget();
     223                 :           0 :             unsigned int conf_target = ParseConfirmTarget(request.params[0], max_target);
     224                 :           0 :             double threshold = 0.95;
     225         [ #  # ]:           0 :             if (!request.params[1].isNull()) {
     226                 :           0 :                 threshold = request.params[1].get_real();
     227                 :             :             }
     228   [ #  #  #  # ]:           0 :             if (threshold < 0 || threshold > 1) {
     229   [ #  #  #  # ]:           0 :                 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid threshold");
     230                 :             :             }
     231                 :             : 
     232                 :           0 :             UniValue result(UniValue::VOBJ);
     233                 :             : 
     234         [ #  # ]:           0 :             for (const FeeEstimateHorizon horizon : ALL_FEE_ESTIMATE_HORIZONS) {
     235                 :           0 :                 CFeeRate feeRate;
     236                 :           0 :                 EstimationResult buckets;
     237                 :             : 
     238                 :             :                 // Only output results for horizons which track the target
     239   [ #  #  #  # ]:           0 :                 if (conf_target > fee_estimator_man.BlockPolicyHighestTargetTracked(horizon)) continue;
     240                 :             : 
     241         [ #  # ]:           0 :                 feeRate = fee_estimator_man.BlockPolicyEstimateRawFee(conf_target, threshold, horizon, &buckets);
     242                 :           0 :                 UniValue horizon_result(UniValue::VOBJ);
     243                 :           0 :                 UniValue errors(UniValue::VARR);
     244                 :           0 :                 UniValue passbucket(UniValue::VOBJ);
     245   [ #  #  #  #  :           0 :                 passbucket.pushKV("startrange", round(buckets.pass.start));
                   #  # ]
     246   [ #  #  #  #  :           0 :                 passbucket.pushKV("endrange", round(buckets.pass.end));
                   #  # ]
     247   [ #  #  #  #  :           0 :                 passbucket.pushKV("withintarget", round(buckets.pass.withinTarget * 100.0) / 100.0);
                   #  # ]
     248   [ #  #  #  #  :           0 :                 passbucket.pushKV("totalconfirmed", round(buckets.pass.totalConfirmed * 100.0) / 100.0);
                   #  # ]
     249   [ #  #  #  #  :           0 :                 passbucket.pushKV("inmempool", round(buckets.pass.inMempool * 100.0) / 100.0);
                   #  # ]
     250   [ #  #  #  #  :           0 :                 passbucket.pushKV("leftmempool", round(buckets.pass.leftMempool * 100.0) / 100.0);
                   #  # ]
     251                 :           0 :                 UniValue failbucket(UniValue::VOBJ);
     252   [ #  #  #  #  :           0 :                 failbucket.pushKV("startrange", round(buckets.fail.start));
                   #  # ]
     253   [ #  #  #  #  :           0 :                 failbucket.pushKV("endrange", round(buckets.fail.end));
                   #  # ]
     254   [ #  #  #  #  :           0 :                 failbucket.pushKV("withintarget", round(buckets.fail.withinTarget * 100.0) / 100.0);
                   #  # ]
     255   [ #  #  #  #  :           0 :                 failbucket.pushKV("totalconfirmed", round(buckets.fail.totalConfirmed * 100.0) / 100.0);
                   #  # ]
     256   [ #  #  #  #  :           0 :                 failbucket.pushKV("inmempool", round(buckets.fail.inMempool * 100.0) / 100.0);
                   #  # ]
     257   [ #  #  #  #  :           0 :                 failbucket.pushKV("leftmempool", round(buckets.fail.leftMempool * 100.0) / 100.0);
                   #  # ]
     258                 :             : 
     259                 :             :                 // CFeeRate(0) is used to indicate error as a return value from estimateRawFee
     260         [ #  # ]:           0 :                 if (feeRate != CFeeRate(0)) {
     261   [ #  #  #  #  :           0 :                     horizon_result.pushKV("feerate", ValueFromAmount(feeRate.GetFeePerK()));
                   #  # ]
     262   [ #  #  #  #  :           0 :                     horizon_result.pushKV("decay", buckets.decay);
                   #  # ]
     263   [ #  #  #  #  :           0 :                     horizon_result.pushKV("scale", buckets.scale);
                   #  # ]
     264   [ #  #  #  # ]:           0 :                     horizon_result.pushKV("pass", std::move(passbucket));
     265                 :             :                     // buckets.fail.start == -1 indicates that all buckets passed, there is no fail bucket to output
     266   [ #  #  #  #  :           0 :                     if (buckets.fail.start != -1) horizon_result.pushKV("fail", std::move(failbucket));
                   #  # ]
     267                 :             :                 } else {
     268                 :             :                     // Output only information that is still meaningful in the event of error
     269   [ #  #  #  #  :           0 :                     horizon_result.pushKV("decay", buckets.decay);
                   #  # ]
     270   [ #  #  #  #  :           0 :                     horizon_result.pushKV("scale", buckets.scale);
                   #  # ]
     271   [ #  #  #  # ]:           0 :                     horizon_result.pushKV("fail", std::move(failbucket));
     272   [ #  #  #  # ]:           0 :                     errors.push_back("Insufficient data or no feerate found which meets threshold");
     273   [ #  #  #  # ]:           0 :                     horizon_result.pushKV("errors", std::move(errors));
     274                 :             :                 }
     275   [ #  #  #  # ]:           0 :                 result.pushKV(StringForFeeEstimateHorizon(horizon), std::move(horizon_result));
     276                 :           0 :             }
     277                 :           0 :             return result;
     278                 :           0 :         },
     279   [ +  -  +  -  :         516 :     };
             +  +  -  - ]
     280   [ +  -  +  -  :         860 : }
          +  -  +  -  +  
             -  -  -  -  
                      - ]
     281                 :             : 
     282                 :         189 : void RegisterFeeRPCCommands(CRPCTable& t)
     283                 :             : {
     284                 :         189 :     static const CRPCCommand commands[]{
     285         [ +  - ]:          86 :         {"util", &estimatesmartfee},
     286         [ +  - ]:          86 :         {"hidden", &estimaterawfee},
     287   [ +  +  +  -  :         275 :     };
          +  -  +  -  -  
                      - ]
     288         [ +  + ]:         567 :     for (const auto& c : commands) {
     289                 :         378 :         t.appendCommand(c.name, &c);
     290                 :             :     }
     291                 :         189 : }
        

Generated by: LCOV version 2.0-1