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