Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
1001LogWarning("Failed to close fee estimates file %s: %s. Continuing anyway.", fs::PathToString(m_estimation_filepath), SysErrorString(errno));1002return;1003}1004LogDebug(BCLog::ESTIMATEFEE, "Flushed fee estimates to %s.", fs::PathToString(m_estimation_filepath));1005}1007bool CBlockPolicyEstimator::Write(AutoFile& fileout) const1008{1009try {1010LOCK(m_cs_fee_estimator);1011fileout << CURRENT_FEES_FILE_VERSION;1012fileout << nBestSeenHeight;1013if (BlockSpan() > HistoricalBlockSpan()/2) {1014fileout << firstRecordedHeight << nBestSeenHeight;1015}1016else {1017fileout << historicalFirst << historicalBest;1018}1019fileout << Using<VectorFormatter<EncodedDoubleFormatter>>(buckets);1020feeStats->Write(fileout);1021shortStats->Write(fileout);1022longStats->Write(fileout);1023}1024catch (const std::exception&) {1025LogWarning("Unable to write policy estimator data (non-fatal)");1026return false;1027}1028return true;1029}1031bool CBlockPolicyEstimator::Read(AutoFile& filein)1032{1033try {1034LOCK(m_cs_fee_estimator);1035int nVersionRequired;1036filein >> nVersionRequired;1037if (nVersionRequired > CURRENT_FEES_FILE_VERSION) {1038throw std::runtime_error{strprintf("File version (%d) too high to be read.", nVersionRequired)};1039}1040if (nVersionRequired < CURRENT_FEES_FILE_VERSION) {1041throw std::runtime_error{strprintf("File version (%d) incompatible: Too old to be read", nVersionRequired)};1042}1044// Read fee estimates file into temporary variables so existing data1045// structures aren't corrupted if there is an exception.1046unsigned int nFileBestSeenHeight;1047filein >> nFileBestSeenHeight;1049// nVersionRequired == CURRENT_FEES_FILE_VERSION1050unsigned int nFileHistoricalFirst, nFileHistoricalBest;1051filein >> nFileHistoricalFirst >> nFileHistoricalBest;1052if (nFileHistoricalFirst > nFileHistoricalBest || nFileHistoricalBest > nFileBestSeenHeight) {1053throw std::runtime_error("Corrupt estimates file. Historical block range for estimates is invalid");1054}1055std::vector<double> fileBuckets;1056filein >> Using<VectorFormatter<EncodedDoubleFormatter>>(fileBuckets);1057size_t numBuckets = fileBuckets.size();1058if (numBuckets <= 1 || numBuckets > 1000) {1059throw std::runtime_error("Corrupt estimates file. Must have between 2 and 1000 feerate buckets");1060}1062std::unique_ptr<TxConfirmStats> fileFeeStats(new TxConfirmStats(buckets, bucketMap, MED_BLOCK_PERIODS, MED_DECAY, MED_SCALE));1063std::unique_ptr<TxConfirmStats> fileShortStats(new TxConfirmStats(buckets, bucketMap, SHORT_BLOCK_PERIODS, SHORT_DECAY, SHORT_SCALE));1064std::unique_ptr<TxConfirmStats> fileLongStats(new TxConfirmStats(buckets, bucketMap, LONG_BLOCK_PERIODS, LONG_DECAY, LONG_SCALE));1065fileFeeStats->Read(filein, numBuckets);1066fileShortStats->Read(filein, numBuckets);1067fileLongStats->Read(filein, numBuckets);1069// Fee estimates file parsed correctly1070// Copy buckets from file and refresh our bucketmap1071buckets = fileBuckets;1072bucketMap.clear();1073for (unsigned int i = 0; i < buckets.size(); i++) {1074bucketMap[buckets[i]] = i;1075}1077// Destroy old TxConfirmStats and point to new ones that already reference buckets and bucketMap1078feeStats = std::move(fileFeeStats);1079shortStats = std::move(fileShortStats);1080longStats = std::move(fileLongStats);1082nBestSeenHeight = nFileBestSeenHeight;1083historicalFirst = nFileHistoricalFirst;1084historicalBest = nFileHistoricalBest;1085}1086catch (const std::exception& e) {1087LogWarning("Unable to read policy estimator data (non-fatal): %s", e.what());1088return false;1089}1090return true;1091}1093void CBlockPolicyEstimator::FlushUnconfirmed()1094{1095const auto startclear{SteadyClock::now()};1096LOCK(m_cs_fee_estimator);1097size_t num_entries = mapMemPoolTxs.size();1098// Remove every entry in mapMemPoolTxs1099while (!mapMemPoolTxs.empty()) {1100auto mi = mapMemPoolTxs.begin();1101_removeTx(mi->first, false); // this calls erase() on mapMemPoolTxs1102}1103const auto endclear{SteadyClock::now()};1104LogDebug(BCLog::ESTIMATEFEE, "Recorded %u unconfirmed txs from mempool in %.3fs\n", num_entries, Ticks<SecondsDouble>(endclear - startclear));1105}1107std::chrono::hours CBlockPolicyEstimator::GetFeeEstimatorFileAge()1108{1109auto file_time{fs::last_write_time(m_estimation_filepath)};1110auto now{fs::file_time_type::clock::now()};1111return std::chrono::duration_cast<std::chrono::hours>(now - file_time);1112}1114static std::set<double> MakeFeeSet(const CFeeRate& min_incremental_fee,1115double max_filter_fee_rate,1116double fee_filter_spacing)1117{1118std::set<double> fee_set;1120const CAmount min_fee_limit{std::max(CAmount(1), min_incremental_fee.GetFeePerK() / 2)};1121fee_set.insert(0);1122for (double bucket_boundary = min_fee_limit;1123bucket_boundary <= max_filter_fee_rate;1124bucket_boundary *= fee_filter_spacing) {1126fee_set.insert(bucket_boundary);1127}1129return fee_set;1130}1132FeeFilterRounder::FeeFilterRounder(const CFeeRate& minIncrementalFee, FastRandomContext& rng)1133: m_fee_set{MakeFeeSet(minIncrementalFee, MAX_FILTER_FEERATE, FEE_FILTER_SPACING)},1134insecure_rand{rng}1135{1136}1138CAmount FeeFilterRounder::round(CAmount currentMinFee)1139{1140AssertLockNotHeld(m_insecure_rand_mutex);1141std::set<double>::iterator it = m_fee_set.lower_bound(currentMinFee);1142if (it == m_fee_set.end() ||1143(it != m_fee_set.begin() &&1144WITH_LOCK(m_insecure_rand_mutex, return insecure_rand.rand32()) % 3 != 0)) {1145--it;1146}1147return static_cast<CAmount>(*it);1148}
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.