Bitcoin Core  29.1.0
P2P Digital Currency
fees.cpp
Go to the documentation of this file.
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2022 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 <policy/fees.h>
7 
8 #include <common/system.h>
9 #include <consensus/amount.h>
10 #include <kernel/mempool_entry.h>
11 #include <logging.h>
12 #include <policy/feerate.h>
13 #include <primitives/transaction.h>
14 #include <random.h>
15 #include <serialize.h>
16 #include <streams.h>
17 #include <sync.h>
18 #include <tinyformat.h>
19 #include <uint256.h>
20 #include <util/fs.h>
21 #include <util/serfloat.h>
22 #include <util/time.h>
23 
24 #include <algorithm>
25 #include <cassert>
26 #include <chrono>
27 #include <cmath>
28 #include <cstddef>
29 #include <cstdint>
30 #include <exception>
31 #include <stdexcept>
32 #include <utility>
33 
34 // The current format written, and the version required to read. Must be
35 // increased to at least 289900+1 on the next breaking change.
36 constexpr int CURRENT_FEES_FILE_VERSION{149900};
37 
38 static constexpr double INF_FEERATE = 1e99;
39 
41 {
42  switch (horizon) {
43  case FeeEstimateHorizon::SHORT_HALFLIFE: return "short";
44  case FeeEstimateHorizon::MED_HALFLIFE: return "medium";
45  case FeeEstimateHorizon::LONG_HALFLIFE: return "long";
46  } // no default case, so the compiler can warn about missing cases
47  assert(false);
48 }
49 
50 namespace {
51 
52 struct EncodedDoubleFormatter
53 {
54  template<typename Stream> void Ser(Stream &s, double v)
55  {
56  s << EncodeDouble(v);
57  }
58 
59  template<typename Stream> void Unser(Stream& s, double& v)
60  {
61  uint64_t encoded;
62  s >> encoded;
63  v = DecodeDouble(encoded);
64  }
65 };
66 
67 } // namespace
68 
78 {
79 private:
80  //Define the buckets we will group transactions into
81  const std::vector<double>& buckets; // The upper-bound of the range for the bucket (inclusive)
82  const std::map<double, unsigned int>& bucketMap; // Map of bucket upper-bound to index into all vectors by bucket
83 
84  // For each bucket X:
85  // Count the total # of txs in each bucket
86  // Track the historical moving average of this total over blocks
87  std::vector<double> txCtAvg;
88 
89  // Count the total # of txs confirmed within Y blocks in each bucket
90  // Track the historical moving average of these totals over blocks
91  std::vector<std::vector<double>> confAvg; // confAvg[Y][X]
92 
93  // Track moving avg of txs which have been evicted from the mempool
94  // after failing to be confirmed within Y blocks
95  std::vector<std::vector<double>> failAvg; // failAvg[Y][X]
96 
97  // Sum the total feerate of all tx's in each bucket
98  // Track the historical moving average of this total over blocks
99  std::vector<double> m_feerate_avg;
100 
101  // Combine the conf counts with tx counts to calculate the confirmation % for each Y,X
102  // Combine the total value with the tx counts to calculate the avg feerate per bucket
103 
104  double decay;
105 
106  // Resolution (# of blocks) with which confirmations are tracked
107  unsigned int scale;
108 
109  // Mempool counts of outstanding transactions
110  // For each bucket X, track the number of transactions in the mempool
111  // that are unconfirmed for each possible confirmation value Y
112  std::vector<std::vector<int> > unconfTxs; //unconfTxs[Y][X]
113  // transactions still unconfirmed after GetMaxConfirms for each bucket
114  std::vector<int> oldUnconfTxs;
115 
116  void resizeInMemoryCounters(size_t newbuckets);
117 
118 public:
126  TxConfirmStats(const std::vector<double>& defaultBuckets, const std::map<double, unsigned int>& defaultBucketMap,
127  unsigned int maxPeriods, double decay, unsigned int scale);
128 
130  void ClearCurrent(unsigned int nBlockHeight);
131 
138  void Record(int blocksToConfirm, double val);
139 
141  unsigned int NewTx(unsigned int nBlockHeight, double val);
142 
144  void removeTx(unsigned int entryHeight, unsigned int nBestSeenHeight,
145  unsigned int bucketIndex, bool inBlock);
146 
149  void UpdateMovingAverages();
150 
160  double EstimateMedianVal(int confTarget, double sufficientTxVal,
161  double minSuccess, unsigned int nBlockHeight,
162  EstimationResult *result = nullptr) const;
163 
165  unsigned int GetMaxConfirms() const { return scale * confAvg.size(); }
166 
168  void Write(AutoFile& fileout) const;
169 
174  void Read(AutoFile& filein, size_t numBuckets);
175 };
176 
177 
178 TxConfirmStats::TxConfirmStats(const std::vector<double>& defaultBuckets,
179  const std::map<double, unsigned int>& defaultBucketMap,
180  unsigned int maxPeriods, double _decay, unsigned int _scale)
181  : buckets(defaultBuckets), bucketMap(defaultBucketMap), decay(_decay), scale(_scale)
182 {
183  assert(_scale != 0 && "_scale must be non-zero");
184  confAvg.resize(maxPeriods);
185  failAvg.resize(maxPeriods);
186  for (unsigned int i = 0; i < maxPeriods; i++) {
187  confAvg[i].resize(buckets.size());
188  failAvg[i].resize(buckets.size());
189  }
190 
191  txCtAvg.resize(buckets.size());
192  m_feerate_avg.resize(buckets.size());
193 
195 }
196 
197 void TxConfirmStats::resizeInMemoryCounters(size_t newbuckets) {
198  // newbuckets must be passed in because the buckets referred to during Read have not been updated yet.
199  unconfTxs.resize(GetMaxConfirms());
200  for (unsigned int i = 0; i < unconfTxs.size(); i++) {
201  unconfTxs[i].resize(newbuckets);
202  }
203  oldUnconfTxs.resize(newbuckets);
204 }
205 
206 // Roll the unconfirmed txs circular buffer
207 void TxConfirmStats::ClearCurrent(unsigned int nBlockHeight)
208 {
209  for (unsigned int j = 0; j < buckets.size(); j++) {
210  oldUnconfTxs[j] += unconfTxs[nBlockHeight % unconfTxs.size()][j];
211  unconfTxs[nBlockHeight%unconfTxs.size()][j] = 0;
212  }
213 }
214 
215 
216 void TxConfirmStats::Record(int blocksToConfirm, double feerate)
217 {
218  // blocksToConfirm is 1-based
219  if (blocksToConfirm < 1)
220  return;
221  int periodsToConfirm = (blocksToConfirm + scale - 1) / scale;
222  unsigned int bucketindex = bucketMap.lower_bound(feerate)->second;
223  for (size_t i = periodsToConfirm; i <= confAvg.size(); i++) {
224  confAvg[i - 1][bucketindex]++;
225  }
226  txCtAvg[bucketindex]++;
227  m_feerate_avg[bucketindex] += feerate;
228 }
229 
231 {
232  assert(confAvg.size() == failAvg.size());
233  for (unsigned int j = 0; j < buckets.size(); j++) {
234  for (unsigned int i = 0; i < confAvg.size(); i++) {
235  confAvg[i][j] *= decay;
236  failAvg[i][j] *= decay;
237  }
238  m_feerate_avg[j] *= decay;
239  txCtAvg[j] *= decay;
240  }
241 }
242 
243 // returns -1 on error conditions
244 double TxConfirmStats::EstimateMedianVal(int confTarget, double sufficientTxVal,
245  double successBreakPoint, unsigned int nBlockHeight,
246  EstimationResult *result) const
247 {
248  // Counters for a bucket (or range of buckets)
249  double nConf = 0; // Number of tx's confirmed within the confTarget
250  double totalNum = 0; // Total number of tx's that were ever confirmed
251  int extraNum = 0; // Number of tx's still in mempool for confTarget or longer
252  double failNum = 0; // Number of tx's that were never confirmed but removed from the mempool after confTarget
253  const int periodTarget = (confTarget + scale - 1) / scale;
254  const int maxbucketindex = buckets.size() - 1;
255 
256  // We'll combine buckets until we have enough samples.
257  // The near and far variables will define the range we've combined
258  // The best variables are the last range we saw which still had a high
259  // enough confirmation rate to count as success.
260  // The cur variables are the current range we're counting.
261  unsigned int curNearBucket = maxbucketindex;
262  unsigned int bestNearBucket = maxbucketindex;
263  unsigned int curFarBucket = maxbucketindex;
264  unsigned int bestFarBucket = maxbucketindex;
265 
266  // We'll always group buckets into sets that meet sufficientTxVal --
267  // this ensures that we're using consistent groups between different
268  // confirmation targets.
269  double partialNum = 0;
270 
271  bool foundAnswer = false;
272  unsigned int bins = unconfTxs.size();
273  bool newBucketRange = true;
274  bool passing = true;
275  EstimatorBucket passBucket;
276  EstimatorBucket failBucket;
277 
278  // Start counting from highest feerate transactions
279  for (int bucket = maxbucketindex; bucket >= 0; --bucket) {
280  if (newBucketRange) {
281  curNearBucket = bucket;
282  newBucketRange = false;
283  }
284  curFarBucket = bucket;
285  nConf += confAvg[periodTarget - 1][bucket];
286  partialNum += txCtAvg[bucket];
287  totalNum += txCtAvg[bucket];
288  failNum += failAvg[periodTarget - 1][bucket];
289  for (unsigned int confct = confTarget; confct < GetMaxConfirms(); confct++)
290  extraNum += unconfTxs[(nBlockHeight - confct) % bins][bucket];
291  extraNum += oldUnconfTxs[bucket];
292  // If we have enough transaction data points in this range of buckets,
293  // we can test for success
294  // (Only count the confirmed data points, so that each confirmation count
295  // will be looking at the same amount of data and same bucket breaks)
296 
297  if (partialNum < sufficientTxVal / (1 - decay)) {
298  // the buckets we've added in this round aren't sufficient
299  // so keep adding
300  continue;
301  } else {
302  partialNum = 0; // reset for the next range we'll add
303 
304  double curPct = nConf / (totalNum + failNum + extraNum);
305 
306  // Check to see if we are no longer getting confirmed at the success rate
307  if (curPct < successBreakPoint) {
308  if (passing == true) {
309  // First time we hit a failure record the failed bucket
310  unsigned int failMinBucket = std::min(curNearBucket, curFarBucket);
311  unsigned int failMaxBucket = std::max(curNearBucket, curFarBucket);
312  failBucket.start = failMinBucket ? buckets[failMinBucket - 1] : 0;
313  failBucket.end = buckets[failMaxBucket];
314  failBucket.withinTarget = nConf;
315  failBucket.totalConfirmed = totalNum;
316  failBucket.inMempool = extraNum;
317  failBucket.leftMempool = failNum;
318  passing = false;
319  }
320  continue;
321  }
322  // Otherwise update the cumulative stats, and the bucket variables
323  // and reset the counters
324  else {
325  failBucket = EstimatorBucket(); // Reset any failed bucket, currently passing
326  foundAnswer = true;
327  passing = true;
328  passBucket.withinTarget = nConf;
329  nConf = 0;
330  passBucket.totalConfirmed = totalNum;
331  totalNum = 0;
332  passBucket.inMempool = extraNum;
333  passBucket.leftMempool = failNum;
334  failNum = 0;
335  extraNum = 0;
336  bestNearBucket = curNearBucket;
337  bestFarBucket = curFarBucket;
338  newBucketRange = true;
339  }
340  }
341  }
342 
343  double median = -1;
344  double txSum = 0;
345 
346  // Calculate the "average" feerate of the best bucket range that met success conditions
347  // Find the bucket with the median transaction and then report the average feerate from that bucket
348  // This is a compromise between finding the median which we can't since we don't save all tx's
349  // and reporting the average which is less accurate
350  unsigned int minBucket = std::min(bestNearBucket, bestFarBucket);
351  unsigned int maxBucket = std::max(bestNearBucket, bestFarBucket);
352  for (unsigned int j = minBucket; j <= maxBucket; j++) {
353  txSum += txCtAvg[j];
354  }
355  if (foundAnswer && txSum != 0) {
356  txSum = txSum / 2;
357  for (unsigned int j = minBucket; j <= maxBucket; j++) {
358  if (txCtAvg[j] < txSum)
359  txSum -= txCtAvg[j];
360  else { // we're in the right bucket
361  median = m_feerate_avg[j] / txCtAvg[j];
362  break;
363  }
364  }
365 
366  passBucket.start = minBucket ? buckets[minBucket-1] : 0;
367  passBucket.end = buckets[maxBucket];
368  }
369 
370  // If we were passing until we reached last few buckets with insufficient data, then report those as failed
371  if (passing && !newBucketRange) {
372  unsigned int failMinBucket = std::min(curNearBucket, curFarBucket);
373  unsigned int failMaxBucket = std::max(curNearBucket, curFarBucket);
374  failBucket.start = failMinBucket ? buckets[failMinBucket - 1] : 0;
375  failBucket.end = buckets[failMaxBucket];
376  failBucket.withinTarget = nConf;
377  failBucket.totalConfirmed = totalNum;
378  failBucket.inMempool = extraNum;
379  failBucket.leftMempool = failNum;
380  }
381 
382  float passed_within_target_perc = 0.0;
383  float failed_within_target_perc = 0.0;
384  if ((passBucket.totalConfirmed + passBucket.inMempool + passBucket.leftMempool)) {
385  passed_within_target_perc = 100 * passBucket.withinTarget / (passBucket.totalConfirmed + passBucket.inMempool + passBucket.leftMempool);
386  }
387  if ((failBucket.totalConfirmed + failBucket.inMempool + failBucket.leftMempool)) {
388  failed_within_target_perc = 100 * failBucket.withinTarget / (failBucket.totalConfirmed + failBucket.inMempool + failBucket.leftMempool);
389  }
390 
391  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",
392  confTarget, 100.0 * successBreakPoint, decay,
393  median, passBucket.start, passBucket.end,
394  passed_within_target_perc,
395  passBucket.withinTarget, passBucket.totalConfirmed, passBucket.inMempool, passBucket.leftMempool,
396  failBucket.start, failBucket.end,
397  failed_within_target_perc,
398  failBucket.withinTarget, failBucket.totalConfirmed, failBucket.inMempool, failBucket.leftMempool);
399 
400 
401  if (result) {
402  result->pass = passBucket;
403  result->fail = failBucket;
404  result->decay = decay;
405  result->scale = scale;
406  }
407  return median;
408 }
409 
410 void TxConfirmStats::Write(AutoFile& fileout) const
411 {
412  fileout << Using<EncodedDoubleFormatter>(decay);
413  fileout << scale;
414  fileout << Using<VectorFormatter<EncodedDoubleFormatter>>(m_feerate_avg);
415  fileout << Using<VectorFormatter<EncodedDoubleFormatter>>(txCtAvg);
416  fileout << Using<VectorFormatter<VectorFormatter<EncodedDoubleFormatter>>>(confAvg);
417  fileout << Using<VectorFormatter<VectorFormatter<EncodedDoubleFormatter>>>(failAvg);
418 }
419 
420 void TxConfirmStats::Read(AutoFile& filein, size_t numBuckets)
421 {
422  // Read data file and do some very basic sanity checking
423  // buckets and bucketMap are not updated yet, so don't access them
424  // If there is a read failure, we'll just discard this entire object anyway
425  size_t maxConfirms, maxPeriods;
426 
427  // The current version will store the decay with each individual TxConfirmStats and also keep a scale factor
428  filein >> Using<EncodedDoubleFormatter>(decay);
429  if (decay <= 0 || decay >= 1) {
430  throw std::runtime_error("Corrupt estimates file. Decay must be between 0 and 1 (non-inclusive)");
431  }
432  filein >> scale;
433  if (scale == 0) {
434  throw std::runtime_error("Corrupt estimates file. Scale must be non-zero");
435  }
436 
437  filein >> Using<VectorFormatter<EncodedDoubleFormatter>>(m_feerate_avg);
438  if (m_feerate_avg.size() != numBuckets) {
439  throw std::runtime_error("Corrupt estimates file. Mismatch in feerate average bucket count");
440  }
441  filein >> Using<VectorFormatter<EncodedDoubleFormatter>>(txCtAvg);
442  if (txCtAvg.size() != numBuckets) {
443  throw std::runtime_error("Corrupt estimates file. Mismatch in tx count bucket count");
444  }
445  filein >> Using<VectorFormatter<VectorFormatter<EncodedDoubleFormatter>>>(confAvg);
446  maxPeriods = confAvg.size();
447  maxConfirms = scale * maxPeriods;
448 
449  if (maxConfirms <= 0 || maxConfirms > 6 * 24 * 7) { // one week
450  throw std::runtime_error("Corrupt estimates file. Must maintain estimates for between 1 and 1008 (one week) confirms");
451  }
452  for (unsigned int i = 0; i < maxPeriods; i++) {
453  if (confAvg[i].size() != numBuckets) {
454  throw std::runtime_error("Corrupt estimates file. Mismatch in feerate conf average bucket count");
455  }
456  }
457 
458  filein >> Using<VectorFormatter<VectorFormatter<EncodedDoubleFormatter>>>(failAvg);
459  if (maxPeriods != failAvg.size()) {
460  throw std::runtime_error("Corrupt estimates file. Mismatch in confirms tracked for failures");
461  }
462  for (unsigned int i = 0; i < maxPeriods; i++) {
463  if (failAvg[i].size() != numBuckets) {
464  throw std::runtime_error("Corrupt estimates file. Mismatch in one of failure average bucket counts");
465  }
466  }
467 
468  // Resize the current block variables which aren't stored in the data file
469  // to match the number of confirms and buckets
470  resizeInMemoryCounters(numBuckets);
471 
472  LogDebug(BCLog::ESTIMATEFEE, "Reading estimates: %u buckets counting confirms up to %u blocks\n",
473  numBuckets, maxConfirms);
474 }
475 
476 unsigned int TxConfirmStats::NewTx(unsigned int nBlockHeight, double val)
477 {
478  unsigned int bucketindex = bucketMap.lower_bound(val)->second;
479  unsigned int blockIndex = nBlockHeight % unconfTxs.size();
480  unconfTxs[blockIndex][bucketindex]++;
481  return bucketindex;
482 }
483 
484 void TxConfirmStats::removeTx(unsigned int entryHeight, unsigned int nBestSeenHeight, unsigned int bucketindex, bool inBlock)
485 {
486  //nBestSeenHeight is not updated yet for the new block
487  int blocksAgo = nBestSeenHeight - entryHeight;
488  if (nBestSeenHeight == 0) // the BlockPolicyEstimator hasn't seen any blocks yet
489  blocksAgo = 0;
490  if (blocksAgo < 0) {
491  LogDebug(BCLog::ESTIMATEFEE, "Blockpolicy error, blocks ago is negative for mempool tx\n");
492  return; //This can't happen because we call this with our best seen height, no entries can have higher
493  }
494 
495  if (blocksAgo >= (int)unconfTxs.size()) {
496  if (oldUnconfTxs[bucketindex] > 0) {
497  oldUnconfTxs[bucketindex]--;
498  } else {
499  LogDebug(BCLog::ESTIMATEFEE, "Blockpolicy error, mempool tx removed from >25 blocks,bucketIndex=%u already\n",
500  bucketindex);
501  }
502  }
503  else {
504  unsigned int blockIndex = entryHeight % unconfTxs.size();
505  if (unconfTxs[blockIndex][bucketindex] > 0) {
506  unconfTxs[blockIndex][bucketindex]--;
507  } else {
508  LogDebug(BCLog::ESTIMATEFEE, "Blockpolicy error, mempool tx removed from blockIndex=%u,bucketIndex=%u already\n",
509  blockIndex, bucketindex);
510  }
511  }
512  if (!inBlock && (unsigned int)blocksAgo >= scale) { // Only counts as a failure if not confirmed for entire period
513  assert(scale != 0);
514  unsigned int periodsAgo = blocksAgo / scale;
515  for (size_t i = 0; i < periodsAgo && i < failAvg.size(); i++) {
516  failAvg[i][bucketindex]++;
517  }
518  }
519 }
520 
522 {
524  return _removeTx(hash, /*inBlock=*/false);
525 }
526 
527 bool CBlockPolicyEstimator::_removeTx(const uint256& hash, bool inBlock)
528 {
530  std::map<uint256, TxStatsInfo>::iterator pos = mapMemPoolTxs.find(hash);
531  if (pos != mapMemPoolTxs.end()) {
532  feeStats->removeTx(pos->second.blockHeight, nBestSeenHeight, pos->second.bucketIndex, inBlock);
533  shortStats->removeTx(pos->second.blockHeight, nBestSeenHeight, pos->second.bucketIndex, inBlock);
534  longStats->removeTx(pos->second.blockHeight, nBestSeenHeight, pos->second.bucketIndex, inBlock);
535  mapMemPoolTxs.erase(hash);
536  return true;
537  } else {
538  return false;
539  }
540 }
541 
542 CBlockPolicyEstimator::CBlockPolicyEstimator(const fs::path& estimation_filepath, const bool read_stale_estimates)
543  : m_estimation_filepath{estimation_filepath}
544 {
545  static_assert(MIN_BUCKET_FEERATE > 0, "Min feerate must be nonzero");
546  size_t bucketIndex = 0;
547 
548  for (double bucketBoundary = MIN_BUCKET_FEERATE; bucketBoundary <= MAX_BUCKET_FEERATE; bucketBoundary *= FEE_SPACING, bucketIndex++) {
549  buckets.push_back(bucketBoundary);
550  bucketMap[bucketBoundary] = bucketIndex;
551  }
552  buckets.push_back(INF_FEERATE);
553  bucketMap[INF_FEERATE] = bucketIndex;
554  assert(bucketMap.size() == buckets.size());
555 
556  feeStats = std::unique_ptr<TxConfirmStats>(new TxConfirmStats(buckets, bucketMap, MED_BLOCK_PERIODS, MED_DECAY, MED_SCALE));
557  shortStats = std::unique_ptr<TxConfirmStats>(new TxConfirmStats(buckets, bucketMap, SHORT_BLOCK_PERIODS, SHORT_DECAY, SHORT_SCALE));
558  longStats = std::unique_ptr<TxConfirmStats>(new TxConfirmStats(buckets, bucketMap, LONG_BLOCK_PERIODS, LONG_DECAY, LONG_SCALE));
559 
560  AutoFile est_file{fsbridge::fopen(m_estimation_filepath, "rb")};
561 
562  if (est_file.IsNull()) {
563  LogPrintf("%s is not found. Continue anyway.\n", fs::PathToString(m_estimation_filepath));
564  return;
565  }
566 
567  std::chrono::hours file_age = GetFeeEstimatorFileAge();
568  if (file_age > MAX_FILE_AGE && !read_stale_estimates) {
569  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));
570  return;
571  }
572 
573  if (!Read(est_file)) {
574  LogPrintf("Failed to read fee estimates from %s. Continue anyway.\n", fs::PathToString(m_estimation_filepath));
575  }
576 }
577 
579 
581 {
582  processTransaction(tx);
583 }
584 
586 {
587  removeTx(tx->GetHash());
588 }
589 
590 void CBlockPolicyEstimator::MempoolTransactionsRemovedForBlock(const std::vector<RemovedMempoolTransactionInfo>& txs_removed_for_block, unsigned int nBlockHeight)
591 {
592  processBlock(txs_removed_for_block, nBlockHeight);
593 }
594 
596 {
598  const unsigned int txHeight = tx.info.txHeight;
599  const auto& hash = tx.info.m_tx->GetHash();
600  if (mapMemPoolTxs.count(hash)) {
601  LogDebug(BCLog::ESTIMATEFEE, "Blockpolicy error mempool tx %s already being tracked\n",
602  hash.ToString());
603  return;
604  }
605 
606  if (txHeight != nBestSeenHeight) {
607  // Ignore side chains and re-orgs; assuming they are random they don't
608  // affect the estimate. We'll potentially double count transactions in 1-block reorgs.
609  // Ignore txs if BlockPolicyEstimator is not in sync with ActiveChain().Tip().
610  // It will be synced next time a block is processed.
611  return;
612  }
613  // This transaction should only count for fee estimation if:
614  // - it's not being re-added during a reorg which bypasses typical mempool fee limits
615  // - the node is not behind
616  // - the transaction is not dependent on any other transactions in the mempool
617  // - it's not part of a package.
618  const bool validForFeeEstimation = !tx.m_mempool_limit_bypassed && !tx.m_submitted_in_package && tx.m_chainstate_is_current && tx.m_has_no_mempool_parents;
619 
620  // Only want to be updating estimates when our blockchain is synced,
621  // otherwise we'll miscalculate how many blocks its taking to get included.
622  if (!validForFeeEstimation) {
623  untrackedTxs++;
624  return;
625  }
626  trackedTxs++;
627 
628  // Feerates are stored and reported as BTC-per-kb:
629  const CFeeRate feeRate(tx.info.m_fee, tx.info.m_virtual_transaction_size);
630 
631  mapMemPoolTxs[hash].blockHeight = txHeight;
632  unsigned int bucketIndex = feeStats->NewTx(txHeight, static_cast<double>(feeRate.GetFeePerK()));
633  mapMemPoolTxs[hash].bucketIndex = bucketIndex;
634  unsigned int bucketIndex2 = shortStats->NewTx(txHeight, static_cast<double>(feeRate.GetFeePerK()));
635  assert(bucketIndex == bucketIndex2);
636  unsigned int bucketIndex3 = longStats->NewTx(txHeight, static_cast<double>(feeRate.GetFeePerK()));
637  assert(bucketIndex == bucketIndex3);
638 }
639 
641 {
643  if (!_removeTx(tx.info.m_tx->GetHash(), true)) {
644  // This transaction wasn't being tracked for fee estimation
645  return false;
646  }
647 
648  // How many blocks did it take for miners to include this transaction?
649  // blocksToConfirm is 1-based, so a transaction included in the earliest
650  // possible block has confirmation count of 1
651  int blocksToConfirm = nBlockHeight - tx.info.txHeight;
652  if (blocksToConfirm <= 0) {
653  // This can't happen because we don't process transactions from a block with a height
654  // lower than our greatest seen height
655  LogDebug(BCLog::ESTIMATEFEE, "Blockpolicy error Transaction had negative blocksToConfirm\n");
656  return false;
657  }
658 
659  // Feerates are stored and reported as BTC-per-kb:
661 
662  feeStats->Record(blocksToConfirm, static_cast<double>(feeRate.GetFeePerK()));
663  shortStats->Record(blocksToConfirm, static_cast<double>(feeRate.GetFeePerK()));
664  longStats->Record(blocksToConfirm, static_cast<double>(feeRate.GetFeePerK()));
665  return true;
666 }
667 
668 void CBlockPolicyEstimator::processBlock(const std::vector<RemovedMempoolTransactionInfo>& txs_removed_for_block,
669  unsigned int nBlockHeight)
670 {
672  if (nBlockHeight <= nBestSeenHeight) {
673  // Ignore side chains and re-orgs; assuming they are random
674  // they don't affect the estimate.
675  // And if an attacker can re-org the chain at will, then
676  // you've got much bigger problems than "attacker can influence
677  // transaction fees."
678  return;
679  }
680 
681  // Must update nBestSeenHeight in sync with ClearCurrent so that
682  // calls to removeTx (via processBlockTx) correctly calculate age
683  // of unconfirmed txs to remove from tracking.
684  nBestSeenHeight = nBlockHeight;
685 
686  // Update unconfirmed circular buffer
687  feeStats->ClearCurrent(nBlockHeight);
688  shortStats->ClearCurrent(nBlockHeight);
689  longStats->ClearCurrent(nBlockHeight);
690 
691  // Decay all exponential averages
692  feeStats->UpdateMovingAverages();
693  shortStats->UpdateMovingAverages();
694  longStats->UpdateMovingAverages();
695 
696  unsigned int countedTxs = 0;
697  // Update averages with data points from current block
698  for (const auto& tx : txs_removed_for_block) {
699  if (processBlockTx(nBlockHeight, tx))
700  countedTxs++;
701  }
702 
703  if (firstRecordedHeight == 0 && countedTxs > 0) {
704  firstRecordedHeight = nBestSeenHeight;
705  LogDebug(BCLog::ESTIMATEFEE, "Blockpolicy first recorded height %u\n", firstRecordedHeight);
706  }
707 
708 
709  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",
710  countedTxs, txs_removed_for_block.size(), trackedTxs, trackedTxs + untrackedTxs, mapMemPoolTxs.size(),
711  MaxUsableEstimate(), HistoricalBlockSpan() > BlockSpan() ? "historical" : "current");
712 
713  trackedTxs = 0;
714  untrackedTxs = 0;
715 }
716 
718 {
719  // It's not possible to get reasonable estimates for confTarget of 1
720  if (confTarget <= 1)
721  return CFeeRate(0);
722 
724 }
725 
726 CFeeRate CBlockPolicyEstimator::estimateRawFee(int confTarget, double successThreshold, FeeEstimateHorizon horizon, EstimationResult* result) const
727 {
728  TxConfirmStats* stats = nullptr;
729  double sufficientTxs = SUFFICIENT_FEETXS;
730  switch (horizon) {
732  stats = shortStats.get();
733  sufficientTxs = SUFFICIENT_TXS_SHORT;
734  break;
735  }
737  stats = feeStats.get();
738  break;
739  }
741  stats = longStats.get();
742  break;
743  }
744  } // no default case, so the compiler can warn about missing cases
745  assert(stats);
746 
748  // Return failure if trying to analyze a target we're not tracking
749  if (confTarget <= 0 || (unsigned int)confTarget > stats->GetMaxConfirms())
750  return CFeeRate(0);
751  if (successThreshold > 1)
752  return CFeeRate(0);
753 
754  double median = stats->EstimateMedianVal(confTarget, sufficientTxs, successThreshold, nBestSeenHeight, result);
755 
756  if (median < 0)
757  return CFeeRate(0);
758 
759  return CFeeRate(llround(median));
760 }
761 
763 {
765  switch (horizon) {
767  return shortStats->GetMaxConfirms();
768  }
770  return feeStats->GetMaxConfirms();
771  }
773  return longStats->GetMaxConfirms();
774  }
775  } // no default case, so the compiler can warn about missing cases
776  assert(false);
777 }
778 
780 {
781  if (firstRecordedHeight == 0) return 0;
782  assert(nBestSeenHeight >= firstRecordedHeight);
783 
784  return nBestSeenHeight - firstRecordedHeight;
785 }
786 
788 {
789  if (historicalFirst == 0) return 0;
790  assert(historicalBest >= historicalFirst);
791 
792  if (nBestSeenHeight - historicalBest > OLDEST_ESTIMATE_HISTORY) return 0;
793 
794  return historicalBest - historicalFirst;
795 }
796 
798 {
799  // Block spans are divided by 2 to make sure there are enough potential failing data points for the estimate
800  return std::min(longStats->GetMaxConfirms(), std::max(BlockSpan(), HistoricalBlockSpan()) / 2);
801 }
802 
807 double CBlockPolicyEstimator::estimateCombinedFee(unsigned int confTarget, double successThreshold, bool checkShorterHorizon, EstimationResult *result) const
808 {
809  double estimate = -1;
810  if (confTarget >= 1 && confTarget <= longStats->GetMaxConfirms()) {
811  // Find estimate from shortest time horizon possible
812  if (confTarget <= shortStats->GetMaxConfirms()) { // short horizon
813  estimate = shortStats->EstimateMedianVal(confTarget, SUFFICIENT_TXS_SHORT, successThreshold, nBestSeenHeight, result);
814  }
815  else if (confTarget <= feeStats->GetMaxConfirms()) { // medium horizon
816  estimate = feeStats->EstimateMedianVal(confTarget, SUFFICIENT_FEETXS, successThreshold, nBestSeenHeight, result);
817  }
818  else { // long horizon
819  estimate = longStats->EstimateMedianVal(confTarget, SUFFICIENT_FEETXS, successThreshold, nBestSeenHeight, result);
820  }
821  if (checkShorterHorizon) {
822  EstimationResult tempResult;
823  // If a lower confTarget from a more recent horizon returns a lower answer use it.
824  if (confTarget > feeStats->GetMaxConfirms()) {
825  double medMax = feeStats->EstimateMedianVal(feeStats->GetMaxConfirms(), SUFFICIENT_FEETXS, successThreshold, nBestSeenHeight, &tempResult);
826  if (medMax > 0 && (estimate == -1 || medMax < estimate)) {
827  estimate = medMax;
828  if (result) *result = tempResult;
829  }
830  }
831  if (confTarget > shortStats->GetMaxConfirms()) {
832  double shortMax = shortStats->EstimateMedianVal(shortStats->GetMaxConfirms(), SUFFICIENT_TXS_SHORT, successThreshold, nBestSeenHeight, &tempResult);
833  if (shortMax > 0 && (estimate == -1 || shortMax < estimate)) {
834  estimate = shortMax;
835  if (result) *result = tempResult;
836  }
837  }
838  }
839  }
840  return estimate;
841 }
842 
847 {
848  double estimate = -1;
849  EstimationResult tempResult;
850  if (doubleTarget <= shortStats->GetMaxConfirms()) {
851  estimate = feeStats->EstimateMedianVal(doubleTarget, SUFFICIENT_FEETXS, DOUBLE_SUCCESS_PCT, nBestSeenHeight, result);
852  }
853  if (doubleTarget <= feeStats->GetMaxConfirms()) {
854  double longEstimate = longStats->EstimateMedianVal(doubleTarget, SUFFICIENT_FEETXS, DOUBLE_SUCCESS_PCT, nBestSeenHeight, &tempResult);
855  if (longEstimate > estimate) {
856  estimate = longEstimate;
857  if (result) *result = tempResult;
858  }
859  }
860  return estimate;
861 }
862 
870 CFeeRate CBlockPolicyEstimator::estimateSmartFee(int confTarget, FeeCalculation *feeCalc, bool conservative) const
871 {
873 
874  if (feeCalc) {
875  feeCalc->desiredTarget = confTarget;
876  feeCalc->returnedTarget = confTarget;
877  }
878 
879  double median = -1;
880  EstimationResult tempResult;
881 
882  // Return failure if trying to analyze a target we're not tracking
883  if (confTarget <= 0 || (unsigned int)confTarget > longStats->GetMaxConfirms()) {
884  return CFeeRate(0); // error condition
885  }
886 
887  // It's not possible to get reasonable estimates for confTarget of 1
888  if (confTarget == 1) confTarget = 2;
889 
890  unsigned int maxUsableEstimate = MaxUsableEstimate();
891  if ((unsigned int)confTarget > maxUsableEstimate) {
892  confTarget = maxUsableEstimate;
893  }
894  if (feeCalc) feeCalc->returnedTarget = confTarget;
895 
896  if (confTarget <= 1) return CFeeRate(0); // error condition
897 
898  assert(confTarget > 0); //estimateCombinedFee and estimateConservativeFee take unsigned ints
909  double halfEst = estimateCombinedFee(confTarget/2, HALF_SUCCESS_PCT, true, &tempResult);
910  if (feeCalc) {
911  feeCalc->est = tempResult;
912  feeCalc->reason = FeeReason::HALF_ESTIMATE;
913  }
914  median = halfEst;
915  double actualEst = estimateCombinedFee(confTarget, SUCCESS_PCT, true, &tempResult);
916  if (actualEst > median) {
917  median = actualEst;
918  if (feeCalc) {
919  feeCalc->est = tempResult;
920  feeCalc->reason = FeeReason::FULL_ESTIMATE;
921  }
922  }
923  double doubleEst = estimateCombinedFee(2 * confTarget, DOUBLE_SUCCESS_PCT, !conservative, &tempResult);
924  if (doubleEst > median) {
925  median = doubleEst;
926  if (feeCalc) {
927  feeCalc->est = tempResult;
929  }
930  }
931 
932  if (conservative || median == -1) {
933  double consEst = estimateConservativeFee(2 * confTarget, &tempResult);
934  if (consEst > median) {
935  median = consEst;
936  if (feeCalc) {
937  feeCalc->est = tempResult;
938  feeCalc->reason = FeeReason::CONSERVATIVE;
939  }
940  }
941  }
942 
943  if (median < 0) return CFeeRate(0); // error condition
944 
945  return CFeeRate(llround(median));
946 }
947 
951 }
952 
954 {
956  if (est_file.IsNull() || !Write(est_file)) {
957  LogPrintf("Failed to write fee estimates to %s. Continue anyway.\n", fs::PathToString(m_estimation_filepath));
958  } else {
959  LogPrintf("Flushed fee estimates to %s.\n", fs::PathToString(m_estimation_filepath.filename()));
960  }
961 }
962 
964 {
965  try {
967  fileout << CURRENT_FEES_FILE_VERSION;
968  fileout << int{0}; // Unused dummy field. Written files may contain any value in [0, 289900]
969  fileout << nBestSeenHeight;
970  if (BlockSpan() > HistoricalBlockSpan()/2) {
971  fileout << firstRecordedHeight << nBestSeenHeight;
972  }
973  else {
974  fileout << historicalFirst << historicalBest;
975  }
976  fileout << Using<VectorFormatter<EncodedDoubleFormatter>>(buckets);
977  feeStats->Write(fileout);
978  shortStats->Write(fileout);
979  longStats->Write(fileout);
980  }
981  catch (const std::exception&) {
982  LogWarning("Unable to write policy estimator data (non-fatal)");
983  return false;
984  }
985  return true;
986 }
987 
989 {
990  try {
992  int nVersionRequired, dummy;
993  filein >> nVersionRequired >> dummy;
994  if (nVersionRequired > CURRENT_FEES_FILE_VERSION) {
995  throw std::runtime_error{strprintf("File version (%d) too high to be read.", nVersionRequired)};
996  }
997 
998  // Read fee estimates file into temporary variables so existing data
999  // structures aren't corrupted if there is an exception.
1000  unsigned int nFileBestSeenHeight;
1001  filein >> nFileBestSeenHeight;
1002 
1003  if (nVersionRequired < CURRENT_FEES_FILE_VERSION) {
1004  LogWarning("Incompatible old fee estimation data (non-fatal). Version: %d", nVersionRequired);
1005  } else { // nVersionRequired == CURRENT_FEES_FILE_VERSION
1006  unsigned int nFileHistoricalFirst, nFileHistoricalBest;
1007  filein >> nFileHistoricalFirst >> nFileHistoricalBest;
1008  if (nFileHistoricalFirst > nFileHistoricalBest || nFileHistoricalBest > nFileBestSeenHeight) {
1009  throw std::runtime_error("Corrupt estimates file. Historical block range for estimates is invalid");
1010  }
1011  std::vector<double> fileBuckets;
1012  filein >> Using<VectorFormatter<EncodedDoubleFormatter>>(fileBuckets);
1013  size_t numBuckets = fileBuckets.size();
1014  if (numBuckets <= 1 || numBuckets > 1000) {
1015  throw std::runtime_error("Corrupt estimates file. Must have between 2 and 1000 feerate buckets");
1016  }
1017 
1018  std::unique_ptr<TxConfirmStats> fileFeeStats(new TxConfirmStats(buckets, bucketMap, MED_BLOCK_PERIODS, MED_DECAY, MED_SCALE));
1019  std::unique_ptr<TxConfirmStats> fileShortStats(new TxConfirmStats(buckets, bucketMap, SHORT_BLOCK_PERIODS, SHORT_DECAY, SHORT_SCALE));
1020  std::unique_ptr<TxConfirmStats> fileLongStats(new TxConfirmStats(buckets, bucketMap, LONG_BLOCK_PERIODS, LONG_DECAY, LONG_SCALE));
1021  fileFeeStats->Read(filein, numBuckets);
1022  fileShortStats->Read(filein, numBuckets);
1023  fileLongStats->Read(filein, numBuckets);
1024 
1025  // Fee estimates file parsed correctly
1026  // Copy buckets from file and refresh our bucketmap
1027  buckets = fileBuckets;
1028  bucketMap.clear();
1029  for (unsigned int i = 0; i < buckets.size(); i++) {
1030  bucketMap[buckets[i]] = i;
1031  }
1032 
1033  // Destroy old TxConfirmStats and point to new ones that already reference buckets and bucketMap
1034  feeStats = std::move(fileFeeStats);
1035  shortStats = std::move(fileShortStats);
1036  longStats = std::move(fileLongStats);
1037 
1038  nBestSeenHeight = nFileBestSeenHeight;
1039  historicalFirst = nFileHistoricalFirst;
1040  historicalBest = nFileHistoricalBest;
1041  }
1042  }
1043  catch (const std::exception& e) {
1044  LogWarning("Unable to read policy estimator data (non-fatal): %s", e.what());
1045  return false;
1046  }
1047  return true;
1048 }
1049 
1051 {
1052  const auto startclear{SteadyClock::now()};
1054  size_t num_entries = mapMemPoolTxs.size();
1055  // Remove every entry in mapMemPoolTxs
1056  while (!mapMemPoolTxs.empty()) {
1057  auto mi = mapMemPoolTxs.begin();
1058  _removeTx(mi->first, false); // this calls erase() on mapMemPoolTxs
1059  }
1060  const auto endclear{SteadyClock::now()};
1061  LogDebug(BCLog::ESTIMATEFEE, "Recorded %u unconfirmed txs from mempool in %.3fs\n", num_entries, Ticks<SecondsDouble>(endclear - startclear));
1062 }
1063 
1065 {
1066  auto file_time{fs::last_write_time(m_estimation_filepath)};
1067  auto now{fs::file_time_type::clock::now()};
1068  return std::chrono::duration_cast<std::chrono::hours>(now - file_time);
1069 }
1070 
1071 static std::set<double> MakeFeeSet(const CFeeRate& min_incremental_fee,
1072  double max_filter_fee_rate,
1073  double fee_filter_spacing)
1074 {
1075  std::set<double> fee_set;
1076 
1077  const CAmount min_fee_limit{std::max(CAmount(1), min_incremental_fee.GetFeePerK() / 2)};
1078  fee_set.insert(0);
1079  for (double bucket_boundary = min_fee_limit;
1080  bucket_boundary <= max_filter_fee_rate;
1081  bucket_boundary *= fee_filter_spacing) {
1082 
1083  fee_set.insert(bucket_boundary);
1084  }
1085 
1086  return fee_set;
1087 }
1088 
1090  : m_fee_set{MakeFeeSet(minIncrementalFee, MAX_FILTER_FEERATE, FEE_FILTER_SPACING)},
1091  insecure_rand{rng}
1092 {
1093 }
1094 
1096 {
1098  std::set<double>::iterator it = m_fee_set.lower_bound(currentMinFee);
1099  if (it == m_fee_set.end() ||
1100  (it != m_fee_set.begin() &&
1101  WITH_LOCK(m_insecure_rand_mutex, return insecure_rand.rand32()) % 3 != 0)) {
1102  --it;
1103  }
1104  return static_cast<CAmount>(*it);
1105 }
std::shared_ptr< const CTransaction > CTransactionRef
Definition: transaction.h:423
static constexpr double MED_DECAY
Decay of .9952 is a half-life of 144 blocks or about 1 day.
Definition: fees.h:166
constexpr int CURRENT_FEES_FILE_VERSION
Definition: fees.cpp:36
std::vector< std::vector< double > > failAvg
Definition: fees.cpp:95
void TransactionAddedToMempool(const NewMempoolTransactionInfo &tx, uint64_t) override EXCLUSIVE_LOCKS_REQUIRED(!m_cs_fee_estimator)
Overridden from CValidationInterface.
Definition: fees.cpp:580
bool _removeTx(const uint256 &hash, bool inBlock) EXCLUSIVE_LOCKS_REQUIRED(m_cs_fee_estimator)
A non-thread-safe helper for the removeTx function.
Definition: fees.cpp:527
CFeeRate estimateFee(int confTarget) const EXCLUSIVE_LOCKS_REQUIRED(!m_cs_fee_estimator)
DEPRECATED.
Definition: fees.cpp:717
AssertLockHeld(pool.cs)
EstimationResult est
Definition: fees.h:94
assert(!tx.IsCoinBase())
FILE * fopen(const fs::path &p, const char *mode)
Definition: fs.cpp:26
int returnedTarget
Definition: fees.h:97
static constexpr double HALF_SUCCESS_PCT
Require greater than 60% of X feerate transactions to be confirmed within Y/2 blocks.
Definition: fees.h:171
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1172
static constexpr unsigned int MED_BLOCK_PERIODS
Track confirm delays up to 48 blocks for medium horizon.
Definition: fees.h:155
double start
Definition: fees.h:75
TxConfirmStats(const std::vector< double > &defaultBuckets, const std::map< double, unsigned int > &defaultBucketMap, unsigned int maxPeriods, double decay, unsigned int scale)
Create new TxConfirmStats.
Definition: fees.cpp:178
double estimateConservativeFee(unsigned int doubleTarget, EstimationResult *result) const EXCLUSIVE_LOCKS_REQUIRED(m_cs_fee_estimator)
Helper for estimateSmartFee.
Definition: fees.cpp:846
MemPoolRemovalReason
Reason why a transaction was removed from the mempool, this is passed to the notification signal...
static constexpr std::chrono::hours MAX_FILE_AGE
fee_estimates.dat that are more than 60 hours (2.5 days) old will not be read, as fee estimates are b...
Definition: fees.h:33
unsigned int HistoricalBlockSpan() const EXCLUSIVE_LOCKS_REQUIRED(m_cs_fee_estimator)
Number of blocks of recorded fee estimate data represented in saved data file.
Definition: fees.cpp:787
FeeReason reason
Definition: fees.h:95
static constexpr double MAX_FILTER_FEERATE
Definition: fees.h:325
We will instantiate an instance of this class to track transactions that were included in a block...
Definition: fees.cpp:77
void processTransaction(const NewMempoolTransactionInfo &tx) EXCLUSIVE_LOCKS_REQUIRED(!m_cs_fee_estimator)
Process a transaction accepted to the mempool.
Definition: fees.cpp:595
std::string StringForFeeEstimateHorizon(FeeEstimateHorizon horizon)
Definition: fees.cpp:40
static constexpr double DOUBLE_SUCCESS_PCT
Require greater than 95% of X feerate transactions to be confirmed within 2 * Y blocks.
Definition: fees.h:175
unsigned int MaxUsableEstimate() const EXCLUSIVE_LOCKS_REQUIRED(m_cs_fee_estimator)
Calculation of highest target that reasonable estimate can be provided for.
Definition: fees.cpp:797
double decay
Definition: fees.cpp:104
void Record(int blocksToConfirm, double val)
Record a new transaction data point in the current block stats.
Definition: fees.cpp:216
Mutex m_insecure_rand_mutex
Definition: fees.h:341
double withinTarget
Definition: fees.h:77
Non-refcounted RAII wrapper for FILE*.
Definition: streams.h:391
bool removeTx(uint256 hash) EXCLUSIVE_LOCKS_REQUIRED(!m_cs_fee_estimator)
Remove a transaction from the mempool tracking stats for non BLOCK removal reasons.
Definition: fees.cpp:521
uint64_t EncodeDouble(double f) noexcept
Definition: serfloat.cpp:37
void resizeInMemoryCounters(size_t newbuckets)
Definition: fees.cpp:197
Mutex m_cs_fee_estimator
Definition: fees.h:275
void ClearCurrent(unsigned int nBlockHeight)
Roll the circular buffer for unconfirmed txs.
Definition: fees.cpp:207
int desiredTarget
Definition: fees.h:96
const int64_t m_virtual_transaction_size
The virtual transaction size.
static constexpr double SUFFICIENT_TXS_SHORT
Require an avg of 0.5 tx when using short decay since there are fewer blocks considered.
Definition: fees.h:180
void FlushFeeEstimates() EXCLUSIVE_LOCKS_REQUIRED(!m_cs_fee_estimator)
Record current fee estimations.
Definition: fees.cpp:953
static constexpr double FEE_FILTER_SPACING
FEE_FILTER_SPACING is just used to provide some quantization of fee filter results.
Definition: fees.h:330
int64_t CAmount
Amount in satoshis (Can be negative)
Definition: amount.h:12
std::chrono::hours GetFeeEstimatorFileAge()
Calculates the age of the file, since last modified.
Definition: fees.cpp:1064
static constexpr double SUCCESS_PCT
Require greater than 85% of X feerate transactions to be confirmed within Y blocks.
Definition: fees.h:173
double EstimateMedianVal(int confTarget, double sufficientTxVal, double minSuccess, unsigned int nBlockHeight, EstimationResult *result=nullptr) const
Calculate a feerate estimate.
Definition: fees.cpp:244
const std::map< double, unsigned int > & bucketMap
Definition: fees.cpp:82
static constexpr unsigned int SHORT_SCALE
Definition: fees.h:153
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.
Definition: fees.cpp:668
static constexpr double LONG_DECAY
Decay of .99931 is a half-life of 1008 blocks or about 1 week.
Definition: fees.h:168
std::vector< std::vector< double > > confAvg
Definition: fees.cpp:91
const bool m_chainstate_is_current
static std::string PathToString(const path &path)
Convert path object to a byte string.
Definition: fs.h:151
bool Write(AutoFile &fileout) const EXCLUSIVE_LOCKS_REQUIRED(!m_cs_fee_estimator)
Write estimation data to a file.
Definition: fees.cpp:963
unsigned int NewTx(unsigned int nBlockHeight, double val)
Record a new transaction entering the mempool.
Definition: fees.cpp:476
double end
Definition: fees.h:76
void Read(AutoFile &filein, size_t numBuckets)
Read saved state of estimation data from a file and replace all internal data structures and variable...
Definition: fees.cpp:420
#define LOCK(cs)
Definition: sync.h:257
void removeTx(unsigned int entryHeight, unsigned int nBestSeenHeight, unsigned int bucketIndex, bool inBlock)
Remove a transaction from mempool tracking stats.
Definition: fees.cpp:484
CAmount round(CAmount currentMinFee) EXCLUSIVE_LOCKS_REQUIRED(!m_insecure_rand_mutex)
Quantize a minimum fee for privacy purpose before broadcast.
Definition: fees.cpp:1095
unsigned int scale
Definition: fees.cpp:107
Fast randomness source.
Definition: random.h:376
FeeFilterRounder(const CFeeRate &min_incremental_fee, FastRandomContext &rng)
Create new FeeFilterRounder.
Definition: fees.cpp:1089
double DecodeDouble(uint64_t v) noexcept
Definition: serfloat.cpp:10
const std::vector< double > & buckets
Definition: fees.cpp:81
unsigned int BlockSpan() const EXCLUSIVE_LOCKS_REQUIRED(m_cs_fee_estimator)
Number of blocks of data recorded while fee estimates have been running.
Definition: fees.cpp:779
double inMempool
Definition: fees.h:79
void Flush() EXCLUSIVE_LOCKS_REQUIRED(!m_cs_fee_estimator)
Drop still unconfirmed transactions and record current estimations, if the fee estimation file is pre...
Definition: fees.cpp:948
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.
Definition: fees.cpp:870
double estimateCombinedFee(unsigned int confTarget, double successThreshold, bool checkShorterHorizon, EstimationResult *result) const EXCLUSIVE_LOCKS_REQUIRED(m_cs_fee_estimator)
Helper for estimateSmartFee.
Definition: fees.cpp:807
void Write(AutoFile &fileout) const
Write state of estimation data to a file.
Definition: fees.cpp:410
CBlockPolicyEstimator(const fs::path &estimation_filepath, const bool read_stale_estimates)
Create new BlockPolicyEstimator and initialize stats tracking classes with default values...
Definition: fees.cpp:542
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
Definition: sync.h:301
static constexpr unsigned int LONG_SCALE
Definition: fees.h:159
FeeEstimateHorizon
Definition: fees.h:45
std::vector< std::vector< int > > unconfTxs
Definition: fees.cpp:112
const bool m_has_no_mempool_parents
256-bit opaque blob.
Definition: uint256.h:201
static constexpr unsigned int MED_SCALE
Definition: fees.h:156
static const unsigned int OLDEST_ESTIMATE_HISTORY
Historical estimates that are older than this aren&#39;t valid.
Definition: fees.h:161
auto result
Definition: common-types.h:74
const bool m_mempool_limit_bypassed
#define LogDebug(category,...)
Definition: logging.h:381
std::vector< int > oldUnconfTxs
Definition: fees.cpp:114
bool Read(AutoFile &filein) EXCLUSIVE_LOCKS_REQUIRED(!m_cs_fee_estimator)
Read estimation data from a file.
Definition: fees.cpp:988
double leftMempool
Definition: fees.h:80
unsigned int GetMaxConfirms() const
Return the max number of confirms we&#39;re tracking.
Definition: fees.cpp:165
static constexpr unsigned int LONG_BLOCK_PERIODS
Track confirm delays up to 1008 blocks for long horizon.
Definition: fees.h:158
const CTransactionRef m_tx
Fee rate in satoshis per kilovirtualbyte: CAmount / kvB.
Definition: feerate.h:32
#define AssertLockNotHeld(cs)
Definition: sync.h:147
#define LogWarning(...)
Definition: logging.h:357
static constexpr unsigned int SHORT_BLOCK_PERIODS
Track confirm delays up to 12 blocks for short horizon.
Definition: fees.h:152
static constexpr double INF_FEERATE
Definition: fees.cpp:38
double totalConfirmed
Definition: fees.h:78
static constexpr double SUFFICIENT_FEETXS
Require an avg of 0.1 tx in the combined feerate bucket per block to have stat significance.
Definition: fees.h:178
virtual ~CBlockPolicyEstimator()
std::vector< double > m_feerate_avg
Definition: fees.cpp:99
const CAmount m_fee
static constexpr double SHORT_DECAY
Decay of .962 is a half-life of 18 blocks or about 3 hours.
Definition: fees.h:164
path filename() const
Definition: fs.h:72
static std::set< double > MakeFeeSet(const CFeeRate &min_incremental_fee, double max_filter_fee_rate, double fee_filter_spacing)
Definition: fees.cpp:1071
std::vector< double > txCtAvg
Definition: fees.cpp:87
#define LogPrintf(...)
Definition: logging.h:361
void UpdateMovingAverages()
Update our estimates by decaying our historical moving average and updating with the data gathered fr...
Definition: fees.cpp:230
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...
Definition: fees.cpp:726
Path class wrapper to block calls to the fs::path(std::string) implicit constructor and the fs::path:...
Definition: fs.h:32
const fs::path m_estimation_filepath
Definition: fees.h:199
void FlushUnconfirmed() EXCLUSIVE_LOCKS_REQUIRED(!m_cs_fee_estimator)
Empty mempool transactions on shutdown to record failure to confirm for txs still in mempool...
Definition: fees.cpp:1050
unsigned int HighestTargetTracked(FeeEstimateHorizon horizon) const EXCLUSIVE_LOCKS_REQUIRED(!m_cs_fee_estimator)
Calculation of highest target that estimates are tracked for.
Definition: fees.cpp:762
const unsigned int txHeight
void MempoolTransactionsRemovedForBlock(const std::vector< RemovedMempoolTransactionInfo > &txs_removed_for_block, unsigned int nBlockHeight) override EXCLUSIVE_LOCKS_REQUIRED(!m_cs_fee_estimator)
Definition: fees.cpp:590
CAmount GetFeePerK() const
Return the fee in satoshis for a vsize of 1000 vbytes.
Definition: feerate.h:60
void TransactionRemovedFromMempool(const CTransactionRef &tx, MemPoolRemovalReason, uint64_t) override EXCLUSIVE_LOCKS_REQUIRED(!m_cs_fee_estimator)
Notifies listeners of a transaction leaving mempool.
Definition: fees.cpp:585
bool processBlockTx(unsigned int nBlockHeight, const RemovedMempoolTransactionInfo &tx) EXCLUSIVE_LOCKS_REQUIRED(m_cs_fee_estimator)
Process a transaction confirmed in a block.
Definition: fees.cpp:640
const std::set< double > m_fee_set
Definition: fees.h:340