15 unsigned int maxConfirms,
double _decay)
18 for (
unsigned int i = 0; i < defaultBuckets.size(); i++) {
19 buckets.push_back(defaultBuckets[i]);
25 for (
unsigned int i = 0; i < maxConfirms; i++) {
41 for (
unsigned int j = 0; j <
buckets.size(); j++) {
55 if (blocksToConfirm < 1)
57 unsigned int bucketindex =
bucketMap.lower_bound(val)->second;
58 for (
size_t i = blocksToConfirm; i <=
curBlockConf.size(); i++) {
67 for (
unsigned int j = 0; j <
buckets.size(); j++) {
68 for (
unsigned int i = 0; i <
confAvg.size(); i++)
77 double successBreakPoint,
bool requireGreater,
78 unsigned int nBlockHeight)
85 int maxbucketindex =
buckets.size() - 1;
91 unsigned int startbucket = requireGreater ? maxbucketindex : 0;
92 int step = requireGreater ? -1 : 1;
99 unsigned int curNearBucket = startbucket;
100 unsigned int bestNearBucket = startbucket;
101 unsigned int curFarBucket = startbucket;
102 unsigned int bestFarBucket = startbucket;
104 bool foundAnswer =
false;
108 for (
int bucket = startbucket; bucket >= 0 && bucket <= maxbucketindex; bucket += step) {
109 curFarBucket = bucket;
110 nConf +=
confAvg[confTarget - 1][bucket];
112 for (
unsigned int confct = confTarget; confct <
GetMaxConfirms(); confct++)
113 extraNum +=
unconfTxs[(nBlockHeight - confct)%bins][bucket];
119 if (totalNum >= sufficientTxVal / (1 -
decay)) {
120 double curPct = nConf / (totalNum + extraNum);
123 if (requireGreater && curPct < successBreakPoint)
125 if (!requireGreater && curPct > successBreakPoint)
135 bestNearBucket = curNearBucket;
136 bestFarBucket = curFarBucket;
137 curNearBucket = bucket + step;
149 unsigned int minBucket = bestNearBucket < bestFarBucket ? bestNearBucket : bestFarBucket;
150 unsigned int maxBucket = bestNearBucket > bestFarBucket ? bestNearBucket : bestFarBucket;
151 for (
unsigned int j = minBucket; j <= maxBucket; j++) {
154 if (foundAnswer && txSum != 0) {
156 for (
unsigned int j = minBucket; j <= maxBucket; j++) {
166 LogPrint(
BCLog::ESTIMATEFEE,
"%3d: For conf success %s %4.2f need feerate %s: %12.5g from buckets %8g - %8g Cur Bucket stats %6.2f%% %8.1f/(%.1f+%d mempool)\n",
167 confTarget, requireGreater ?
">" :
"<", successBreakPoint,
168 requireGreater ?
">" :
"<", median,
buckets[minBucket],
buckets[maxBucket],
169 100 * nConf / (totalNum + extraNum), nConf, totalNum, extraNum);
186 std::vector<double> fileBuckets;
187 std::vector<double> fileAvg;
188 std::vector<std::vector<double> > fileConfAvg;
189 std::vector<double> fileTxCtAvg;
195 if (fileDecay <= 0 || fileDecay >= 1)
196 throw std::runtime_error(
"Corrupt estimates file. Decay must be between 0 and 1 (non-inclusive)");
197 filein >> fileBuckets;
198 numBuckets = fileBuckets.size();
199 if (numBuckets <= 1 || numBuckets > 1000)
200 throw std::runtime_error(
"Corrupt estimates file. Must have between 2 and 1000 feerate buckets");
202 if (fileAvg.size() != numBuckets)
203 throw std::runtime_error(
"Corrupt estimates file. Mismatch in feerate average bucket count");
204 filein >> fileTxCtAvg;
205 if (fileTxCtAvg.size() != numBuckets)
206 throw std::runtime_error(
"Corrupt estimates file. Mismatch in tx count bucket count");
207 filein >> fileConfAvg;
208 maxConfirms = fileConfAvg.size();
209 if (maxConfirms <= 0 || maxConfirms > 6 * 24 * 7)
210 throw std::runtime_error(
"Corrupt estimates file. Must maintain estimates for between 1 and 1008 (one week) confirms");
211 for (
unsigned int i = 0; i < maxConfirms; i++) {
212 if (fileConfAvg[i].size() != numBuckets)
213 throw std::runtime_error(
"Corrupt estimates file. Mismatch in feerate conf average bucket count");
227 for (
unsigned int i = 0; i < maxConfirms; i++) {
234 for (
unsigned int i = 0; i < maxConfirms; i++) {
239 for (
unsigned int i = 0; i <
buckets.size(); i++)
243 numBuckets, maxConfirms);
248 unsigned int bucketindex =
bucketMap.lower_bound(val)->second;
249 unsigned int blockIndex = nBlockHeight %
unconfTxs.size();
257 int blocksAgo = nBestSeenHeight - entryHeight;
258 if (nBestSeenHeight == 0)
265 if (blocksAgo >= (
int)
unconfTxs.size()) {
273 unsigned int blockIndex = entryHeight %
unconfTxs.size();
274 if (
unconfTxs[blockIndex][bucketindex] > 0)
278 blockIndex, bucketindex);
289 std::map<uint256, TxStatsInfo>::iterator pos =
mapMemPoolTxs.find(hash);
299 : nBestSeenHeight(0), trackedTxs(0), untrackedTxs(0)
301 static_assert(MIN_FEERATE > 0,
"Min feerate must be nonzero");
303 std::vector<double> vfeelist;
304 for (
double bucketBoundary =
minTrackedFee.
GetFeePerK(); bucketBoundary <= MAX_FEERATE; bucketBoundary *= FEE_SPACING) {
305 vfeelist.push_back(bucketBoundary);
307 vfeelist.push_back(INF_FEERATE);
318 unsigned int txHeight = entry.
GetHeight();
336 if (!validFeeEstimate) {
364 int blocksToConfirm = nBlockHeight - entry->
GetHeight();
365 if (blocksToConfirm <= 0) {
380 std::vector<const CTxMemPoolEntry*>& entries)
399 unsigned int countedTxs = 0;
401 for (
unsigned int i = 0; i < entries.size(); i++) {
409 LogPrint(
BCLog::ESTIMATEFEE,
"Blockpolicy after updating estimates for %u of %u txs in block, since last block %u of %u tracked, new mempool map size %u\n",
432 if (answerFoundAtTarget)
433 *answerFoundAtTarget = confTarget;
443 if (answerFoundAtTarget)
444 *answerFoundAtTarget = confTarget - 1;
448 if (minPoolFee > 0 && minPoolFee > median)
465 int nFileBestSeenHeight;
466 filein >> nFileBestSeenHeight;
469 if (nFileVersion < 4029900) {
471 priStats.
Read(filein);
int64_t CAmount
Amount in PIV (Can be negative)
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
Non-refcounted RAII wrapper for FILE*.
unsigned int untrackedTxs
unsigned int nBestSeenHeight
Passed to constructor to avoid dependency on main.
TxConfirmStats feeStats
Classes to track historical data on transaction confirmations.
bool removeTx(const uint256 &hash)
Remove a transaction from the mempool tracking stats.
void Write(CAutoFile &fileout)
Write estimation data to a file.
CFeeRate estimateFee(int confTarget)
Return a feerate estimate.
CBlockPolicyEstimator(const CFeeRate &minRelayFee)
Create new BlockPolicyEstimator and initialize stats tracking classes with default values.
void Read(CAutoFile &filein, int nFileVersion)
Read estimation data from a file.
CFeeRate estimateSmartFee(int confTarget, int *answerFoundAtTarget, const CTxMemPool &pool)
Estimate feerate needed to get be included in a block within confTarget blocks.
bool processBlockTx(unsigned int nBlockHeight, const CTxMemPoolEntry *entry)
Process a transaction confirmed in a block.
std::map< uint256, TxStatsInfo > mapMemPoolTxs
void processTransaction(const CTxMemPoolEntry &entry, bool validFeeEstimate)
Process a transaction accepted to the mempool.
void processBlock(unsigned int nBlockHeight, std::vector< const CTxMemPoolEntry * > &entries)
Process all the transactions that have been included in a block.
Fee rate in PIV per kilobyte: CAmount / kB.
CAmount GetFeePerK() const
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
bool HasZerocoins() const
const CAmount & GetFee() const
CTxMemPool stores valid-according-to-the-current-best-chain transactions that may be included in the ...
CFeeRate GetMinFee(size_t sizelimit) const
The minimum fee to get into the mempool, which may itself not be enough for larger-sized transactions...
We will instantiate an instance of this class to track transactions that were included in a block.
std::vector< double > buckets
std::vector< double > curBlockVal
std::map< double, unsigned int > bucketMap
void Read(CAutoFile &filein)
Read saved state of estimation data from a file and replace all internal data structures and variable...
void ClearCurrent(unsigned int nBlockHeight)
Clear the state of the curBlock variables to start counting for the new block.
void removeTx(unsigned int entryHeight, unsigned int nBestSeenHeight, unsigned int bucketIndex)
Remove a transaction from mempool tracking stats.
void Write(CAutoFile &fileout)
Write state of estimation data to a file.
void Record(int blocksToConfirm, double val)
Record a new transaction data point in the current block stats.
std::vector< double > txCtAvg
double EstimateMedianVal(int confTarget, double sufficientTxVal, double minSuccess, bool requireGreater, unsigned int nBlockHeight)
Calculate a feerate estimate.
std::vector< int > oldUnconfTxs
std::vector< int > curBlockTxCt
std::vector< std::vector< int > > curBlockConf
void UpdateMovingAverages()
Update our estimates by decaying our historical moving average and updating with the data gathered fr...
void Initialize(std::vector< double > &defaultBuckets, unsigned int maxConfirms, double decay)
Initialize the data structures.
std::vector< double > avg
std::vector< std::vector< double > > confAvg
unsigned int GetMaxConfirms()
Return the max number of confirms we're tracking.
std::vector< std::vector< int > > unconfTxs
unsigned int NewTx(unsigned int nBlockHeight, double val)
Record a new transaction entering the mempool.
std::string ToString() const
#define LogPrint(category,...)