16 unsigned int maxConfirms,
double _decay, std::string _dataTypeString)
20 for (
unsigned int i = 0; i < defaultBuckets.size(); i++) {
21 buckets.push_back(defaultBuckets[i]);
27 for (
unsigned int i = 0; i < maxConfirms; i++) {
43 for (
unsigned int j = 0; j <
buckets.size(); j++) {
57 if (blocksToConfirm < 1)
59 unsigned int bucketindex =
bucketMap.lower_bound(val)->second;
60 for (
size_t i = blocksToConfirm; i <=
curBlockConf.size(); i++) {
69 for (
unsigned int j = 0; j <
buckets.size(); j++) {
70 for (
unsigned int i = 0; i <
confAvg.size(); i++)
79 double successBreakPoint,
bool requireGreater,
80 unsigned int nBlockHeight)
87 int maxbucketindex =
buckets.size() - 1;
93 unsigned int startbucket = requireGreater ? maxbucketindex : 0;
94 int step = requireGreater ? -1 : 1;
101 unsigned int curNearBucket = startbucket;
102 unsigned int bestNearBucket = startbucket;
103 unsigned int curFarBucket = startbucket;
104 unsigned int bestFarBucket = startbucket;
106 bool foundAnswer =
false;
110 for (
int bucket = startbucket; bucket >= 0 && bucket <= maxbucketindex; bucket += step) {
111 curFarBucket = bucket;
112 nConf +=
confAvg[confTarget - 1][bucket];
114 for (
unsigned int confct = confTarget; confct <
GetMaxConfirms(); confct++)
115 extraNum +=
unconfTxs[(nBlockHeight - confct)%bins][bucket];
121 if (totalNum >= sufficientTxVal / (1 -
decay)) {
122 double curPct = nConf / (totalNum + extraNum);
125 if (requireGreater && curPct < successBreakPoint)
127 if (!requireGreater && curPct > successBreakPoint)
137 bestNearBucket = curNearBucket;
138 bestFarBucket = curFarBucket;
139 curNearBucket = bucket + step;
151 unsigned int minBucket = bestNearBucket < bestFarBucket ? bestNearBucket : bestFarBucket;
152 unsigned int maxBucket = bestNearBucket > bestFarBucket ? bestNearBucket : bestFarBucket;
153 for (
unsigned int j = minBucket; j <= maxBucket; j++) {
156 if (foundAnswer && txSum != 0) {
158 for (
unsigned int j = minBucket; j <= maxBucket; j++) {
168 LogPrint(
"estimatefee",
"%3d: For conf success %s %4.2f need %s %s: %12.5g from buckets %8g - %8g Cur Bucket stats %6.2f%% %8.1f/(%.1f+%d mempool)\n",
169 confTarget, requireGreater ?
">" :
"<", successBreakPoint,
dataTypeString,
170 requireGreater ?
">" :
"<", median,
buckets[minBucket],
buckets[maxBucket],
171 100 * nConf / (totalNum + extraNum), nConf, totalNum, extraNum);
188 std::vector<double> fileBuckets;
189 std::vector<double> fileAvg;
190 std::vector<std::vector<double> > fileConfAvg;
191 std::vector<double> fileTxCtAvg;
197 if (fileDecay <= 0 || fileDecay >= 1)
198 throw std::runtime_error(
"Corrupt estimates file. Decay must be between 0 and 1 (non-inclusive)");
199 filein >> fileBuckets;
200 numBuckets = fileBuckets.size();
201 if (numBuckets <= 1 || numBuckets > 1000)
202 throw std::runtime_error(
"Corrupt estimates file. Must have between 2 and 1000 fee/pri buckets");
204 if (fileAvg.size() != numBuckets)
205 throw std::runtime_error(
"Corrupt estimates file. Mismatch in fee/pri average bucket count");
206 filein >> fileTxCtAvg;
207 if (fileTxCtAvg.size() != numBuckets)
208 throw std::runtime_error(
"Corrupt estimates file. Mismatch in tx count bucket count");
209 filein >> fileConfAvg;
210 maxConfirms = fileConfAvg.size();
211 if (maxConfirms <= 0 || maxConfirms > 6 * 24 * 7)
212 throw std::runtime_error(
"Corrupt estimates file. Must maintain estimates for between 1 and 1008 (one week) confirms");
213 for (
unsigned int i = 0; i < maxConfirms; i++) {
214 if (fileConfAvg[i].size() != numBuckets)
215 throw std::runtime_error(
"Corrupt estimates file. Mismatch in fee/pri conf average bucket count");
229 for (
unsigned int i = 0; i < maxConfirms; i++) {
236 for (
unsigned int i = 0; i < maxConfirms; i++) {
241 for (
unsigned int i = 0; i <
buckets.size(); i++)
244 LogPrint(
"estimatefee",
"Reading estimates: %u %s buckets counting confirms up to %u blocks\n",
250 unsigned int bucketindex =
bucketMap.lower_bound(val)->second;
251 unsigned int blockIndex = nBlockHeight %
unconfTxs.size();
260 int blocksAgo = nBestSeenHeight - entryHeight;
261 if (nBestSeenHeight == 0)
264 LogPrint(
"estimatefee",
"Blockpolicy error, blocks ago is negative for mempool tx\n");
268 if (blocksAgo >= (
int)
unconfTxs.size()) {
272 LogPrint(
"estimatefee",
"Blockpolicy error, mempool tx removed from >25 blocks,bucketIndex=%u already\n",
276 unsigned int blockIndex = entryHeight %
unconfTxs.size();
277 if (
unconfTxs[blockIndex][bucketindex] > 0)
280 LogPrint(
"estimatefee",
"Blockpolicy error, mempool tx removed from blockIndex=%u,bucketIndex=%u already\n",
281 blockIndex, bucketindex);
287 std::map<uint256, TxStatsInfo>::iterator pos =
mapMemPoolTxs.find(hash);
289 LogPrint(
"estimatefee",
"Blockpolicy error mempool tx %s not found for removeTx\n", hash.
ToString());
293 unsigned int entryHeight = pos->second.blockHeight;
294 unsigned int bucketIndex = pos->second.bucketIndex;
305 std::vector<double> vfeelist;
307 vfeelist.push_back(bucketBoundary);
313 std::vector<double> vprilist;
315 vprilist.push_back(bucketBoundary);
329 (pri < priUnlikely && fee >
feeLikely)) {
338 (fee < feeUnlikely && pri >
priLikely)) {
346 unsigned int txHeight = entry.
GetHeight();
349 LogPrint(
"estimatefee",
"Blockpolicy error mempool tx %s already being tracked\n", hash.
ToString());
361 if (!fCurrentEstimate)
380 LogPrint(
"estimatefee",
"Blockpolicy mempool tx %s ", hash.
ToString().substr(0,10));
392 LogPrint(
"estimatefee",
"not adding");
409 int blocksToConfirm = nBlockHeight - entry.
GetHeight();
410 if (blocksToConfirm <= 0) {
413 LogPrint(
"estimatefee",
"Blockpolicy error Transaction had negative blocksToConfirm\n");
435 std::vector<CTxMemPoolEntry>& entries,
bool fCurrentEstimate)
449 if (!fCurrentEstimate)
455 LogPrint(
"estimatefee",
"Blockpolicy recalculating dynamic cutoffs:\n");
461 if (feeLikelyEst == -1)
471 if (feeUnlikelyEst == -1)
481 for (
unsigned int i = 0; i < entries.size(); i++)
488 LogPrint(
"estimatefee",
"Blockpolicy after updating estimates for %u confirmed entries, new mempool map size %u\n",
508 if (answerFoundAtTarget)
509 *answerFoundAtTarget = confTarget;
519 if (answerFoundAtTarget)
520 *answerFoundAtTarget = confTarget - 1;
524 if (minPoolFee > 0 && minPoolFee > median)
544 if (answerFoundAtTarget)
545 *answerFoundAtTarget = confTarget;
560 if (answerFoundAtTarget)
561 *answerFoundAtTarget = confTarget - 1;
575 int nFileBestSeenHeight;
576 filein >> nFileBestSeenHeight;
static const double PRI_SPACING
std::vector< double > txCtAvg
double estimateSmartPriority(int confTarget, int *answerFoundAtTarget, const CTxMemPool &pool)
void processTransaction(const CTxMemPoolEntry &entry, bool fCurrentEstimate)
std::vector< std::vector< int > > unconfTxs
double EstimateMedianVal(int confTarget, double sufficientTxVal, double minSuccess, bool requireGreater, unsigned int nBlockHeight)
std::vector< int > curBlockTxCt
double minTrackedPriority
Passed to constructor to avoid dependency on main.
CBlockPolicyEstimator(const CFeeRate &minRelayFee)
unsigned int GetHeight() const
std::string dataTypeString
static const unsigned int DEFAULT_MAX_MEMPOOL_SIZE
double AllowFreeThreshold()
void Record(int blocksToConfirm, double val)
void Read(CAutoFile &filein)
static const double UNLIKELY_PCT
void ClearCurrent(unsigned int nBlockHeight)
static const double MIN_FEERATE
void UpdateMovingAverages()
static const double INF_FEERATE
static const double SUFFICIENT_PRITXS
CFeeRate estimateFee(int confTarget)
const CAmount & GetFee() const
static const double MAX_PRIORITY
std::map< double, unsigned int > bucketMap
void processBlockTx(unsigned int nBlockHeight, const CTxMemPoolEntry &entry)
CFeeRate estimateSmartFee(int confTarget, int *answerFoundAtTarget, const CTxMemPool &pool)
static int LogPrint(const char *category, const char *format)
const CTransaction & GetTx() const
CAmount GetFeePerK() const
unsigned int GetMaxConfirms()
unsigned int NewTx(unsigned int nBlockHeight, double val)
std::string ToString() const
std::vector< double > avg
void Initialize(std::vector< double > &defaultBuckets, unsigned int maxConfirms, double decay, std::string dataTypeString)
std::vector< double > curBlockVal
void removeTx(unsigned int entryHeight, unsigned int nBestSeenHeight, unsigned int bucketIndex)
static const double SUFFICIENT_FEETXS
static const double DEFAULT_DECAY
static const double MIN_SUCCESS_PCT
const uint256 & GetHash() const
void removeTx(uint256 hash)
static const double INF_PRIORITY
bool isFeeDataPoint(const CFeeRate &fee, double pri)
static const double MIN_PRIORITY
bool isPriDataPoint(const CFeeRate &fee, double pri)
static const double MAX_FEERATE
unsigned int nBestSeenHeight
Set to AllowFreeThreshold.
void Read(CAutoFile &filein)
CFeeRate GetMinFee(size_t sizelimit) const
void processBlock(unsigned int nBlockHeight, std::vector< CTxMemPoolEntry > &entries, bool fCurrentEstimate)
void Write(CAutoFile &fileout)
std::vector< int > oldUnconfTxs
double GetPriority(unsigned int currentHeight) const
std::string GetArg(const std::string &strArg, const std::string &strDefault)
bool WasClearAtEntry() const
std::vector< std::vector< double > > confAvg
std::vector< std::vector< int > > curBlockConf
std::map< uint256, TxStatsInfo > mapMemPoolTxs
void Write(CAutoFile &fileout)
static const unsigned int MAX_BLOCK_CONFIRMS
std::vector< double > buckets
double estimatePriority(int confTarget)
static const double FEE_SPACING