16
16
17
17
static constexpr double INF_FEERATE = 1e99 ;
18
18
19
+ std::string StringForFeeReason (FeeReason reason) {
20
+ static const std::map<FeeReason, std::string> fee_reason_strings = {
21
+ {FeeReason::NONE, " None" },
22
+ {FeeReason::HALF_ESTIMATE, " Half Target 60% Threshold" },
23
+ {FeeReason::FULL_ESTIMATE, " Target 85% Threshold" },
24
+ {FeeReason::DOUBLE_ESTIMATE, " Double Target 95% Threshold" },
25
+ {FeeReason::CONSERVATIVE, " Conservative Double Target longer horizon" },
26
+ {FeeReason::MEMPOOL_MIN, " Mempool Min Fee" },
27
+ {FeeReason::PAYTXFEE, " PayTxFee set" },
28
+ {FeeReason::FALLBACK, " Fallback fee" },
29
+ {FeeReason::REQUIRED, " Minimum Required Fee" },
30
+ {FeeReason::MAXTXFEE, " MaxTxFee limit" }
31
+ };
32
+ auto reason_string = fee_reason_strings.find (reason);
33
+
34
+ if (reason_string == fee_reason_strings.end ()) return " Unknown" ;
35
+
36
+ return reason_string->second ;
37
+ }
38
+
19
39
/* *
20
40
* We will instantiate an instance of this class to track transactions that were
21
41
* included in a block. We will lump transactions into a bucket according to their
@@ -698,31 +718,36 @@ unsigned int CBlockPolicyEstimator::MaxUsableEstimate() const
698
718
* time horizon which tracks confirmations up to the desired target. If
699
719
* checkShorterHorizon is requested, also allow short time horizon estimates
700
720
* for a lower target to reduce the given answer */
701
- double CBlockPolicyEstimator::estimateCombinedFee (unsigned int confTarget, double successThreshold, bool checkShorterHorizon) const
721
+ double CBlockPolicyEstimator::estimateCombinedFee (unsigned int confTarget, double successThreshold, bool checkShorterHorizon, EstimationResult *result ) const
702
722
{
703
723
double estimate = -1 ;
704
724
if (confTarget >= 1 && confTarget <= longStats->GetMaxConfirms ()) {
705
725
// Find estimate from shortest time horizon possible
706
726
if (confTarget <= shortStats->GetMaxConfirms ()) { // short horizon
707
- estimate = shortStats->EstimateMedianVal (confTarget, SUFFICIENT_TXS_SHORT, successThreshold, true , nBestSeenHeight);
727
+ estimate = shortStats->EstimateMedianVal (confTarget, SUFFICIENT_TXS_SHORT, successThreshold, true , nBestSeenHeight, result );
708
728
}
709
729
else if (confTarget <= feeStats->GetMaxConfirms ()) { // medium horizon
710
- estimate = feeStats->EstimateMedianVal (confTarget, SUFFICIENT_FEETXS, successThreshold, true , nBestSeenHeight);
730
+ estimate = feeStats->EstimateMedianVal (confTarget, SUFFICIENT_FEETXS, successThreshold, true , nBestSeenHeight, result );
711
731
}
712
732
else { // long horizon
713
- estimate = longStats->EstimateMedianVal (confTarget, SUFFICIENT_FEETXS, successThreshold, true , nBestSeenHeight);
733
+ estimate = longStats->EstimateMedianVal (confTarget, SUFFICIENT_FEETXS, successThreshold, true , nBestSeenHeight, result );
714
734
}
715
735
if (checkShorterHorizon) {
736
+ EstimationResult tempResult;
716
737
// If a lower confTarget from a more recent horizon returns a lower answer use it.
717
738
if (confTarget > feeStats->GetMaxConfirms ()) {
718
- double medMax = feeStats->EstimateMedianVal (feeStats->GetMaxConfirms (), SUFFICIENT_FEETXS, successThreshold, true , nBestSeenHeight);
719
- if (medMax > 0 && (estimate == -1 || medMax < estimate))
739
+ double medMax = feeStats->EstimateMedianVal (feeStats->GetMaxConfirms (), SUFFICIENT_FEETXS, successThreshold, true , nBestSeenHeight, &tempResult );
740
+ if (medMax > 0 && (estimate == -1 || medMax < estimate)) {
720
741
estimate = medMax;
742
+ if (result) *result = tempResult;
743
+ }
721
744
}
722
745
if (confTarget > shortStats->GetMaxConfirms ()) {
723
- double shortMax = shortStats->EstimateMedianVal (shortStats->GetMaxConfirms (), SUFFICIENT_TXS_SHORT, successThreshold, true , nBestSeenHeight);
724
- if (shortMax > 0 && (estimate == -1 || shortMax < estimate))
746
+ double shortMax = shortStats->EstimateMedianVal (shortStats->GetMaxConfirms (), SUFFICIENT_TXS_SHORT, successThreshold, true , nBestSeenHeight, &tempResult );
747
+ if (shortMax > 0 && (estimate == -1 || shortMax < estimate)) {
725
748
estimate = shortMax;
749
+ if (result) *result = tempResult;
750
+ }
726
751
}
727
752
}
728
753
}
@@ -732,16 +757,18 @@ double CBlockPolicyEstimator::estimateCombinedFee(unsigned int confTarget, doubl
732
757
/* * Ensure that for a conservative estimate, the DOUBLE_SUCCESS_PCT is also met
733
758
* at 2 * target for any longer time horizons.
734
759
*/
735
- double CBlockPolicyEstimator::estimateConservativeFee (unsigned int doubleTarget) const
760
+ double CBlockPolicyEstimator::estimateConservativeFee (unsigned int doubleTarget, EstimationResult *result ) const
736
761
{
737
762
double estimate = -1 ;
763
+ EstimationResult tempResult;
738
764
if (doubleTarget <= shortStats->GetMaxConfirms ()) {
739
- estimate = feeStats->EstimateMedianVal (doubleTarget, SUFFICIENT_FEETXS, DOUBLE_SUCCESS_PCT, true , nBestSeenHeight);
765
+ estimate = feeStats->EstimateMedianVal (doubleTarget, SUFFICIENT_FEETXS, DOUBLE_SUCCESS_PCT, true , nBestSeenHeight, result );
740
766
}
741
767
if (doubleTarget <= feeStats->GetMaxConfirms ()) {
742
- double longEstimate = longStats->EstimateMedianVal (doubleTarget, SUFFICIENT_FEETXS, DOUBLE_SUCCESS_PCT, true , nBestSeenHeight);
768
+ double longEstimate = longStats->EstimateMedianVal (doubleTarget, SUFFICIENT_FEETXS, DOUBLE_SUCCESS_PCT, true , nBestSeenHeight, &tempResult );
743
769
if (longEstimate > estimate) {
744
770
estimate = longEstimate;
771
+ if (result) *result = tempResult;
745
772
}
746
773
}
747
774
return estimate;
@@ -754,12 +781,15 @@ double CBlockPolicyEstimator::estimateConservativeFee(unsigned int doubleTarget)
754
781
* estimates, however, required the 95% threshold at 2 * target be met for any
755
782
* longer time horizons also.
756
783
*/
757
- CFeeRate CBlockPolicyEstimator::estimateSmartFee (int confTarget, int *answerFoundAtTarget , const CTxMemPool& pool, bool conservative) const
784
+ CFeeRate CBlockPolicyEstimator::estimateSmartFee (int confTarget, FeeCalculation *feeCalc , const CTxMemPool& pool, bool conservative) const
758
785
{
759
- if (answerFoundAtTarget)
760
- *answerFoundAtTarget = confTarget;
786
+ if (feeCalc) {
787
+ feeCalc->desiredTarget = confTarget;
788
+ feeCalc->returnedTarget = confTarget;
789
+ }
761
790
762
791
double median = -1 ;
792
+ EstimationResult tempResult;
763
793
{
764
794
LOCK (cs_feeEstimator);
765
795
@@ -780,7 +810,6 @@ CFeeRate CBlockPolicyEstimator::estimateSmartFee(int confTarget, int *answerFoun
780
810
}
781
811
782
812
assert (confTarget > 0 ); // estimateCombinedFee and estimateConservativeFee take unsigned ints
783
-
784
813
/* * true is passed to estimateCombined fee for target/2 and target so
785
814
* that we check the max confirms for shorter time horizons as well.
786
815
* This is necessary to preserve monotonically increasing estimates.
@@ -791,32 +820,49 @@ CFeeRate CBlockPolicyEstimator::estimateSmartFee(int confTarget, int *answerFoun
791
820
* the purpose of conservative estimates is not to let short term
792
821
* fluctuations lower our estimates by too much.
793
822
*/
794
- double halfEst = estimateCombinedFee (confTarget/2 , HALF_SUCCESS_PCT, true );
795
- double actualEst = estimateCombinedFee (confTarget, SUCCESS_PCT, true );
796
- double doubleEst = estimateCombinedFee (2 * confTarget, DOUBLE_SUCCESS_PCT, !conservative);
823
+ double halfEst = estimateCombinedFee (confTarget/2 , HALF_SUCCESS_PCT, true , &tempResult);
824
+ if (feeCalc) {
825
+ feeCalc->est = tempResult;
826
+ feeCalc->reason = FeeReason::HALF_ESTIMATE;
827
+ }
797
828
median = halfEst;
829
+ double actualEst = estimateCombinedFee (confTarget, SUCCESS_PCT, true , &tempResult);
798
830
if (actualEst > median) {
799
831
median = actualEst;
832
+ if (feeCalc) {
833
+ feeCalc->est = tempResult;
834
+ feeCalc->reason = FeeReason::FULL_ESTIMATE;
835
+ }
800
836
}
837
+ double doubleEst = estimateCombinedFee (2 * confTarget, DOUBLE_SUCCESS_PCT, !conservative, &tempResult);
801
838
if (doubleEst > median) {
802
839
median = doubleEst;
840
+ if (feeCalc) {
841
+ feeCalc->est = tempResult;
842
+ feeCalc->reason = FeeReason::DOUBLE_ESTIMATE;
843
+ }
803
844
}
804
845
805
846
if (conservative || median == -1 ) {
806
- double consEst = estimateConservativeFee (2 * confTarget);
847
+ double consEst = estimateConservativeFee (2 * confTarget, &tempResult );
807
848
if (consEst > median) {
808
849
median = consEst;
850
+ if (feeCalc) {
851
+ feeCalc->est = tempResult;
852
+ feeCalc->reason = FeeReason::CONSERVATIVE;
853
+ }
809
854
}
810
855
}
811
856
} // Must unlock cs_feeEstimator before taking mempool locks
812
857
813
- if (answerFoundAtTarget)
814
- *answerFoundAtTarget = confTarget;
858
+ if (feeCalc) feeCalc->returnedTarget = confTarget;
815
859
816
860
// If mempool is limiting txs , return at least the min feerate from the mempool
817
861
CAmount minPoolFee = pool.GetMinFee (GetArg (" -maxmempool" , DEFAULT_MAX_MEMPOOL_SIZE) * 1000000 ).GetFeePerK ();
818
- if (minPoolFee > 0 && minPoolFee > median)
862
+ if (minPoolFee > 0 && minPoolFee > median) {
863
+ if (feeCalc) feeCalc->reason = FeeReason::MEMPOOL_MIN;
819
864
return CFeeRate (minPoolFee);
865
+ }
820
866
821
867
if (median < 0 )
822
868
return CFeeRate (0 );
0 commit comments