@@ -658,31 +658,107 @@ CFeeRate CBlockPolicyEstimator::estimateRawFee(int confTarget, double successThr
658
658
return CFeeRate (median);
659
659
}
660
660
661
- CFeeRate CBlockPolicyEstimator::estimateSmartFee (int confTarget, int *answerFoundAtTarget, const CTxMemPool& pool) const
661
+
662
+ /* * Return a fee estimate at the required successThreshold from the shortest
663
+ * time horizon which tracks confirmations up to the desired target. If
664
+ * checkShorterHorizon is requested, also allow short time horizon estimates
665
+ * for a lower target to reduce the given answer */
666
+ double CBlockPolicyEstimator::estimateCombinedFee (unsigned int confTarget, double successThreshold, bool checkShorterHorizon) const
667
+ {
668
+ double estimate = -1 ;
669
+ if (confTarget >= 1 && confTarget <= longStats->GetMaxConfirms ()) {
670
+ // Find estimate from shortest time horizon possible
671
+ if (confTarget <= shortStats->GetMaxConfirms ()) { // short horizon
672
+ estimate = shortStats->EstimateMedianVal (confTarget, SUFFICIENT_TXS_SHORT, successThreshold, true , nBestSeenHeight);
673
+ }
674
+ else if (confTarget <= feeStats->GetMaxConfirms ()) { // medium horizon
675
+ estimate = feeStats->EstimateMedianVal (confTarget, SUFFICIENT_FEETXS, successThreshold, true , nBestSeenHeight);
676
+ }
677
+ else { // long horizon
678
+ estimate = longStats->EstimateMedianVal (confTarget, SUFFICIENT_FEETXS, successThreshold, true , nBestSeenHeight);
679
+ }
680
+ if (checkShorterHorizon) {
681
+ // If a lower confTarget from a more recent horizon returns a lower answer use it.
682
+ if (confTarget > feeStats->GetMaxConfirms ()) {
683
+ double medMax = feeStats->EstimateMedianVal (feeStats->GetMaxConfirms (), SUFFICIENT_FEETXS, successThreshold, true , nBestSeenHeight);
684
+ if (medMax > 0 && (estimate == -1 || medMax < estimate))
685
+ estimate = medMax;
686
+ }
687
+ if (confTarget > shortStats->GetMaxConfirms ()) {
688
+ double shortMax = shortStats->EstimateMedianVal (shortStats->GetMaxConfirms (), SUFFICIENT_TXS_SHORT, successThreshold, true , nBestSeenHeight);
689
+ if (shortMax > 0 && (estimate == -1 || shortMax < estimate))
690
+ estimate = shortMax;
691
+ }
692
+ }
693
+ }
694
+ return estimate;
695
+ }
696
+
697
+ double CBlockPolicyEstimator::estimateConservativeFee (unsigned int doubleTarget) const
698
+ {
699
+ double estimate = -1 ;
700
+ if (doubleTarget <= shortStats->GetMaxConfirms ()) {
701
+ estimate = feeStats->EstimateMedianVal (doubleTarget, SUFFICIENT_FEETXS, DOUBLE_SUCCESS_PCT, true , nBestSeenHeight);
702
+ }
703
+ if (doubleTarget <= feeStats->GetMaxConfirms ()) {
704
+ double longEstimate = longStats->EstimateMedianVal (doubleTarget, SUFFICIENT_FEETXS, DOUBLE_SUCCESS_PCT, true , nBestSeenHeight);
705
+ if (longEstimate > estimate) {
706
+ estimate = longEstimate;
707
+ }
708
+ }
709
+ return estimate;
710
+ }
711
+
712
+ CFeeRate CBlockPolicyEstimator::estimateSmartFee (int confTarget, int *answerFoundAtTarget, const CTxMemPool& pool, bool conservative) const
662
713
{
663
714
if (answerFoundAtTarget)
664
715
*answerFoundAtTarget = confTarget;
665
716
666
717
double median = -1 ;
667
-
668
718
{
669
719
LOCK (cs_feeEstimator);
670
720
671
721
// Return failure if trying to analyze a target we're not tracking
672
- if (confTarget <= 0 || (unsigned int )confTarget > feeStats ->GetMaxConfirms ())
722
+ if (confTarget <= 0 || (unsigned int )confTarget > longStats ->GetMaxConfirms ())
673
723
return CFeeRate (0 );
674
724
675
725
// It's not possible to get reasonable estimates for confTarget of 1
676
726
if (confTarget == 1 )
677
727
confTarget = 2 ;
678
728
679
- while (median < 0 && (unsigned int )confTarget <= feeStats->GetMaxConfirms ()) {
680
- median = feeStats->EstimateMedianVal (confTarget++, SUFFICIENT_FEETXS, DOUBLE_SUCCESS_PCT, true , nBestSeenHeight);
729
+ assert (confTarget > 0 ); // estimateCombinedFee and estimateConservativeFee take unsigned ints
730
+
731
+ /* * true is passed to estimateCombined fee for target/2 and target so
732
+ * that we check the max confirms for shorter time horizons as well.
733
+ * This is necessary to preserve monotonically increasing estimates.
734
+ * For non-conservative estimates we do the same thing for 2*target, but
735
+ * for conservative estimates we want to skip these shorter horizons
736
+ * checks for 2*target becuase we are taking the max over all time
737
+ * horizons so we already have monotonically increasing estimates and
738
+ * the purpose of conservative estimates is not to let short term
739
+ * fluctuations lower our estimates by too much.
740
+ */
741
+ double halfEst = estimateCombinedFee (confTarget/2 , HALF_SUCCESS_PCT, true );
742
+ double actualEst = estimateCombinedFee (confTarget, SUCCESS_PCT, true );
743
+ double doubleEst = estimateCombinedFee (2 * confTarget, DOUBLE_SUCCESS_PCT, !conservative);
744
+ median = halfEst;
745
+ if (actualEst > median) {
746
+ median = actualEst;
747
+ }
748
+ if (doubleEst > median) {
749
+ median = doubleEst;
750
+ }
751
+
752
+ if (conservative || median == -1 ) {
753
+ double consEst = estimateConservativeFee (2 * confTarget);
754
+ if (consEst > median) {
755
+ median = consEst;
756
+ }
681
757
}
682
758
} // Must unlock cs_feeEstimator before taking mempool locks
683
759
684
760
if (answerFoundAtTarget)
685
- *answerFoundAtTarget = confTarget - 1 ;
761
+ *answerFoundAtTarget = confTarget;
686
762
687
763
// If mempool is limiting txs , return at least the min feerate from the mempool
688
764
CAmount minPoolFee = pool.GetMinFee (GetArg (" -maxmempool" , DEFAULT_MAX_MEMPOOL_SIZE) * 1000000 ).GetFeePerK ();
@@ -695,6 +771,7 @@ CFeeRate CBlockPolicyEstimator::estimateSmartFee(int confTarget, int *answerFoun
695
771
return CFeeRate (median);
696
772
}
697
773
774
+
698
775
bool CBlockPolicyEstimator::Write (CAutoFile& fileout) const
699
776
{
700
777
try {
0 commit comments