Skip to content

Commit

Permalink
rpc: create an rpc estimatefeewithforecasters
Browse files Browse the repository at this point in the history
Given a confirmation target, we use fee estimator module that call all
available fee estimator forcasters and return the fee rate with highest
confidence level that if a transaction use will likely confirm in a given
confirmation target.

Co-authored-by: willcl-ark <will@256k1.dev>
  • Loading branch information
ismaelsadeeq and willcl-ark committed Apr 24, 2024
1 parent 80306ae commit 1e26bc8
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/rpc/client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "estimatesmartfee", 0, "conf_target" },
{ "estimaterawfee", 0, "conf_target" },
{ "estimaterawfee", 1, "threshold" },
{ "estimatefeewithforecasters", 0, "conf_target" },
{ "prioritisetransaction", 1, "dummy" },
{ "prioritisetransaction", 2, "fee_delta" },
{ "setban", 2, "bantime" },
Expand Down
40 changes: 40 additions & 0 deletions src/rpc/fees.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <node/context.h>
#include <policy/feerate.h>
#include <policy/fees.h>
#include <policy/estimator.h>
#include <rpc/protocol.h>
#include <rpc/request.h>
#include <rpc/server.h>
Expand All @@ -15,6 +16,7 @@
#include <txmempool.h>
#include <univalue.h>
#include <util/fees.h>
#include <validation.h>
#include <validationinterface.h>

#include <algorithm>
Expand Down Expand Up @@ -96,6 +98,43 @@ static RPCHelpMan estimatesmartfee()
};
}

static RPCHelpMan estimatefeewithforecasters()
{
return RPCHelpMan{
"estimatefeewithforecasters",
"\nEstimates the approximate fee per kilobyte needed for a transaction to begin\n"
"confirmation within conf_target blocks if possible Uses virtual transaction size as defined\n"
"in BIP 141 (witness data is discounted). By default caches values for 30 seconds to avoid\n"
"repeatedly running expensive block-building algorithm.\n",
{
{"conf_target", RPCArg::Type::NUM, RPCArg::Optional::NO, "Confirmation target in blocks"},
},
RPCResult{
RPCResult::Type::OBJ, "", "",
{
{RPCResult::Type::NUM, "Fee rate estimate", /*optional=*/true, "estimate fee rate in " + CURRENCY_UNIT + "/kvB (only present if no errors were encountered)"},
{RPCResult::Type::ARR, "errors", /*optional=*/true, "Errors encountered during processing (if there are any)",
{{RPCResult::Type::STR, "", "error"},}
},
}},
RPCExamples{HelpExampleCli("estimatefeewithforecasters", "2") + HelpExampleRpc("estimatefeewithforecasters", "2")},
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue {
FeeEstimator& fee_estimator = EnsureAnyFeeForecasters(request.context);
const unsigned int conf_target = request.params[0].getInt<unsigned int>();
CFeeRate fee_estimate = fee_estimator.getFeeEstimateForecast(conf_target);
UniValue result(UniValue::VOBJ);
UniValue errors(UniValue::VARR);
if (fee_estimate == CFeeRate(0)) {
result.pushKV("Fee rate estimate", ValueFromAmount(fee_estimate.GetFeePerK()));
} else {
errors.push_back("Failed to get estimate from forecasters");
result.pushKV("errors", errors);
}
return result;
},
};
}

static RPCHelpMan estimaterawfee()
{
return RPCHelpMan{"estimaterawfee",
Expand Down Expand Up @@ -220,6 +259,7 @@ void RegisterFeeRPCCommands(CRPCTable& t)
{
static const CRPCCommand commands[]{
{"util", &estimatesmartfee},
{"util", &estimatefeewithforecasters},
{"hidden", &estimaterawfee},
};
for (const auto& c : commands) {
Expand Down
13 changes: 13 additions & 0 deletions src/rpc/server_util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,19 @@ CBlockPolicyEstimator& EnsureAnyFeeEstimator(const std::any& context)
return EnsureFeeEstimator(EnsureAnyNodeContext(context));
}

FeeEstimator& EnsureFeeForecasters(const NodeContext& node)
{
if (!node.fee_estimator) {
throw JSONRPCError(RPC_INTERNAL_ERROR, "Fee estimation disabled");
}
return *node.fee_estimator;
}

FeeEstimator& EnsureAnyFeeForecasters(const std::any& context)
{
return EnsureFeeForecasters(EnsureAnyNodeContext(context));
}

CConnman& EnsureConnman(const NodeContext& node)
{
if (!node.connman) {
Expand Down
3 changes: 3 additions & 0 deletions src/rpc/server_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ class AddrMan;
class ArgsManager;
class CBlockPolicyEstimator;
class CConnman;
class FeeEstimator;
class CTxMemPool;
class ChainstateManager;
class PeerManager;
Expand All @@ -30,6 +31,8 @@ ChainstateManager& EnsureChainman(const node::NodeContext& node);
ChainstateManager& EnsureAnyChainman(const std::any& context);
CBlockPolicyEstimator& EnsureFeeEstimator(const node::NodeContext& node);
CBlockPolicyEstimator& EnsureAnyFeeEstimator(const std::any& context);
FeeEstimator& EnsureFeeForecasters(const node::NodeContext& node);
FeeEstimator& EnsureAnyFeeForecasters(const std::any& context);
CConnman& EnsureConnman(const node::NodeContext& node);
PeerManager& EnsurePeerman(const node::NodeContext& node);
AddrMan& EnsureAddrman(const node::NodeContext& node);
Expand Down

0 comments on commit 1e26bc8

Please sign in to comment.