Skip to content

sweep: handle zero fee rate delta in LinearFeeFunction#10614

Open
darioAnongba wants to merge 1 commit intolightningnetwork:masterfrom
darioAnongba:fix/fee-function
Open

sweep: handle zero fee rate delta in LinearFeeFunction#10614
darioAnongba wants to merge 1 commit intolightningnetwork:masterfrom
darioAnongba:fix/fee-function

Conversation

@darioAnongba
Copy link
Contributor

Fix NewLinearFeeFunction to handle the case where starting and ending fee rates are equal (delta=0) by creating a flat-rate fee function instead of returning ErrZeroFeeRateDelta

Problem

When the fee estimator returns a rate higher than the budget-derived max fee rate, both the starting fee rate (estimated, clamped to max) and ending fee rate (budget max) become equal. This causes delta = (end - start) / width = 0, and NewLinearFeeFunction rejects the initialization with ErrZeroFeeRateDelta.

This means the sweep is never even attempted, even though the budget is sufficient to pay the fee at the max budget rate. The sweeper logs repeated errors like:

Failed to init fee function: startingFeeRate=742 sat/kw, endingFeeRate=742 sat/kw, width=1004, delta=0 mSAT/kw

This can happen in practice when:

  • A small UTXO has a tight budget, resulting in a low max fee rate
  • The fee estimator returns a rate above this budget max
  • Both rates get clamped to the budget max

Fix

Instead of returning an error when delta == 0 && width > 1, we now:

  1. Log a warning that fee bumping is disabled
  2. Set width = 0 so the fee function is considered already at its maximum
  3. Return a valid fee function that will use the flat rate for the initial sweep attempt

The sweep will be attempted at the budget-max fee rate. If it passes mempool acceptance, it succeeds. If a fee bump is needed later, Increment() immediately returns ErrMaxPosition, which the fee bumper handles by retrying with a different grouping strategy.

@gemini-code-assist
Copy link

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request resolves an issue in the NewLinearFeeFunction where a zero fee rate delta, caused by estimated and budget-derived max fee rates being equal, would prevent transaction sweeps from being attempted. The change modifies the function to gracefully handle this scenario by creating a valid flat-rate fee function, allowing the initial sweep attempt to proceed and improving the robustness of the fee bumping mechanism.

Highlights

  • Zero Fee Rate Delta Handling: Modified NewLinearFeeFunction to no longer return ErrZeroFeeRateDelta when the starting and ending fee rates are equal. Instead, it now creates a flat-rate fee function, logs a warning, and sets the function's width to zero.
  • Improved Sweep Attempt Logic: This change ensures that sweeps are still attempted at the budget-max fee rate even when fee bumping is not possible, preventing unnecessary failures and allowing the fee bumper to retry with different strategies if needed.
  • Test Case Update: The TestLinearFeeFunctionNewZeroFeeRateDelta test case was updated to reflect the new behavior, asserting that no error is returned and that the fee function's width is correctly set to zero, causing Increment() to immediately return ErrMaxPosition.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • sweep/fee_function.go
    • Changed error return to setting l.width = 0 and logging a warning when l.deltaFeeRate == 0 && l.width != 1.
    • Updated comments to reflect the new behavior for zero delta fee rates.
  • sweep/fee_function_test.go
    • Updated test description for TestLinearFeeFunctionNewZeroFeeRateDelta to reflect the new behavior of returning a flat-rate function.
    • Modified assertions in TestLinearFeeFunctionNewZeroFeeRateDelta to expect no error, verify the internal state (e.g., width is zero), and confirm that Increment() returns ErrMaxPosition.
Activity
  • No human activity has been recorded for this pull request yet.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@lightninglabs-deploy lightninglabs-deploy added the severity-critical Requires expert review - security/consensus critical label Feb 27, 2026
@lightninglabs-deploy
Copy link
Collaborator

🔴 PR Severity: CRITICAL

Automated classification | 1 file (non-test) | 20 lines changed (non-test)

🔴 Critical (1 file)
  • sweep/fee_function.go - fee function logic in the sweep package (output sweeping, fund recovery, fee bumping)
🧪 Test-only (excluded from classification)
  • sweep/fee_function_test.go - test file, excluded from severity counting

Analysis

This PR modifies sweep/fee_function.go, which falls under the sweep/* package. The sweep subsystem is responsible for critical fund-recovery operations: sweeping time-locked or contested outputs, fee-rate selection for on-chain transactions, and fee bumping. Changes to fee functions directly affect how funds are recovered and at what fee rate, making this a CRITICAL change requiring expert review.

No severity bump was triggered: only 1 non-test file was changed (threshold: >20) and only 20 non-test lines were modified (threshold: >500).


To override, add a severity-override-{critical,high,medium,low} label.

@darioAnongba darioAnongba marked this pull request as ready for review February 27, 2026 11:13
Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request gracefully handles the case where the fee rate delta is zero in NewLinearFeeFunction by creating a flat-rate fee function instead of returning an error. The change is logical, well-implemented, and includes corresponding updates to the tests. My main feedback is a suggestion to refactor the updated test case to use a table-driven approach, which is preferred by the repository's style guide and would improve maintainability.

@darioAnongba darioAnongba changed the title sweep: handle zero fee rate delta gracefully in LinearFeeFunction sweep: handle zero fee rate delta in LinearFeeFunction Feb 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

severity-critical Requires expert review - security/consensus critical

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants