fees: wallet: remove block policy fee estimator internals from wallet #34617

pull ismaelsadeeq wants to merge 7 commits into bitcoin:master from ismaelsadeeq:02-2026-remove-estimatesmartfee-internals-from-wallet changing 18 files +181 −136
  1. ismaelsadeeq commented at 6:45 pm on February 18, 2026: member

    Part of #34075

    Motivation

    The wallet currently knows the block policy estimator’s internals from the response returned by estimateSmartFee. estimateSmartFee logging, which is supposed to be inside the method, is done in the wallet. Also, the source of a wallet transaction fee is saved in the CBlockPolicyEstimator::FeeReason enum. This shows that there is tight coupling between the wallet and CBlockPolicyEstimator, which results in code that is a bit messy to extend and even read. In #34075 the wallet is going to use a response returned via a fee rate estimator manager which does not return all those internals, hence motivating this refactor. This PR refactors the interface between the wallet and the fee estimator to improve encapsulation and separate two distinct concerns: the source of a fee rate (where it came from) and the estimator’s reason (why the algorithm chose it).

    Key Changes

    • Separate FeeSource from FeeReason: Introduced a new FeeSource enum in src/util/fees.h to represent the high-level origin of a fee rate (e.g., PAYTXFEE, FALLBACK, FEE_RATE_ESTIMATOR). The existing FeeReason is now strictly scoped to internal CBlockPolicyEstimator details.
    • Encapsulate estimateSmartFee Logging: Moved the fee calculation logging logic into CBlockPolicyEstimator. This removes the need for the wallet to manage a FeeCalculation object just to facilitate logging, especially when the caller passes nullptr.
    • Refactor GetMinimumFeeRate: Updated wallet::GetMinimumFeeRate to return a MinimumFeeRateResult struct. This avoids the use of output parameters and provides a cleaner interface for retrieving the fee rate, source, and target.
    • Move StringForFeeReason: Moved StringForFeeReason to src/policy/fees/block_policy_estimator.cpp to align with the location of the FeeReason enum. The function was also refactored to use a switch statement without a default case to ensure compile-time coverage of all reasons.
    • RPC Breaking Change: Renamed the fee_reason field to fee_source in wallet RPCs (such as send, walletcreatefundedpsbt). This correctly identifies the origin of the fee rate rather than the estimator’s internal logic.
    • Additional Logging: Added logging for transaction fee, size, and source in CreateTransactionInternal to improve debugging of fee selection.
  2. DrahtBot renamed this:
    fees: wallet: remove block policy fee estimator internals from wallet
    fees: wallet: remove block policy fee estimator internals from wallet
    on Feb 18, 2026
  3. DrahtBot added the label TX fees and policy on Feb 18, 2026
  4. DrahtBot commented at 6:45 pm on February 18, 2026: contributor

    The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

    Reviews

    See the guideline for information on the review process. A summary of reviews will appear here.

    Conflicts

    Reviewers, this pull request conflicts with the following ones:

    • #34405 (wallet: skip APS when no partial spend exists by 8144225309)
    • #30343 (wallet, logging: Replace WalletLogPrintf() with LogInfo() by ryanofsky)

    If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

    LLM Linter (✨ experimental)

    Possible typos and grammar issues:

    • “Fallbackfee” -> “Fallback fee” [Two occurrences use the concatenated form “Fallbackfee”, which is grammatically incorrect and may slightly impair readability; separating into “Fallback fee” clarifies meaning.]

    2026-02-19 14:45:04

  5. DrahtBot added the label Needs rebase on Feb 19, 2026
  6. refactor: use switch in `StringForFeeReason`
    - An `assert(false)` is added after the switch to catch any unhandled
      cases during development and testing.
    8d7741ddd5
  7. refactor: split fee source from estimation reason enum
    - The FeeReason enum mixed two distinct concepts: the source of a fee
      rate (e.g fallback, required and fee rate estimator) and the reason of estimateSmartFee
      output (e.g., half-estimate, conservative).
    
    - This commit refactor this enum separating concerns by
      introducing a new `FeeSource` enum.
    
        - `FeeSource`: Represents the origin of a fee, such as
          `FEE_RATE_ESTIMATOR`, `MEMPOOL_MIN`, `USER_SPECIFIED`
          `FALLBACK`, and `REQUIRED`.
    
        - `FeeReason`: Now exclusively represents the reason for a fee
          estimateSmartFee output, such as `HALF_ESTIMATE` or `CONSERVATIVE`.
    
    - Functions like `GetMinimumFeeRate` and `GetMinimumFee` are updated to
      accept a `FeeSource*` parameter, enabling callers to determine the
      source of the resulting fee rate.
    
    - A functional test in `wallet_basic.py` has been temporarily commented out.
      This test validates the wallet sending rpc return the correct fee source,
      with the current split of the enums, the fee_reason output does not
      contain the expected result.
      This will be fixed in a subsequent commit.
    d1c6403745
  8. rpc: breaking: rename fee_reason to fee_source
    - This change aligns the RPC output with the internal 'FeeSource' enum,
      which provides a more accurate and descriptive origin for a transaction's fee,
      such as from the fee estimator, mempool minimum, or fallback fee.
    
    - BREAKING CHANGE: Clients parsing/matching this field must update their code to use 'fee_source'
      instead of 'fee_reason'.
    1b6ee3c07c
  9. fees: make estimateSmartFee log internal
    - Since the FeeCalc argument can be a nullptr and we
      want to log values of the FeeCalc in estimateSmartFee.
      This commit updates estimateSmartFee to create a FeeCalc local
      variable which is used for the log and then copied into the
      user passed FeeCalc argument if it is not a nullptr.
    
    - The omitted Reason field from the log will be returned in a subsequent commit.
    18715aef14
  10. refactor: fees: move StringForFeeReason to block policy estimator
    - This commit also added the Reason field back to to the log
      of estimateSmartFee method.
    be6d0e9ebb
  11. wallet: log transaction fee in `CreateTransactionInternal`
    - The transaction size in bytes and the transaction fee source
      are also logged.
    ec898e8ce3
  12. refactor: return struct from GetMinimumFeeRate instead of using out-params
    - This commit refactors the `GetMinimumFeeRate` function to return a
      `MinimumFeeRateResult` struct containing the fee rate, fee source, and
      confirmation target. This avoids the use of output parameters, leading to
      cleaner and more readable code.
    
    - The `GetMinimumFee` function is also updated to take the new struct as a
      parameter.
    
    - All call sites have been updated to use the new function signatures.
    991df9bd18
  13. ismaelsadeeq force-pushed on Feb 19, 2026
  14. DrahtBot removed the label Needs rebase on Feb 19, 2026
  15. in src/policy/fees/block_policy_estimator.h:66 in d1c6403745 outdated
    62@@ -63,9 +63,6 @@ enum class FeeReason {
    63     FULL_ESTIMATE,
    64     DOUBLE_ESTIMATE,
    65     CONSERVATIVE,
    66-    MEMPOOL_MIN,
    


    Eunovo commented at 6:49 am on February 24, 2026:

    https://github.com/bitcoin/bitcoin/pull/34617/commits/d1c640374532b0e78abaaeacb4805e7192c49835:

    Removing these from block_policy_estimator seems sensible, because they are not used in estimateSmartFee, and they are not part of the possible FeeReason that can be returned from estimateSmartFee.

  16. in src/qt/sendcoinsdialog.cpp:866 in d1c6403745 outdated
    862@@ -862,7 +863,7 @@ void SendCoinsDialog::updateSmartFeeLabel()
    863 
    864     ui->labelSmartFee->setText(tr("%1/kvB").arg(BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), feeRate.GetFeePerK())));
    865 
    866-    if (reason == FeeReason::FALLBACK) {
    867+    if (reason == FeeReason::NONE) { // FIXME: use correct enum
    


    Eunovo commented at 6:53 am on February 24, 2026:

    ismaelsadeeq commented at 7:02 am on February 24, 2026:
    This is an intermediate commit to simplify review. It is used here 991df9bd182679e1fb1632ea1688042030fd264f

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-02-26 06:13 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me