1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2016 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.
6 #include "policy/fees.h"
7 #include "policy/policy.h"
10 #include "clientversion.h"
11 #include "primitives/transaction.h"
14 #include "txmempool.h"
18 * We will instantiate an instance of this class to track transactions that were
19 * included in a block. We will lump transactions into a bucket according to their
20 * approximate feerate and then track how long it took for those txs to be included in a block
22 * The tracking of unconfirmed (mempool) transactions is completely independent of the
23 * historical tracking of transactions that have been confirmed in a block.
28 //Define the buckets we will group transactions into
29 std::vector
<double> buckets
; // The upper-bound of the range for the bucket (inclusive)
30 std::map
<double, unsigned int> bucketMap
; // Map of bucket upper-bound to index into all vectors by bucket
33 // Count the total # of txs in each bucket
34 // Track the historical moving average of this total over blocks
35 std::vector
<double> txCtAvg
;
36 // and calculate the total for the current block to update the moving average
37 std::vector
<int> curBlockTxCt
;
39 // Count the total # of txs confirmed within Y blocks in each bucket
40 // Track the historical moving average of theses totals over blocks
41 std::vector
<std::vector
<double> > confAvg
; // confAvg[Y][X]
42 // and calculate the totals for the current block to update the moving averages
43 std::vector
<std::vector
<int> > curBlockConf
; // curBlockConf[Y][X]
45 // Sum the total feerate of all tx's in each bucket
46 // Track the historical moving average of this total over blocks
47 std::vector
<double> avg
;
48 // and calculate the total for the current block to update the moving average
49 std::vector
<double> curBlockVal
;
51 // Combine the conf counts with tx counts to calculate the confirmation % for each Y,X
52 // Combine the total value with the tx counts to calculate the avg feerate per bucket
56 // Mempool counts of outstanding transactions
57 // For each bucket X, track the number of transactions in the mempool
58 // that are unconfirmed for each possible confirmation value Y
59 std::vector
<std::vector
<int> > unconfTxs
; //unconfTxs[Y][X]
60 // transactions still unconfirmed after MAX_CONFIRMS for each bucket
61 std::vector
<int> oldUnconfTxs
;
65 * Create new TxConfirmStats. This is called by BlockPolicyEstimator's
66 * constructor with default values.
67 * @param defaultBuckets contains the upper limits for the bucket boundaries
68 * @param maxConfirms max number of confirms to track
69 * @param decay how much to decay the historical moving average per block
71 TxConfirmStats(const std::vector
<double>& defaultBuckets
, unsigned int maxConfirms
, double decay
);
73 /** Clear the state of the curBlock variables to start counting for the new block */
74 void ClearCurrent(unsigned int nBlockHeight
);
77 * Record a new transaction data point in the current block stats
78 * @param blocksToConfirm the number of blocks it took this transaction to confirm
79 * @param val the feerate of the transaction
80 * @warning blocksToConfirm is 1-based and has to be >= 1
82 void Record(int blocksToConfirm
, double val
);
84 /** Record a new transaction entering the mempool*/
85 unsigned int NewTx(unsigned int nBlockHeight
, double val
);
87 /** Remove a transaction from mempool tracking stats*/
88 void removeTx(unsigned int entryHeight
, unsigned int nBestSeenHeight
,
89 unsigned int bucketIndex
);
91 /** Update our estimates by decaying our historical moving average and updating
92 with the data gathered from the current block */
93 void UpdateMovingAverages();
96 * Calculate a feerate estimate. Find the lowest value bucket (or range of buckets
97 * to make sure we have enough data points) whose transactions still have sufficient likelihood
98 * of being confirmed within the target number of confirmations
99 * @param confTarget target number of confirmations
100 * @param sufficientTxVal required average number of transactions per block in a bucket range
101 * @param minSuccess the success probability we require
102 * @param requireGreater return the lowest feerate such that all higher values pass minSuccess OR
103 * return the highest feerate such that all lower values fail minSuccess
104 * @param nBlockHeight the current block height
106 double EstimateMedianVal(int confTarget
, double sufficientTxVal
,
107 double minSuccess
, bool requireGreater
, unsigned int nBlockHeight
) const;
109 /** Return the max number of confirms we're tracking */
110 unsigned int GetMaxConfirms() const { return confAvg
.size(); }
112 /** Write state of estimation data to a file*/
113 void Write(CAutoFile
& fileout
) const;
116 * Read saved state of estimation data from a file and replace all internal data structures and
117 * variables with this state.
119 void Read(CAutoFile
& filein
);
123 TxConfirmStats::TxConfirmStats(const std::vector
<double>& defaultBuckets
,
124 unsigned int maxConfirms
, double _decay
)
127 for (unsigned int i
= 0; i
< defaultBuckets
.size(); i
++) {
128 buckets
.push_back(defaultBuckets
[i
]);
129 bucketMap
[defaultBuckets
[i
]] = i
;
131 confAvg
.resize(maxConfirms
);
132 curBlockConf
.resize(maxConfirms
);
133 unconfTxs
.resize(maxConfirms
);
134 for (unsigned int i
= 0; i
< maxConfirms
; i
++) {
135 confAvg
[i
].resize(buckets
.size());
136 curBlockConf
[i
].resize(buckets
.size());
137 unconfTxs
[i
].resize(buckets
.size());
140 oldUnconfTxs
.resize(buckets
.size());
141 curBlockTxCt
.resize(buckets
.size());
142 txCtAvg
.resize(buckets
.size());
143 curBlockVal
.resize(buckets
.size());
144 avg
.resize(buckets
.size());
147 // Zero out the data for the current block
148 void TxConfirmStats::ClearCurrent(unsigned int nBlockHeight
)
150 for (unsigned int j
= 0; j
< buckets
.size(); j
++) {
151 oldUnconfTxs
[j
] += unconfTxs
[nBlockHeight
%unconfTxs
.size()][j
];
152 unconfTxs
[nBlockHeight
%unconfTxs
.size()][j
] = 0;
153 for (unsigned int i
= 0; i
< curBlockConf
.size(); i
++)
154 curBlockConf
[i
][j
] = 0;
161 void TxConfirmStats::Record(int blocksToConfirm
, double val
)
163 // blocksToConfirm is 1-based
164 if (blocksToConfirm
< 1)
166 unsigned int bucketindex
= bucketMap
.lower_bound(val
)->second
;
167 for (size_t i
= blocksToConfirm
; i
<= curBlockConf
.size(); i
++) {
168 curBlockConf
[i
- 1][bucketindex
]++;
170 curBlockTxCt
[bucketindex
]++;
171 curBlockVal
[bucketindex
] += val
;
174 void TxConfirmStats::UpdateMovingAverages()
176 for (unsigned int j
= 0; j
< buckets
.size(); j
++) {
177 for (unsigned int i
= 0; i
< confAvg
.size(); i
++)
178 confAvg
[i
][j
] = confAvg
[i
][j
] * decay
+ curBlockConf
[i
][j
];
179 avg
[j
] = avg
[j
] * decay
+ curBlockVal
[j
];
180 txCtAvg
[j
] = txCtAvg
[j
] * decay
+ curBlockTxCt
[j
];
184 // returns -1 on error conditions
185 double TxConfirmStats::EstimateMedianVal(int confTarget
, double sufficientTxVal
,
186 double successBreakPoint
, bool requireGreater
,
187 unsigned int nBlockHeight
) const
189 // Counters for a bucket (or range of buckets)
190 double nConf
= 0; // Number of tx's confirmed within the confTarget
191 double totalNum
= 0; // Total number of tx's that were ever confirmed
192 int extraNum
= 0; // Number of tx's still in mempool for confTarget or longer
194 int maxbucketindex
= buckets
.size() - 1;
196 // requireGreater means we are looking for the lowest feerate such that all higher
197 // values pass, so we start at maxbucketindex (highest feerate) and look at successively
198 // smaller buckets until we reach failure. Otherwise, we are looking for the highest
199 // feerate such that all lower values fail, and we go in the opposite direction.
200 unsigned int startbucket
= requireGreater
? maxbucketindex
: 0;
201 int step
= requireGreater
? -1 : 1;
203 // We'll combine buckets until we have enough samples.
204 // The near and far variables will define the range we've combined
205 // The best variables are the last range we saw which still had a high
206 // enough confirmation rate to count as success.
207 // The cur variables are the current range we're counting.
208 unsigned int curNearBucket
= startbucket
;
209 unsigned int bestNearBucket
= startbucket
;
210 unsigned int curFarBucket
= startbucket
;
211 unsigned int bestFarBucket
= startbucket
;
213 bool foundAnswer
= false;
214 unsigned int bins
= unconfTxs
.size();
216 // Start counting from highest(default) or lowest feerate transactions
217 for (int bucket
= startbucket
; bucket
>= 0 && bucket
<= maxbucketindex
; bucket
+= step
) {
218 curFarBucket
= bucket
;
219 nConf
+= confAvg
[confTarget
- 1][bucket
];
220 totalNum
+= txCtAvg
[bucket
];
221 for (unsigned int confct
= confTarget
; confct
< GetMaxConfirms(); confct
++)
222 extraNum
+= unconfTxs
[(nBlockHeight
- confct
)%bins
][bucket
];
223 extraNum
+= oldUnconfTxs
[bucket
];
224 // If we have enough transaction data points in this range of buckets,
225 // we can test for success
226 // (Only count the confirmed data points, so that each confirmation count
227 // will be looking at the same amount of data and same bucket breaks)
228 if (totalNum
>= sufficientTxVal
/ (1 - decay
)) {
229 double curPct
= nConf
/ (totalNum
+ extraNum
);
231 // Check to see if we are no longer getting confirmed at the success rate
232 if (requireGreater
&& curPct
< successBreakPoint
)
234 if (!requireGreater
&& curPct
> successBreakPoint
)
237 // Otherwise update the cumulative stats, and the bucket variables
238 // and reset the counters
244 bestNearBucket
= curNearBucket
;
245 bestFarBucket
= curFarBucket
;
246 curNearBucket
= bucket
+ step
;
254 // Calculate the "average" feerate of the best bucket range that met success conditions
255 // Find the bucket with the median transaction and then report the average feerate from that bucket
256 // This is a compromise between finding the median which we can't since we don't save all tx's
257 // and reporting the average which is less accurate
258 unsigned int minBucket
= bestNearBucket
< bestFarBucket
? bestNearBucket
: bestFarBucket
;
259 unsigned int maxBucket
= bestNearBucket
> bestFarBucket
? bestNearBucket
: bestFarBucket
;
260 for (unsigned int j
= minBucket
; j
<= maxBucket
; j
++) {
263 if (foundAnswer
&& txSum
!= 0) {
265 for (unsigned int j
= minBucket
; j
<= maxBucket
; j
++) {
266 if (txCtAvg
[j
] < txSum
)
268 else { // we're in the right bucket
269 median
= avg
[j
] / txCtAvg
[j
];
275 LogPrint(BCLog::ESTIMATEFEE
, "%3d: For conf success %s %4.2f need feerate %s: %12.5g from buckets %8g - %8g Cur Bucket stats %6.2f%% %8.1f/(%.1f+%d mempool)\n",
276 confTarget
, requireGreater
? ">" : "<", successBreakPoint
,
277 requireGreater
? ">" : "<", median
, buckets
[minBucket
], buckets
[maxBucket
],
278 100 * nConf
/ (totalNum
+ extraNum
), nConf
, totalNum
, extraNum
);
283 void TxConfirmStats::Write(CAutoFile
& fileout
) const
292 void TxConfirmStats::Read(CAutoFile
& filein
)
294 // Read data file into temporary variables and do some very basic sanity checking
295 std::vector
<double> fileBuckets
;
296 std::vector
<double> fileAvg
;
297 std::vector
<std::vector
<double> > fileConfAvg
;
298 std::vector
<double> fileTxCtAvg
;
304 if (fileDecay
<= 0 || fileDecay
>= 1)
305 throw std::runtime_error("Corrupt estimates file. Decay must be between 0 and 1 (non-inclusive)");
306 filein
>> fileBuckets
;
307 numBuckets
= fileBuckets
.size();
308 if (numBuckets
<= 1 || numBuckets
> 1000)
309 throw std::runtime_error("Corrupt estimates file. Must have between 2 and 1000 feerate buckets");
311 if (fileAvg
.size() != numBuckets
)
312 throw std::runtime_error("Corrupt estimates file. Mismatch in feerate average bucket count");
313 filein
>> fileTxCtAvg
;
314 if (fileTxCtAvg
.size() != numBuckets
)
315 throw std::runtime_error("Corrupt estimates file. Mismatch in tx count bucket count");
316 filein
>> fileConfAvg
;
317 maxConfirms
= fileConfAvg
.size();
318 if (maxConfirms
<= 0 || maxConfirms
> 6 * 24 * 7) // one week
319 throw std::runtime_error("Corrupt estimates file. Must maintain estimates for between 1 and 1008 (one week) confirms");
320 for (unsigned int i
= 0; i
< maxConfirms
; i
++) {
321 if (fileConfAvg
[i
].size() != numBuckets
)
322 throw std::runtime_error("Corrupt estimates file. Mismatch in feerate conf average bucket count");
324 // Now that we've processed the entire feerate estimate data file and not
325 // thrown any errors, we can copy it to our data structures
327 buckets
= fileBuckets
;
329 confAvg
= fileConfAvg
;
330 txCtAvg
= fileTxCtAvg
;
333 // Resize the current block variables which aren't stored in the data file
334 // to match the number of confirms and buckets
335 curBlockConf
.resize(maxConfirms
);
336 for (unsigned int i
= 0; i
< maxConfirms
; i
++) {
337 curBlockConf
[i
].resize(buckets
.size());
339 curBlockTxCt
.resize(buckets
.size());
340 curBlockVal
.resize(buckets
.size());
342 unconfTxs
.resize(maxConfirms
);
343 for (unsigned int i
= 0; i
< maxConfirms
; i
++) {
344 unconfTxs
[i
].resize(buckets
.size());
346 oldUnconfTxs
.resize(buckets
.size());
348 for (unsigned int i
= 0; i
< buckets
.size(); i
++)
349 bucketMap
[buckets
[i
]] = i
;
351 LogPrint(BCLog::ESTIMATEFEE
, "Reading estimates: %u buckets counting confirms up to %u blocks\n",
352 numBuckets
, maxConfirms
);
355 unsigned int TxConfirmStats::NewTx(unsigned int nBlockHeight
, double val
)
357 unsigned int bucketindex
= bucketMap
.lower_bound(val
)->second
;
358 unsigned int blockIndex
= nBlockHeight
% unconfTxs
.size();
359 unconfTxs
[blockIndex
][bucketindex
]++;
363 void TxConfirmStats::removeTx(unsigned int entryHeight
, unsigned int nBestSeenHeight
, unsigned int bucketindex
)
365 //nBestSeenHeight is not updated yet for the new block
366 int blocksAgo
= nBestSeenHeight
- entryHeight
;
367 if (nBestSeenHeight
== 0) // the BlockPolicyEstimator hasn't seen any blocks yet
370 LogPrint(BCLog::ESTIMATEFEE
, "Blockpolicy error, blocks ago is negative for mempool tx\n");
371 return; //This can't happen because we call this with our best seen height, no entries can have higher
374 if (blocksAgo
>= (int)unconfTxs
.size()) {
375 if (oldUnconfTxs
[bucketindex
] > 0) {
376 oldUnconfTxs
[bucketindex
]--;
378 LogPrint(BCLog::ESTIMATEFEE
, "Blockpolicy error, mempool tx removed from >25 blocks,bucketIndex=%u already\n",
383 unsigned int blockIndex
= entryHeight
% unconfTxs
.size();
384 if (unconfTxs
[blockIndex
][bucketindex
] > 0) {
385 unconfTxs
[blockIndex
][bucketindex
]--;
387 LogPrint(BCLog::ESTIMATEFEE
, "Blockpolicy error, mempool tx removed from blockIndex=%u,bucketIndex=%u already\n",
388 blockIndex
, bucketindex
);
393 // This function is called from CTxMemPool::removeUnchecked to ensure
394 // txs removed from the mempool for any reason are no longer
395 // tracked. Txs that were part of a block have already been removed in
396 // processBlockTx to ensure they are never double tracked, but it is
397 // of no harm to try to remove them again.
398 bool CBlockPolicyEstimator::removeTx(uint256 hash
)
400 LOCK(cs_feeEstimator
);
401 std::map
<uint256
, TxStatsInfo
>::iterator pos
= mapMemPoolTxs
.find(hash
);
402 if (pos
!= mapMemPoolTxs
.end()) {
403 feeStats
->removeTx(pos
->second
.blockHeight
, nBestSeenHeight
, pos
->second
.bucketIndex
);
404 mapMemPoolTxs
.erase(hash
);
411 CBlockPolicyEstimator::CBlockPolicyEstimator()
412 : nBestSeenHeight(0), trackedTxs(0), untrackedTxs(0)
414 static_assert(MIN_BUCKET_FEERATE
> 0, "Min feerate must be nonzero");
415 minTrackedFee
= CFeeRate(MIN_BUCKET_FEERATE
);
416 std::vector
<double> vfeelist
;
417 for (double bucketBoundary
= minTrackedFee
.GetFeePerK(); bucketBoundary
<= MAX_BUCKET_FEERATE
; bucketBoundary
*= FEE_SPACING
) {
418 vfeelist
.push_back(bucketBoundary
);
420 vfeelist
.push_back(INF_FEERATE
);
421 feeStats
= new TxConfirmStats(vfeelist
, MAX_BLOCK_CONFIRMS
, DEFAULT_DECAY
);
424 CBlockPolicyEstimator::~CBlockPolicyEstimator()
429 void CBlockPolicyEstimator::processTransaction(const CTxMemPoolEntry
& entry
, bool validFeeEstimate
)
431 LOCK(cs_feeEstimator
);
432 unsigned int txHeight
= entry
.GetHeight();
433 uint256 hash
= entry
.GetTx().GetHash();
434 if (mapMemPoolTxs
.count(hash
)) {
435 LogPrint(BCLog::ESTIMATEFEE
, "Blockpolicy error mempool tx %s already being tracked\n",
436 hash
.ToString().c_str());
440 if (txHeight
!= nBestSeenHeight
) {
441 // Ignore side chains and re-orgs; assuming they are random they don't
442 // affect the estimate. We'll potentially double count transactions in 1-block reorgs.
443 // Ignore txs if BlockPolicyEstimator is not in sync with chainActive.Tip().
444 // It will be synced next time a block is processed.
448 // Only want to be updating estimates when our blockchain is synced,
449 // otherwise we'll miscalculate how many blocks its taking to get included.
450 if (!validFeeEstimate
) {
456 // Feerates are stored and reported as BTC-per-kb:
457 CFeeRate
feeRate(entry
.GetFee(), entry
.GetTxSize());
459 mapMemPoolTxs
[hash
].blockHeight
= txHeight
;
460 mapMemPoolTxs
[hash
].bucketIndex
= feeStats
->NewTx(txHeight
, (double)feeRate
.GetFeePerK());
463 bool CBlockPolicyEstimator::processBlockTx(unsigned int nBlockHeight
, const CTxMemPoolEntry
* entry
)
465 if (!removeTx(entry
->GetTx().GetHash())) {
466 // This transaction wasn't being tracked for fee estimation
470 // How many blocks did it take for miners to include this transaction?
471 // blocksToConfirm is 1-based, so a transaction included in the earliest
472 // possible block has confirmation count of 1
473 int blocksToConfirm
= nBlockHeight
- entry
->GetHeight();
474 if (blocksToConfirm
<= 0) {
475 // This can't happen because we don't process transactions from a block with a height
476 // lower than our greatest seen height
477 LogPrint(BCLog::ESTIMATEFEE
, "Blockpolicy error Transaction had negative blocksToConfirm\n");
481 // Feerates are stored and reported as BTC-per-kb:
482 CFeeRate
feeRate(entry
->GetFee(), entry
->GetTxSize());
484 feeStats
->Record(blocksToConfirm
, (double)feeRate
.GetFeePerK());
488 void CBlockPolicyEstimator::processBlock(unsigned int nBlockHeight
,
489 std::vector
<const CTxMemPoolEntry
*>& entries
)
491 LOCK(cs_feeEstimator
);
492 if (nBlockHeight
<= nBestSeenHeight
) {
493 // Ignore side chains and re-orgs; assuming they are random
494 // they don't affect the estimate.
495 // And if an attacker can re-org the chain at will, then
496 // you've got much bigger problems than "attacker can influence
497 // transaction fees."
501 // Must update nBestSeenHeight in sync with ClearCurrent so that
502 // calls to removeTx (via processBlockTx) correctly calculate age
503 // of unconfirmed txs to remove from tracking.
504 nBestSeenHeight
= nBlockHeight
;
506 // Clear the current block state and update unconfirmed circular buffer
507 feeStats
->ClearCurrent(nBlockHeight
);
509 unsigned int countedTxs
= 0;
510 // Repopulate the current block states
511 for (unsigned int i
= 0; i
< entries
.size(); i
++) {
512 if (processBlockTx(nBlockHeight
, entries
[i
]))
516 // Update all exponential averages with the current block state
517 feeStats
->UpdateMovingAverages();
519 LogPrint(BCLog::ESTIMATEFEE
, "Blockpolicy after updating estimates for %u of %u txs in block, since last block %u of %u tracked, new mempool map size %u\n",
520 countedTxs
, entries
.size(), trackedTxs
, trackedTxs
+ untrackedTxs
, mapMemPoolTxs
.size());
526 CFeeRate
CBlockPolicyEstimator::estimateFee(int confTarget
) const
528 LOCK(cs_feeEstimator
);
529 // Return failure if trying to analyze a target we're not tracking
530 // It's not possible to get reasonable estimates for confTarget of 1
531 if (confTarget
<= 1 || (unsigned int)confTarget
> feeStats
->GetMaxConfirms())
534 double median
= feeStats
->EstimateMedianVal(confTarget
, SUFFICIENT_FEETXS
, MIN_SUCCESS_PCT
, true, nBestSeenHeight
);
539 return CFeeRate(median
);
542 CFeeRate
CBlockPolicyEstimator::estimateSmartFee(int confTarget
, int *answerFoundAtTarget
, const CTxMemPool
& pool
) const
544 if (answerFoundAtTarget
)
545 *answerFoundAtTarget
= confTarget
;
550 LOCK(cs_feeEstimator
);
552 // Return failure if trying to analyze a target we're not tracking
553 if (confTarget
<= 0 || (unsigned int)confTarget
> feeStats
->GetMaxConfirms())
556 // It's not possible to get reasonable estimates for confTarget of 1
560 while (median
< 0 && (unsigned int)confTarget
<= feeStats
->GetMaxConfirms()) {
561 median
= feeStats
->EstimateMedianVal(confTarget
++, SUFFICIENT_FEETXS
, MIN_SUCCESS_PCT
, true, nBestSeenHeight
);
563 } // Must unlock cs_feeEstimator before taking mempool locks
565 if (answerFoundAtTarget
)
566 *answerFoundAtTarget
= confTarget
- 1;
568 // If mempool is limiting txs , return at least the min feerate from the mempool
569 CAmount minPoolFee
= pool
.GetMinFee(GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE
) * 1000000).GetFeePerK();
570 if (minPoolFee
> 0 && minPoolFee
> median
)
571 return CFeeRate(minPoolFee
);
576 return CFeeRate(median
);
579 bool CBlockPolicyEstimator::Write(CAutoFile
& fileout
) const
582 LOCK(cs_feeEstimator
);
583 fileout
<< 139900; // version required to read: 0.13.99 or later
584 fileout
<< CLIENT_VERSION
; // version that wrote the file
585 fileout
<< nBestSeenHeight
;
586 feeStats
->Write(fileout
);
588 catch (const std::exception
&) {
589 LogPrintf("CBlockPolicyEstimator::Write(): unable to write policy estimator data (non-fatal)\n");
595 bool CBlockPolicyEstimator::Read(CAutoFile
& filein
)
598 LOCK(cs_feeEstimator
);
599 int nVersionRequired
, nVersionThatWrote
, nFileBestSeenHeight
;
600 filein
>> nVersionRequired
>> nVersionThatWrote
;
601 if (nVersionRequired
> CLIENT_VERSION
)
602 return error("CBlockPolicyEstimator::Read(): up-version (%d) fee estimate file", nVersionRequired
);
603 filein
>> nFileBestSeenHeight
;
604 feeStats
->Read(filein
);
605 nBestSeenHeight
= nFileBestSeenHeight
;
606 // if nVersionThatWrote < 139900 then another TxConfirmStats (for priority) follows but can be ignored.
608 catch (const std::exception
&) {
609 LogPrintf("CBlockPolicyEstimator::Read(): unable to read policy estimator data (non-fatal)\n");
615 FeeFilterRounder::FeeFilterRounder(const CFeeRate
& minIncrementalFee
)
617 CAmount minFeeLimit
= std::max(CAmount(1), minIncrementalFee
.GetFeePerK() / 2);
619 for (double bucketBoundary
= minFeeLimit
; bucketBoundary
<= MAX_BUCKET_FEERATE
; bucketBoundary
*= FEE_SPACING
) {
620 feeset
.insert(bucketBoundary
);
624 CAmount
FeeFilterRounder::round(CAmount currentMinFee
)
626 std::set
<double>::iterator it
= feeset
.lower_bound(currentMinFee
);
627 if ((it
!= feeset
.begin() && insecure_rand
.rand32() % 3 != 0) || it
== feeset
.end()) {