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