Skip to content

multi: fix SIMPLE_TAPROOT_FINAL acceptor and overlay RBF auto-enable#10763

Merged
yyforyongyu merged 3 commits intolightningnetwork:masterfrom
GeorgeTsagk:taproot-final-acceptor
Apr 21, 2026
Merged

multi: fix SIMPLE_TAPROOT_FINAL acceptor and overlay RBF auto-enable#10763
yyforyongyu merged 3 commits intolightningnetwork:masterfrom
GeorgeTsagk:taproot-final-acceptor

Conversation

@GeorgeTsagk
Copy link
Copy Markdown
Collaborator

Description

Adds the missing SIMPLE_TAPROOT_FINAL cases to the RPC acceptor switch so external acceptor clients no longer see UNKNOWN_COMMITMENT_TYPE for final-taproot channel opens, and narrows the taproot RBF auto-enable to skip taproot-overlay (where the RBF coop-close state machine does not yet thread through the AuxCloser hook).

The feature-bits-to-lnrpc-enum switch in sendAcceptRequests covered
every commitment type the RPC acceptor can be asked about, except the
production taproot variant introduced alongside the prod-taproot-chans
work. For a channel open using SimpleTaprootChannelsRequiredFinal (with
any combination of the scid-alias / zero-conf modifiers), the switch
fell through to the default branch, which logs a warning and leaves
commitmentType at its zero value -- lnrpc.CommitmentType_UNKNOWN_COMMITMENT_TYPE.
External acceptor clients then see UNKNOWN rather than the actual
commitment type and either reject or misclassify the channel.

Add the four missing cases so the new commitment type is reported to
acceptor clients correctly.
An earlier commit added an auto-enable that forces RbfCoopClose=true
whenever either taproot channel flag is set. This breaks
taproot-overlay channels, because the RBF coop close state machine in
lnwallet/chancloser/rbf_coop_*.go does not integrate the AuxCloser
(or any other aux) hook that overlay channels depend on to build
aux-aware close transactions. A node that enables
--protocol.simple-taproot-overlay-chans ends up with RBF force-on and
its overlay channel closes silently fail, leaving the aux closer
unable to finalize on-chain.

Narrow the auto-enable so it only fires for TaprootChans (staging /
final taproot) and explicitly skips it when TaprootOverlayChans is set.
Operators that positively want RBF can still opt in via
--protocol.rbf-coop-close; this change only removes the forced path
that silently breaks overlay closes.
@GeorgeTsagk GeorgeTsagk self-assigned this Apr 20, 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 improves channel management and protocol interoperability. It addresses a reporting issue for final-taproot channels in the RPC acceptor and modifies the server configuration logic to safely handle RBF cooperative close auto-enabling in the presence of taproot-overlay channels.

Highlights

  • RPC Acceptor Updates: Added missing SIMPLE_TAPROOT_FINAL cases to the RPC acceptor switch to ensure external clients correctly identify final-taproot channel opens.
  • RBF Auto-enable Logic: Refined the RBF cooperative close auto-enable logic to exclude taproot-overlay channels, preventing potential issues with the AuxCloser hook.

🧠 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.

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.

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.

@github-actions github-actions Bot added the severity-critical Requires expert review - security/consensus critical label Apr 20, 2026
@github-actions
Copy link
Copy Markdown

🔴 PR Severity: CRITICAL

Automated classification | 2 files | 41 lines changed

🔴 Critical (1 file)
  • server.go - Core server coordination (explicitly listed as CRITICAL)
