52struct EncodedDoubleFormatter
54 template<
typename Stream>
void Ser(Stream &
s,
double v)
59 template<
typename Stream>
void Unser(Stream&
s,
double& v)
126 TxConfirmStats(
const std::vector<double>& defaultBuckets,
const std::map<double, unsigned int>& defaultBucketMap,
127 unsigned int maxPeriods,
double decay,
unsigned int scale);
138 void Record(
int blocksToConfirm,
double val);
141 unsigned int NewTx(
unsigned int nBlockHeight,
double val);
144 void removeTx(
unsigned int entryHeight,
unsigned int nBestSeenHeight,
145 unsigned int bucketIndex,
bool inBlock);
161 double minSuccess,
unsigned int nBlockHeight,
179 const std::map<double, unsigned int>& defaultBucketMap,
180 unsigned int maxPeriods,
double _decay,
unsigned int _scale)
181 : buckets(defaultBuckets), bucketMap(defaultBucketMap), decay(_decay), scale(_scale)
183 assert(_scale != 0 &&
"_scale must be non-zero");
186 for (
unsigned int i = 0; i < maxPeriods; i++) {
200 for (
unsigned int i = 0; i <
unconfTxs.size(); i++) {
209 for (
unsigned int j = 0; j <
buckets.size(); j++) {
219 if (blocksToConfirm < 1)
221 int periodsToConfirm = (blocksToConfirm +
scale - 1) /
scale;
222 unsigned int bucketindex =
bucketMap.lower_bound(feerate)->second;
223 for (
size_t i = periodsToConfirm; i <=
confAvg.size(); i++) {
233 for (
unsigned int j = 0; j <
buckets.size(); j++) {
234 for (
unsigned int i = 0; i <
confAvg.size(); i++) {
245 double successBreakPoint,
unsigned int nBlockHeight,
253 const int periodTarget = (confTarget +
scale - 1) /
scale;
254 const int maxbucketindex =
buckets.size() - 1;
261 unsigned int curNearBucket = maxbucketindex;
262 unsigned int bestNearBucket = maxbucketindex;
263 unsigned int curFarBucket = maxbucketindex;
264 unsigned int bestFarBucket = maxbucketindex;
269 double partialNum = 0;
271 bool foundAnswer =
false;
273 bool newBucketRange =
true;
279 for (
int bucket = maxbucketindex; bucket >= 0; --bucket) {
280 if (newBucketRange) {
281 curNearBucket = bucket;
282 newBucketRange =
false;
284 curFarBucket = bucket;
285 nConf +=
confAvg[periodTarget - 1][bucket];
288 failNum +=
failAvg[periodTarget - 1][bucket];
289 for (
unsigned int confct = confTarget; confct <
GetMaxConfirms(); confct++)
290 extraNum +=
unconfTxs[(nBlockHeight - confct) % bins][bucket];
297 if (partialNum < sufficientTxVal / (1 -
decay)) {
304 double curPct = nConf / (totalNum + failNum + extraNum);
307 if (curPct < successBreakPoint) {
308 if (passing ==
true) {
310 unsigned int failMinBucket = std::min(curNearBucket, curFarBucket);
311 unsigned int failMaxBucket = std::max(curNearBucket, curFarBucket);
312 failBucket.
start = failMinBucket ?
buckets[failMinBucket - 1] : 0;
336 bestNearBucket = curNearBucket;
337 bestFarBucket = curFarBucket;
338 newBucketRange =
true;
350 unsigned int minBucket = std::min(bestNearBucket, bestFarBucket);
351 unsigned int maxBucket = std::max(bestNearBucket, bestFarBucket);
352 for (
unsigned int j = minBucket; j <= maxBucket; j++) {
355 if (foundAnswer && txSum != 0) {
357 for (
unsigned int j = minBucket; j <= maxBucket; j++) {
366 passBucket.
start = minBucket ?
buckets[minBucket-1] : 0;
371 if (passing && !newBucketRange) {
372 unsigned int failMinBucket = std::min(curNearBucket, curFarBucket);
373 unsigned int failMaxBucket = std::max(curNearBucket, curFarBucket);
374 failBucket.
start = failMinBucket ?
buckets[failMinBucket - 1] : 0;
382 float passed_within_target_perc = 0.0;
383 float failed_within_target_perc = 0.0;
391 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",
392 confTarget, 100.0 * successBreakPoint,
decay,
393 median, passBucket.
start, passBucket.
end,
394 passed_within_target_perc,
397 failed_within_target_perc,
402 result->
pass = passBucket;
403 result->
fail = failBucket;
412 fileout << Using<EncodedDoubleFormatter>(
decay);
414 fileout << Using<VectorFormatter<EncodedDoubleFormatter>>(
m_feerate_avg);
415 fileout << Using<VectorFormatter<EncodedDoubleFormatter>>(
txCtAvg);
416 fileout << Using<VectorFormatter<VectorFormatter<EncodedDoubleFormatter>>>(
confAvg);
417 fileout << Using<VectorFormatter<VectorFormatter<EncodedDoubleFormatter>>>(
failAvg);
425 size_t maxConfirms, maxPeriods;
428 filein >> Using<EncodedDoubleFormatter>(
decay);
429 if (decay <= 0 || decay >= 1) {
430 throw std::runtime_error(
"Corrupt estimates file. Decay must be between 0 and 1 (non-inclusive)");
434 throw std::runtime_error(
"Corrupt estimates file. Scale must be non-zero");
437 filein >> Using<VectorFormatter<EncodedDoubleFormatter>>(
m_feerate_avg);
439 throw std::runtime_error(
"Corrupt estimates file. Mismatch in feerate average bucket count");
441 filein >> Using<VectorFormatter<EncodedDoubleFormatter>>(
txCtAvg);
442 if (
txCtAvg.size() != numBuckets) {
443 throw std::runtime_error(
"Corrupt estimates file. Mismatch in tx count bucket count");
445 filein >> Using<VectorFormatter<VectorFormatter<EncodedDoubleFormatter>>>(
confAvg);
447 maxConfirms =
scale * maxPeriods;
449 if (maxConfirms <= 0 || maxConfirms > 6 * 24 * 7) {
450 throw std::runtime_error(
"Corrupt estimates file. Must maintain estimates for between 1 and 1008 (one week) confirms");
452 for (
unsigned int i = 0; i < maxPeriods; i++) {
453 if (
confAvg[i].size() != numBuckets) {
454 throw std::runtime_error(
"Corrupt estimates file. Mismatch in feerate conf average bucket count");
458 filein >> Using<VectorFormatter<VectorFormatter<EncodedDoubleFormatter>>>(
failAvg);
459 if (maxPeriods !=
failAvg.size()) {
460 throw std::runtime_error(
"Corrupt estimates file. Mismatch in confirms tracked for failures");
462 for (
unsigned int i = 0; i < maxPeriods; i++) {
463 if (
failAvg[i].size() != numBuckets) {
464 throw std::runtime_error(
"Corrupt estimates file. Mismatch in one of failure average bucket counts");
473 numBuckets, maxConfirms);
478 unsigned int bucketindex =
bucketMap.lower_bound(val)->second;
479 unsigned int blockIndex = nBlockHeight %
unconfTxs.size();
487 int blocksAgo = nBestSeenHeight - entryHeight;
488 if (nBestSeenHeight == 0)
495 if (blocksAgo >= (
int)
unconfTxs.size()) {
504 unsigned int blockIndex = entryHeight %
unconfTxs.size();
505 if (
unconfTxs[blockIndex][bucketindex] > 0) {
509 blockIndex, bucketindex);
512 if (!inBlock && (
unsigned int)blocksAgo >=
scale) {
514 unsigned int periodsAgo = blocksAgo /
scale;
515 for (
size_t i = 0; i < periodsAgo && i <
failAvg.size(); i++) {
530 std::map<uint256, TxStatsInfo>::iterator pos = mapMemPoolTxs.find(hash);
531 if (pos != mapMemPoolTxs.end()) {
532 feeStats->removeTx(pos->second.blockHeight, nBestSeenHeight, pos->second.bucketIndex, inBlock);
533 shortStats->removeTx(pos->second.blockHeight, nBestSeenHeight, pos->second.bucketIndex, inBlock);
534 longStats->removeTx(pos->second.blockHeight, nBestSeenHeight, pos->second.bucketIndex, inBlock);
535 mapMemPoolTxs.erase(hash);
543 : m_estimation_filepath{estimation_filepath}
546 size_t bucketIndex = 0;
549 buckets.push_back(bucketBoundary);
550 bucketMap[bucketBoundary] = bucketIndex;
554 assert(bucketMap.size() == buckets.size());
562 if (est_file.IsNull()) {
573 if (!
Read(est_file)) {
599 const auto& hash = tx.
info.
m_tx->GetHash();
600 if (mapMemPoolTxs.count(hash)) {
606 if (txHeight != nBestSeenHeight) {
622 if (!validForFeeEstimation) {
631 mapMemPoolTxs[hash].blockHeight = txHeight;
632 unsigned int bucketIndex = feeStats->NewTx(txHeight,
static_cast<double>(feeRate.
GetFeePerK()));
633 mapMemPoolTxs[hash].bucketIndex = bucketIndex;
634 unsigned int bucketIndex2 = shortStats->NewTx(txHeight,
static_cast<double>(feeRate.
GetFeePerK()));
635 assert(bucketIndex == bucketIndex2);
636 unsigned int bucketIndex3 = longStats->NewTx(txHeight,
static_cast<double>(feeRate.
GetFeePerK()));
637 assert(bucketIndex == bucketIndex3);
652 if (blocksToConfirm <= 0) {
662 feeStats->Record(blocksToConfirm,
static_cast<double>(feeRate.
GetFeePerK()));
663 shortStats->Record(blocksToConfirm,
static_cast<double>(feeRate.
GetFeePerK()));
664 longStats->Record(blocksToConfirm,
static_cast<double>(feeRate.
GetFeePerK()));
669 unsigned int nBlockHeight)
672 if (nBlockHeight <= nBestSeenHeight) {
684 nBestSeenHeight = nBlockHeight;
687 feeStats->ClearCurrent(nBlockHeight);
688 shortStats->ClearCurrent(nBlockHeight);
689 longStats->ClearCurrent(nBlockHeight);
692 feeStats->UpdateMovingAverages();
693 shortStats->UpdateMovingAverages();
694 longStats->UpdateMovingAverages();
696 unsigned int countedTxs = 0;
698 for (
const auto& tx : txs_removed_for_block) {
703 if (firstRecordedHeight == 0 && countedTxs > 0) {
704 firstRecordedHeight = nBestSeenHeight;
709 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",
710 countedTxs, txs_removed_for_block.size(), trackedTxs, trackedTxs + untrackedTxs, mapMemPoolTxs.size(),
732 stats = shortStats.get();
737 stats = feeStats.get();
741 stats = longStats.get();
749 if (confTarget <= 0 || (
unsigned int)confTarget > stats->
GetMaxConfirms())
751 if (successThreshold > 1)
754 double median = stats->
EstimateMedianVal(confTarget, sufficientTxs, successThreshold, nBestSeenHeight, result);
767 return shortStats->GetMaxConfirms();
770 return feeStats->GetMaxConfirms();
773 return longStats->GetMaxConfirms();
781 if (firstRecordedHeight == 0)
return 0;
782 assert(nBestSeenHeight >= firstRecordedHeight);
784 return nBestSeenHeight - firstRecordedHeight;
789 if (historicalFirst == 0)
return 0;
790 assert(historicalBest >= historicalFirst);
794 return historicalBest - historicalFirst;
809 double estimate = -1;
810 if (confTarget >= 1 && confTarget <= longStats->GetMaxConfirms()) {
812 if (confTarget <= shortStats->GetMaxConfirms()) {
813 estimate = shortStats->EstimateMedianVal(confTarget,
SUFFICIENT_TXS_SHORT, successThreshold, nBestSeenHeight, result);
815 else if (confTarget <= feeStats->GetMaxConfirms()) {
816 estimate = feeStats->EstimateMedianVal(confTarget,
SUFFICIENT_FEETXS, successThreshold, nBestSeenHeight, result);
819 estimate = longStats->EstimateMedianVal(confTarget,
SUFFICIENT_FEETXS, successThreshold, nBestSeenHeight, result);
821 if (checkShorterHorizon) {
824 if (confTarget > feeStats->GetMaxConfirms()) {
825 double medMax = feeStats->EstimateMedianVal(feeStats->GetMaxConfirms(),
SUFFICIENT_FEETXS, successThreshold, nBestSeenHeight, &tempResult);
826 if (medMax > 0 && (estimate == -1 || medMax < estimate)) {
828 if (result) *result = tempResult;
831 if (confTarget > shortStats->GetMaxConfirms()) {
832 double shortMax = shortStats->EstimateMedianVal(shortStats->GetMaxConfirms(),
SUFFICIENT_TXS_SHORT, successThreshold, nBestSeenHeight, &tempResult);
833 if (shortMax > 0 && (estimate == -1 || shortMax < estimate)) {
835 if (result) *result = tempResult;
848 double estimate = -1;
850 if (doubleTarget <= shortStats->GetMaxConfirms()) {
853 if (doubleTarget <= feeStats->GetMaxConfirms()) {
855 if (longEstimate > estimate) {
856 estimate = longEstimate;
857 if (result) *result = tempResult;
883 if (confTarget <= 0 || (
unsigned int)confTarget > longStats->GetMaxConfirms()) {
888 if (confTarget == 1) confTarget = 2;
891 if ((
unsigned int)confTarget > maxUsableEstimate) {
892 confTarget = maxUsableEstimate;
896 if (confTarget <= 1)
return CFeeRate(0);
911 feeCalc->
est = tempResult;
916 if (actualEst > median) {
919 feeCalc->
est = tempResult;
924 if (doubleEst > median) {
927 feeCalc->
est = tempResult;
932 if (conservative || median == -1) {
934 if (consEst > median) {
937 feeCalc->
est = tempResult;
956 if (est_file.IsNull() || !
Write(est_file)) {
969 fileout << nBestSeenHeight;
971 fileout << firstRecordedHeight << nBestSeenHeight;
974 fileout << historicalFirst << historicalBest;
976 fileout << Using<VectorFormatter<EncodedDoubleFormatter>>(buckets);
977 feeStats->Write(fileout);
978 shortStats->Write(fileout);
979 longStats->Write(fileout);
981 catch (
const std::exception&) {
982 LogWarning(
"Unable to write policy estimator data (non-fatal)");
992 int nVersionRequired, dummy;
993 filein >> nVersionRequired >> dummy;
995 throw std::runtime_error{
strprintf(
"File version (%d) too high to be read.", nVersionRequired)};
1000 unsigned int nFileBestSeenHeight;
1001 filein >> nFileBestSeenHeight;
1004 LogWarning(
"Incompatible old fee estimation data (non-fatal). Version: %d", nVersionRequired);
1006 unsigned int nFileHistoricalFirst, nFileHistoricalBest;
1007 filein >> nFileHistoricalFirst >> nFileHistoricalBest;
1008 if (nFileHistoricalFirst > nFileHistoricalBest || nFileHistoricalBest > nFileBestSeenHeight) {
1009 throw std::runtime_error(
"Corrupt estimates file. Historical block range for estimates is invalid");
1011 std::vector<double> fileBuckets;
1012 filein >> Using<VectorFormatter<EncodedDoubleFormatter>>(fileBuckets);
1013 size_t numBuckets = fileBuckets.size();
1014 if (numBuckets <= 1 || numBuckets > 1000) {
1015 throw std::runtime_error(
"Corrupt estimates file. Must have between 2 and 1000 feerate buckets");
1021 fileFeeStats->Read(filein, numBuckets);
1022 fileShortStats->Read(filein, numBuckets);
1023 fileLongStats->Read(filein, numBuckets);
1027 buckets = fileBuckets;
1029 for (
unsigned int i = 0; i < buckets.size(); i++) {
1030 bucketMap[buckets[i]] = i;
1034 feeStats = std::move(fileFeeStats);
1035 shortStats = std::move(fileShortStats);
1036 longStats = std::move(fileLongStats);
1038 nBestSeenHeight = nFileBestSeenHeight;
1039 historicalFirst = nFileHistoricalFirst;
1040 historicalBest = nFileHistoricalBest;
1043 catch (
const std::exception& e) {
1044 LogWarning(
"Unable to read policy estimator data (non-fatal): %s", e.what());
1052 const auto startclear{SteadyClock::now()};
1054 size_t num_entries = mapMemPoolTxs.size();
1056 while (!mapMemPoolTxs.empty()) {
1057 auto mi = mapMemPoolTxs.begin();
1060 const auto endclear{SteadyClock::now()};
1061 LogDebug(
BCLog::ESTIMATEFEE,
"Recorded %u unconfirmed txs from mempool in %.3fs\n", num_entries, Ticks<SecondsDouble>(endclear - startclear));
1067 auto now{fs::file_time_type::clock::now()};
1068 return std::chrono::duration_cast<std::chrono::hours>(now - file_time);
1072 double max_filter_fee_rate,
1073 double fee_filter_spacing)
1075 std::set<double> fee_set;
1079 for (
double bucket_boundary = min_fee_limit;
1080 bucket_boundary <= max_filter_fee_rate;
1081 bucket_boundary *= fee_filter_spacing) {
1083 fee_set.insert(bucket_boundary);
1090 : m_fee_set{
MakeFeeSet(minIncrementalFee, MAX_FILTER_FEERATE, FEE_FILTER_SPACING)},
1098 std::set<double>::iterator it =
m_fee_set.lower_bound(currentMinFee);
1104 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.
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.
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.
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.
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.
bool removeTx(uint256 hash) EXCLUSIVE_LOCKS_REQUIRED(!m_cs_fee_estimator)
Remove a transaction from the mempool tracking stats for non BLOCK removal reasons.
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 kilovirtualbyte: CAmount / kvB.
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.
Path class wrapper to block calls to the fs::path(std::string) implicit constructor and the fs::path:...
#define LogDebug(category,...)
MemPoolRemovalReason
Reason why a transaction was removed from the mempool, this is passed to the notification signal.
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)
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.