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