diff options
author | ismaelsadeeq <ask4ismailsadiq@gmail.com> | 2023-06-14 22:32:27 +0100 |
---|---|---|
committer | fanquake <fanquake@gmail.com> | 2023-10-02 13:09:01 +0100 |
commit | 16bb9161fabee70edac4c3e64b1ff4b47945cbdd (patch) | |
tree | 77f5b2652df8a0515266ee32a2738a3bbf62b2d1 | |
parent | c4dd5989b36e6da62dedb4e0bfceade75abb0ac5 (diff) |
tx fees, policy: do not read estimates of old fee_estimates.dat
Old fee estimates could cause transactions to become stuck in the
mempool. This commit prevents the node from using stale estimates
from an old file.
Github-Pull: #27622
Rebased-From: 3eb241a141defa564c94cb95c5bbaf4c5bd9682e
-rw-r--r-- | src/policy/fees.cpp | 25 | ||||
-rw-r--r-- | src/policy/fees.h | 8 |
2 files changed, 31 insertions, 2 deletions
diff --git a/src/policy/fees.cpp b/src/policy/fees.cpp index 035896c4bd..d88ae3ae0d 100644 --- a/src/policy/fees.cpp +++ b/src/policy/fees.cpp @@ -24,6 +24,7 @@ #include <algorithm> #include <cassert> +#include <chrono> #include <cmath> #include <cstddef> #include <cstdint> @@ -545,9 +546,22 @@ CBlockPolicyEstimator::CBlockPolicyEstimator(const fs::path& estimation_filepath shortStats = std::unique_ptr<TxConfirmStats>(new TxConfirmStats(buckets, bucketMap, SHORT_BLOCK_PERIODS, SHORT_DECAY, SHORT_SCALE)); longStats = std::unique_ptr<TxConfirmStats>(new TxConfirmStats(buckets, bucketMap, LONG_BLOCK_PERIODS, LONG_DECAY, LONG_SCALE)); - // If the fee estimation file is present, read recorded estimations AutoFile est_file{fsbridge::fopen(m_estimation_filepath, "rb")}; - if (est_file.IsNull() || !Read(est_file)) { + + // Whenever the fee estimation file is not present return early + if (est_file.IsNull()) { + LogPrintf("%s is not found. Continue anyway.\n", fs::PathToString(m_estimation_filepath)); + return; + } + + std::chrono::hours file_age = GetFeeEstimatorFileAge(); + // fee estimate file must not be too old to avoid wrong fee estimates. + if (file_age > MAX_FILE_AGE) { + LogPrintf("Fee estimation file %s too old (age=%lld > %lld hours) and will not be used to avoid serving stale estimates.\n", fs::PathToString(m_estimation_filepath), Ticks<std::chrono::hours>(file_age), Ticks<std::chrono::hours>(MAX_FILE_AGE)); + return; + } + + if (!Read(est_file)) { LogPrintf("Failed to read fee estimates from %s. Continue anyway.\n", fs::PathToString(m_estimation_filepath)); } } @@ -1017,6 +1031,13 @@ void CBlockPolicyEstimator::FlushUnconfirmed() LogPrint(BCLog::ESTIMATEFEE, "Recorded %u unconfirmed txs from mempool in %gs\n", num_entries, Ticks<SecondsDouble>(endclear - startclear)); } +std::chrono::hours CBlockPolicyEstimator::GetFeeEstimatorFileAge() +{ + auto file_time = std::filesystem::last_write_time(m_estimation_filepath); + auto now = std::filesystem::file_time_type::clock::now(); + return std::chrono::duration_cast<std::chrono::hours>(now - file_time); +} + static std::set<double> MakeFeeSet(const CFeeRate& min_incremental_fee, double max_filter_fee_rate, double fee_filter_spacing) diff --git a/src/policy/fees.h b/src/policy/fees.h index a6c45839b9..a348ba05d8 100644 --- a/src/policy/fees.h +++ b/src/policy/fees.h @@ -25,6 +25,11 @@ // How often to flush fee estimates to fee_estimates.dat. static constexpr std::chrono::hours FEE_FLUSH_INTERVAL{1}; +/** fee_estimates.dat that are more than 60 hours (2.5 days) will not be read, + * as the estimates in the file are stale. + */ +static constexpr std::chrono::hours MAX_FILE_AGE{60}; + class AutoFile; class CTxMemPoolEntry; class TxConfirmStats; @@ -248,6 +253,9 @@ public: void FlushFeeEstimates() EXCLUSIVE_LOCKS_REQUIRED(!m_cs_fee_estimator); + /** Calculates the age of the file, since last modified */ + std::chrono::hours GetFeeEstimatorFileAge(); + private: mutable Mutex m_cs_fee_estimator; |