Line data Source code
1 : // Copyright (c) 2009-2010 Satoshi Nakamoto
2 : // Copyright (c) 2009-2015 The Bitcoin 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 "amount.h"
9 : #include "primitives/transaction.h"
10 : #include "streams.h"
11 : #include "txmempool.h"
12 : #include "util.h"
13 :
14 198 : void TxConfirmStats::Initialize(std::vector<double>& defaultBuckets,
15 : unsigned int maxConfirms, double _decay, std::string _dataTypeString)
16 : {
17 198 : decay = _decay;
18 198 : dataTypeString = _dataTypeString;
19 22470 : for (unsigned int i = 0; i < defaultBuckets.size(); i++) {
20 22074 : buckets.push_back(defaultBuckets[i]);
21 22074 : bucketMap[defaultBuckets[i]] = i;
22 : }
23 396 : confAvg.resize(maxConfirms);
24 396 : curBlockConf.resize(maxConfirms);
25 396 : unconfTxs.resize(maxConfirms);
26 5148 : for (unsigned int i = 0; i < maxConfirms; i++) {
27 14850 : confAvg[i].resize(buckets.size());
28 14850 : curBlockConf[i].resize(buckets.size());
29 14850 : unconfTxs[i].resize(buckets.size());
30 : }
31 :
32 396 : oldUnconfTxs.resize(buckets.size());
33 396 : curBlockTxCt.resize(buckets.size());
34 396 : txCtAvg.resize(buckets.size());
35 396 : curBlockVal.resize(buckets.size());
36 396 : avg.resize(buckets.size());
37 198 : }
38 :
39 : // Zero out the data for the current block
40 10120 : void TxConfirmStats::ClearCurrent(unsigned int nBlockHeight)
41 : {
42 1145850 : for (unsigned int j = 0; j < buckets.size(); j++) {
43 2814025 : oldUnconfTxs[j] += unconfTxs[nBlockHeight%unconfTxs.size()][j];
44 562805 : unconfTxs[nBlockHeight%unconfTxs.size()][j] = 0;
45 29265860 : for (unsigned int i = 0; i < curBlockConf.size(); i++)
46 42210375 : curBlockConf[i][j] = 0;
47 1125610 : curBlockTxCt[j] = 0;
48 1125610 : curBlockVal[j] = 0;
49 : }
50 10120 : }
51 :
52 :
53 15112 : void TxConfirmStats::Record(int blocksToConfirm, double val)
54 : {
55 : // blocksToConfirm is 1-based
56 15112 : if (blocksToConfirm < 1)
57 15112 : return;
58 45336 : unsigned int bucketindex = bucketMap.lower_bound(val)->second;
59 752804 : for (size_t i = blocksToConfirm; i <= curBlockConf.size(); i++) {
60 1083870 : curBlockConf[i - 1][bucketindex]++;
61 : }
62 30224 : curBlockTxCt[bucketindex]++;
63 30224 : curBlockVal[bucketindex] += val;
64 : }
65 :
66 10120 : void TxConfirmStats::UpdateMovingAverages()
67 : {
68 1145850 : for (unsigned int j = 0; j < buckets.size(); j++) {
69 28703055 : for (unsigned int i = 0; i < confAvg.size(); i++)
70 70350625 : confAvg[i][j] = confAvg[i][j] * decay + curBlockConf[i][j];
71 1688415 : avg[j] = avg[j] * decay + curBlockVal[j];
72 1688415 : txCtAvg[j] = txCtAvg[j] * decay + curBlockTxCt[j];
73 : }
74 10120 : }
75 :
76 : // returns -1 on error conditions
77 20666 : double TxConfirmStats::EstimateMedianVal(int confTarget, double sufficientTxVal,
78 : double successBreakPoint, bool requireGreater,
79 : unsigned int nBlockHeight)
80 : {
81 : // Counters for a bucket (or range of buckets)
82 20666 : double nConf = 0; // Number of tx's confirmed within the confTarget
83 20666 : double totalNum = 0; // Total number of tx's that were ever confirmed
84 20666 : int extraNum = 0; // Number of tx's still in mempool for confTarget or longer
85 :
86 41332 : int maxbucketindex = buckets.size() - 1;
87 :
88 : // requireGreater means we are looking for the lowest fee/priority such that all higher
89 : // values pass, so we start at maxbucketindex (highest fee) and look at succesively
90 : // smaller buckets until we reach failure. Otherwise, we are looking for the highest
91 : // fee/priority such that all lower values fail, and we go in the opposite direction.
92 20666 : unsigned int startbucket = requireGreater ? maxbucketindex : 0;
93 20666 : int step = requireGreater ? -1 : 1;
94 :
95 : // We'll combine buckets until we have enough samples.
96 : // The near and far variables will define the range we've combined
97 : // The best variables are the last range we saw which still had a high
98 : // enough confirmation rate to count as success.
99 : // The cur variables are the current range we're counting.
100 20666 : unsigned int curNearBucket = startbucket;
101 20666 : unsigned int bestNearBucket = startbucket;
102 20666 : unsigned int curFarBucket = startbucket;
103 20666 : unsigned int bestFarBucket = startbucket;
104 :
105 20666 : bool foundAnswer = false;
106 41332 : unsigned int bins = unconfTxs.size();
107 :
108 : // Start counting from highest(default) or lowest fee/pri transactions
109 1120927 : for (int bucket = startbucket; bucket >= 0 && bucket <= maxbucketindex; bucket += step) {
110 1101758 : curFarBucket = bucket;
111 3305274 : nConf += confAvg[confTarget - 1][bucket];
112 2203516 : totalNum += txCtAvg[bucket];
113 44376386 : for (unsigned int confct = confTarget; confct < GetMaxConfirms(); confct++)
114 63259305 : extraNum += unconfTxs[(nBlockHeight - confct)%bins][bucket];
115 2203516 : extraNum += oldUnconfTxs[bucket];
116 : // If we have enough transaction data points in this range of buckets,
117 : // we can test for success
118 : // (Only count the confirmed data points, so that each confirmation count
119 : // will be looking at the same amount of data and same bucket breaks)
120 1101758 : if (totalNum >= sufficientTxVal / (1 - decay)) {
121 3867 : double curPct = nConf / (totalNum + extraNum);
122 :
123 : // Check to see if we are no longer getting confirmed at the success rate
124 3867 : if (requireGreater && curPct < successBreakPoint)
125 : break;
126 3073 : if (!requireGreater && curPct > successBreakPoint)
127 : break;
128 :
129 : // Otherwise update the cumulative stats, and the bucket variables
130 : // and reset the counters
131 : else {
132 2370 : foundAnswer = true;
133 2370 : nConf = 0;
134 2370 : totalNum = 0;
135 2370 : extraNum = 0;
136 2370 : bestNearBucket = curNearBucket;
137 2370 : bestFarBucket = curFarBucket;
138 2370 : curNearBucket = bucket + step;
139 : }
140 : }
141 : }
142 :
143 20666 : double median = -1;
144 20666 : double txSum = 0;
145 :
146 : // Calculate the "average" fee of the best bucket range that met success conditions
147 : // Find the bucket with the median transaction and then report the average fee from that bucket
148 : // This is a compromise between finding the median which we can't since we don't save all tx's
149 : // and reporting the average which is less accurate
150 20666 : unsigned int minBucket = bestNearBucket < bestFarBucket ? bestNearBucket : bestFarBucket;
151 20666 : unsigned int maxBucket = bestNearBucket > bestFarBucket ? bestNearBucket : bestFarBucket;
152 48305 : for (unsigned int j = minBucket; j <= maxBucket; j++) {
153 55278 : txSum += txCtAvg[j];
154 : }
155 20666 : if (foundAnswer && txSum != 0) {
156 789 : txSum = txSum / 2;
157 2020 : for (unsigned int j = minBucket; j <= maxBucket; j++) {
158 2020 : if (txCtAvg[j] < txSum)
159 221 : txSum -= txCtAvg[j];
160 : else { // we're in the right bucket
161 1578 : median = avg[j] / txCtAvg[j];
162 789 : break;
163 : }
164 : }
165 : }
166 :
167 : LogPrint("estimatefee", "%3d: For conf success %s %4.2f need %s %s: %12.5g from buckets %8g - %8g Cur Bucket stats %6.2f%% %8.1f/(%.1f+%d mempool)\n",
168 : confTarget, requireGreater ? ">" : "<", successBreakPoint, dataTypeString,
169 41332 : requireGreater ? ">" : "<", median, buckets[minBucket], buckets[maxBucket],
170 41332 : 100 * nConf / (totalNum + extraNum), nConf, totalNum, extraNum);
171 :
172 20666 : return median;
173 : }
174 :
175 188 : void TxConfirmStats::Write(CAutoFile& fileout)
176 : {
177 188 : fileout << decay;
178 188 : fileout << buckets;
179 188 : fileout << avg;
180 188 : fileout << txCtAvg;
181 188 : fileout << confAvg;
182 188 : }
183 :
184 56 : void TxConfirmStats::Read(CAutoFile& filein)
185 : {
186 : // Read data file into temporary variables and do some very basic sanity checking
187 : std::vector<double> fileBuckets;
188 : std::vector<double> fileAvg;
189 56 : std::vector<std::vector<double> > fileConfAvg;
190 : std::vector<double> fileTxCtAvg;
191 : double fileDecay;
192 : size_t maxConfirms;
193 : size_t numBuckets;
194 :
195 56 : filein >> fileDecay;
196 56 : if (fileDecay <= 0 || fileDecay >= 1)
197 0 : throw std::runtime_error("Corrupt estimates file. Decay must be between 0 and 1 (non-inclusive)");
198 56 : filein >> fileBuckets;
199 112 : numBuckets = fileBuckets.size();
200 56 : if (numBuckets <= 1 || numBuckets > 1000)
201 0 : throw std::runtime_error("Corrupt estimates file. Must have between 2 and 1000 fee/pri buckets");
202 56 : filein >> fileAvg;
203 112 : if (fileAvg.size() != numBuckets)
204 0 : throw std::runtime_error("Corrupt estimates file. Mismatch in fee/pri average bucket count");
205 56 : filein >> fileTxCtAvg;
206 112 : if (fileTxCtAvg.size() != numBuckets)
207 0 : throw std::runtime_error("Corrupt estimates file. Mismatch in tx count bucket count");
208 56 : filein >> fileConfAvg;
209 112 : maxConfirms = fileConfAvg.size();
210 56 : if (maxConfirms <= 0 || maxConfirms > 6 * 24 * 7) // one week
211 0 : throw std::runtime_error("Corrupt estimates file. Must maintain estimates for between 1 and 1008 (one week) confirms");
212 1400 : for (unsigned int i = 0; i < maxConfirms; i++) {
213 2800 : if (fileConfAvg[i].size() != numBuckets)
214 0 : throw std::runtime_error("Corrupt estimates file. Mismatch in fee/pri conf average bucket count");
215 : }
216 : // Now that we've processed the entire fee estimate data file and not
217 : // thrown any errors, we can copy it to our data structures
218 56 : decay = fileDecay;
219 56 : buckets = fileBuckets;
220 56 : avg = fileAvg;
221 56 : confAvg = fileConfAvg;
222 56 : txCtAvg = fileTxCtAvg;
223 56 : bucketMap.clear();
224 :
225 : // Resize the current block variables which aren't stored in the data file
226 : // to match the number of confirms and buckets
227 112 : curBlockConf.resize(maxConfirms);
228 1456 : for (unsigned int i = 0; i < maxConfirms; i++) {
229 4200 : curBlockConf[i].resize(buckets.size());
230 : }
231 112 : curBlockTxCt.resize(buckets.size());
232 112 : curBlockVal.resize(buckets.size());
233 :
234 112 : unconfTxs.resize(maxConfirms);
235 1456 : for (unsigned int i = 0; i < maxConfirms; i++) {
236 4200 : unconfTxs[i].resize(buckets.size());
237 : }
238 112 : oldUnconfTxs.resize(buckets.size());
239 :
240 6216 : for (unsigned int i = 0; i < buckets.size(); i++)
241 6160 : bucketMap[buckets[i]] = i;
242 :
243 : LogPrint("estimatefee", "Reading estimates: %u %s buckets counting confirms up to %u blocks\n",
244 56 : numBuckets, dataTypeString, maxConfirms);
245 56 : }
246 :
247 15933 : unsigned int TxConfirmStats::NewTx(unsigned int nBlockHeight, double val)
248 : {
249 47799 : unsigned int bucketindex = bucketMap.lower_bound(val)->second;
250 31866 : unsigned int blockIndex = nBlockHeight % unconfTxs.size();
251 47799 : unconfTxs[blockIndex][bucketindex]++;
252 15933 : LogPrint("estimatefee", "adding to %s", dataTypeString);
253 15933 : return bucketindex;
254 : }
255 :
256 15918 : void TxConfirmStats::removeTx(unsigned int entryHeight, unsigned int nBestSeenHeight, unsigned int bucketindex)
257 : {
258 : //nBestSeenHeight is not updated yet for the new block
259 15918 : int blocksAgo = nBestSeenHeight - entryHeight;
260 15918 : if (nBestSeenHeight == 0) // the BlockPolicyEstimator hasn't seen any blocks yet
261 6 : blocksAgo = 0;
262 15918 : if (blocksAgo < 0) {
263 0 : LogPrint("estimatefee", "Blockpolicy error, blocks ago is negative for mempool tx\n");
264 15918 : return; //This can't happen because we call this with our best seen height, no entries can have higher
265 : }
266 :
267 31836 : if (blocksAgo >= (int)unconfTxs.size()) {
268 0 : if (oldUnconfTxs[bucketindex] > 0)
269 0 : oldUnconfTxs[bucketindex]--;
270 : else
271 : LogPrint("estimatefee", "Blockpolicy error, mempool tx removed from >25 blocks,bucketIndex=%u already\n",
272 0 : bucketindex);
273 : }
274 : else {
275 15918 : unsigned int blockIndex = entryHeight % unconfTxs.size();
276 47754 : if (unconfTxs[blockIndex][bucketindex] > 0)
277 15918 : unconfTxs[blockIndex][bucketindex]--;
278 : else
279 : LogPrint("estimatefee", "Blockpolicy error, mempool tx removed from blockIndex=%u,bucketIndex=%u already\n",
280 0 : blockIndex, bucketindex);
281 : }
282 : }
283 :
284 16273 : void CBlockPolicyEstimator::removeTx(uint256 hash)
285 : {
286 32546 : std::map<uint256, TxStatsInfo>::iterator pos = mapMemPoolTxs.find(hash);
287 32546 : if (pos == mapMemPoolTxs.end()) {
288 : LogPrint("estimatefee", "Blockpolicy error mempool tx %s not found for removeTx\n",
289 0 : hash.ToString().c_str());
290 16273 : return;
291 : }
292 16273 : TxConfirmStats *stats = pos->second.stats;
293 16273 : unsigned int entryHeight = pos->second.blockHeight;
294 16273 : unsigned int bucketIndex = pos->second.bucketIndex;
295 :
296 16273 : if (stats != NULL)
297 15918 : stats->removeTx(entryHeight, nBestSeenHeight, bucketIndex);
298 16273 : mapMemPoolTxs.erase(hash);
299 : }
300 :
301 99 : CBlockPolicyEstimator::CBlockPolicyEstimator(const CFeeRate& _minRelayFee)
302 396 : : nBestSeenHeight(0)
303 : {
304 198 : minTrackedFee = _minRelayFee < CFeeRate(MIN_FEERATE) ? CFeeRate(MIN_FEERATE) : _minRelayFee;
305 : std::vector<double> vfeelist;
306 8265 : for (double bucketBoundary = minTrackedFee.GetFeePerK(); bucketBoundary <= MAX_FEERATE; bucketBoundary *= FEE_SPACING) {
307 8067 : vfeelist.push_back(bucketBoundary);
308 : }
309 99 : vfeelist.push_back(INF_FEERATE);
310 297 : feeStats.Initialize(vfeelist, MAX_BLOCK_CONFIRMS, DEFAULT_DECAY, "FeeRate");
311 :
312 99 : minTrackedPriority = AllowFreeThreshold() < MIN_PRIORITY ? MIN_PRIORITY : AllowFreeThreshold();
313 : std::vector<double> vprilist;
314 2871 : for (double bucketBoundary = minTrackedPriority; bucketBoundary <= MAX_PRIORITY; bucketBoundary *= PRI_SPACING) {
315 2772 : vprilist.push_back(bucketBoundary);
316 : }
317 99 : vprilist.push_back(INF_PRIORITY);
318 297 : priStats.Initialize(vprilist, MAX_BLOCK_CONFIRMS, DEFAULT_DECAY, "Priority");
319 :
320 99 : feeUnlikely = CFeeRate(0);
321 99 : feeLikely = CFeeRate(INF_FEERATE);
322 99 : priUnlikely = 0;
323 99 : priLikely = INF_PRIORITY;
324 99 : }
325 :
326 0 : bool CBlockPolicyEstimator::isFeeDataPoint(const CFeeRate &fee, double pri)
327 : {
328 76320 : if ((pri < minTrackedPriority && fee >= minTrackedFee) ||
329 576 : (pri < priUnlikely && fee > feeLikely)) {
330 : return true;
331 : }
332 0 : return false;
333 : }
334 :
335 0 : bool CBlockPolicyEstimator::isPriDataPoint(const CFeeRate &fee, double pri)
336 : {
337 101760 : if ((fee < minTrackedFee && pri >= minTrackedPriority) ||
338 25440 : (fee < feeUnlikely && pri > priLikely)) {
339 : return true;
340 : }
341 0 : return false;
342 : }
343 :
344 17437 : void CBlockPolicyEstimator::processTransaction(const CTxMemPoolEntry& entry, bool fCurrentEstimate)
345 : {
346 17437 : unsigned int txHeight = entry.GetHeight();
347 17437 : uint256 hash = entry.GetTx().GetHash();
348 17437 : if (mapMemPoolTxs[hash].stats != NULL) {
349 : LogPrint("estimatefee", "Blockpolicy error mempool tx %s already being tracked\n",
350 0 : hash.ToString().c_str());
351 1238 : return;
352 : }
353 :
354 17437 : if (txHeight < nBestSeenHeight) {
355 : // Ignore side chains and re-orgs; assuming they are random they don't
356 : // affect the estimate. We'll potentially double count transactions in 1-block reorgs.
357 : return;
358 : }
359 :
360 : // Only want to be updating estimates when our blockchain is synced,
361 : // otherwise we'll miscalculate how many blocks its taking to get included.
362 16286 : if (!fCurrentEstimate)
363 : return;
364 :
365 16257 : if (!entry.WasClearAtEntry()) {
366 : // This transaction depends on other transactions in the mempool to
367 : // be included in a block before it will be able to be included, so
368 : // we shouldn't include it in our calculations
369 : return;
370 : }
371 :
372 : // Fees are stored and reported as BTC-per-kb:
373 16199 : CFeeRate feeRate(entry.GetFee(), entry.GetTxSize());
374 :
375 : // Want the priority of the tx at confirmation. However we don't know
376 : // what that will be and its too hard to continue updating it
377 : // so use starting priority as a proxy
378 16199 : double curPri = entry.GetPriority(txHeight);
379 16199 : mapMemPoolTxs[hash].blockHeight = txHeight;
380 :
381 48597 : LogPrint("estimatefee", "Blockpolicy mempool tx %s ", hash.ToString().substr(0,10));
382 : // Record this as a priority estimate
383 29229 : if (entry.GetFee() == 0 || isPriDataPoint(feeRate, curPri)) {
384 3169 : mapMemPoolTxs[hash].stats = &priStats;
385 3169 : mapMemPoolTxs[hash].bucketIndex = priStats.NewTx(txHeight, curPri);
386 : }
387 : // Record this as a fee estimate
388 13030 : else if (isFeeDataPoint(feeRate, curPri)) {
389 12764 : mapMemPoolTxs[hash].stats = &feeStats;
390 25528 : mapMemPoolTxs[hash].bucketIndex = feeStats.NewTx(txHeight, (double)feeRate.GetFeePerK());
391 : }
392 : else {
393 266 : LogPrint("estimatefee", "not adding");
394 : }
395 16199 : LogPrint("estimatefee", "\n");
396 : }
397 :
398 15470 : void CBlockPolicyEstimator::processBlockTx(unsigned int nBlockHeight, const CTxMemPoolEntry& entry)
399 : {
400 15470 : if (!entry.WasClearAtEntry()) {
401 : // This transaction depended on other transactions in the mempool to
402 : // be included in a block before it was able to be included, so
403 : // we shouldn't include it in our calculations
404 48 : return;
405 : }
406 :
407 : // How many blocks did it take for miners to include this transaction?
408 : // blocksToConfirm is 1-based, so a transaction included in the earliest
409 : // possible block has confirmation count of 1
410 15422 : int blocksToConfirm = nBlockHeight - entry.GetHeight();
411 15422 : if (blocksToConfirm <= 0) {
412 : // This can't happen because we don't process transactions from a block with a height
413 : // lower than our greatest seen height
414 0 : LogPrint("estimatefee", "Blockpolicy error Transaction had negative blocksToConfirm\n");
415 : return;
416 : }
417 :
418 : // Fees are stored and reported as BTC-per-kb:
419 15422 : CFeeRate feeRate(entry.GetFee(), entry.GetTxSize());
420 :
421 : // Want the priority of the tx at confirmation. The priority when it
422 : // entered the mempool could easily be very small and change quickly
423 15422 : double curPri = entry.GetPriority(nBlockHeight);
424 :
425 : // Record this as a priority estimate
426 27832 : if (entry.GetFee() == 0 || isPriDataPoint(feeRate, curPri)) {
427 3012 : priStats.Record(blocksToConfirm, curPri);
428 : }
429 : // Record this as a fee estimate
430 12410 : else if (isFeeDataPoint(feeRate, curPri)) {
431 12100 : feeStats.Record(blocksToConfirm, (double)feeRate.GetFeePerK());
432 : }
433 : }
434 :
435 5868 : void CBlockPolicyEstimator::processBlock(unsigned int nBlockHeight,
436 : std::vector<CTxMemPoolEntry>& entries, bool fCurrentEstimate)
437 : {
438 5868 : if (nBlockHeight <= nBestSeenHeight) {
439 : // Ignore side chains and re-orgs; assuming they are random
440 : // they don't affect the estimate.
441 : // And if an attacker can re-org the chain at will, then
442 : // you've got much bigger problems than "attacker can influence
443 : // transaction fees."
444 : return;
445 : }
446 5234 : nBestSeenHeight = nBlockHeight;
447 :
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 5234 : if (!fCurrentEstimate)
451 : return;
452 :
453 : // Update the dynamic cutoffs
454 : // a fee/priority is "likely" the reason your tx was included in a block if >85% of such tx's
455 : // were confirmed in 2 blocks and is "unlikely" if <50% were confirmed in 10 blocks
456 5060 : LogPrint("estimatefee", "Blockpolicy recalculating dynamic cutoffs:\n");
457 5060 : priLikely = priStats.EstimateMedianVal(2, SUFFICIENT_PRITXS, MIN_SUCCESS_PCT, true, nBlockHeight);
458 5060 : if (priLikely == -1)
459 4718 : priLikely = INF_PRIORITY;
460 :
461 5060 : double feeLikelyEst = feeStats.EstimateMedianVal(2, SUFFICIENT_FEETXS, MIN_SUCCESS_PCT, true, nBlockHeight);
462 5060 : if (feeLikelyEst == -1)
463 4721 : feeLikely = CFeeRate(INF_FEERATE);
464 : else
465 339 : feeLikely = CFeeRate(feeLikelyEst);
466 :
467 5060 : priUnlikely = priStats.EstimateMedianVal(10, SUFFICIENT_PRITXS, UNLIKELY_PCT, false, nBlockHeight);
468 5060 : if (priUnlikely == -1)
469 5060 : priUnlikely = 0;
470 :
471 5060 : double feeUnlikelyEst = feeStats.EstimateMedianVal(10, SUFFICIENT_FEETXS, UNLIKELY_PCT, false, nBlockHeight);
472 5060 : if (feeUnlikelyEst == -1)
473 5060 : feeUnlikely = CFeeRate(0);
474 : else
475 0 : feeUnlikely = CFeeRate(feeUnlikelyEst);
476 :
477 : // Clear the current block states
478 5060 : feeStats.ClearCurrent(nBlockHeight);
479 5060 : priStats.ClearCurrent(nBlockHeight);
480 :
481 : // Repopulate the current block states
482 41060 : for (unsigned int i = 0; i < entries.size(); i++)
483 30940 : processBlockTx(nBlockHeight, entries[i]);
484 :
485 : // Update all exponential averages with the current block states
486 5060 : feeStats.UpdateMovingAverages();
487 5060 : priStats.UpdateMovingAverages();
488 :
489 : LogPrint("estimatefee", "Blockpolicy after updating estimates for %u confirmed entries, new mempool map size %u\n",
490 15180 : entries.size(), mapMemPoolTxs.size());
491 : }
492 :
493 373 : CFeeRate CBlockPolicyEstimator::estimateFee(int confTarget)
494 : {
495 : // Return failure if trying to analyze a target we're not tracking
496 746 : if (confTarget <= 0 || (unsigned int)confTarget > feeStats.GetMaxConfirms())
497 0 : return CFeeRate(0);
498 :
499 373 : double median = feeStats.EstimateMedianVal(confTarget, SUFFICIENT_FEETXS, MIN_SUCCESS_PCT, true, nBestSeenHeight);
500 :
501 373 : if (median < 0)
502 318 : return CFeeRate(0);
503 :
504 55 : return CFeeRate(median);
505 : }
506 :
507 53 : double CBlockPolicyEstimator::estimatePriority(int confTarget)
508 : {
509 : // Return failure if trying to analyze a target we're not tracking
510 106 : if (confTarget <= 0 || (unsigned int)confTarget > priStats.GetMaxConfirms())
511 : return -1;
512 :
513 53 : return priStats.EstimateMedianVal(confTarget, SUFFICIENT_PRITXS, MIN_SUCCESS_PCT, true, nBestSeenHeight);
514 : }
515 :
516 94 : void CBlockPolicyEstimator::Write(CAutoFile& fileout)
517 : {
518 94 : fileout << nBestSeenHeight;
519 94 : feeStats.Write(fileout);
520 94 : priStats.Write(fileout);
521 94 : }
522 :
523 28 : void CBlockPolicyEstimator::Read(CAutoFile& filein)
524 : {
525 : int nFileBestSeenHeight;
526 28 : filein >> nFileBestSeenHeight;
527 28 : feeStats.Read(filein);
528 28 : priStats.Read(filein);
529 28 : nBestSeenHeight = nFileBestSeenHeight;
530 316 : }
|