diff options
author | Alex Morcos <morcos@chaincode.com> | 2017-04-25 15:39:32 -0400 |
---|---|---|
committer | Alex Morcos <morcos@chaincode.com> | 2017-06-13 12:35:04 -0400 |
commit | 1bebfc8d3aa615dfdd0221f21b87319e36821b71 (patch) | |
tree | 092a7224efb48fac182bc26aa2aef39844884c01 /src/policy/fees.cpp | |
parent | 9c248e39f2807a7f89e555e99cc55cb2de1ad335 (diff) |
Output Fee Estimation Calculations in CreateTransaction
Diffstat (limited to 'src/policy/fees.cpp')
-rw-r--r-- | src/policy/fees.cpp | 90 |
1 files changed, 68 insertions, 22 deletions
diff --git a/src/policy/fees.cpp b/src/policy/fees.cpp index 7a9af5edc2..58a2f6da73 100644 --- a/src/policy/fees.cpp +++ b/src/policy/fees.cpp @@ -16,6 +16,26 @@ static constexpr double INF_FEERATE = 1e99; +std::string StringForFeeReason(FeeReason reason) { + static const std::map<FeeReason, std::string> fee_reason_strings = { + {FeeReason::NONE, "None"}, + {FeeReason::HALF_ESTIMATE, "Half Target 60% Threshold"}, + {FeeReason::FULL_ESTIMATE, "Target 85% Threshold"}, + {FeeReason::DOUBLE_ESTIMATE, "Double Target 95% Threshold"}, + {FeeReason::CONSERVATIVE, "Conservative Double Target longer horizon"}, + {FeeReason::MEMPOOL_MIN, "Mempool Min Fee"}, + {FeeReason::PAYTXFEE, "PayTxFee set"}, + {FeeReason::FALLBACK, "Fallback fee"}, + {FeeReason::REQUIRED, "Minimum Required Fee"}, + {FeeReason::MAXTXFEE, "MaxTxFee limit"} + }; + auto reason_string = fee_reason_strings.find(reason); + + if (reason_string == fee_reason_strings.end()) return "Unknown"; + + return reason_string->second; +} + /** * We will instantiate an instance of this class to track transactions that were * included in a block. We will lump transactions into a bucket according to their @@ -698,31 +718,36 @@ unsigned int CBlockPolicyEstimator::MaxUsableEstimate() const * time horizon which tracks confirmations up to the desired target. If * checkShorterHorizon is requested, also allow short time horizon estimates * for a lower target to reduce the given answer */ -double CBlockPolicyEstimator::estimateCombinedFee(unsigned int confTarget, double successThreshold, bool checkShorterHorizon) const +double CBlockPolicyEstimator::estimateCombinedFee(unsigned int confTarget, double successThreshold, bool checkShorterHorizon, EstimationResult *result) const { double estimate = -1; if (confTarget >= 1 && confTarget <= longStats->GetMaxConfirms()) { // Find estimate from shortest time horizon possible if (confTarget <= shortStats->GetMaxConfirms()) { // short horizon - estimate = shortStats->EstimateMedianVal(confTarget, SUFFICIENT_TXS_SHORT, successThreshold, true, nBestSeenHeight); + estimate = shortStats->EstimateMedianVal(confTarget, SUFFICIENT_TXS_SHORT, successThreshold, true, nBestSeenHeight, result); } else if (confTarget <= feeStats->GetMaxConfirms()) { // medium horizon - estimate = feeStats->EstimateMedianVal(confTarget, SUFFICIENT_FEETXS, successThreshold, true, nBestSeenHeight); + estimate = feeStats->EstimateMedianVal(confTarget, SUFFICIENT_FEETXS, successThreshold, true, nBestSeenHeight, result); } else { // long horizon - estimate = longStats->EstimateMedianVal(confTarget, SUFFICIENT_FEETXS, successThreshold, true, nBestSeenHeight); + estimate = longStats->EstimateMedianVal(confTarget, SUFFICIENT_FEETXS, successThreshold, true, nBestSeenHeight, result); } if (checkShorterHorizon) { + EstimationResult tempResult; // If a lower confTarget from a more recent horizon returns a lower answer use it. if (confTarget > feeStats->GetMaxConfirms()) { - double medMax = feeStats->EstimateMedianVal(feeStats->GetMaxConfirms(), SUFFICIENT_FEETXS, successThreshold, true, nBestSeenHeight); - if (medMax > 0 && (estimate == -1 || medMax < estimate)) + double medMax = feeStats->EstimateMedianVal(feeStats->GetMaxConfirms(), SUFFICIENT_FEETXS, successThreshold, true, nBestSeenHeight, &tempResult); + if (medMax > 0 && (estimate == -1 || medMax < estimate)) { estimate = medMax; + if (result) *result = tempResult; + } } if (confTarget > shortStats->GetMaxConfirms()) { - double shortMax = shortStats->EstimateMedianVal(shortStats->GetMaxConfirms(), SUFFICIENT_TXS_SHORT, successThreshold, true, nBestSeenHeight); - if (shortMax > 0 && (estimate == -1 || shortMax < estimate)) + double shortMax = shortStats->EstimateMedianVal(shortStats->GetMaxConfirms(), SUFFICIENT_TXS_SHORT, successThreshold, true, nBestSeenHeight, &tempResult); + if (shortMax > 0 && (estimate == -1 || shortMax < estimate)) { estimate = shortMax; + if (result) *result = tempResult; + } } } } @@ -732,16 +757,18 @@ double CBlockPolicyEstimator::estimateCombinedFee(unsigned int confTarget, doubl /** Ensure that for a conservative estimate, the DOUBLE_SUCCESS_PCT is also met * at 2 * target for any longer time horizons. */ -double CBlockPolicyEstimator::estimateConservativeFee(unsigned int doubleTarget) const +double CBlockPolicyEstimator::estimateConservativeFee(unsigned int doubleTarget, EstimationResult *result) const { double estimate = -1; + EstimationResult tempResult; if (doubleTarget <= shortStats->GetMaxConfirms()) { - estimate = feeStats->EstimateMedianVal(doubleTarget, SUFFICIENT_FEETXS, DOUBLE_SUCCESS_PCT, true, nBestSeenHeight); + estimate = feeStats->EstimateMedianVal(doubleTarget, SUFFICIENT_FEETXS, DOUBLE_SUCCESS_PCT, true, nBestSeenHeight, result); } if (doubleTarget <= feeStats->GetMaxConfirms()) { - double longEstimate = longStats->EstimateMedianVal(doubleTarget, SUFFICIENT_FEETXS, DOUBLE_SUCCESS_PCT, true, nBestSeenHeight); + double longEstimate = longStats->EstimateMedianVal(doubleTarget, SUFFICIENT_FEETXS, DOUBLE_SUCCESS_PCT, true, nBestSeenHeight, &tempResult); if (longEstimate > estimate) { estimate = longEstimate; + if (result) *result = tempResult; } } return estimate; @@ -754,12 +781,15 @@ double CBlockPolicyEstimator::estimateConservativeFee(unsigned int doubleTarget) * estimates, however, required the 95% threshold at 2 * target be met for any * longer time horizons also. */ -CFeeRate CBlockPolicyEstimator::estimateSmartFee(int confTarget, int *answerFoundAtTarget, const CTxMemPool& pool, bool conservative) const +CFeeRate CBlockPolicyEstimator::estimateSmartFee(int confTarget, FeeCalculation *feeCalc, const CTxMemPool& pool, bool conservative) const { - if (answerFoundAtTarget) - *answerFoundAtTarget = confTarget; + if (feeCalc) { + feeCalc->desiredTarget = confTarget; + feeCalc->returnedTarget = confTarget; + } double median = -1; + EstimationResult tempResult; { LOCK(cs_feeEstimator); @@ -780,7 +810,6 @@ CFeeRate CBlockPolicyEstimator::estimateSmartFee(int confTarget, int *answerFoun } assert(confTarget > 0); //estimateCombinedFee and estimateConservativeFee take unsigned ints - /** true is passed to estimateCombined fee for target/2 and target so * that we check the max confirms for shorter time horizons as well. * This is necessary to preserve monotonically increasing estimates. @@ -791,32 +820,49 @@ CFeeRate CBlockPolicyEstimator::estimateSmartFee(int confTarget, int *answerFoun * the purpose of conservative estimates is not to let short term * fluctuations lower our estimates by too much. */ - double halfEst = estimateCombinedFee(confTarget/2, HALF_SUCCESS_PCT, true); - double actualEst = estimateCombinedFee(confTarget, SUCCESS_PCT, true); - double doubleEst = estimateCombinedFee(2 * confTarget, DOUBLE_SUCCESS_PCT, !conservative); + double halfEst = estimateCombinedFee(confTarget/2, HALF_SUCCESS_PCT, true, &tempResult); + if (feeCalc) { + feeCalc->est = tempResult; + feeCalc->reason = FeeReason::HALF_ESTIMATE; + } median = halfEst; + double actualEst = estimateCombinedFee(confTarget, SUCCESS_PCT, true, &tempResult); if (actualEst > median) { median = actualEst; + if (feeCalc) { + feeCalc->est = tempResult; + feeCalc->reason = FeeReason::FULL_ESTIMATE; + } } + double doubleEst = estimateCombinedFee(2 * confTarget, DOUBLE_SUCCESS_PCT, !conservative, &tempResult); if (doubleEst > median) { median = doubleEst; + if (feeCalc) { + feeCalc->est = tempResult; + feeCalc->reason = FeeReason::DOUBLE_ESTIMATE; + } } if (conservative || median == -1) { - double consEst = estimateConservativeFee(2 * confTarget); + double consEst = estimateConservativeFee(2 * confTarget, &tempResult); if (consEst > median) { median = consEst; + if (feeCalc) { + feeCalc->est = tempResult; + feeCalc->reason = FeeReason::CONSERVATIVE; + } } } } // Must unlock cs_feeEstimator before taking mempool locks - if (answerFoundAtTarget) - *answerFoundAtTarget = confTarget; + if (feeCalc) feeCalc->returnedTarget = confTarget; // If mempool is limiting txs , return at least the min feerate from the mempool CAmount minPoolFee = pool.GetMinFee(GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000).GetFeePerK(); - if (minPoolFee > 0 && minPoolFee > median) + if (minPoolFee > 0 && minPoolFee > median) { + if (feeCalc) feeCalc->reason = FeeReason::MEMPOOL_MIN; return CFeeRate(minPoolFee); + } if (median < 0) return CFeeRate(0); |