Skip to content

sweep: account for aux extra budget when filtering inputs#10897

Open
jtobin wants to merge 2 commits into
lightningnetwork:masterfrom
jtobin:htlc-force-close-sweeper
Open

sweep: account for aux extra budget when filtering inputs#10897
jtobin wants to merge 2 commits into
lightningnetwork:masterfrom
jtobin:htlc-force-close-sweeper

Conversation

@jtobin

@jtobin jtobin commented Jun 11, 2026

Copy link
Copy Markdown
Collaborator

(TLDR, fixes an accounting error that can lead to sweep failures after aux channel force closes. Related to lightninglabs/taproot-assets#1888 and lightninglabs/taproot-assets#1976).

The BudgetAggregator filters out inputs whose budget cannot cover the min relay fee or their requested starting fee rate. For inputs that carry a resolution blob (custom channel outputs), the aux sweeper contributes a sizable extra budget to any input set they join, but the filter only considered the input's own budget, which for asset outputs is tiny.

The filter is mostly harmless with default parameters, but the starting fee rate of an input is ratcheted whenever a sweep attempt fails, including failures that have nothing to do with fees, e.g. when a concurrent sweep transaction spends the wallet UTXO that was backing this input's set (#10816 contains a separate, independent fix for the "always ratchet on every error" issue, which I need to tease out from the flawed leasing approach introduced there). One such collision is enough to push the required starting fee above a small asset input's own budget, after which the input is filtered out of every future input set and the sweep is silently stranded forever.

This change accounts for the aux extra budget in the filter, mirroring how the budget input set itself accounts for it when deciding whether wallet inputs are needed. Inputs without a resolution blob (the only kind that exists without an aux sweeper) are unaffected.

@jtobin jtobin self-assigned this Jun 11, 2026
@gemini-code-assist

Copy link
Copy Markdown

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 addresses an accounting issue in the BudgetAggregator that caused certain inputs to be permanently filtered out of sweep attempts. By failing to account for the extra budget provided by an auxiliary sweeper, the system would incorrectly deem small asset-based inputs as insufficient to cover fees, especially after failed attempts ratcheted up the required starting fee rate. This change ensures the filter correctly considers the total available budget, maintaining consistency with how input sets are formed.

Highlights

  • Auxiliary Budget Integration: Updated the BudgetAggregator to include auxiliary extra budget when evaluating whether an input can cover required fees.
  • Preventing Premature Filtering: Ensured that inputs with small on-chain budgets but significant auxiliary support are not incorrectly filtered out during the sweep process.
  • Fee Rate Validation: Adjusted both minimum fee and starting fee rate checks to use the combined budget, preventing inputs from being stranded due to transient sweep failures.
New Features

🧠 You can now enable Memory (public preview) 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.

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 the 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 counterproductive. 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.

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.

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

Copy link
Copy Markdown

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 updates the budget aggregator in sweep/aggregator.go to account for an extra budget contributed by an auxiliary sweeper when filtering inputs. Feedback suggests passing the underlying input.Input interface (pi.Input) instead of the wrapper pi (*SweeperInput) to ExtraBudgetForInputs to avoid type assertion failures in external implementations like Taproot Assets.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread sweep/aggregator.go
@github-actions github-actions Bot added the severity-critical Requires expert review - security/consensus critical label Jun 11, 2026
@github-actions

Copy link
Copy Markdown

🔴 PR Severity: CRITICAL

Automated classification | 1 file | 30 lines changed

🔴 Critical (1 file)
  • sweep/aggregator.go - Output sweeper aggregator logic; part of the sweep/* package responsible for output sweeping, fund recovery, and fee bumping

Analysis

This PR modifies sweep/aggregator.go, which lives in the sweep/* package. The sweep subsystem handles on-chain output sweeping, fund recovery, and fee bumping — all safety-critical operations that directly affect the recovery of user funds. Any bugs here could result in missed sweeps, incorrect fee estimation, or loss of funds, warranting expert review.

The change is small (1 file, 30 lines), so no severity bump was applied.


To override, add a severity-override-{critical,high,medium,low} label.
<!-- pr-severity-bot -->

jtobin added 2 commits June 11, 2026 13:26
The BudgetAggregator filters out inputs whose budget cannot cover the
min relay fee or their requested starting fee rate. For inputs that
carry a resolution blob (custom channel outputs), the aux sweeper
contributes a sizable extra budget to any input set they join, but the
filter only considered the input's own budget, which for asset outputs
is tiny (their value is carried off-chain).

The filter is mostly harmless with default parameters, but the
starting fee rate of an input is ratcheted whenever a sweep attempt
fails, including failures that have nothing to do with fees: e.g. when
a concurrent sweep transaction spends the wallet UTXO that was backing
this input's set (the sweeper currently doesn't lease selected wallet
UTXOs, so concurrent input sets can pick the same one). One such
collision is enough to push the required starting fee above a small
asset input's own budget, after which the input is filtered out of
every future input set and the sweep is silently stranded forever.

Account for the aux extra budget in the filter, mirroring how the
budget input set itself accounts for it when deciding whether wallet
inputs are needed. Inputs without a resolution blob (the only kind
that exists without an aux sweeper) are unaffected.
@jtobin jtobin force-pushed the htlc-force-close-sweeper branch from b77026e to 75433bb Compare June 11, 2026 16:05
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.

[flake]: suspected custom_channels_htlc_force_close_MPP flake [bug]: After Taproot Assets channel force-closure, funds are not swept.

1 participant