Skip to content

fee_policy: don't quantize explicitly set feerates - #10912

Merged
f321x merged 1 commit into
spesmilo:masterfrom
sashazykov:fix-feerate-quantization
Sep 10, 2026
Merged

f321x merged 1 commit into
spesmilo:masterfrom
sashazykov:fix-feerate-quantization

Conversation

@sashazykov

Copy link
Copy Markdown
Contributor

estimate_fee() rounds the feerate to FEERATE_PRECISION (1 decimal place, half-down) before computing the fee, so payto --feerate 0.45 pays 0.4 sat/vB and --feerate 3.75 (the example from #4259) pays 3.7, with no indication that the requested rate was not used.

The rounding was added in f12798e for consistency with the GUI display, but both GUIs already constrain feerate input to one decimal place before the policy is constructed, so for FeeMethod.FEERATE it only affected CLI- and
config-originated rates. ETA and mempool based estimates keep being quantized. Since 58af1c4 lowered the supported relay floor to 0.1 sat/vB, one-decimal granularity is coarsest exactly where these rates now live.

Note: bump_fee/dscancel have their own quantize_feerate call (which also feeds the new-vs-old rate sanity check); deliberately left untouched here.

When a feerate is set explicitly (CLI --feerate, or a 'feerate:'
fee_policy descriptor), estimate_fee() would round it to
FEERATE_PRECISION (one decimal place, half-down) before computing
the fee. So e.g. 'payto ... --feerate 0.45' paid 0.4 sat/vB, and
'--feerate 3.75' paid 3.7, without any indication that the requested
rate was not used.

The quantization exists to keep the paid fee consistent with the
feerate displayed in the GUI (dynamic estimates are shown rounded to
one decimal place). That reasoning does not apply to FeeMethod.FEERATE:
both GUIs already quantize/validate user feerate input before the
policy is constructed (FeerateEdit._get_amount_from_text in Qt, a
one-decimal RegularExpressionValidator in QML FeePicker), so for
GUI-originated policies the quantization was a no-op; it only changed
rates coming from the CLI or a config descriptor. ETA and mempool
based estimates keep being quantized.
@sashazykov

Copy link
Copy Markdown
Contributor Author

Tested on mainnet: paytomany --feerate 0.315 --unsigned on a hardware wallet built a 532 vB transaction paying 168 sat = ceil(0.315 × 532), signed and broadcast fine. Without this patch the same command pays 160 sat (0.315 rounded to 0.3).

@f321x

f321x commented Sep 10, 2026

Copy link
Copy Markdown
Member

lgtm 44c9c47, thanks for the contribution.

@f321x
f321x merged commit 1c0bc23 into spesmilo:master Sep 10, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants