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.
251BOOST_REQUIRE(result.has_value());252BOOST_CHECK(result->feerate == floor);253BOOST_CHECK(result->feerate_estimator == FeeRateEstimatorType::MEMPOOL_POLICY);254BOOST_CHECK_EQUAL(result->returned_target, MEMPOOL_FEE_ESTIMATOR_MAX_TARGET);256// The floor estimate is cached like any other; a second call returns the same value.257const auto cached_result = mempool_estimator.EstimateFeeRate(/*conservative=*/true);258BOOST_REQUIRE(cached_result.has_value());259BOOST_CHECK(cached_result->feerate == floor);260}261TestMemPoolEntryHelper entry;262const auto tx_vsize = entry.FromTx(MakeRandomTx()).GetTxSize();263const CAmount low_fee{CENT / 3000};264const CAmount med_fee{CENT / 100};265const CAmount high_fee{CENT / 10};266const CAmount very_high_fee{CENT};267// A mempool that cannot fill 50% of a block leaves both percentiles empty,268// so both estimate still fall back to the floor.269{270// Add high_fee transactions until mempool weight exceeds 25% of DEFAULT_BLOCK_MAX_WEIGHT.271{272LOCK2(cs_main, m_node.mempool->cs);273while ((m_node.mempool->GetTotalTxSize() * WITNESS_SCALE_FACTOR) <= (DEFAULT_BLOCK_MAX_WEIGHT * 25 / 100)) {274TryAddToMempool(*m_node.mempool, entry.Fee(high_fee).FromTx(MakeRandomTx()));275}276}277// Expire the cached floor estimate so the denser mempool is observed.278SetMockTime(GetTime<std::chrono::seconds>() + CACHE_LIFE + std::chrono::seconds{1});279const auto result = mempool_estimator.EstimateFeeRate(/*conservative=*/true);280BOOST_REQUIRE(result.has_value());281BOOST_CHECK(result->feerate == floor);282}283// A mempool that fills 50% of a block but not 75% has a conservative (p50)284// estimate, while the economical (p75) estimate falls back to the floor.285{286// Add med_fee transactions until mempool weight exceeds 50% of DEFAULT_BLOCK_MAX_WEIGHT.287{288LOCK2(cs_main, m_node.mempool->cs);289while ((m_node.mempool->GetTotalTxSize() * WITNESS_SCALE_FACTOR) <= (DEFAULT_BLOCK_MAX_WEIGHT * 50 / 100)) {290TryAddToMempool(*m_node.mempool, entry.Fee(med_fee).FromTx(MakeRandomTx()));291}292}293SetMockTime(GetTime<std::chrono::seconds>() + CACHE_LIFE + std::chrono::seconds{1});294const auto conservative = mempool_estimator.EstimateFeeRate(/*conservative=*/true);295const auto economical = mempool_estimator.EstimateFeeRate(/*conservative=*/false);296BOOST_REQUIRE(conservative.has_value());297BOOST_REQUIRE(economical.has_value());298BOOST_CHECK(conservative->feerate == FeeFrac(med_fee, tx_vsize));299BOOST_CHECK(economical->feerate == floor);300}301// Mempool transactions are enough to provide both feerate estimates.302{303// Add low_fee transactions until mempool transactions weight304// is enough to reach the 75% coverage requirement305{306LOCK2(cs_main, m_node.mempool->cs);307while ((m_node.mempool->GetTotalTxSize() * WITNESS_SCALE_FACTOR) <= (DEFAULT_BLOCK_MAX_WEIGHT * 75 / 100)) {308TryAddToMempool(*m_node.mempool, entry.Fee(low_fee).FromTx(MakeRandomTx()));309}310}311// Expire the sparse-result cache before expecting the estimator to observe the denser mempool.312SetMockTime(GetTime<std::chrono::seconds>() + CACHE_LIFE + std::chrono::seconds{1});313const auto result_conservative = mempool_estimator.EstimateFeeRate(/*conservative=*/true);314const auto result_economical = mempool_estimator.EstimateFeeRate(/*conservative=*/false);315BOOST_CHECK(result_conservative.has_value());316BOOST_CHECK(result_economical.has_value());317BOOST_CHECK(result_economical->feerate == FeeFrac(low_fee, tx_vsize));318BOOST_CHECK(result_conservative->feerate == FeeFrac(med_fee, tx_vsize));319BOOST_CHECK(ByRatio{result_conservative->feerate} > ByRatio{result_economical->feerate});320BOOST_CHECK(result_conservative->feerate_estimator == FeeRateEstimatorType::MEMPOOL_POLICY);321BOOST_CHECK(result_economical->feerate_estimator == FeeRateEstimatorType::MEMPOOL_POLICY);322BOOST_CHECK_EQUAL(result_conservative->returned_target, MEMPOOL_FEE_ESTIMATOR_MAX_TARGET);323BOOST_CHECK_EQUAL(result_economical->returned_target, MEMPOOL_FEE_ESTIMATOR_MAX_TARGET);325// Adding another 30% of very-high-fee transactions should change the326// estimates after recomputation, but not while the cached estimate is fresh.327{328LOCK2(cs_main, m_node.mempool->cs);329while ((m_node.mempool->GetTotalTxSize() * WITNESS_SCALE_FACTOR) <=330(DEFAULT_BLOCK_MAX_WEIGHT * 105 / 100)) {331TryAddToMempool(*m_node.mempool, entry.Fee(very_high_fee).FromTx(MakeRandomTx()));332}333}334BOOST_CHECK(mempool_estimator.EstimateFeeRate(/*conservative=*/false).value().feerate == FeeFrac(low_fee, tx_vsize));335BOOST_CHECK(mempool_estimator.EstimateFeeRate(/*conservative=*/true).value().feerate == FeeFrac(med_fee, tx_vsize));336// Expire the cache by advancing mock time past CACHE_LIFE so the next call recomputes.337SetMockTime(GetTime<std::chrono::seconds>() + CACHE_LIFE + std::chrono::seconds{1});338BOOST_CHECK(mempool_estimator.EstimateFeeRate(/*conservative=*/false).value().feerate == FeeFrac(med_fee, tx_vsize));339BOOST_CHECK(mempool_estimator.EstimateFeeRate(/*conservative=*/true).value().feerate == FeeFrac(high_fee, tx_vsize));340}341}343BOOST_AUTO_TEST_SUITE_END()
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.