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