Difference between long-term-fee-rate and discard fee-rate
In the bitcoin-core codebase, it seems that discard fee-rate and long-term fee-rate are used interchangeably when computing the cost of change. Consider the following code
excerpts:
cost_of_change = discard_feerate.GetFee(change_spend_size) + effective_feerate.GetFee(change_output_size);
ref: https://github.com/bitcoin/bitcoin/blob/2990bd773551c835ab0b6b59d85730adab2fd428/src/wallet/spend.cpp#L1182
and also:
cost_of_change = effective_feerate.GetFee(change_output_size) + long_term_feerate.GetFee(change_spend_size);
ref: https://github.com/bitcoin/bitcoin/blob/2990bd773551c835ab0b6b59d85730adab2fd428/src/wallet/test/fuzz/coinselection.cpp#L96
In both of these snippets, the cost_of_change is being computed, however, one uses the long-term fee-rate while the other uses the discard fee-rate. Are these two terms actually distinct or can they be used interchangeably?
To my knowledge, cost_of_change should be calculated using the discard fee_rate, and the long_term fee_rate is useful as a parameter within the selection algorithm for knowing if the current fee-rate is cheap or expensive. And yet, I see these two code pieces which seem to conflate the two.
Top Answer/Comment:
The discard feerate and the long-term feerate are both estimates of what it'll cost to spend a UTXO in the future, and since Bitcoin Core v24 both default to 10 sat/vB, which is precisely why they get confused. The difference is which UTXO each one prices, and at which stage of building the transaction. The discard feerate governs a single change output; the long-term feerate governs input selection.
The discard feerate (-discardfee, DEFAULT_DISCARD_FEE = 10 sat/vB, added in PR #10817) answers one question: once a selection leaves some leftover value, is that leftover worth turning into change, or should it just go to the fee? A change output costs you twice, once to create now and again to spend later, and the discard rate prices that future spend. If the change would be dust at that rate, meaning it would cost more to redeem than it's worth, Core drops it into the fee rather than creating an output you'd never economically spend. In Branch and Bound this is the cost_of_change window, discard_feerate.GetFee(change_spend_size) + effective_feerate.GetFee(change_output_size), within which giving the excess to fee beats making change. Two bounds apply from the option's own help text: the effective rate is floored by the dust relay fee and capped by the longest-target fee estimate, so a very high -discardfee can't discard arbitrarily large change.
The long-term feerate (-consolidatefeerate, default 10 sat/vB) lives only inside the waste metric that scores candidate input sets, and it represents the feerate at which you'd be content to consolidate UTXOs. Waste includes, per input, input_size × (current_feerate − long_term_feerate), and the sign of that difference is the entire mechanism. When the current feerate sits above the long-term rate, each extra input adds positive waste, so the wallet prefers fewer inputs and avoids overpaying to move coins while fees are high. When the current feerate sits below it, each extra input adds negative waste, so the wallet prefers more inputs and consolidates cheaply now, since spending them later is expected to cost more. It never changes the fee you actually pay on this transaction; it only decides which valid input set wins. Before PR #22009 (v24) this was the dynamic 1008-block estimateSmartFee value, swapped for a static configurable rate because the week-out estimate often sat near the floor and skewed selection toward constant consolidation.
So both encode "what will it cost to spend a coin later," both live in the coin-selection and change machinery, and both default to 10 sat/vB, but they act on different coins at different moments. The discard feerate acts on the change output and whether it survives, applied after a selection is made to trim uneconomical change. The long-term feerate acts on the inputs and how many to pick, applied during selection to compare whole input sets.
상단 광고의 [X] 버튼을 누르면 내용이 보입니다