33#include <system_error>
58 return "Half Target 60% Threshold";
60 return "Target 85% Threshold";
62 return "Double Target 95% Threshold";
64 return "Conservative Double Target longer horizon";
71struct EncodedDoubleFormatter
73 template<
typename Stream>
void Ser(Stream &s,
double v)
78 template<
typename Stream>
void Unser(Stream& s,
double& v)
164 unsigned int bucketIndex,
bool inBlock);
205 for (
unsigned int i = 0; i <
maxPeriods; i++) {
219 for (
unsigned int i = 0; i <
unconfTxs.size(); i++) {
228 for (
unsigned int j = 0;
j <
buckets.size();
j++) {
252 for (
unsigned int j = 0;
j <
buckets.size();
j++) {
253 for (
unsigned int i = 0; i <
confAvg.size(); i++) {
410 LogDebug(
BCLog::ESTIMATEFEE,
"FeeEst: %d > %.0f%% decay %.5f: feerate: %g from (%g - %g) %.2f%% %.1f/(%.1f %d mem %.1f out) Fail: (%g - %g) %.2f%% %.1f/(%.1f %d mem %.1f out)\n",
449 throw std::runtime_error(
"Corrupt estimates file. Decay must be between 0 and 1 (non-inclusive)");
453 throw std::runtime_error(
"Corrupt estimates file. Scale must be non-zero");
458 throw std::runtime_error(
"Corrupt estimates file. Mismatch in feerate average bucket count");
462 throw std::runtime_error(
"Corrupt estimates file. Mismatch in tx count bucket count");
469 throw std::runtime_error(
"Corrupt estimates file. Must maintain estimates for between 1 and 1008 (one week) confirms");
471 for (
unsigned int i = 0; i <
maxPeriods; i++) {
473 throw std::runtime_error(
"Corrupt estimates file. Mismatch in feerate conf average bucket count");
479 throw std::runtime_error(
"Corrupt estimates file. Mismatch in confirms tracked for failures");
481 for (
unsigned int i = 0; i <
maxPeriods; i++) {
483 throw std::runtime_error(
"Corrupt estimates file. Mismatch in one of failure average bucket counts");
549 std::map<Txid, TxStatsInfo>::iterator pos =
mapMemPoolTxs.find(hash);
565 size_t bucketIndex = 0;
573 assert(bucketMap.size() == buckets.size());
603 const auto& hash = tx.
info.
m_tx->GetHash();
636 unsigned int bucketIndex =
feeStats->NewTx(txHeight,
static_cast<double>(
feeRate.GetFeePerK()));
713 LogDebug(
BCLog::ESTIMATEFEE,
"Blockpolicy estimates updated by %u of %u block txs, since last block %u of %u tracked, mempool map size %u, max target %u from %s\n",
951 LogDebug(
BCLog::ESTIMATEFEE,
"estimateSmartFee Selected feerate: %g Tgt: %d (requested %d) Reason: \"%s\" Decay %.5f: Estimation: (%g - %g) %.2f%% %.1f/(%.1f %d mem %.1f out) Fail: (%g - %g) %.2f%% %.1f/(%.1f %d mem %.1f out)",
954 (
feeCalc->est.pass.totalConfirmed +
feeCalc->est.pass.inMempool +
feeCalc->est.pass.leftMempool) > 0.0 ? 100 *
feeCalc->est.pass.withinTarget / (
feeCalc->est.pass.totalConfirmed +
feeCalc->est.pass.inMempool +
feeCalc->est.pass.leftMempool) : 0.0,
957 (
feeCalc->est.fail.totalConfirmed +
feeCalc->est.fail.inMempool +
feeCalc->est.fail.leftMempool) > 0.0 ? 100 *
feeCalc->est.fail.withinTarget / (
feeCalc->est.fail.totalConfirmed +
feeCalc->est.fail.inMempool +
feeCalc->est.fail.leftMempool) : 0.0,
986 std::error_code error;
1024 catch (
const std::exception&) {
1025 LogWarning(
"Unable to write policy estimator data (non-fatal)");
1053 throw std::runtime_error(
"Corrupt estimates file. Historical block range for estimates is invalid");
1059 throw std::runtime_error(
"Corrupt estimates file. Must have between 2 and 1000 feerate buckets");
1073 for (
unsigned int i = 0; i < buckets.size(); i++) {
1074 bucketMap[buckets[i]] = i;
1086 catch (
const std::exception&
e) {
1087 LogWarning(
"Unable to read policy estimator data (non-fatal): %s",
e.what());
1103 const auto endclear{SteadyClock::now()};
1110 auto now{fs::file_time_type::clock::now()};
1111 return std::chrono::duration_cast<std::chrono::hours>(now -
file_time);
1147 return static_cast<CAmount>(*it);
int64_t CAmount
Amount in satoshis (Can be negative)
std::string StringForBlockPolicyEstimateReason(BlockPolicyEstimateReason reason)
constexpr std::chrono::hours MAX_FILE_AGE
Block policy estimate files that are more than 60 hours (2.5 days) old will not be read,...
BlockPolicyEstimateReason
Non-refcounted RAII wrapper for FILE*.
void processTransaction(const NewMempoolTransactionInfo &tx) EXCLUSIVE_LOCKS_REQUIRED(!m_cs_fee_estimator)
Process a transaction accepted to the mempool.
static constexpr unsigned int LONG_SCALE
static constexpr double SUCCESS_PCT
Require greater than 85% of X feerate transactions to be confirmed within Y blocks.
static constexpr double MIN_BUCKET_FEERATE
Minimum and Maximum values for tracking feerates The MIN_BUCKET_FEERATE should just be set to the low...
double estimateCombinedFee(unsigned int confTarget, double successThreshold, bool checkShorterHorizon, EstimationResult *result) const EXCLUSIVE_LOCKS_REQUIRED(m_cs_fee_estimator)
Helper for estimateSmartFee.
static constexpr double FEE_SPACING
Spacing of FeeRate buckets We have to lump transactions into buckets based on feerate,...
void Flush() EXCLUSIVE_LOCKS_REQUIRED(!m_cs_fee_estimator)
Drop still unconfirmed transactions and record current estimations, if the fee estimation file is pre...
static constexpr double SUFFICIENT_FEETXS
Require an avg of 0.1 tx in the combined feerate bucket per block to have stat significance.
bool removeTx(Txid hash) EXCLUSIVE_LOCKS_REQUIRED(!m_cs_fee_estimator)
Remove a transaction from the mempool tracking stats for non BLOCK removal reasons.
static constexpr double MAX_BUCKET_FEERATE
CBlockPolicyEstimator(const fs::path &estimation_filepath, bool read_stale_estimates)
Create new BlockPolicyEstimator and initialize stats tracking classes with default values.
void FlushFeeEstimates() EXCLUSIVE_LOCKS_REQUIRED(!m_cs_fee_estimator)
Record current fee estimations.
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.
static constexpr unsigned int LONG_BLOCK_PERIODS
Track confirm delays up to 1008 blocks for long horizon.
bool Write(AutoFile &fileout) const EXCLUSIVE_LOCKS_REQUIRED(!m_cs_fee_estimator)
Write estimation data to a file.
static constexpr double SHORT_DECAY
Decay of .962 is a half-life of 18 blocks or about 3 hours.
std::chrono::hours GetFeeEstimatorFileAge()
Calculates the age of the file, since last modified.
virtual unsigned int HighestTargetTracked(FeeEstimateHorizon horizon) const EXCLUSIVE_LOCKS_REQUIRED(!m_cs_fee_estimator)
Calculation of highest target that estimates are tracked for.
static constexpr double LONG_DECAY
Decay of .99931 is a half-life of 1008 blocks or about 1 week.
double estimateConservativeFee(unsigned int doubleTarget, EstimationResult *result) const EXCLUSIVE_LOCKS_REQUIRED(m_cs_fee_estimator)
Helper for estimateSmartFee.
static constexpr double HALF_SUCCESS_PCT
Require greater than 60% of X feerate transactions to be confirmed within Y/2 blocks.
static constexpr double MED_DECAY
Decay of .9952 is a half-life of 144 blocks or about 1 day.
CFeeRate estimateFee(int confTarget) const EXCLUSIVE_LOCKS_REQUIRED(!m_cs_fee_estimator)
DEPRECATED.
bool _removeTx(const Txid &hash, bool inBlock) EXCLUSIVE_LOCKS_REQUIRED(m_cs_fee_estimator)
A non-thread-safe helper for the removeTx function.
unsigned int MaxUsableEstimate() const EXCLUSIVE_LOCKS_REQUIRED(m_cs_fee_estimator)
Calculation of highest target that reasonable estimate can be provided for.
util::Expected< FeeRateEstimation, FeeRateEstimationError > EstimateFeeRate(int target, bool conservative) const EXCLUSIVE_LOCKS_REQUIRED(!m_cs_fee_estimator)
Estimate the feerate needed to confirm within target blocks; wraps estimateSmartFee into a FeeRateEst...
static constexpr unsigned int SHORT_SCALE
unsigned int BlockSpan() const EXCLUSIVE_LOCKS_REQUIRED(m_cs_fee_estimator)
Number of blocks of data recorded while fee estimates have been running.
bool Read(AutoFile &filein) EXCLUSIVE_LOCKS_REQUIRED(!m_cs_fee_estimator)
Read estimation data from a file.
static constexpr unsigned int SHORT_BLOCK_PERIODS
Track confirm delays up to 12 blocks for short horizon.
static constexpr double DOUBLE_SUCCESS_PCT
Require greater than 95% of X feerate transactions to be confirmed within 2 * Y blocks.
unsigned int HistoricalBlockSpan() const EXCLUSIVE_LOCKS_REQUIRED(m_cs_fee_estimator)
Number of blocks of recorded fee estimate data represented in saved data file.
void FlushUnconfirmed() EXCLUSIVE_LOCKS_REQUIRED(!m_cs_fee_estimator)
Empty mempool transactions on shutdown to record failure to confirm for txs still in mempool.
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,...
unsigned int MaximumTarget() const EXCLUSIVE_LOCKS_REQUIRED(!m_cs_fee_estimator)
Return the highest confirmation target for which an estimate can be provided.
static constexpr unsigned int OLDEST_ESTIMATE_HISTORY
Historical estimates that are older than this aren't valid.
static constexpr double SUFFICIENT_TXS_SHORT
Require an avg of 0.5 tx when using short decay since there are fewer blocks considered.
bool processBlockTx(unsigned int nBlockHeight, const RemovedMempoolTransactionInfo &tx) EXCLUSIVE_LOCKS_REQUIRED(m_cs_fee_estimator)
Process a transaction confirmed in a block.
static constexpr unsigned int MED_SCALE
static constexpr unsigned int MED_BLOCK_PERIODS
Track confirm delays up to 48 blocks for medium horizon.
const fs::path m_estimation_filepath
virtual ~CBlockPolicyEstimator()
void processBlock(const std::vector< RemovedMempoolTransactionInfo > &txs_removed_for_block, unsigned int nBlockHeight) EXCLUSIVE_LOCKS_REQUIRED(!m_cs_fee_estimator)
Process all the transactions that have been included in a block.
Fee rate in satoshis per virtualbyte: CAmount / vB the feerate is represented internally as FeeFrac.
const std::set< double > m_fee_set
CAmount round(CAmount currentMinFee) EXCLUSIVE_LOCKS_REQUIRED(!m_insecure_rand_mutex)
Quantize a minimum fee for privacy purpose before broadcast.
FeeFilterRounder(const CFeeRate &min_incremental_fee, FastRandomContext &rng)
Create new FeeFilterRounder.
Mutex m_insecure_rand_mutex
We will instantiate an instance of this class to track transactions that were included in a block.
void removeTx(unsigned int entryHeight, unsigned int nBestSeenHeight, unsigned int bucketIndex, bool inBlock)
Remove a transaction from mempool tracking stats.
std::vector< std::vector< double > > failAvg
TxConfirmStats(const std::vector< double > &defaultBuckets, const std::map< double, unsigned int > &defaultBucketMap, unsigned int maxPeriods, double decay, unsigned int scale)
Create new TxConfirmStats.
unsigned int GetMaxConfirms() const
Return the max number of confirms we're tracking.
void ClearCurrent(unsigned int nBlockHeight)
Roll the circular buffer for unconfirmed txs.
void Record(int blocksToConfirm, double val)
Record a new transaction data point in the current block stats.
void resizeInMemoryCounters(size_t newbuckets)
std::vector< double > txCtAvg
std::vector< int > oldUnconfTxs
void UpdateMovingAverages()
Update our estimates by decaying our historical moving average and updating with the data gathered fr...
const std::map< double, unsigned int > & bucketMap
const std::vector< double > & buckets
void Read(AutoFile &filein, size_t numBuckets)
Read saved state of estimation data from a file and replace all internal data structures and variable...
std::vector< std::vector< double > > confAvg
void Write(AutoFile &fileout) const
Write state of estimation data to a file.
std::vector< std::vector< int > > unconfTxs
unsigned int NewTx(unsigned int nBlockHeight, double val)
Record a new transaction entering the mempool.
std::vector< double > m_feerate_avg
double EstimateMedianVal(int confTarget, double sufficientTxVal, double minSuccess, unsigned int nBlockHeight, EstimationResult *result=nullptr) const
Calculate a feerate estimate.
The util::Expected class provides a standard way for low-level functions to return either error value...
static std::string PathToString(const path &path)
Convert path object to a byte string.
#define LogDebug(category,...)
static util::Unexpected< FeeRateEstimationError > EstimationError(std::string error)
Build the error result for a failed mempool fee rate estimation.
FILE * fopen(const fs::path &p, const char *mode)
static constexpr double INF_FEERATE
static std::set< double > MakeFeeSet(const CFeeRate &min_incremental_fee, double max_filter_fee_rate, double fee_filter_spacing)
std::string StringForBlockPolicyEstimateReason(BlockPolicyEstimateReason reason)
constexpr int CURRENT_FEES_FILE_VERSION
std::string StringForFeeEstimateHorizon(FeeEstimateHorizon horizon)
uint64_t EncodeDouble(double f) noexcept
double DecodeDouble(uint64_t v) noexcept
A successful fee rate estimate returned by a fee rate estimator.
const bool m_submitted_in_package
const bool m_has_no_mempool_parents
const bool m_chainstate_is_current
const bool m_mempool_limit_bypassed
const unsigned int txHeight
const CTransactionRef m_tx
const int64_t m_virtual_transaction_size
The virtual transaction size.
#define AssertLockNotHeld(cs)
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
#define AssertLockHeld(cs)
std::string SysErrorString(int err)
Return system error string from errno value.
constexpr auto Ticks(Dur2 d)
Helper to count the seconds of a duration/time_point.