@@ -477,7 +477,7 @@ bool CBlockPolicyEstimator::removeTx(uint256 hash, bool inBlock)
477
477
}
478
478
479
479
CBlockPolicyEstimator::CBlockPolicyEstimator ()
480
- : nBestSeenHeight(0 ), firstRecordedHeight(0 ), trackedTxs(0 ), untrackedTxs(0 )
480
+ : nBestSeenHeight(0 ), firstRecordedHeight(0 ), historicalFirst( 0 ), historicalBest( 0 ), trackedTxs(0 ), untrackedTxs(0 )
481
481
{
482
482
static_assert (MIN_BUCKET_FEERATE > 0 , " Min feerate must be nonzero" );
483
483
minTrackedFee = CFeeRate (MIN_BUCKET_FEERATE);
@@ -609,8 +609,9 @@ void CBlockPolicyEstimator::processBlock(unsigned int nBlockHeight,
609
609
}
610
610
611
611
612
- 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 " ,
613
- countedTxs, entries.size (), trackedTxs, trackedTxs + untrackedTxs, mapMemPoolTxs.size ());
612
+ LogPrint (BCLog::ESTIMATEFEE, " Blockpolicy estimates updated by %u of %u block txs, since last block %u of %u tracked, mempool map size %u, max target %u from %s\n " ,
613
+ countedTxs, entries.size (), trackedTxs, trackedTxs + untrackedTxs, mapMemPoolTxs.size (),
614
+ MaxUsableEstimate (), HistoricalBlockSpan () > BlockSpan () ? " historical" : " current" );
614
615
615
616
trackedTxs = 0 ;
616
617
untrackedTxs = 0 ;
@@ -663,6 +664,29 @@ CFeeRate CBlockPolicyEstimator::estimateRawFee(int confTarget, double successThr
663
664
return CFeeRate (median);
664
665
}
665
666
667
+ unsigned int CBlockPolicyEstimator::BlockSpan () const
668
+ {
669
+ if (firstRecordedHeight == 0 ) return 0 ;
670
+ assert (nBestSeenHeight >= firstRecordedHeight);
671
+
672
+ return nBestSeenHeight - firstRecordedHeight;
673
+ }
674
+
675
+ unsigned int CBlockPolicyEstimator::HistoricalBlockSpan () const
676
+ {
677
+ if (historicalFirst == 0 ) return 0 ;
678
+ assert (historicalBest >= historicalFirst);
679
+
680
+ if (nBestSeenHeight - historicalBest > OLDEST_ESTIMATE_HISTORY) return 0 ;
681
+
682
+ return historicalBest - historicalFirst;
683
+ }
684
+
685
+ unsigned int CBlockPolicyEstimator::MaxUsableEstimate () const
686
+ {
687
+ // Block spans are divided by 2 to make sure there are enough potential failing data points for the estimate
688
+ return std::min (longStats->GetMaxConfirms (), std::max (BlockSpan (), HistoricalBlockSpan ()) / 2 );
689
+ }
666
690
667
691
/* * Return a fee estimate at the required successThreshold from the shortest
668
692
* time horizon which tracks confirmations up to the desired target. If
@@ -731,6 +755,14 @@ CFeeRate CBlockPolicyEstimator::estimateSmartFee(int confTarget, int *answerFoun
731
755
if (confTarget == 1 )
732
756
confTarget = 2 ;
733
757
758
+ unsigned int maxUsableEstimate = MaxUsableEstimate ();
759
+ if (maxUsableEstimate <= 1 )
760
+ return CFeeRate (0 );
761
+
762
+ if ((unsigned int )confTarget > maxUsableEstimate) {
763
+ confTarget = maxUsableEstimate;
764
+ }
765
+
734
766
assert (confTarget > 0 ); // estimateCombinedFee and estimateConservativeFee take unsigned ints
735
767
736
768
/* * true is passed to estimateCombined fee for target/2 and target so
@@ -784,8 +816,12 @@ bool CBlockPolicyEstimator::Write(CAutoFile& fileout) const
784
816
fileout << 149900 ; // version required to read: 0.14.99 or later
785
817
fileout << CLIENT_VERSION; // version that wrote the file
786
818
fileout << nBestSeenHeight;
787
- unsigned int future1 = 0 , future2 = 0 ;
788
- fileout << future1 << future2;
819
+ if (BlockSpan () > HistoricalBlockSpan ()/2 ) {
820
+ fileout << firstRecordedHeight << nBestSeenHeight;
821
+ }
822
+ else {
823
+ fileout << historicalFirst << historicalBest;
824
+ }
789
825
fileout << buckets;
790
826
feeStats->Write (fileout);
791
827
shortStats->Write (fileout);
@@ -803,7 +839,7 @@ bool CBlockPolicyEstimator::Read(CAutoFile& filein)
803
839
try {
804
840
LOCK (cs_feeEstimator);
805
841
int nVersionRequired, nVersionThatWrote;
806
- unsigned int nFileBestSeenHeight;
842
+ unsigned int nFileBestSeenHeight, nFileHistoricalFirst, nFileHistoricalBest ;
807
843
filein >> nVersionRequired >> nVersionThatWrote;
808
844
if (nVersionRequired > CLIENT_VERSION)
809
845
return error (" CBlockPolicyEstimator::Read(): up-version (%d) fee estimate file" , nVersionRequired);
@@ -838,9 +874,10 @@ bool CBlockPolicyEstimator::Read(CAutoFile& filein)
838
874
}
839
875
}
840
876
else { // nVersionThatWrote >= 149900
841
- unsigned int future1, future2;
842
- filein >> future1 >> future2;
843
-
877
+ filein >> nFileHistoricalFirst >> nFileHistoricalBest;
878
+ if (nFileHistoricalFirst > nFileHistoricalBest || nFileHistoricalBest > nFileBestSeenHeight) {
879
+ throw std::runtime_error (" Corrupt estimates file. Historical block range for estimates is invalid" );
880
+ }
844
881
std::vector<double > fileBuckets;
845
882
filein >> fileBuckets;
846
883
size_t numBuckets = fileBuckets.size ();
@@ -871,6 +908,8 @@ bool CBlockPolicyEstimator::Read(CAutoFile& filein)
871
908
longStats = fileLongStats.release ();
872
909
873
910
nBestSeenHeight = nFileBestSeenHeight;
911
+ historicalFirst = nFileHistoricalFirst;
912
+ historicalBest = nFileHistoricalBest;
874
913
}
875
914
}
876
915
catch (const std::exception& e) {
0 commit comments