🟠 High (1 file)
  • chanacceptor/rpcacceptor.go - Channel acceptor RPC logic (chanacceptor/* is HIGH)

Analysis

This PR modifies server.go, which is explicitly categorized as CRITICAL as it handles core server coordination in lnd. The highest-severity file determines the PR severity, so this PR is classified as CRITICAL regardless of the HIGH-severity chanacceptor/rpcacceptor.go change.

The change is small (2 files, 41 lines total), so no severity bump was triggered. However, expert review is warranted given that server.go is the central coordination point for the daemon.


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

Copy link
Copy Markdown

@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 introduces support for the SIMPLE_TAPROOT_FINAL commitment type by handling various feature bit combinations in the RPC acceptor. Additionally, it updates the server logic to ensure RBF cooperative close is not automatically enabled when taproot-overlay channels are active, preventing potential issues with the current state machine. A review comment suggests refactoring the repetitive case statements in rpcacceptor.go into a more concise and maintainable block by cloning the feature vector and unsetting allowed bits.

Comment on lines +359 to +381
case channelFeatures.OnlyContains(
lnwire.SimpleTaprootChannelsRequiredFinal,
lnwire.ZeroConfRequired,
lnwire.ScidAliasRequired,
):
commitmentType = lnrpc.CommitmentType_SIMPLE_TAPROOT_FINAL

case channelFeatures.OnlyContains(
lnwire.SimpleTaprootChannelsRequiredFinal,
lnwire.ZeroConfRequired,
):
commitmentType = lnrpc.CommitmentType_SIMPLE_TAPROOT_FINAL

case channelFeatures.OnlyContains(
lnwire.SimpleTaprootChannelsRequiredFinal,
lnwire.ScidAliasRequired,
):
commitmentType = lnrpc.CommitmentType_SIMPLE_TAPROOT_FINAL

case channelFeatures.OnlyContains(
lnwire.SimpleTaprootChannelsRequiredFinal,
):
commitmentType = lnrpc.CommitmentType_SIMPLE_TAPROOT_FINAL
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

These four case statements for SIMPLE_TAPROOT_FINAL are all setting the same commitmentType and are quite repetitive. This could be simplified to improve readability and maintainability. A single case can handle all combinations by checking for the base feature and ensuring no other unexpected features are present.

This pattern of repeated case statements is also used for other commitment types in this switch block and could be refactored similarly.

Suggested change
case channelFeatures.OnlyContains(
lnwire.SimpleTaprootChannelsRequiredFinal,
lnwire.ZeroConfRequired,
lnwire.ScidAliasRequired,
):
commitmentType = lnrpc.CommitmentType_SIMPLE_TAPROOT_FINAL
case channelFeatures.OnlyContains(
lnwire.SimpleTaprootChannelsRequiredFinal,
lnwire.ZeroConfRequired,
):
commitmentType = lnrpc.CommitmentType_SIMPLE_TAPROOT_FINAL
case channelFeatures.OnlyContains(
lnwire.SimpleTaprootChannelsRequiredFinal,
lnwire.ScidAliasRequired,
):
commitmentType = lnrpc.CommitmentType_SIMPLE_TAPROOT_FINAL
case channelFeatures.OnlyContains(
lnwire.SimpleTaprootChannelsRequiredFinal,
):
commitmentType = lnrpc.CommitmentType_SIMPLE_TAPROOT_FINAL
case channelFeatures.IsSet(lnwire.SimpleTaprootChannelsRequiredFinal):
// We'll clone the feature vector and unset all allowed
// bits. If the vector is empty after, we know that
// no other unexpected bits were set.
clone := (&channelFeatures).Clone()
clone.Unset(lnwire.SimpleTaprootChannelsRequiredFinal)
clone.Unset(lnwire.ZeroConfRequired)
clone.Unset(lnwire.ScidAliasRequired)
if clone.IsEmpty() {
commitmentType = lnrpc.CommitmentType_SIMPLE_TAPROOT_FINAL
}

Copy link
Copy Markdown
Collaborator

@ziggie1984 ziggie1984 left a comment

Choose a reason for hiding this comment

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

LGTM

Comment thread server.go
// to build the aux-aware close transaction. Forcing RBF on for a
// node that holds overlay channels would silently break their coop
// closes.
if cfg.ProtocolOptions.TaprootChans &&
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

does this mean if we have overlay channels the rbf protocol is also switch off for the normal taproot channels ?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

but if the user sets it via the config it still breaks the coop close flow for overlay channels, we should prio this fix on the taproot assets side then.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

yes we don't want to auto-enable it for overlay chans

the proper fix involves LND diff (integrating the AuxCloser in the RBF closer) and maybe some supporting code in taproot assets. Since we're already at the rc phase this should be enough. We control the flags in litd so for now we'll just try to protect & discourage the user from setting the flag (or even fail early in litd).

Copy link
Copy Markdown
Member

@Roasbeef Roasbeef left a comment

Choose a reason for hiding this comment

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

LGTM 🛡️

Copy link
Copy Markdown
Member

@Roasbeef Roasbeef left a comment

Choose a reason for hiding this comment

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

LGTM 🛡️

@yyforyongyu yyforyongyu merged commit a8a3e13 into lightningnetwork:master Apr 21, 2026
82 of 88 checks passed
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.

4 participants