48 struct EncodedDoubleFormatter
50 template<
typename Stream>
void Ser(Stream &s,
double v)
55 template<
typename Stream>
void Unser(Stream& s,
double& v)
122 TxConfirmStats(
const std::vector<double>& defaultBuckets,
const std::map<double, unsigned int>& defaultBucketMap,
123 unsigned int maxPeriods,
double decay,
unsigned int scale);
134 void Record(
int blocksToConfirm,
double val);
137 unsigned int NewTx(
unsigned int nBlockHeight,
double val);
140 void removeTx(
unsigned int entryHeight,
unsigned int nBestSeenHeight,
141 unsigned int bucketIndex,
bool inBlock);
157 double minSuccess,
unsigned int nBlockHeight,
170 void Read(
AutoFile& filein,
int nFileVersion,
size_t numBuckets);
175 const std::map<double, unsigned int>& defaultBucketMap,
176 unsigned int maxPeriods,
double _decay,
unsigned int _scale)
177 : buckets(defaultBuckets), bucketMap(defaultBucketMap), decay(_decay), scale(_scale)
179 assert(_scale != 0 &&
"_scale must be non-zero");
182 for (
unsigned int i = 0; i < maxPeriods; i++) {
196 for (
unsigned int i = 0; i <
unconfTxs.size(); i++) {
205 for (
unsigned int j = 0; j <
buckets.size(); j++) {
215 if (blocksToConfirm < 1)
217 int periodsToConfirm = (blocksToConfirm +
scale - 1) /
scale;
218 unsigned int bucketindex =
bucketMap.lower_bound(feerate)->second;
219 for (
size_t i = periodsToConfirm; i <=
confAvg.size(); i++) {
229 for (
unsigned int j = 0; j <
buckets.size(); j++) {
230 for (
unsigned int i = 0; i <
confAvg.size(); i++) {
241 double successBreakPoint,
unsigned int nBlockHeight,
249 const int periodTarget = (confTarget +
scale - 1) /
scale;
250 const int maxbucketindex =
buckets.size() - 1;
257 unsigned int curNearBucket = maxbucketindex;
258 unsigned int bestNearBucket = maxbucketindex;
259 unsigned int curFarBucket = maxbucketindex;
260 unsigned int bestFarBucket = maxbucketindex;
262 bool foundAnswer =
false;
264 bool newBucketRange =
true;
270 for (
int bucket = maxbucketindex; bucket >= 0; --bucket) {
271 if (newBucketRange) {
272 curNearBucket = bucket;
273 newBucketRange =
false;
275 curFarBucket = bucket;
276 nConf +=
confAvg[periodTarget - 1][bucket];
278 failNum +=
failAvg[periodTarget - 1][bucket];
279 for (
unsigned int confct = confTarget; confct <
GetMaxConfirms(); confct++)
280 extraNum +=
unconfTxs[(nBlockHeight - confct) % bins][bucket];
286 if (totalNum >= sufficientTxVal / (1 -
decay)) {
287 double curPct = nConf / (totalNum + failNum + extraNum);
290 if (curPct < successBreakPoint) {
291 if (passing ==
true) {
293 unsigned int failMinBucket = std::min(curNearBucket, curFarBucket);
294 unsigned int failMaxBucket = std::max(curNearBucket, curFarBucket);
295 failBucket.
start = failMinBucket ?
buckets[failMinBucket - 1] : 0;
319 bestNearBucket = curNearBucket;
320 bestFarBucket = curFarBucket;
321 newBucketRange =
true;
333 unsigned int minBucket = std::min(bestNearBucket, bestFarBucket);
334 unsigned int maxBucket = std::max(bestNearBucket, bestFarBucket);
335 for (
unsigned int j = minBucket; j <= maxBucket; j++) {
338 if (foundAnswer && txSum != 0) {
340 for (
unsigned int j = minBucket; j <= maxBucket; j++) {
349 passBucket.
start = minBucket ?
buckets[minBucket-1] : 0;
354 if (passing && !newBucketRange) {
355 unsigned int failMinBucket = std::min(curNearBucket, curFarBucket);
356 unsigned int failMaxBucket = std::max(curNearBucket, curFarBucket);
357 failBucket.
start = failMinBucket ?
buckets[failMinBucket - 1] : 0;
365 float passed_within_target_perc = 0.0;
366 float failed_within_target_perc = 0.0;
374 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",
375 confTarget, 100.0 * successBreakPoint,
decay,
376 median, passBucket.
start, passBucket.
end,
377 passed_within_target_perc,
380 failed_within_target_perc,
385 result->
pass = passBucket;
386 result->
fail = failBucket;
395 fileout << Using<EncodedDoubleFormatter>(
decay);
397 fileout << Using<VectorFormatter<EncodedDoubleFormatter>>(
m_feerate_avg);
398 fileout << Using<VectorFormatter<EncodedDoubleFormatter>>(
txCtAvg);
399 fileout << Using<VectorFormatter<VectorFormatter<EncodedDoubleFormatter>>>(
confAvg);
400 fileout << Using<VectorFormatter<VectorFormatter<EncodedDoubleFormatter>>>(
failAvg);
408 size_t maxConfirms, maxPeriods;
411 filein >> Using<EncodedDoubleFormatter>(
decay);
412 if (decay <= 0 || decay >= 1) {
413 throw std::runtime_error(
"Corrupt estimates file. Decay must be between 0 and 1 (non-inclusive)");
417 throw std::runtime_error(
"Corrupt estimates file. Scale must be non-zero");
420 filein >> Using<VectorFormatter<EncodedDoubleFormatter>>(
m_feerate_avg);
422 throw std::runtime_error(
"Corrupt estimates file. Mismatch in feerate average bucket count");
424 filein >> Using<VectorFormatter<EncodedDoubleFormatter>>(
txCtAvg);
425 if (
txCtAvg.size() != numBuckets) {
426 throw std::runtime_error(
"Corrupt estimates file. Mismatch in tx count bucket count");
428 filein >> Using<VectorFormatter<VectorFormatter<EncodedDoubleFormatter>>>(
confAvg);
430 maxConfirms =
scale * maxPeriods;
432 if (maxConfirms <= 0 || maxConfirms > 6 * 24 * 7) {
433 throw std::runtime_error(
"Corrupt estimates file. Must maintain estimates for between 1 and 1008 (one week) confirms");
435 for (
unsigned int i = 0; i < maxPeriods; i++) {
436 if (
confAvg[i].size() != numBuckets) {
437 throw std::runtime_error(
"Corrupt estimates file. Mismatch in feerate conf average bucket count");
441 filein >> Using<VectorFormatter<VectorFormatter<EncodedDoubleFormatter>>>(
failAvg);
442 if (maxPeriods !=
failAvg.size()) {
443 throw std::runtime_error(
"Corrupt estimates file. Mismatch in confirms tracked for failures");
445 for (
unsigned int i = 0; i < maxPeriods; i++) {
446 if (
failAvg[i].size() != numBuckets) {
447 throw std::runtime_error(
"Corrupt estimates file. Mismatch in one of failure average bucket counts");
456 numBuckets, maxConfirms);
461 unsigned int bucketindex =
bucketMap.lower_bound(val)->second;
462 unsigned int blockIndex = nBlockHeight %
unconfTxs.size();
470 int blocksAgo = nBestSeenHeight - entryHeight;
471 if (nBestSeenHeight == 0)
478 if (blocksAgo >= (
int)
unconfTxs.size()) {
487 unsigned int blockIndex = entryHeight %
unconfTxs.size();
488 if (
unconfTxs[blockIndex][bucketindex] > 0) {
492 blockIndex, bucketindex);
495 if (!inBlock && (
unsigned int)blocksAgo >=
scale) {
497 unsigned int periodsAgo = blocksAgo /
scale;
498 for (
size_t i = 0; i < periodsAgo && i <
failAvg.size(); i++) {
518 std::map<uint256, TxStatsInfo>::iterator pos = mapMemPoolTxs.find(hash);
519 if (pos != mapMemPoolTxs.end()) {
520 feeStats->removeTx(pos->second.blockHeight, nBestSeenHeight, pos->second.bucketIndex, inBlock);
521 shortStats->removeTx(pos->second.blockHeight, nBestSeenHeight, pos->second.bucketIndex, inBlock);
522 longStats->removeTx(pos->second.blockHeight, nBestSeenHeight, pos->second.bucketIndex, inBlock);
523 mapMemPoolTxs.erase(hash);
531 : m_estimation_filepath{estimation_filepath}
534 size_t bucketIndex = 0;
537 buckets.push_back(bucketBoundary);
538 bucketMap[bucketBoundary] = bucketIndex;
542 assert(bucketMap.size() == buckets.size());
550 if (est_file.IsNull() || !
Read(est_file)) {
560 unsigned int txHeight = entry.
GetHeight();
562 if (mapMemPoolTxs.count(hash)) {
568 if (txHeight != nBestSeenHeight) {
578 if (!validFeeEstimate) {
587 mapMemPoolTxs[hash].blockHeight = txHeight;
588 unsigned int bucketIndex = feeStats->NewTx(txHeight, (
double)feeRate.
GetFeePerK());
589 mapMemPoolTxs[hash].bucketIndex = bucketIndex;
590 unsigned int bucketIndex2 = shortStats->NewTx(txHeight, (
double)feeRate.
GetFeePerK());
591 assert(bucketIndex == bucketIndex2);
592 unsigned int bucketIndex3 = longStats->NewTx(txHeight, (
double)feeRate.
GetFeePerK());
593 assert(bucketIndex == bucketIndex3);
607 int blocksToConfirm = nBlockHeight - entry->
GetHeight();
608 if (blocksToConfirm <= 0) {
618 feeStats->Record(blocksToConfirm, (
double)feeRate.
GetFeePerK());
619 shortStats->Record(blocksToConfirm, (
double)feeRate.
GetFeePerK());
620 longStats->Record(blocksToConfirm, (
double)feeRate.
GetFeePerK());
625 std::vector<const CTxMemPoolEntry*>& entries)
628 if (nBlockHeight <= nBestSeenHeight) {
640 nBestSeenHeight = nBlockHeight;
643 feeStats->ClearCurrent(nBlockHeight);
644 shortStats->ClearCurrent(nBlockHeight);
645 longStats->ClearCurrent(nBlockHeight);
648 feeStats->UpdateMovingAverages();
649 shortStats->UpdateMovingAverages();
650 longStats->UpdateMovingAverages();
652 unsigned int countedTxs = 0;
654 for (
const auto& entry : entries) {
659 if (firstRecordedHeight == 0 && countedTxs > 0) {
660 firstRecordedHeight = nBestSeenHeight;
665 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",
666 countedTxs, entries.size(), trackedTxs, trackedTxs + untrackedTxs, mapMemPoolTxs.size(),
688 stats = shortStats.get();
693 stats = feeStats.get();
697 stats = longStats.get();
705 if (confTarget <= 0 || (
unsigned int)confTarget > stats->
GetMaxConfirms())
707 if (successThreshold > 1)
710 double median = stats->
EstimateMedianVal(confTarget, sufficientTxs, successThreshold, nBestSeenHeight, result);
723 return shortStats->GetMaxConfirms();
726 return feeStats->GetMaxConfirms();
729 return longStats->GetMaxConfirms();
737 if (firstRecordedHeight == 0)
return 0;
738 assert(nBestSeenHeight >= firstRecordedHeight);
740 return nBestSeenHeight - firstRecordedHeight;
745 if (historicalFirst == 0)
return 0;
746 assert(historicalBest >= historicalFirst);
750 return historicalBest - historicalFirst;
765 double estimate = -1;
766 if (confTarget >= 1 && confTarget <= longStats->GetMaxConfirms()) {
768 if (confTarget <= shortStats->GetMaxConfirms()) {
769 estimate = shortStats->EstimateMedianVal(confTarget,
SUFFICIENT_TXS_SHORT, successThreshold, nBestSeenHeight, result);
771 else if (confTarget <= feeStats->GetMaxConfirms()) {
772 estimate = feeStats->EstimateMedianVal(confTarget,
SUFFICIENT_FEETXS, successThreshold, nBestSeenHeight, result);
775 estimate = longStats->EstimateMedianVal(confTarget,
SUFFICIENT_FEETXS, successThreshold, nBestSeenHeight, result);
777 if (checkShorterHorizon) {
780 if (confTarget > feeStats->GetMaxConfirms()) {
781 double medMax = feeStats->EstimateMedianVal(feeStats->GetMaxConfirms(),
SUFFICIENT_FEETXS, successThreshold, nBestSeenHeight, &tempResult);
782 if (medMax > 0 && (estimate == -1 || medMax < estimate)) {
784 if (result) *result = tempResult;
787 if (confTarget > shortStats->GetMaxConfirms()) {
788 double shortMax = shortStats->EstimateMedianVal(shortStats->GetMaxConfirms(),
SUFFICIENT_TXS_SHORT, successThreshold, nBestSeenHeight, &tempResult);
789 if (shortMax > 0 && (estimate == -1 || shortMax < estimate)) {
791 if (result) *result = tempResult;
804 double estimate = -1;
806 if (doubleTarget <= shortStats->GetMaxConfirms()) {
809 if (doubleTarget <= feeStats->GetMaxConfirms()) {
811 if (longEstimate > estimate) {
812 estimate = longEstimate;
813 if (result) *result = tempResult;
839 if (confTarget <= 0 || (
unsigned int)confTarget > longStats->GetMaxConfirms()) {
844 if (confTarget == 1) confTarget = 2;
847 if ((
unsigned int)confTarget > maxUsableEstimate) {
848 confTarget = maxUsableEstimate;
852 if (confTarget <= 1)
return CFeeRate(0);
867 feeCalc->
est = tempResult;
872 if (actualEst > median) {
875 feeCalc->
est = tempResult;
880 if (doubleEst > median) {
883 feeCalc->
est = tempResult;
888 if (conservative || median == -1) {
890 if (consEst > median) {
893 feeCalc->
est = tempResult;
908 if (est_file.IsNull() || !
Write(est_file)) {
919 fileout << nBestSeenHeight;
921 fileout << firstRecordedHeight << nBestSeenHeight;
924 fileout << historicalFirst << historicalBest;
926 fileout << Using<VectorFormatter<EncodedDoubleFormatter>>(buckets);
927 feeStats->Write(fileout);
928 shortStats->Write(fileout);
929 longStats->Write(fileout);
931 catch (
const std::exception&) {
932 LogPrintf(
"CBlockPolicyEstimator::Write(): unable to write policy estimator data (non-fatal)\n");
942 int nVersionRequired, nVersionThatWrote;
943 filein >> nVersionRequired >> nVersionThatWrote;
945 throw std::runtime_error(
strprintf(
"up-version (%d) fee estimate file", nVersionRequired));
950 unsigned int nFileBestSeenHeight;
951 filein >> nFileBestSeenHeight;
953 if (nVersionRequired < 149900) {
954 LogPrintf(
"%s: incompatible old fee estimation data (non-fatal). Version: %d\n", __func__, nVersionRequired);
956 unsigned int nFileHistoricalFirst, nFileHistoricalBest;
957 filein >> nFileHistoricalFirst >> nFileHistoricalBest;
958 if (nFileHistoricalFirst > nFileHistoricalBest || nFileHistoricalBest > nFileBestSeenHeight) {
959 throw std::runtime_error(
"Corrupt estimates file. Historical block range for estimates is invalid");
961 std::vector<double> fileBuckets;
962 filein >> Using<VectorFormatter<EncodedDoubleFormatter>>(fileBuckets);
963 size_t numBuckets = fileBuckets.size();
964 if (numBuckets <= 1 || numBuckets > 1000) {
965 throw std::runtime_error(
"Corrupt estimates file. Must have between 2 and 1000 feerate buckets");
971 fileFeeStats->Read(filein, nVersionThatWrote, numBuckets);
972 fileShortStats->Read(filein, nVersionThatWrote, numBuckets);
973 fileLongStats->Read(filein, nVersionThatWrote, numBuckets);
977 buckets = fileBuckets;
979 for (
unsigned int i = 0; i < buckets.size(); i++) {
980 bucketMap[buckets[i]] = i;
984 feeStats = std::move(fileFeeStats);
985 shortStats = std::move(fileShortStats);
986 longStats = std::move(fileLongStats);
988 nBestSeenHeight = nFileBestSeenHeight;
989 historicalFirst = nFileHistoricalFirst;
990 historicalBest = nFileHistoricalBest;
993 catch (
const std::exception& e) {
994 LogPrintf(
"CBlockPolicyEstimator::Read(): unable to read policy estimator data (non-fatal): %s\n",e.what());
1002 const auto startclear{SteadyClock::now()};
1004 size_t num_entries = mapMemPoolTxs.size();
1006 while (!mapMemPoolTxs.empty()) {
1007 auto mi = mapMemPoolTxs.begin();
1010 const auto endclear{SteadyClock::now()};
1011 LogPrint(
BCLog::ESTIMATEFEE,
"Recorded %u unconfirmed txs from mempool in %gs\n", num_entries, Ticks<SecondsDouble>(endclear - startclear));
1015 double max_filter_fee_rate,
1016 double fee_filter_spacing)
1018 std::set<double> fee_set;
1022 for (
double bucket_boundary = min_fee_limit;
1023 bucket_boundary <= max_filter_fee_rate;
1024 bucket_boundary *= fee_filter_spacing) {
1026 fee_set.insert(bucket_boundary);
1033 : m_fee_set{
MakeFeeSet(minIncrementalFee, MAX_FILTER_FEERATE, FEE_FILTER_SPACING)}
1040 std::set<double>::iterator it =
m_fee_set.lower_bound(currentMinFee);
1046 return static_cast<CAmount>(*it);
int64_t CAmount
Amount in satoshis (Can be negative)
Non-refcounted RAII wrapper for FILE*.
static constexpr unsigned int LONG_SCALE
void processTransaction(const CTxMemPoolEntry &entry, bool validFeeEstimate) EXCLUSIVE_LOCKS_REQUIRED(!m_cs_fee_estimator)
Process a transaction accepted to the mempool.
static constexpr double SUCCESS_PCT
Require greater than 85% of X feerate transactions to be confirmed within Y blocks.
static constexpr double MIN_BUCKET_FEERATE
Minimum and Maximum values for tracking feerates The MIN_BUCKET_FEERATE should just be set to the low...
double estimateCombinedFee(unsigned int confTarget, double successThreshold, bool checkShorterHorizon, EstimationResult *result) const EXCLUSIVE_LOCKS_REQUIRED(m_cs_fee_estimator)
Helper for estimateSmartFee.
void processBlock(unsigned int nBlockHeight, std::vector< const CTxMemPoolEntry * > &entries) EXCLUSIVE_LOCKS_REQUIRED(!m_cs_fee_estimator)
Process all the transactions that have been included in a block.
static constexpr double FEE_SPACING
Spacing of FeeRate buckets We have to lump transactions into buckets based on feerate,...
static const unsigned int OLDEST_ESTIMATE_HISTORY
Historical estimates that are older than this aren't valid.
void Flush() EXCLUSIVE_LOCKS_REQUIRED(!m_cs_fee_estimator)
Drop still unconfirmed transactions and record current estimations, if the fee estimation file is pre...
static constexpr double SUFFICIENT_FEETXS
Require an avg of 0.1 tx in the combined feerate bucket per block to have stat significance.
static constexpr double MAX_BUCKET_FEERATE
CFeeRate estimateSmartFee(int confTarget, FeeCalculation *feeCalc, bool conservative) const EXCLUSIVE_LOCKS_REQUIRED(!m_cs_fee_estimator)
Estimate feerate needed to get be included in a block within confTarget blocks.
static constexpr unsigned int LONG_BLOCK_PERIODS
Track confirm delays up to 1008 blocks for long horizon.
bool Write(AutoFile &fileout) const EXCLUSIVE_LOCKS_REQUIRED(!m_cs_fee_estimator)
Write estimation data to a file.
static constexpr double SHORT_DECAY
Decay of .962 is a half-life of 18 blocks or about 3 hours.
unsigned int HighestTargetTracked(FeeEstimateHorizon horizon) const EXCLUSIVE_LOCKS_REQUIRED(!m_cs_fee_estimator)
Calculation of highest target that estimates are tracked for.
bool _removeTx(const uint256 &hash, bool inBlock) EXCLUSIVE_LOCKS_REQUIRED(m_cs_fee_estimator)
A non-thread-safe helper for the removeTx function.
static constexpr double LONG_DECAY
Decay of .99931 is a half-life of 1008 blocks or about 1 week.
double estimateConservativeFee(unsigned int doubleTarget, EstimationResult *result) const EXCLUSIVE_LOCKS_REQUIRED(m_cs_fee_estimator)
Helper for estimateSmartFee.
static constexpr double HALF_SUCCESS_PCT
Require greater than 60% of X feerate transactions to be confirmed within Y/2 blocks.
static constexpr double MED_DECAY
Decay of .9952 is a half-life of 144 blocks or about 1 day.
CBlockPolicyEstimator(const fs::path &estimation_filepath)
Create new BlockPolicyEstimator and initialize stats tracking classes with default values.
CFeeRate estimateFee(int confTarget) const EXCLUSIVE_LOCKS_REQUIRED(!m_cs_fee_estimator)
DEPRECATED.
unsigned int MaxUsableEstimate() const EXCLUSIVE_LOCKS_REQUIRED(m_cs_fee_estimator)
Calculation of highest target that reasonable estimate can be provided for.
static constexpr unsigned int SHORT_SCALE
unsigned int BlockSpan() const EXCLUSIVE_LOCKS_REQUIRED(m_cs_fee_estimator)
Number of blocks of data recorded while fee estimates have been running.
bool removeTx(uint256 hash, bool inBlock) EXCLUSIVE_LOCKS_REQUIRED(!m_cs_fee_estimator)
Remove a transaction from the mempool tracking stats.
bool Read(AutoFile &filein) EXCLUSIVE_LOCKS_REQUIRED(!m_cs_fee_estimator)
Read estimation data from a file.
static constexpr unsigned int SHORT_BLOCK_PERIODS
Track confirm delays up to 12 blocks for short horizon.
static constexpr double DOUBLE_SUCCESS_PCT
Require greater than 95% of X feerate transactions to be confirmed within 2 * Y blocks.
unsigned int HistoricalBlockSpan() const EXCLUSIVE_LOCKS_REQUIRED(m_cs_fee_estimator)
Number of blocks of recorded fee estimate data represented in saved data file.
void FlushUnconfirmed() EXCLUSIVE_LOCKS_REQUIRED(!m_cs_fee_estimator)
Empty mempool transactions on shutdown to record failure to confirm for txs still in mempool.
CFeeRate estimateRawFee(int confTarget, double successThreshold, FeeEstimateHorizon horizon, EstimationResult *result=nullptr) const EXCLUSIVE_LOCKS_REQUIRED(!m_cs_fee_estimator)
Return a specific fee estimate calculation with a given success threshold and time horizon,...
bool processBlockTx(unsigned int nBlockHeight, const CTxMemPoolEntry *entry) EXCLUSIVE_LOCKS_REQUIRED(m_cs_fee_estimator)
Process a transaction confirmed in a block.
static constexpr double SUFFICIENT_TXS_SHORT
Require an avg of 0.5 tx when using short decay since there are fewer blocks considered.
static constexpr unsigned int MED_SCALE
static constexpr unsigned int MED_BLOCK_PERIODS
Track confirm delays up to 48 blocks for medium horizon.
const fs::path m_estimation_filepath
Fee rate in satoshis per kilovirtualbyte: CAmount / kvB.
CAmount GetFeePerK() const
Return the fee in satoshis for a vsize of 1000 vbytes.
const uint256 & GetHash() const
CTxMemPoolEntry stores data about the corresponding transaction, as well as data about all in-mempool...
const CTransaction & GetTx() const
unsigned int GetHeight() const
const CAmount & GetFee() const
const std::set< double > m_fee_set
CAmount round(CAmount currentMinFee) EXCLUSIVE_LOCKS_REQUIRED(!m_insecure_rand_mutex)
Quantize a minimum fee for privacy purpose before broadcast.
FeeFilterRounder(const CFeeRate &min_incremental_fee)
Create new FeeFilterRounder.
Mutex m_insecure_rand_mutex
We will instantiate an instance of this class to track transactions that were included in a block.
void removeTx(unsigned int entryHeight, unsigned int nBestSeenHeight, unsigned int bucketIndex, bool inBlock)
Remove a transaction from mempool tracking stats.
std::vector< std::vector< double > > failAvg
TxConfirmStats(const std::vector< double > &defaultBuckets, const std::map< double, unsigned int > &defaultBucketMap, unsigned int maxPeriods, double decay, unsigned int scale)
Create new TxConfirmStats.
void Read(AutoFile &filein, int nFileVersion, size_t numBuckets)
Read saved state of estimation data from a file and replace all internal data structures and variable...
unsigned int GetMaxConfirms() const
Return the max number of confirms we're tracking.
void ClearCurrent(unsigned int nBlockHeight)
Roll the circular buffer for unconfirmed txs.
void Record(int blocksToConfirm, double val)
Record a new transaction data point in the current block stats.
void resizeInMemoryCounters(size_t newbuckets)
std::vector< double > txCtAvg
std::vector< int > oldUnconfTxs
void UpdateMovingAverages()
Update our estimates by decaying our historical moving average and updating with the data gathered fr...
const std::map< double, unsigned int > & bucketMap
const std::vector< double > & buckets
std::vector< std::vector< double > > confAvg
void Write(AutoFile &fileout) const
Write state of estimation data to a file.
std::vector< std::vector< int > > unconfTxs
unsigned int NewTx(unsigned int nBlockHeight, double val)
Record a new transaction entering the mempool.
std::vector< double > m_feerate_avg
double EstimateMedianVal(int confTarget, double sufficientTxVal, double minSuccess, unsigned int nBlockHeight, EstimationResult *result=nullptr) const
Calculate a feerate estimate.
std::string ToString() const
Path class wrapper to block calls to the fs::path(std::string) implicit constructor and the fs::path:...
static const int CLIENT_VERSION
bitcoind-res.rc includes this file, but it cannot cope with real c++ code.
#define LogPrint(category,...)
static std::string PathToString(const path &path)
Convert path object to a byte string.
FILE * fopen(const fs::path &p, const char *mode)
static constexpr double INF_FEERATE
static std::set< double > MakeFeeSet(const CFeeRate &min_incremental_fee, double max_filter_fee_rate, double fee_filter_spacing)
std::string StringForFeeEstimateHorizon(FeeEstimateHorizon horizon)
uint64_t EncodeDouble(double f) noexcept
double DecodeDouble(uint64_t v) noexcept
#define AssertLockNotHeld(cs)
#define WITH_LOCK(cs, code)
Run code while locking a mutex.