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