49 struct EncodedDoubleFormatter
51 template<
typename Stream>
void Ser(Stream &s,
double v)
56 template<
typename Stream>
void Unser(Stream& s,
double& v)
123 TxConfirmStats(
const std::vector<double>& defaultBuckets,
const std::map<double, unsigned int>& defaultBucketMap,
124 unsigned int maxPeriods,
double decay,
unsigned int scale);
135 void Record(
int blocksToConfirm,
double val);
138 unsigned int NewTx(
unsigned int nBlockHeight,
double val);
141 void removeTx(
unsigned int entryHeight,
unsigned int nBestSeenHeight,
142 unsigned int bucketIndex,
bool inBlock);
158 double minSuccess,
unsigned int nBlockHeight,
171 void Read(
AutoFile& filein,
int nFileVersion,
size_t numBuckets);
176 const std::map<double, unsigned int>& defaultBucketMap,
177 unsigned int maxPeriods,
double _decay,
unsigned int _scale)
178 : buckets(defaultBuckets), bucketMap(defaultBucketMap), decay(_decay), scale(_scale)
180 assert(_scale != 0 &&
"_scale must be non-zero");
183 for (
unsigned int i = 0; i < maxPeriods; i++) {
197 for (
unsigned int i = 0; i <
unconfTxs.size(); i++) {
206 for (
unsigned int j = 0; j <
buckets.size(); j++) {
216 if (blocksToConfirm < 1)
218 int periodsToConfirm = (blocksToConfirm +
scale - 1) /
scale;
219 unsigned int bucketindex =
bucketMap.lower_bound(feerate)->second;
220 for (
size_t i = periodsToConfirm; i <=
confAvg.size(); i++) {
230 for (
unsigned int j = 0; j <
buckets.size(); j++) {
231 for (
unsigned int i = 0; i <
confAvg.size(); i++) {
242 double successBreakPoint,
unsigned int nBlockHeight,
250 const int periodTarget = (confTarget +
scale - 1) /
scale;
251 const int maxbucketindex =
buckets.size() - 1;
258 unsigned int curNearBucket = maxbucketindex;
259 unsigned int bestNearBucket = maxbucketindex;
260 unsigned int curFarBucket = maxbucketindex;
261 unsigned int bestFarBucket = maxbucketindex;
266 double partialNum = 0;
268 bool foundAnswer =
false;
270 bool newBucketRange =
true;
276 for (
int bucket = maxbucketindex; bucket >= 0; --bucket) {
277 if (newBucketRange) {
278 curNearBucket = bucket;
279 newBucketRange =
false;
281 curFarBucket = bucket;
282 nConf +=
confAvg[periodTarget - 1][bucket];
285 failNum +=
failAvg[periodTarget - 1][bucket];
286 for (
unsigned int confct = confTarget; confct <
GetMaxConfirms(); confct++)
287 extraNum +=
unconfTxs[(nBlockHeight - confct) % bins][bucket];
294 if (partialNum < sufficientTxVal / (1 -
decay)) {
301 double curPct = nConf / (totalNum + failNum + extraNum);
304 if (curPct < successBreakPoint) {
305 if (passing ==
true) {
307 unsigned int failMinBucket = std::min(curNearBucket, curFarBucket);
308 unsigned int failMaxBucket = std::max(curNearBucket, curFarBucket);
309 failBucket.
start = failMinBucket ?
buckets[failMinBucket - 1] : 0;
333 bestNearBucket = curNearBucket;
334 bestFarBucket = curFarBucket;
335 newBucketRange =
true;
347 unsigned int minBucket = std::min(bestNearBucket, bestFarBucket);
348 unsigned int maxBucket = std::max(bestNearBucket, bestFarBucket);
349 for (
unsigned int j = minBucket; j <= maxBucket; j++) {
352 if (foundAnswer && txSum != 0) {
354 for (
unsigned int j = minBucket; j <= maxBucket; j++) {
363 passBucket.
start = minBucket ?
buckets[minBucket-1] : 0;
368 if (passing && !newBucketRange) {
369 unsigned int failMinBucket = std::min(curNearBucket, curFarBucket);
370 unsigned int failMaxBucket = std::max(curNearBucket, curFarBucket);
371 failBucket.
start = failMinBucket ?
buckets[failMinBucket - 1] : 0;
379 float passed_within_target_perc = 0.0;
380 float failed_within_target_perc = 0.0;
388 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",
389 confTarget, 100.0 * successBreakPoint,
decay,
390 median, passBucket.
start, passBucket.
end,
391 passed_within_target_perc,
394 failed_within_target_perc,
399 result->
pass = passBucket;
400 result->
fail = failBucket;
409 fileout << Using<EncodedDoubleFormatter>(
decay);
411 fileout << Using<VectorFormatter<EncodedDoubleFormatter>>(
m_feerate_avg);
412 fileout << Using<VectorFormatter<EncodedDoubleFormatter>>(
txCtAvg);
413 fileout << Using<VectorFormatter<VectorFormatter<EncodedDoubleFormatter>>>(
confAvg);
414 fileout << Using<VectorFormatter<VectorFormatter<EncodedDoubleFormatter>>>(
failAvg);
422 size_t maxConfirms, maxPeriods;
425 filein >> Using<EncodedDoubleFormatter>(
decay);
426 if (decay <= 0 || decay >= 1) {
427 throw std::runtime_error(
"Corrupt estimates file. Decay must be between 0 and 1 (non-inclusive)");
431 throw std::runtime_error(
"Corrupt estimates file. Scale must be non-zero");
434 filein >> Using<VectorFormatter<EncodedDoubleFormatter>>(
m_feerate_avg);
436 throw std::runtime_error(
"Corrupt estimates file. Mismatch in feerate average bucket count");
438 filein >> Using<VectorFormatter<EncodedDoubleFormatter>>(
txCtAvg);
439 if (
txCtAvg.size() != numBuckets) {
440 throw std::runtime_error(
"Corrupt estimates file. Mismatch in tx count bucket count");
442 filein >> Using<VectorFormatter<VectorFormatter<EncodedDoubleFormatter>>>(
confAvg);
444 maxConfirms =
scale * maxPeriods;
446 if (maxConfirms <= 0 || maxConfirms > 6 * 24 * 7) {
447 throw std::runtime_error(
"Corrupt estimates file. Must maintain estimates for between 1 and 1008 (one week) confirms");
449 for (
unsigned int i = 0; i < maxPeriods; i++) {
450 if (
confAvg[i].size() != numBuckets) {
451 throw std::runtime_error(
"Corrupt estimates file. Mismatch in feerate conf average bucket count");
455 filein >> Using<VectorFormatter<VectorFormatter<EncodedDoubleFormatter>>>(
failAvg);
456 if (maxPeriods !=
failAvg.size()) {
457 throw std::runtime_error(
"Corrupt estimates file. Mismatch in confirms tracked for failures");
459 for (
unsigned int i = 0; i < maxPeriods; i++) {
460 if (
failAvg[i].size() != numBuckets) {
461 throw std::runtime_error(
"Corrupt estimates file. Mismatch in one of failure average bucket counts");
470 numBuckets, maxConfirms);
475 unsigned int bucketindex =
bucketMap.lower_bound(val)->second;
476 unsigned int blockIndex = nBlockHeight %
unconfTxs.size();
484 int blocksAgo = nBestSeenHeight - entryHeight;
485 if (nBestSeenHeight == 0)
492 if (blocksAgo >= (
int)
unconfTxs.size()) {
501 unsigned int blockIndex = entryHeight %
unconfTxs.size();
502 if (
unconfTxs[blockIndex][bucketindex] > 0) {
506 blockIndex, bucketindex);
509 if (!inBlock && (
unsigned int)blocksAgo >=
scale) {
511 unsigned int periodsAgo = blocksAgo /
scale;
512 for (
size_t i = 0; i < periodsAgo && i <
failAvg.size(); i++) {
527 std::map<uint256, TxStatsInfo>::iterator pos = mapMemPoolTxs.find(hash);
528 if (pos != mapMemPoolTxs.end()) {
529 feeStats->removeTx(pos->second.blockHeight, nBestSeenHeight, pos->second.bucketIndex, inBlock);
530 shortStats->removeTx(pos->second.blockHeight, nBestSeenHeight, pos->second.bucketIndex, inBlock);
531 longStats->removeTx(pos->second.blockHeight, nBestSeenHeight, pos->second.bucketIndex, inBlock);
532 mapMemPoolTxs.erase(hash);
540 : m_estimation_filepath{estimation_filepath}
543 size_t bucketIndex = 0;
546 buckets.push_back(bucketBoundary);
547 bucketMap[bucketBoundary] = bucketIndex;
551 assert(bucketMap.size() == buckets.size());
559 if (est_file.IsNull()) {
570 if (!
Read(est_file)) {
596 const auto& hash = tx.
info.
m_tx->GetHash();
597 if (mapMemPoolTxs.count(hash)) {
603 if (txHeight != nBestSeenHeight) {
619 if (!validForFeeEstimation) {
628 mapMemPoolTxs[hash].blockHeight = txHeight;
629 unsigned int bucketIndex = feeStats->NewTx(txHeight,
static_cast<double>(feeRate.
GetFeePerK()));
630 mapMemPoolTxs[hash].bucketIndex = bucketIndex;
631 unsigned int bucketIndex2 = shortStats->NewTx(txHeight,
static_cast<double>(feeRate.
GetFeePerK()));
632 assert(bucketIndex == bucketIndex2);
633 unsigned int bucketIndex3 = longStats->NewTx(txHeight,
static_cast<double>(feeRate.
GetFeePerK()));
634 assert(bucketIndex == bucketIndex3);
649 if (blocksToConfirm <= 0) {
659 feeStats->Record(blocksToConfirm,
static_cast<double>(feeRate.
GetFeePerK()));
660 shortStats->Record(blocksToConfirm,
static_cast<double>(feeRate.
GetFeePerK()));
661 longStats->Record(blocksToConfirm,
static_cast<double>(feeRate.
GetFeePerK()));
666 unsigned int nBlockHeight)
669 if (nBlockHeight <= nBestSeenHeight) {
681 nBestSeenHeight = nBlockHeight;
684 feeStats->ClearCurrent(nBlockHeight);
685 shortStats->ClearCurrent(nBlockHeight);
686 longStats->ClearCurrent(nBlockHeight);
689 feeStats->UpdateMovingAverages();
690 shortStats->UpdateMovingAverages();
691 longStats->UpdateMovingAverages();
693 unsigned int countedTxs = 0;
695 for (
const auto& tx : txs_removed_for_block) {
700 if (firstRecordedHeight == 0 && countedTxs > 0) {
701 firstRecordedHeight = nBestSeenHeight;
706 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",
707 countedTxs, txs_removed_for_block.size(), trackedTxs, trackedTxs + untrackedTxs, mapMemPoolTxs.size(),
729 stats = shortStats.get();
734 stats = feeStats.get();
738 stats = longStats.get();
746 if (confTarget <= 0 || (
unsigned int)confTarget > stats->
GetMaxConfirms())
748 if (successThreshold > 1)
751 double median = stats->
EstimateMedianVal(confTarget, sufficientTxs, successThreshold, nBestSeenHeight, result);
764 return shortStats->GetMaxConfirms();
767 return feeStats->GetMaxConfirms();
770 return longStats->GetMaxConfirms();
778 if (firstRecordedHeight == 0)
return 0;
779 assert(nBestSeenHeight >= firstRecordedHeight);
781 return nBestSeenHeight - firstRecordedHeight;
786 if (historicalFirst == 0)
return 0;
787 assert(historicalBest >= historicalFirst);
791 return historicalBest - historicalFirst;
806 double estimate = -1;
807 if (confTarget >= 1 && confTarget <= longStats->GetMaxConfirms()) {
809 if (confTarget <= shortStats->GetMaxConfirms()) {
810 estimate = shortStats->EstimateMedianVal(confTarget,
SUFFICIENT_TXS_SHORT, successThreshold, nBestSeenHeight, result);
812 else if (confTarget <= feeStats->GetMaxConfirms()) {
813 estimate = feeStats->EstimateMedianVal(confTarget,
SUFFICIENT_FEETXS, successThreshold, nBestSeenHeight, result);
816 estimate = longStats->EstimateMedianVal(confTarget,
SUFFICIENT_FEETXS, successThreshold, nBestSeenHeight, result);
818 if (checkShorterHorizon) {
821 if (confTarget > feeStats->GetMaxConfirms()) {
822 double medMax = feeStats->EstimateMedianVal(feeStats->GetMaxConfirms(),
SUFFICIENT_FEETXS, successThreshold, nBestSeenHeight, &tempResult);
823 if (medMax > 0 && (estimate == -1 || medMax < estimate)) {
825 if (result) *result = tempResult;
828 if (confTarget > shortStats->GetMaxConfirms()) {
829 double shortMax = shortStats->EstimateMedianVal(shortStats->GetMaxConfirms(),
SUFFICIENT_TXS_SHORT, successThreshold, nBestSeenHeight, &tempResult);
830 if (shortMax > 0 && (estimate == -1 || shortMax < estimate)) {
832 if (result) *result = tempResult;
845 double estimate = -1;
847 if (doubleTarget <= shortStats->GetMaxConfirms()) {
850 if (doubleTarget <= feeStats->GetMaxConfirms()) {
852 if (longEstimate > estimate) {
853 estimate = longEstimate;
854 if (result) *result = tempResult;
880 if (confTarget <= 0 || (
unsigned int)confTarget > longStats->GetMaxConfirms()) {
885 if (confTarget == 1) confTarget = 2;
888 if ((
unsigned int)confTarget > maxUsableEstimate) {
889 confTarget = maxUsableEstimate;
893 if (confTarget <= 1)
return CFeeRate(0);
908 feeCalc->
est = tempResult;
913 if (actualEst > median) {
916 feeCalc->
est = tempResult;
921 if (doubleEst > median) {
924 feeCalc->
est = tempResult;
929 if (conservative || median == -1) {
931 if (consEst > median) {
934 feeCalc->
est = tempResult;
953 if (est_file.IsNull() || !
Write(est_file)) {
966 fileout << nBestSeenHeight;
968 fileout << firstRecordedHeight << nBestSeenHeight;
971 fileout << historicalFirst << historicalBest;
973 fileout << Using<VectorFormatter<EncodedDoubleFormatter>>(buckets);
974 feeStats->Write(fileout);
975 shortStats->Write(fileout);
976 longStats->Write(fileout);
978 catch (
const std::exception&) {
979 LogPrintf(
"CBlockPolicyEstimator::Write(): unable to write policy estimator data (non-fatal)\n");
989 int nVersionRequired, nVersionThatWrote;
990 filein >> nVersionRequired >> nVersionThatWrote;
992 throw std::runtime_error(
strprintf(
"up-version (%d) fee estimate file", nVersionRequired));
997 unsigned int nFileBestSeenHeight;
998 filein >> nFileBestSeenHeight;
1000 if (nVersionRequired < 149900) {
1001 LogPrintf(
"%s: incompatible old fee estimation data (non-fatal). Version: %d\n", __func__, nVersionRequired);
1003 unsigned int nFileHistoricalFirst, nFileHistoricalBest;
1004 filein >> nFileHistoricalFirst >> nFileHistoricalBest;
1005 if (nFileHistoricalFirst > nFileHistoricalBest || nFileHistoricalBest > nFileBestSeenHeight) {
1006 throw std::runtime_error(
"Corrupt estimates file. Historical block range for estimates is invalid");
1008 std::vector<double> fileBuckets;
1009 filein >> Using<VectorFormatter<EncodedDoubleFormatter>>(fileBuckets);
1010 size_t numBuckets = fileBuckets.size();
1011 if (numBuckets <= 1 || numBuckets > 1000) {
1012 throw std::runtime_error(
"Corrupt estimates file. Must have between 2 and 1000 feerate buckets");
1018 fileFeeStats->Read(filein, nVersionThatWrote, numBuckets);
1019 fileShortStats->Read(filein, nVersionThatWrote, numBuckets);
1020 fileLongStats->Read(filein, nVersionThatWrote, numBuckets);
1024 buckets = fileBuckets;
1026 for (
unsigned int i = 0; i < buckets.size(); i++) {
1027 bucketMap[buckets[i]] = i;
1031 feeStats = std::move(fileFeeStats);
1032 shortStats = std::move(fileShortStats);
1033 longStats = std::move(fileLongStats);
1035 nBestSeenHeight = nFileBestSeenHeight;
1036 historicalFirst = nFileHistoricalFirst;
1037 historicalBest = nFileHistoricalBest;
1040 catch (
const std::exception& e) {
1041 LogPrintf(
"CBlockPolicyEstimator::Read(): unable to read policy estimator data (non-fatal): %s\n",e.what());
1049 const auto startclear{SteadyClock::now()};
1051 size_t num_entries = mapMemPoolTxs.size();
1053 while (!mapMemPoolTxs.empty()) {
1054 auto mi = mapMemPoolTxs.begin();
1057 const auto endclear{SteadyClock::now()};
1058 LogPrint(
BCLog::ESTIMATEFEE,
"Recorded %u unconfirmed txs from mempool in %.3fs\n", num_entries, Ticks<SecondsDouble>(endclear - startclear));
1064 auto now{fs::file_time_type::clock::now()};
1065 return std::chrono::duration_cast<std::chrono::hours>(now - file_time);
1069 double max_filter_fee_rate,
1070 double fee_filter_spacing)
1072 std::set<double> fee_set;
1076 for (
double bucket_boundary = min_fee_limit;
1077 bucket_boundary <= max_filter_fee_rate;
1078 bucket_boundary *= fee_filter_spacing) {
1080 fee_set.insert(bucket_boundary);
1087 : m_fee_set{
MakeFeeSet(minIncrementalFee, MAX_FILTER_FEERATE, FEE_FILTER_SPACING)},
1095 std::set<double>::iterator it =
m_fee_set.lower_bound(currentMinFee);
1101 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.
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.
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,...)
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)
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.