53struct EncodedDoubleFormatter
55 template<
typename Stream>
void Ser(Stream &
s,
double v)
60 template<
typename Stream>
void Unser(Stream&
s,
double& v)
127 TxConfirmStats(
const std::vector<double>& defaultBuckets,
const std::map<double, unsigned int>& defaultBucketMap,
128 unsigned int maxPeriods,
double decay,
unsigned int scale);
139 void Record(
int blocksToConfirm,
double val);
142 unsigned int NewTx(
unsigned int nBlockHeight,
double val);
145 void removeTx(
unsigned int entryHeight,
unsigned int nBestSeenHeight,
146 unsigned int bucketIndex,
bool inBlock);
162 double minSuccess,
unsigned int nBlockHeight,
180 const std::map<double, unsigned int>& defaultBucketMap,
181 unsigned int maxPeriods,
double _decay,
unsigned int _scale)
182 : buckets(defaultBuckets), bucketMap(defaultBucketMap), decay(_decay), scale(_scale)
184 assert(_scale != 0 &&
"_scale must be non-zero");
187 for (
unsigned int i = 0; i < maxPeriods; i++) {
201 for (
unsigned int i = 0; i <
unconfTxs.size(); i++) {
210 for (
unsigned int j = 0; j <
buckets.size(); j++) {
220 if (blocksToConfirm < 1)
222 int periodsToConfirm = (blocksToConfirm +
scale - 1) /
scale;
223 unsigned int bucketindex =
bucketMap.lower_bound(feerate)->second;
224 for (
size_t i = periodsToConfirm; i <=
confAvg.size(); i++) {
234 for (
unsigned int j = 0; j <
buckets.size(); j++) {
235 for (
unsigned int i = 0; i <
confAvg.size(); i++) {
246 double successBreakPoint,
unsigned int nBlockHeight,
254 const int periodTarget = (confTarget +
scale - 1) /
scale;
255 const int maxbucketindex =
buckets.size() - 1;
262 unsigned int curNearBucket = maxbucketindex;
263 unsigned int bestNearBucket = maxbucketindex;
264 unsigned int curFarBucket = maxbucketindex;
265 unsigned int bestFarBucket = maxbucketindex;
270 double partialNum = 0;
272 bool foundAnswer =
false;
274 bool newBucketRange =
true;
280 for (
int bucket = maxbucketindex; bucket >= 0; --bucket) {
281 if (newBucketRange) {
282 curNearBucket = bucket;
283 newBucketRange =
false;
285 curFarBucket = bucket;
286 nConf +=
confAvg[periodTarget - 1][bucket];
289 failNum +=
failAvg[periodTarget - 1][bucket];
290 for (
unsigned int confct = confTarget; confct <
GetMaxConfirms(); confct++)
291 extraNum +=
unconfTxs[(nBlockHeight - confct) % bins][bucket];
298 if (partialNum < sufficientTxVal / (1 -
decay)) {
305 double curPct = nConf / (totalNum + failNum + extraNum);
308 if (curPct < successBreakPoint) {
309 if (passing ==
true) {
311 unsigned int failMinBucket = std::min(curNearBucket, curFarBucket);
312 unsigned int failMaxBucket = std::max(curNearBucket, curFarBucket);
313 failBucket.
start = failMinBucket ?
buckets[failMinBucket - 1] : 0;
337 bestNearBucket = curNearBucket;
338 bestFarBucket = curFarBucket;
339 newBucketRange =
true;
351 unsigned int minBucket = std::min(bestNearBucket, bestFarBucket);
352 unsigned int maxBucket = std::max(bestNearBucket, bestFarBucket);
353 for (
unsigned int j = minBucket; j <= maxBucket; j++) {
356 if (foundAnswer && txSum != 0) {
358 for (
unsigned int j = minBucket; j <= maxBucket; j++) {
367 passBucket.
start = minBucket ?
buckets[minBucket-1] : 0;
372 if (passing && !newBucketRange) {
373 unsigned int failMinBucket = std::min(curNearBucket, curFarBucket);
374 unsigned int failMaxBucket = std::max(curNearBucket, curFarBucket);
375 failBucket.
start = failMinBucket ?
buckets[failMinBucket - 1] : 0;
383 float passed_within_target_perc = 0.0;
384 float failed_within_target_perc = 0.0;
392 LogDebug(
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",
393 confTarget, 100.0 * successBreakPoint,
decay,
394 median, passBucket.
start, passBucket.
end,
395 passed_within_target_perc,
398 failed_within_target_perc,
403 result->
pass = passBucket;
404 result->
fail = failBucket;
413 fileout << Using<EncodedDoubleFormatter>(
decay);
415 fileout << Using<VectorFormatter<EncodedDoubleFormatter>>(
m_feerate_avg);
416 fileout << Using<VectorFormatter<EncodedDoubleFormatter>>(
txCtAvg);
417 fileout << Using<VectorFormatter<VectorFormatter<EncodedDoubleFormatter>>>(
confAvg);
418 fileout << Using<VectorFormatter<VectorFormatter<EncodedDoubleFormatter>>>(
failAvg);
426 size_t maxConfirms, maxPeriods;
429 filein >> Using<EncodedDoubleFormatter>(
decay);
430 if (decay <= 0 || decay >= 1) {
431 throw std::runtime_error(
"Corrupt estimates file. Decay must be between 0 and 1 (non-inclusive)");
435 throw std::runtime_error(
"Corrupt estimates file. Scale must be non-zero");
438 filein >> Using<VectorFormatter<EncodedDoubleFormatter>>(
m_feerate_avg);
440 throw std::runtime_error(
"Corrupt estimates file. Mismatch in feerate average bucket count");
442 filein >> Using<VectorFormatter<EncodedDoubleFormatter>>(
txCtAvg);
443 if (
txCtAvg.size() != numBuckets) {
444 throw std::runtime_error(
"Corrupt estimates file. Mismatch in tx count bucket count");
446 filein >> Using<VectorFormatter<VectorFormatter<EncodedDoubleFormatter>>>(
confAvg);
448 maxConfirms =
scale * maxPeriods;
450 if (maxConfirms <= 0 || maxConfirms > 6 * 24 * 7) {
451 throw std::runtime_error(
"Corrupt estimates file. Must maintain estimates for between 1 and 1008 (one week) confirms");
453 for (
unsigned int i = 0; i < maxPeriods; i++) {
454 if (
confAvg[i].size() != numBuckets) {
455 throw std::runtime_error(
"Corrupt estimates file. Mismatch in feerate conf average bucket count");
459 filein >> Using<VectorFormatter<VectorFormatter<EncodedDoubleFormatter>>>(
failAvg);
460 if (maxPeriods !=
failAvg.size()) {
461 throw std::runtime_error(
"Corrupt estimates file. Mismatch in confirms tracked for failures");
463 for (
unsigned int i = 0; i < maxPeriods; i++) {
464 if (
failAvg[i].size() != numBuckets) {
465 throw std::runtime_error(
"Corrupt estimates file. Mismatch in one of failure average bucket counts");
474 numBuckets, maxConfirms);
479 unsigned int bucketindex =
bucketMap.lower_bound(val)->second;
480 unsigned int blockIndex = nBlockHeight %
unconfTxs.size();
488 int blocksAgo = nBestSeenHeight - entryHeight;
489 if (nBestSeenHeight == 0)
496 if (blocksAgo >= (
int)
unconfTxs.size()) {
505 unsigned int blockIndex = entryHeight %
unconfTxs.size();
506 if (
unconfTxs[blockIndex][bucketindex] > 0) {
510 blockIndex, bucketindex);
513 if (!inBlock && (
unsigned int)blocksAgo >=
scale) {
515 unsigned int periodsAgo = blocksAgo /
scale;
516 for (
size_t i = 0; i < periodsAgo && i <
failAvg.size(); i++) {
531 std::map<Txid, TxStatsInfo>::iterator pos = mapMemPoolTxs.find(hash);
532 if (pos != mapMemPoolTxs.end()) {
533 feeStats->removeTx(pos->second.blockHeight, nBestSeenHeight, pos->second.bucketIndex, inBlock);
534 shortStats->removeTx(pos->second.blockHeight, nBestSeenHeight, pos->second.bucketIndex, inBlock);
535 longStats->removeTx(pos->second.blockHeight, nBestSeenHeight, pos->second.bucketIndex, inBlock);
536 mapMemPoolTxs.erase(hash);
544 : m_estimation_filepath{estimation_filepath}
547 size_t bucketIndex = 0;
550 buckets.push_back(bucketBoundary);
551 bucketMap[bucketBoundary] = bucketIndex;
555 assert(bucketMap.size() == buckets.size());
563 if (est_file.IsNull()) {
574 if (!
Read(est_file)) {
600 const auto& hash = tx.
info.
m_tx->GetHash();
601 if (mapMemPoolTxs.count(hash)) {
607 if (txHeight != nBestSeenHeight) {
623 if (!validForFeeEstimation) {
632 mapMemPoolTxs[hash].blockHeight = txHeight;
633 unsigned int bucketIndex = feeStats->NewTx(txHeight,
static_cast<double>(feeRate.
GetFeePerK()));
634 mapMemPoolTxs[hash].bucketIndex = bucketIndex;
635 unsigned int bucketIndex2 = shortStats->NewTx(txHeight,
static_cast<double>(feeRate.
GetFeePerK()));
636 assert(bucketIndex == bucketIndex2);
637 unsigned int bucketIndex3 = longStats->NewTx(txHeight,
static_cast<double>(feeRate.
GetFeePerK()));
638 assert(bucketIndex == bucketIndex3);
653 if (blocksToConfirm <= 0) {
663 feeStats->Record(blocksToConfirm,
static_cast<double>(feeRate.
GetFeePerK()));
664 shortStats->Record(blocksToConfirm,
static_cast<double>(feeRate.
GetFeePerK()));
665 longStats->Record(blocksToConfirm,
static_cast<double>(feeRate.
GetFeePerK()));
670 unsigned int nBlockHeight)
673 if (nBlockHeight <= nBestSeenHeight) {
685 nBestSeenHeight = nBlockHeight;
688 feeStats->ClearCurrent(nBlockHeight);
689 shortStats->ClearCurrent(nBlockHeight);
690 longStats->ClearCurrent(nBlockHeight);
693 feeStats->UpdateMovingAverages();
694 shortStats->UpdateMovingAverages();
695 longStats->UpdateMovingAverages();
697 unsigned int countedTxs = 0;
699 for (
const auto& tx : txs_removed_for_block) {
704 if (firstRecordedHeight == 0 && countedTxs > 0) {
705 firstRecordedHeight = nBestSeenHeight;
710 LogDebug(
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",
711 countedTxs, txs_removed_for_block.size(), trackedTxs, trackedTxs + untrackedTxs, mapMemPoolTxs.size(),
733 stats = shortStats.get();
738 stats = feeStats.get();
742 stats = longStats.get();
750 if (confTarget <= 0 || (
unsigned int)confTarget > stats->
GetMaxConfirms())
752 if (successThreshold > 1)
755 double median = stats->
EstimateMedianVal(confTarget, sufficientTxs, successThreshold, nBestSeenHeight, result);
768 return shortStats->GetMaxConfirms();
771 return feeStats->GetMaxConfirms();
774 return longStats->GetMaxConfirms();
782 if (firstRecordedHeight == 0)
return 0;
783 assert(nBestSeenHeight >= firstRecordedHeight);
785 return nBestSeenHeight - firstRecordedHeight;
790 if (historicalFirst == 0)
return 0;
791 assert(historicalBest >= historicalFirst);
795 return historicalBest - historicalFirst;
810 double estimate = -1;
811 if (confTarget >= 1 && confTarget <= longStats->GetMaxConfirms()) {
813 if (confTarget <= shortStats->GetMaxConfirms()) {
814 estimate = shortStats->EstimateMedianVal(confTarget,
SUFFICIENT_TXS_SHORT, successThreshold, nBestSeenHeight, result);
816 else if (confTarget <= feeStats->GetMaxConfirms()) {
817 estimate = feeStats->EstimateMedianVal(confTarget,
SUFFICIENT_FEETXS, successThreshold, nBestSeenHeight, result);
820 estimate = longStats->EstimateMedianVal(confTarget,
SUFFICIENT_FEETXS, successThreshold, nBestSeenHeight, result);
822 if (checkShorterHorizon) {
825 if (confTarget > feeStats->GetMaxConfirms()) {
826 double medMax = feeStats->EstimateMedianVal(feeStats->GetMaxConfirms(),
SUFFICIENT_FEETXS, successThreshold, nBestSeenHeight, &tempResult);
827 if (medMax > 0 && (estimate == -1 || medMax < estimate)) {
829 if (result) *result = tempResult;
832 if (confTarget > shortStats->GetMaxConfirms()) {
833 double shortMax = shortStats->EstimateMedianVal(shortStats->GetMaxConfirms(),
SUFFICIENT_TXS_SHORT, successThreshold, nBestSeenHeight, &tempResult);
834 if (shortMax > 0 && (estimate == -1 || shortMax < estimate)) {
836 if (result) *result = tempResult;
849 double estimate = -1;
851 if (doubleTarget <= shortStats->GetMaxConfirms()) {
854 if (doubleTarget <= feeStats->GetMaxConfirms()) {
856 if (longEstimate > estimate) {
857 estimate = longEstimate;
858 if (result) *result = tempResult;
884 if (confTarget <= 0 || (
unsigned int)confTarget > longStats->GetMaxConfirms()) {
889 if (confTarget == 1) confTarget = 2;
892 if ((
unsigned int)confTarget > maxUsableEstimate) {
893 confTarget = maxUsableEstimate;
897 if (confTarget <= 1)
return CFeeRate(0);
920 feeCalc->
est = tempResult;
925 if (actualEst > median) {
928 feeCalc->
est = tempResult;
933 if (doubleEst > median) {
936 feeCalc->
est = tempResult;
941 if (conservative || median == -1) {
943 if (consEst > median) {
946 feeCalc->
est = tempResult;
965 if (est_file.IsNull() || !
Write(est_file)) {
967 (void)est_file.fclose();
970 if (est_file.fclose() != 0) {
983 fileout << nBestSeenHeight;
985 fileout << firstRecordedHeight << nBestSeenHeight;
988 fileout << historicalFirst << historicalBest;
990 fileout << Using<VectorFormatter<EncodedDoubleFormatter>>(buckets);
991 feeStats->Write(fileout);
992 shortStats->Write(fileout);
993 longStats->Write(fileout);
995 catch (
const std::exception&) {
996 LogWarning(
"Unable to write policy estimator data (non-fatal)");
1006 int nVersionRequired, dummy;
1007 filein >> nVersionRequired >> dummy;
1009 throw std::runtime_error{
strprintf(
"File version (%d) too high to be read.", nVersionRequired)};
1014 unsigned int nFileBestSeenHeight;
1015 filein >> nFileBestSeenHeight;
1018 LogWarning(
"Incompatible old fee estimation data (non-fatal). Version: %d", nVersionRequired);
1020 unsigned int nFileHistoricalFirst, nFileHistoricalBest;
1021 filein >> nFileHistoricalFirst >> nFileHistoricalBest;
1022 if (nFileHistoricalFirst > nFileHistoricalBest || nFileHistoricalBest > nFileBestSeenHeight) {
1023 throw std::runtime_error(
"Corrupt estimates file. Historical block range for estimates is invalid");
1025 std::vector<double> fileBuckets;
1026 filein >> Using<VectorFormatter<EncodedDoubleFormatter>>(fileBuckets);
1027 size_t numBuckets = fileBuckets.size();
1028 if (numBuckets <= 1 || numBuckets > 1000) {
1029 throw std::runtime_error(
"Corrupt estimates file. Must have between 2 and 1000 feerate buckets");
1035 fileFeeStats->Read(filein, numBuckets);
1036 fileShortStats->Read(filein, numBuckets);
1037 fileLongStats->Read(filein, numBuckets);
1041 buckets = fileBuckets;
1043 for (
unsigned int i = 0; i < buckets.size(); i++) {
1044 bucketMap[buckets[i]] = i;
1048 feeStats = std::move(fileFeeStats);
1049 shortStats = std::move(fileShortStats);
1050 longStats = std::move(fileLongStats);
1052 nBestSeenHeight = nFileBestSeenHeight;
1053 historicalFirst = nFileHistoricalFirst;
1054 historicalBest = nFileHistoricalBest;
1057 catch (
const std::exception& e) {
1058 LogWarning(
"Unable to read policy estimator data (non-fatal): %s", e.what());
1066 const auto startclear{SteadyClock::now()};
1068 size_t num_entries = mapMemPoolTxs.size();
1070 while (!mapMemPoolTxs.empty()) {
1071 auto mi = mapMemPoolTxs.begin();
1074 const auto endclear{SteadyClock::now()};
1075 LogDebug(
BCLog::ESTIMATEFEE,
"Recorded %u unconfirmed txs from mempool in %.3fs\n", num_entries, Ticks<SecondsDouble>(endclear - startclear));
1081 auto now{fs::file_time_type::clock::now()};
1082 return std::chrono::duration_cast<std::chrono::hours>(now - file_time);
1086 double max_filter_fee_rate,
1087 double fee_filter_spacing)
1089 std::set<double> fee_set;
1093 for (
double bucket_boundary = min_fee_limit;
1094 bucket_boundary <= max_filter_fee_rate;
1095 bucket_boundary *= fee_filter_spacing) {
1097 fee_set.insert(bucket_boundary);
1104 : m_fee_set{
MakeFeeSet(minIncrementalFee, MAX_FILTER_FEERATE, FEE_FILTER_SPACING)},
1112 std::set<double>::iterator it =
m_fee_set.lower_bound(currentMinFee);
1118 return static_cast<CAmount>(*it);
int64_t CAmount
Amount in satoshis (Can be negative)
Non-refcounted RAII wrapper for FILE*.
void processTransaction(const NewMempoolTransactionInfo &tx) EXCLUSIVE_LOCKS_REQUIRED(!m_cs_fee_estimator)
Process a transaction accepted to the mempool.
static constexpr unsigned int LONG_SCALE
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.
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.
bool removeTx(Txid hash) EXCLUSIVE_LOCKS_REQUIRED(!m_cs_fee_estimator)
Remove a transaction from the mempool tracking stats for non BLOCK removal reasons.
static constexpr double MAX_BUCKET_FEERATE
void FlushFeeEstimates() EXCLUSIVE_LOCKS_REQUIRED(!m_cs_fee_estimator)
Record current fee estimations.
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.
std::chrono::hours GetFeeEstimatorFileAge()
Calculates the age of the file, since last modified.
unsigned int HighestTargetTracked(FeeEstimateHorizon horizon) const EXCLUSIVE_LOCKS_REQUIRED(!m_cs_fee_estimator)
Calculation of highest target that estimates are tracked for.
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.
void TransactionRemovedFromMempool(const CTransactionRef &tx, MemPoolRemovalReason, uint64_t) override EXCLUSIVE_LOCKS_REQUIRED(!m_cs_fee_estimator)
Notifies listeners of a transaction leaving mempool.
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.
CFeeRate estimateFee(int confTarget) const EXCLUSIVE_LOCKS_REQUIRED(!m_cs_fee_estimator)
DEPRECATED.
CBlockPolicyEstimator(const fs::path &estimation_filepath, const bool read_stale_estimates)
Create new BlockPolicyEstimator and initialize stats tracking classes with default values.
bool _removeTx(const Txid &hash, bool inBlock) EXCLUSIVE_LOCKS_REQUIRED(m_cs_fee_estimator)
A non-thread-safe helper for the removeTx function.
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.
void MempoolTransactionsRemovedForBlock(const std::vector< RemovedMempoolTransactionInfo > &txs_removed_for_block, unsigned int nBlockHeight) override EXCLUSIVE_LOCKS_REQUIRED(!m_cs_fee_estimator)
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,...
static constexpr double SUFFICIENT_TXS_SHORT
Require an avg of 0.5 tx when using short decay since there are fewer blocks considered.
bool processBlockTx(unsigned int nBlockHeight, const RemovedMempoolTransactionInfo &tx) EXCLUSIVE_LOCKS_REQUIRED(m_cs_fee_estimator)
Process a transaction confirmed in a block.
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
virtual ~CBlockPolicyEstimator()
void TransactionAddedToMempool(const NewMempoolTransactionInfo &tx, uint64_t) override EXCLUSIVE_LOCKS_REQUIRED(!m_cs_fee_estimator)
Overridden from CValidationInterface.
void processBlock(const std::vector< RemovedMempoolTransactionInfo > &txs_removed_for_block, unsigned int nBlockHeight) EXCLUSIVE_LOCKS_REQUIRED(!m_cs_fee_estimator)
Process all the transactions that have been included in a block.
Fee rate in satoshis per virtualbyte: CAmount / vB the feerate is represented internally as FeeFrac.
CAmount GetFeePerK() const
Return the fee in satoshis for a vsize of 1000 vbytes.
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, FastRandomContext &rng)
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.
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
void Read(AutoFile &filein, size_t numBuckets)
Read saved state of estimation data from a file and replace all internal data structures and variable...
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.
static std::string PathToString(const path &path)
Convert path object to a byte string.
#define LogDebug(category,...)
MemPoolRemovalReason
Reason why a transaction was removed from the mempool, this is passed to the notification signal.
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)
constexpr int CURRENT_FEES_FILE_VERSION
std::string StringForFeeEstimateHorizon(FeeEstimateHorizon horizon)
static constexpr std::chrono::hours MAX_FILE_AGE
fee_estimates.dat that are more than 60 hours (2.5 days) old will not be read, as fee estimates are b...
std::shared_ptr< const CTransaction > CTransactionRef
uint64_t EncodeDouble(double f) noexcept
double DecodeDouble(uint64_t v) noexcept
const bool m_submitted_in_package
const bool m_has_no_mempool_parents
const bool m_chainstate_is_current
const bool m_mempool_limit_bypassed
const unsigned int txHeight
const CTransactionRef m_tx
const int64_t m_virtual_transaction_size
The virtual transaction size.
#define AssertLockNotHeld(cs)
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
std::string SysErrorString(int err)
Return system error string from errno value.