Skip to content

Commit

Permalink
rpc: use cachedEstimates in estimatefeewithmempool
Browse files Browse the repository at this point in the history
  • Loading branch information
willcl-ark committed Feb 20, 2024
1 parent c4d4bc7 commit 338d84b
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 16 deletions.
30 changes: 20 additions & 10 deletions src/policy/mempool_fees.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@ using node::GetCustomBlockFeeRateHistogram;

MemPoolPolicyEstimator::MemPoolPolicyEstimator() {}

CFeeRate MemPoolPolicyEstimator::EstimateFeeWithMemPool(Chainstate& chainstate, const CTxMemPool& mempool, unsigned int confTarget, std::string& err_message) const
CFeeRate MemPoolPolicyEstimator::EstimateFeeWithMemPool(Chainstate& chainstate, const CTxMemPool& mempool, unsigned int confTarget, const bool force, std::string& err_message) const
{
std::optional<CFeeRate> cached_fee{std::nullopt};
CFeeRate fee_rate{0};

if (confTarget > MAX_CONF_TARGET) {
err_message = strprintf("Confirmation target %s is above maximum limit of %s, mempool conditions might change and estimates above %s are unreliable.\n", confTarget, MAX_CONF_TARGET, MAX_CONF_TARGET);
Expand All @@ -25,18 +27,26 @@ CFeeRate MemPoolPolicyEstimator::EstimateFeeWithMemPool(Chainstate& chainstate,
err_message = "Mempool did not finish loading, can't get accurate fee rate estimate.";
return CFeeRate(0);
}

std::map<CFeeRate, uint64_t> mempool_fee_stats;
size_t target_weight = confTarget * DEFAULT_BLOCK_MAX_WEIGHT;
{
mempool_fee_stats = GetCustomBlockFeeRateHistogram(chainstate, &mempool, target_weight);
// Try the cache if not forced
if (!force) {
cached_fee = cache.get(confTarget);
}

if (mempool_fee_stats.empty()) {
err_message = "No transactions available in the mempool yet.";
return CFeeRate(0); // Return an appropriate default value (no txs in the mempool)
if (!cached_fee) {
// Run block builder and update cache
std::map<CFeeRate, uint64_t> mempool_fee_stats;
size_t target_weight = confTarget * DEFAULT_BLOCK_MAX_WEIGHT;
mempool_fee_stats = GetCustomBlockFeeRateHistogram(chainstate, &mempool, target_weight);
if (mempool_fee_stats.empty()) {
err_message = "No transactions available in the mempool yet.";
return CFeeRate(0); // Return an appropriate default value (no txs in the mempool)
}
cache.update(mempool_fee_stats);
fee_rate = EstimateBlockFeeRate(mempool_fee_stats, confTarget, target_weight);
} else {
// Use the cached value
fee_rate = *cached_fee;
}
auto fee_rate = EstimateBlockFeeRate(mempool_fee_stats, confTarget, target_weight);

if (fee_rate == CFeeRate(0)) {
err_message = "Insufficient mempool transactions to perform an estimate.";
Expand Down
2 changes: 1 addition & 1 deletion src/policy/mempool_fees.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ class MemPoolPolicyEstimator
* @param[out] err_message optional error message.
* @return The estimated fee rate.
*/
CFeeRate EstimateFeeWithMemPool(Chainstate& chainstate, const CTxMemPool& mempool, unsigned int confTarget, std::string& err_message) const;
CFeeRate EstimateFeeWithMemPool(Chainstate& chainstate, const CTxMemPool& mempool, unsigned int confTarget, const bool force, std::string& err_message) const;

private:
mutable CachedEstimates cache;
Expand Down
13 changes: 8 additions & 5 deletions src/rpc/fees.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,15 +101,17 @@ static RPCHelpMan estimatesmartfee()
};
}

static RPCHelpMan estimatesfeewithmempool()
static RPCHelpMan estimatefeewithmempool()
{
return RPCHelpMan{
"estimatesfeewithmempool",
"estimatefeewithmempool",
"\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).\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"},
{"force", RPCArg::Type::BOOL, RPCArg::Default{false}, "Force run block-building algorithm, bypassing any cached values."},
},
RPCResult{
RPCResult::Type::OBJ, "", "", {
Expand All @@ -126,11 +128,12 @@ static RPCHelpMan estimatesfeewithmempool()
ChainstateManager& chainman = EnsureChainman(node);
Chainstate& chainstate = chainman.ActiveChainstate();
const unsigned int conf_target = request.params[0].getInt<unsigned int>();
const bool force = request.params[1].get_bool();
CFeeRate feeRate;
std::string err_message;
{
LOCK2(cs_main, mempool.cs);
feeRate = fee_estimator.EstimateFeeWithMemPool(chainstate, mempool, conf_target, err_message);
feeRate = fee_estimator.EstimateFeeWithMemPool(chainstate, mempool, conf_target, force, err_message);
}
UniValue result(UniValue::VOBJ);
UniValue errors(UniValue::VARR);
Expand Down Expand Up @@ -271,7 +274,7 @@ void RegisterFeeRPCCommands(CRPCTable& t)
{
static const CRPCCommand commands[]{
{"util", &estimatesmartfee},
{"util", &estimatesfeewithmempool},
{"util", &estimatefeewithmempool},
{"hidden", &estimaterawfee},
};
for (const auto& c : commands) {
Expand Down

0 comments on commit 338d84b

Please sign in to comment.