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-2020 The Bitcoin Core developers
3// Distributed under the MIT software license, see the accompanying
4// file COPYING or http://www.opensource.org/licenses/mit-license.php.
5
6#include <policy/fees.h>
7
8#include <clientversion.h>
9#include <fs.h>
10#include <logging.h>
11#include <streams.h>
12#include <txmempool.h>
13#include <util/serfloat.h>
14#include <util/system.h>
15
16static const char* FEE_ESTIMATES_FILENAME = "fee_estimates.dat";
17
18static 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
30namespace {
31
32struct 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{
59private:
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
98public:
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
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
158TxConfirmStats::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
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
187void 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
196void 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
224double 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
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
387void 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
443unsigned 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
451void 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.
494{
496 std::map<uint256, TxStatsInfo>::iterator pos = mapMemPoolTxs.find(hash);
497 if (pos != mapMemPoolTxs.end()) {
498 feeStats->removeTx(pos->second.blockHeight, nBestSeenHeight, pos->second.bucketIndex, inBlock);
499 shortStats->removeTx(pos->second.blockHeight, nBestSeenHeight, pos->second.bucketIndex, inBlock);
500 longStats->removeTx(pos->second.blockHeight, nBestSeenHeight, pos->second.bucketIndex, inBlock);
501 mapMemPoolTxs.erase(hash);
502 return true;
503 } else {
504 return false;
505 }
506}
507
509 : nBestSeenHeight(0), firstRecordedHeight(0), historicalFirst(0), historicalBest(0), trackedTxs(0), untrackedTxs(0)
510{
511 static_assert(MIN_BUCKET_FEERATE > 0, "Min feerate must be nonzero");
512 size_t bucketIndex = 0;
513
514 for (double bucketBoundary = MIN_BUCKET_FEERATE; bucketBoundary <= MAX_BUCKET_FEERATE; bucketBoundary *= FEE_SPACING, bucketIndex++) {
515 buckets.push_back(bucketBoundary);
516 bucketMap[bucketBoundary] = bucketIndex;
517 }
518 buckets.push_back(INF_FEERATE);
519 bucketMap[INF_FEERATE] = bucketIndex;
520 assert(bucketMap.size() == buckets.size());
521
522 feeStats = std::unique_ptr<TxConfirmStats>(new TxConfirmStats(buckets, bucketMap, MED_BLOCK_PERIODS, MED_DECAY, MED_SCALE));
523 shortStats = std::unique_ptr<TxConfirmStats>(new TxConfirmStats(buckets, bucketMap, SHORT_BLOCK_PERIODS, SHORT_DECAY, SHORT_SCALE));
524 longStats = std::unique_ptr<TxConfirmStats>(new TxConfirmStats(buckets, bucketMap, LONG_BLOCK_PERIODS, LONG_DECAY, LONG_SCALE));
525
526 // If the fee estimation file is present, read recorded estimations
528 CAutoFile est_file(fsbridge::fopen(est_filepath, "rb"), SER_DISK, CLIENT_VERSION);
529 if (est_file.IsNull() || !Read(est_file)) {
530 LogPrintf("Failed to read fee estimates from %s. Continue anyway.\n", fs::PathToString(est_filepath));
531 }
532}
533
535{
536}
537
538void CBlockPolicyEstimator::processTransaction(const CTxMemPoolEntry& entry, bool validFeeEstimate)
539{
541 unsigned int txHeight = entry.GetHeight();
542 uint256 hash = entry.GetTx().GetHash();
543 if (mapMemPoolTxs.count(hash)) {
544 LogPrint(BCLog::ESTIMATEFEE, "Blockpolicy error mempool tx %s already being tracked\n",
545 hash.ToString());
546 return;
547 }
548
549 if (txHeight != nBestSeenHeight) {
550 // Ignore side chains and re-orgs; assuming they are random they don't
551 // affect the estimate. We'll potentially double count transactions in 1-block reorgs.
552 // Ignore txs if BlockPolicyEstimator is not in sync with ActiveChain().Tip().
553 // It will be synced next time a block is processed.
554 return;
555 }
556
557 // Only want to be updating estimates when our blockchain is synced,
558 // otherwise we'll miscalculate how many blocks its taking to get included.
559 if (!validFeeEstimate) {
560 untrackedTxs++;
561 return;
562 }
563 trackedTxs++;
564
565 // Feerates are stored and reported as BTC-per-kb:
566 CFeeRate feeRate(entry.GetFee(), entry.GetTxSize());
567
568 mapMemPoolTxs[hash].blockHeight = txHeight;
569 unsigned int bucketIndex = feeStats->NewTx(txHeight, (double)feeRate.GetFeePerK());
570 mapMemPoolTxs[hash].bucketIndex = bucketIndex;
571 unsigned int bucketIndex2 = shortStats->NewTx(txHeight, (double)feeRate.GetFeePerK());
572 assert(bucketIndex == bucketIndex2);
573 unsigned int bucketIndex3 = longStats->NewTx(txHeight, (double)feeRate.GetFeePerK());
574 assert(bucketIndex == bucketIndex3);
575}
576
577bool CBlockPolicyEstimator::processBlockTx(unsigned int nBlockHeight, const CTxMemPoolEntry* entry)
578{
579 if (!removeTx(entry->GetTx().GetHash(), true)) {
580 // This transaction wasn't being tracked for fee estimation
581 return false;
582 }
583
584 // How many blocks did it take for miners to include this transaction?
585 // blocksToConfirm is 1-based, so a transaction included in the earliest
586 // possible block has confirmation count of 1
587 int blocksToConfirm = nBlockHeight - entry->GetHeight();
588 if (blocksToConfirm <= 0) {
589 // This can't happen because we don't process transactions from a block with a height
590 // lower than our greatest seen height
591 LogPrint(BCLog::ESTIMATEFEE, "Blockpolicy error Transaction had negative blocksToConfirm\n");
592 return false;
593 }
594
595 // Feerates are stored and reported as BTC-per-kb:
596 CFeeRate feeRate(entry->GetFee(), entry->GetTxSize());
597
598 feeStats->Record(blocksToConfirm, (double)feeRate.GetFeePerK());
599 shortStats->Record(blocksToConfirm, (double)feeRate.GetFeePerK());
600 longStats->Record(blocksToConfirm, (double)feeRate.GetFeePerK());
601 return true;
602}
603
604void CBlockPolicyEstimator::processBlock(unsigned int nBlockHeight,
605 std::vector<const CTxMemPoolEntry*>& entries)
606{
608 if (nBlockHeight <= nBestSeenHeight) {
609 // Ignore side chains and re-orgs; assuming they are random
610 // they don't affect the estimate.
611 // And if an attacker can re-org the chain at will, then
612 // you've got much bigger problems than "attacker can influence
613 // transaction fees."
614 return;
615 }
616
617 // Must update nBestSeenHeight in sync with ClearCurrent so that
618 // calls to removeTx (via processBlockTx) correctly calculate age
619 // of unconfirmed txs to remove from tracking.
620 nBestSeenHeight = nBlockHeight;
621
622 // Update unconfirmed circular buffer
623 feeStats->ClearCurrent(nBlockHeight);
624 shortStats->ClearCurrent(nBlockHeight);
625 longStats->ClearCurrent(nBlockHeight);
626
627 // Decay all exponential averages
628 feeStats->UpdateMovingAverages();
629 shortStats->UpdateMovingAverages();
630 longStats->UpdateMovingAverages();
631
632 unsigned int countedTxs = 0;
633 // Update averages with data points from current block
634 for (const auto& entry : entries) {
635 if (processBlockTx(nBlockHeight, entry))
636 countedTxs++;
637 }
638
639 if (firstRecordedHeight == 0 && countedTxs > 0) {
640 firstRecordedHeight = nBestSeenHeight;
641 LogPrint(BCLog::ESTIMATEFEE, "Blockpolicy first recorded height %u\n", firstRecordedHeight);
642 }
643
644
645 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",
646 countedTxs, entries.size(), trackedTxs, trackedTxs + untrackedTxs, mapMemPoolTxs.size(),
647 MaxUsableEstimate(), HistoricalBlockSpan() > BlockSpan() ? "historical" : "current");
648
649 trackedTxs = 0;
650 untrackedTxs = 0;
651}
652
654{
655 // It's not possible to get reasonable estimates for confTarget of 1
656 if (confTarget <= 1)
657 return CFeeRate(0);
658
660}
661
662CFeeRate CBlockPolicyEstimator::estimateRawFee(int confTarget, double successThreshold, FeeEstimateHorizon horizon, EstimationResult* result) const
663{
664 TxConfirmStats* stats = nullptr;
665 double sufficientTxs = SUFFICIENT_FEETXS;
666 switch (horizon) {
668 stats = shortStats.get();
669 sufficientTxs = SUFFICIENT_TXS_SHORT;
670 break;
671 }
673 stats = feeStats.get();
674 break;
675 }
677 stats = longStats.get();
678 break;
679 }
680 } // no default case, so the compiler can warn about missing cases
681 assert(stats);
682
684 // Return failure if trying to analyze a target we're not tracking
685 if (confTarget <= 0 || (unsigned int)confTarget > stats->GetMaxConfirms())
686 return CFeeRate(0);
687 if (successThreshold > 1)
688 return CFeeRate(0);
689
690 double median = stats->EstimateMedianVal(confTarget, sufficientTxs, successThreshold, nBestSeenHeight, result);
691
692 if (median < 0)
693 return CFeeRate(0);
694
695 return CFeeRate(llround(median));
696}
697
699{
701 switch (horizon) {
703 return shortStats->GetMaxConfirms();
704 }
706 return feeStats->GetMaxConfirms();
707 }
709 return longStats->GetMaxConfirms();
710 }
711 } // no default case, so the compiler can warn about missing cases
712 assert(false);
713}
714
716{
717 if (firstRecordedHeight == 0) return 0;
718 assert(nBestSeenHeight >= firstRecordedHeight);
719
720 return nBestSeenHeight - firstRecordedHeight;
721}
722
724{
725 if (historicalFirst == 0) return 0;
726 assert(historicalBest >= historicalFirst);
727
728 if (nBestSeenHeight - historicalBest > OLDEST_ESTIMATE_HISTORY) return 0;
729
730 return historicalBest - historicalFirst;
731}
732
734{
735 // Block spans are divided by 2 to make sure there are enough potential failing data points for the estimate
736 return std::min(longStats->GetMaxConfirms(), std::max(BlockSpan(), HistoricalBlockSpan()) / 2);
737}
738
743double CBlockPolicyEstimator::estimateCombinedFee(unsigned int confTarget, double successThreshold, bool checkShorterHorizon, EstimationResult *result) const
744{
745 double estimate = -1;
746 if (confTarget >= 1 && confTarget <= longStats->GetMaxConfirms()) {
747 // Find estimate from shortest time horizon possible
748 if (confTarget <= shortStats->GetMaxConfirms()) { // short horizon
749 estimate = shortStats->EstimateMedianVal(confTarget, SUFFICIENT_TXS_SHORT, successThreshold, nBestSeenHeight, result);
750 }
751 else if (confTarget <= feeStats->GetMaxConfirms()) { // medium horizon
752 estimate = feeStats->EstimateMedianVal(confTarget, SUFFICIENT_FEETXS, successThreshold, nBestSeenHeight, result);
753 }
754 else { // long horizon
755 estimate = longStats->EstimateMedianVal(confTarget, SUFFICIENT_FEETXS, successThreshold, nBestSeenHeight, result);
756 }
757 if (checkShorterHorizon) {
758 EstimationResult tempResult;
759 // If a lower confTarget from a more recent horizon returns a lower answer use it.
760 if (confTarget > feeStats->GetMaxConfirms()) {
761 double medMax = feeStats->EstimateMedianVal(feeStats->GetMaxConfirms(), SUFFICIENT_FEETXS, successThreshold, nBestSeenHeight, &tempResult);
762 if (medMax > 0 && (estimate == -1 || medMax < estimate)) {
763 estimate = medMax;
764 if (result) *result = tempResult;
765 }
766 }
767 if (confTarget > shortStats->GetMaxConfirms()) {
768 double shortMax = shortStats->EstimateMedianVal(shortStats->GetMaxConfirms(), SUFFICIENT_TXS_SHORT, successThreshold, nBestSeenHeight, &tempResult);
769 if (shortMax > 0 && (estimate == -1 || shortMax < estimate)) {
770 estimate = shortMax;
771 if (result) *result = tempResult;
772 }
773 }
774 }
775 }
776 return estimate;
777}
778
782double CBlockPolicyEstimator::estimateConservativeFee(unsigned int doubleTarget, EstimationResult *result) const
783{
784 double estimate = -1;
785 EstimationResult tempResult;
786 if (doubleTarget <= shortStats->GetMaxConfirms()) {
787 estimate = feeStats->EstimateMedianVal(doubleTarget, SUFFICIENT_FEETXS, DOUBLE_SUCCESS_PCT, nBestSeenHeight, result);
788 }
789 if (doubleTarget <= feeStats->GetMaxConfirms()) {
790 double longEstimate = longStats->EstimateMedianVal(doubleTarget, SUFFICIENT_FEETXS, DOUBLE_SUCCESS_PCT, nBestSeenHeight, &tempResult);
791 if (longEstimate > estimate) {
792 estimate = longEstimate;
793 if (result) *result = tempResult;
794 }
795 }
796 return estimate;
797}
798
806CFeeRate CBlockPolicyEstimator::estimateSmartFee(int confTarget, FeeCalculation *feeCalc, bool conservative) const
807{
809
810 if (feeCalc) {
811 feeCalc->desiredTarget = confTarget;
812 feeCalc->returnedTarget = confTarget;
813 }
814
815 double median = -1;
816 EstimationResult tempResult;
817
818 // Return failure if trying to analyze a target we're not tracking
819 if (confTarget <= 0 || (unsigned int)confTarget > longStats->GetMaxConfirms()) {
820 return CFeeRate(0); // error condition
821 }
822
823 // It's not possible to get reasonable estimates for confTarget of 1
824 if (confTarget == 1) confTarget = 2;
825
826 unsigned int maxUsableEstimate = MaxUsableEstimate();
827 if ((unsigned int)confTarget > maxUsableEstimate) {
828 confTarget = maxUsableEstimate;
829 }
830 if (feeCalc) feeCalc->returnedTarget = confTarget;
831
832 if (confTarget <= 1) return CFeeRate(0); // error condition
833
834 assert(confTarget > 0); //estimateCombinedFee and estimateConservativeFee take unsigned ints
845 double halfEst = estimateCombinedFee(confTarget/2, HALF_SUCCESS_PCT, true, &tempResult);
846 if (feeCalc) {
847 feeCalc->est = tempResult;
849 }
850 median = halfEst;
851 double actualEst = estimateCombinedFee(confTarget, SUCCESS_PCT, true, &tempResult);
852 if (actualEst > median) {
853 median = actualEst;
854 if (feeCalc) {
855 feeCalc->est = tempResult;
857 }
858 }
859 double doubleEst = estimateCombinedFee(2 * confTarget, DOUBLE_SUCCESS_PCT, !conservative, &tempResult);
860 if (doubleEst > median) {
861 median = doubleEst;
862 if (feeCalc) {
863 feeCalc->est = tempResult;
865 }
866 }
867
868 if (conservative || median == -1) {
869 double consEst = estimateConservativeFee(2 * confTarget, &tempResult);
870 if (consEst > median) {
871 median = consEst;
872 if (feeCalc) {
873 feeCalc->est = tempResult;
875 }
876 }
877 }
878
879 if (median < 0) return CFeeRate(0); // error condition
880
881 return CFeeRate(llround(median));
882}
883
886
888 CAutoFile est_file(fsbridge::fopen(est_filepath, "wb"), SER_DISK, CLIENT_VERSION);
889 if (est_file.IsNull() || !Write(est_file)) {
890 LogPrintf("Failed to write fee estimates to %s. Continue anyway.\n", fs::PathToString(est_filepath));
891 }
892}
893
895{
896 try {
898 fileout << 149900; // version required to read: 0.14.99 or later
899 fileout << CLIENT_VERSION; // version that wrote the file
900 fileout << nBestSeenHeight;
901 if (BlockSpan() > HistoricalBlockSpan()/2) {
902 fileout << firstRecordedHeight << nBestSeenHeight;
903 }
904 else {
905 fileout << historicalFirst << historicalBest;
906 }
907 fileout << Using<VectorFormatter<EncodedDoubleFormatter>>(buckets);
908 feeStats->Write(fileout);
909 shortStats->Write(fileout);
910 longStats->Write(fileout);
911 }
912 catch (const std::exception&) {
913 LogPrintf("CBlockPolicyEstimator::Write(): unable to write policy estimator data (non-fatal)\n");
914 return false;
915 }
916 return true;
917}
918
920{
921 try {
923 int nVersionRequired, nVersionThatWrote;
924 filein >> nVersionRequired >> nVersionThatWrote;
925 if (nVersionRequired > CLIENT_VERSION) {
926 throw std::runtime_error(strprintf("up-version (%d) fee estimate file", nVersionRequired));
927 }
928
929 // Read fee estimates file into temporary variables so existing data
930 // structures aren't corrupted if there is an exception.
931 unsigned int nFileBestSeenHeight;
932 filein >> nFileBestSeenHeight;
933
934 if (nVersionRequired < 149900) {
935 LogPrintf("%s: incompatible old fee estimation data (non-fatal). Version: %d\n", __func__, nVersionRequired);
936 } else { // New format introduced in 149900
937 unsigned int nFileHistoricalFirst, nFileHistoricalBest;
938 filein >> nFileHistoricalFirst >> nFileHistoricalBest;
939 if (nFileHistoricalFirst > nFileHistoricalBest || nFileHistoricalBest > nFileBestSeenHeight) {
940 throw std::runtime_error("Corrupt estimates file. Historical block range for estimates is invalid");
941 }
942 std::vector<double> fileBuckets;
943 filein >> Using<VectorFormatter<EncodedDoubleFormatter>>(fileBuckets);
944 size_t numBuckets = fileBuckets.size();
945 if (numBuckets <= 1 || numBuckets > 1000) {
946 throw std::runtime_error("Corrupt estimates file. Must have between 2 and 1000 feerate buckets");
947 }
948
949 std::unique_ptr<TxConfirmStats> fileFeeStats(new TxConfirmStats(buckets, bucketMap, MED_BLOCK_PERIODS, MED_DECAY, MED_SCALE));
950 std::unique_ptr<TxConfirmStats> fileShortStats(new TxConfirmStats(buckets, bucketMap, SHORT_BLOCK_PERIODS, SHORT_DECAY, SHORT_SCALE));
951 std::unique_ptr<TxConfirmStats> fileLongStats(new TxConfirmStats(buckets, bucketMap, LONG_BLOCK_PERIODS, LONG_DECAY, LONG_SCALE));
952 fileFeeStats->Read(filein, nVersionThatWrote, numBuckets);
953 fileShortStats->Read(filein, nVersionThatWrote, numBuckets);
954 fileLongStats->Read(filein, nVersionThatWrote, numBuckets);
955
956 // Fee estimates file parsed correctly
957 // Copy buckets from file and refresh our bucketmap
958 buckets = fileBuckets;
959 bucketMap.clear();
960 for (unsigned int i = 0; i < buckets.size(); i++) {
961 bucketMap[buckets[i]] = i;
962 }
963
964 // Destroy old TxConfirmStats and point to new ones that already reference buckets and bucketMap
965 feeStats = std::move(fileFeeStats);
966 shortStats = std::move(fileShortStats);
967 longStats = std::move(fileLongStats);
968
969 nBestSeenHeight = nFileBestSeenHeight;
970 historicalFirst = nFileHistoricalFirst;
971 historicalBest = nFileHistoricalBest;
972 }
973 }
974 catch (const std::exception& e) {
975 LogPrintf("CBlockPolicyEstimator::Read(): unable to read policy estimator data (non-fatal): %s\n",e.what());
976 return false;
977 }
978 return true;
979}
980
982 int64_t startclear = GetTimeMicros();
984 size_t num_entries = mapMemPoolTxs.size();
985 // Remove every entry in mapMemPoolTxs
986 while (!mapMemPoolTxs.empty()) {
987 auto mi = mapMemPoolTxs.begin();
988 removeTx(mi->first, false); // this calls erase() on mapMemPoolTxs
989 }
990 int64_t endclear = GetTimeMicros();
991 LogPrint(BCLog::ESTIMATEFEE, "Recorded %u unconfirmed txs from mempool in %gs\n", num_entries, (endclear - startclear)*0.000001);
992}
993
995{
996 CAmount minFeeLimit = std::max(CAmount(1), minIncrementalFee.GetFeePerK() / 2);
997 feeset.insert(0);
998 for (double bucketBoundary = minFeeLimit; bucketBoundary <= MAX_FILTER_FEERATE; bucketBoundary *= FEE_FILTER_SPACING) {
999 feeset.insert(bucketBoundary);
1000 }
1001}
1002
1004{
1005 std::set<double>::iterator it = feeset.lower_bound(currentMinFee);
1006 if ((it != feeset.begin() && insecure_rand.rand32() % 3 != 0) || it == feeset.end()) {
1007 it--;
1008 }
1009 return static_cast<CAmount>(*it);
1010}
int64_t CAmount
Amount in satoshis (Can be negative)
Definition: amount.h:12
const fs::path & GetDataDirNet() const
Get data directory path with appended network identifier.
Definition: system.h:288
Non-refcounted RAII wrapper for FILE*.
Definition: streams.h:565
bool IsNull() const
Return true if the wrapped FILE* is nullptr, false otherwise.
Definition: streams.h:609
RecursiveMutex m_cs_fee_estimator
Definition: fees.h:229
static constexpr unsigned int LONG_SCALE
Definition: fees.h:142
bool Read(CAutoFile &filein)
Read estimation data from a file.
Definition: fees.cpp:919
static constexpr double SUCCESS_PCT
Require greater than 85% of X feerate transactions to be confirmed within Y blocks.
Definition: fees.h:156
static constexpr double MIN_BUCKET_FEERATE
Minimum and Maximum values for tracking feerates The MIN_BUCKET_FEERATE should just be set to the low...
Definition: fees.h:172
double estimateCombinedFee(unsigned int confTarget, double successThreshold, bool checkShorterHorizon, EstimationResult *result) const EXCLUSIVE_LOCKS_REQUIRED(m_cs_fee_estimator)
Helper for estimateSmartFee.
Definition: fees.cpp:743
static constexpr double FEE_SPACING
Spacing of FeeRate buckets We have to lump transactions into buckets based on feerate,...
Definition: fees.h:180
static const unsigned int OLDEST_ESTIMATE_HISTORY
Historical estimates that are older than this aren't valid.
Definition: fees.h:144
CFeeRate estimateRawFee(int confTarget, double successThreshold, FeeEstimateHorizon horizon, EstimationResult *result=nullptr) const
Return a specific fee estimate calculation with a given success threshold and time horizon,...
Definition: fees.cpp:662
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
static constexpr double MAX_BUCKET_FEERATE
Definition: fees.h:173
static constexpr unsigned int LONG_BLOCK_PERIODS
Track confirm delays up to 1008 blocks for long horizon.
Definition: fees.h:141
static constexpr double SHORT_DECAY
Decay of .962 is a half-life of 18 blocks or about 3 hours.
Definition: fees.h:147
bool Write(CAutoFile &fileout) const
Write estimation data to a file.
Definition: fees.cpp:894
CBlockPolicyEstimator()
Create new BlockPolicyEstimator and initialize stats tracking classes with default values.
Definition: fees.cpp:508
static constexpr double LONG_DECAY
Decay of .99931 is a half-life of 1008 blocks or about 1 week.
Definition: fees.h:151
double estimateConservativeFee(unsigned int doubleTarget, EstimationResult *result) const EXCLUSIVE_LOCKS_REQUIRED(m_cs_fee_estimator)
Helper for estimateSmartFee.
Definition: fees.cpp:782
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
static constexpr double MED_DECAY
Decay of .9952 is a half-life of 144 blocks or about 1 day.
Definition: fees.h:149
bool removeTx(uint256 hash, bool inBlock)
Remove a transaction from the mempool tracking stats.
Definition: fees.cpp:493
void FlushUnconfirmed()
Empty mempool transactions on shutdown to record failure to confirm for txs still in mempool.
Definition: fees.cpp:981
void Flush()
Drop still unconfirmed transactions and record current estimations, if the fee estimation file is pre...
Definition: fees.cpp:884
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:733
static constexpr unsigned int SHORT_SCALE
Definition: fees.h:136
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:715
static constexpr unsigned int SHORT_BLOCK_PERIODS
Track confirm delays up to 12 blocks for short horizon.
Definition: fees.h:135
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
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:723
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:577
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
static constexpr unsigned int MED_SCALE
Definition: fees.h:139
static constexpr unsigned int MED_BLOCK_PERIODS
Track confirm delays up to 48 blocks for medium horizon.
Definition: fees.h:138
void processTransaction(const CTxMemPoolEntry &entry, bool validFeeEstimate)
Process a transaction accepted to the mempool.
Definition: fees.cpp:538
void processBlock(unsigned int nBlockHeight, std::vector< const CTxMemPoolEntry * > &entries)
Process all the transactions that have been included in a block.
Definition: fees.cpp:604
CFeeRate estimateSmartFee(int confTarget, FeeCalculation *feeCalc, bool conservative) const
Estimate feerate needed to get be included in a block within confTarget blocks.
Definition: fees.cpp:806
unsigned int HighestTargetTracked(FeeEstimateHorizon horizon) const
Calculation of highest target that estimates are tracked for.
Definition: fees.cpp:698
CFeeRate estimateFee(int confTarget) const
DEPRECATED.
Definition: fees.cpp:653
Fee rate in satoshis per kilobyte: CAmount / kB.
Definition: feerate.h:30
CAmount GetFeePerK() const
Return the fee in satoshis for a size of 1000 bytes.
Definition: feerate.h:57
const uint256 & GetHash() const
Definition: transaction.h:302
CTxMemPoolEntry stores data about the corresponding transaction, as well as data about all in-mempool...
Definition: txmempool.h:80
unsigned int GetHeight() const
Definition: txmempool.h:126
const CTransaction & GetTx() const
Definition: txmempool.h:120
size_t GetTxSize() const
Definition: txmempool.cpp:107
const CAmount & GetFee() const
Definition: txmempool.h:122
uint32_t rand32() noexcept
Generate a random 32-bit integer.
Definition: random.h:205
FastRandomContext insecure_rand
Definition: fees.h:291
static constexpr double MAX_FILTER_FEERATE
Definition: fees.h:275
CAmount round(CAmount currentMinFee)
Quantize a minimum fee for privacy purpose before broadcast.
Definition: fees.cpp:1003
FeeFilterRounder(const CFeeRate &minIncrementalFee)
Create new FeeFilterRounder.
Definition: fees.cpp:994
std::set< double > feeset
Definition: fees.h:290
static constexpr double FEE_FILTER_SPACING
FEE_FILTER_SPACING is just used to provide some quantization of fee filter results.
Definition: fees.h:280
We will instantiate an instance of this class to track transactions that were included in a block.
Definition: fees.cpp:58
void removeTx(unsigned int entryHeight, unsigned int nBestSeenHeight, unsigned int bucketIndex, bool inBlock)
Remove a transaction from mempool tracking stats.
Definition: fees.cpp:451
std::vector< std::vector< double > > failAvg
Definition: fees.cpp:75
TxConfirmStats(const std::vector< double > &defaultBuckets, const std::map< double, unsigned int > &defaultBucketMap, unsigned int maxPeriods, double decay, unsigned int scale)
Create new TxConfirmStats.
Definition: fees.cpp:158
unsigned int GetMaxConfirms() const
Return the max number of confirms we're tracking.
Definition: fees.cpp:145
void ClearCurrent(unsigned int nBlockHeight)
Roll the circular buffer for unconfirmed txs.
Definition: fees.cpp:187
unsigned int scale
Definition: fees.cpp:87
double decay
Definition: fees.cpp:84
void Record(int blocksToConfirm, double val)
Record a new transaction data point in the current block stats.
Definition: fees.cpp:196
void resizeInMemoryCounters(size_t newbuckets)
Definition: fees.cpp:177
std::vector< double > txCtAvg
Definition: fees.cpp:67
std::vector< int > oldUnconfTxs
Definition: fees.cpp:94
void Write(CAutoFile &fileout) const
Write state of estimation data to a file.
Definition: fees.cpp:377
void UpdateMovingAverages()
Update our estimates by decaying our historical moving average and updating with the data gathered fr...
Definition: fees.cpp:210
const std::map< double, unsigned int > & bucketMap
Definition: fees.cpp:62
const std::vector< double > & buckets
Definition: fees.cpp:61
std::vector< std::vector< double > > confAvg
Definition: fees.cpp:71
std::vector< std::vector< int > > unconfTxs
Definition: fees.cpp:92
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
unsigned int NewTx(unsigned int nBlockHeight, double val)
Record a new transaction entering the mempool.
Definition: fees.cpp:443
std::vector< double > m_feerate_avg
Definition: fees.cpp:79
double EstimateMedianVal(int confTarget, double sufficientTxVal, double minSuccess, unsigned int nBlockHeight, EstimationResult *result=nullptr) const
Calculate a feerate estimate.
Definition: fees.cpp:224
std::string ToString() const
Definition: uint256.cpp:64
Path class wrapper to prepare application code for transition from boost::filesystem library to std::...
Definition: fs.h:34
256-bit opaque blob.
Definition: uint256.h:124
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:191
#define LogPrintf(...)
Definition: logging.h:187
@ ESTIMATEFEE
Definition: logging.h:46
static std::string PathToString(const path &path)
Convert path object to byte string.
Definition: fs.h:120
FILE * fopen(const fs::path &p, const char *mode)
Definition: fs.cpp:25
static constexpr double INF_FEERATE
Definition: fees.cpp:18
static const char * FEE_ESTIMATES_FILENAME
Definition: fees.cpp:16
std::string StringForFeeEstimateHorizon(FeeEstimateHorizon horizon)
Definition: fees.cpp:20
FeeEstimateHorizon
Definition: fees.h:28
uint64_t EncodeDouble(double f) noexcept
Definition: serfloat.cpp:37
double DecodeDouble(uint64_t v) noexcept
Definition: serfloat.cpp:10
@ SER_DISK
Definition: serialize.h:139
EstimatorBucket fail
Definition: fees.h:70
EstimatorBucket pass
Definition: fees.h:69
double decay
Definition: fees.h:71
unsigned int scale
Definition: fees.h:72
double totalConfirmed
Definition: fees.h:61
double end
Definition: fees.h:59
double leftMempool
Definition: fees.h:63
double start
Definition: fees.h:58
double withinTarget
Definition: fees.h:60
double inMempool
Definition: fees.h:62
int returnedTarget
Definition: fees.h:80
int desiredTarget
Definition: fees.h:79
FeeReason reason
Definition: fees.h:78
EstimationResult est
Definition: fees.h:77
#define LOCK(cs)
Definition: sync.h:226
int64_t GetTimeMicros()
Returns the system time (not mockable)
Definition: time.cpp:122
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1164
ArgsManager gArgs
Definition: system.cpp:85
assert(!tx.IsCoinBase())