Skip to content

walletrpc+lncli: fix FinalizePsbt for multisig P2WSH, add psbt sign cmd#10584

Draft
Roasbeef wants to merge 2 commits intomasterfrom
fix-psbt-finalize-multisig
Draft

walletrpc+lncli: fix FinalizePsbt for multisig P2WSH, add psbt sign cmd#10584
Roasbeef wants to merge 2 commits intomasterfrom
fix-psbt-finalize-multisig

Conversation

@Roasbeef
Copy link
Member

@Roasbeef Roasbeef commented Feb 16, 2026

Summary

  • Fix FinalizePsbt to handle multisig P2WSH inputs by calling SignPsbt (which uses BIP32 derivation info) before delegating to the base wallet's finalize logic. Previously, FinalizePsbt relied solely on FetchInputInfo (UTXO DB lookup) which would skip multisig inputs not owned by the wallet, leading to "Unsupported script type" errors.
  • Add lncli wallet psbt sign command that exposes the existing SignPsbt RPC, useful for multisig PSBT workflows where users need to add lnd's signature without finalizing.
  • Add regression test for 2-of-2 P2WSH multisig finalization.

Fixes #10575.

Test plan

  • New TestFinalize2of2Multisig unit test passes — creates a 2-of-2 multisig P2WSH, adds external cosigner's partial sig, verifies FinalizePsbt signs and finalizes successfully, then validates via script engine.
  • Existing PSBT tests (TestSignPsbt, TestEstimateInputWeight, TestBip32DerivationFromAddress) continue to pass.
  • Manual test with lncli wallet psbt sign against a running node.

@gemini-code-assist
Copy link

Summary of Changes

Hello @Roasbeef, 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 enhances the wallet's Partially Signed Bitcoin Transaction (PSBT) capabilities by addressing a critical bug in multisig P2WSH finalization and introducing a new command-line interface for signing PSBTs. The changes improve the robustness of multisig workflows and provide more granular control over the signing process, particularly for collaborative transaction construction.

Highlights

  • PSBT Finalization Fix: Fixed FinalizePsbt to correctly handle multisig P2WSH inputs by ensuring SignPsbt is called to utilize BIP32 derivation information before the base wallet's finalization logic. This resolves issues where multisig inputs not directly owned by the wallet were skipped, leading to 'Unsupported script type' errors.
  • New lncli Command: Introduced a new lncli wallet psbt sign command, exposing the existing SignPsbt RPC. This command allows users to add lnd's signature to a PSBT without immediately finalizing it, which is particularly useful for multi-party PSBT workflows.
  • Regression Test: Added a new regression test, TestFinalize2of2Multisig, to specifically verify the correct finalization of 2-of-2 P2WSH multisig PSBTs, ensuring the fix addresses the reported issue.

🧠 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
  • cmd/commands/walletrpc_active.go
    • Added sign subcommand to lncli wallet psbt.
    • Implemented signPsbtResponse struct and signPsbt function to handle the new sign command's RPC client logic.
  • lnwallet/btcwallet/psbt.go
    • Modified FinalizePsbt to invoke SignPsbt prior to its core finalization logic, ensuring inputs with BIP32 derivation information, such as multisig P2WSH, are properly signed.
  • lnwallet/btcwallet/psbt_test.go
    • Added TestFinalize2of2Multisig to validate the corrected FinalizePsbt behavior for 2-of-2 P2WSH multisig transactions.
Activity
  • The pull request includes a detailed summary of the changes and their motivation.
  • A comprehensive test plan is provided, including new unit tests and verification of existing tests.
  • The changes were generated with Claude Code, indicating AI assistance in development.
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 16, 2026
@lightninglabs-deploy
Copy link
Collaborator

🔴 PR Severity: CRITICAL

Initial classification | 3 files | 220 lines changed

🔴 Critical (1 file)
  • lnwallet/btcwallet/psbt.go - Wallet PSBT signing and finalization logic for multisig P2WSH inputs
🟡 Medium (1 file)
  • cmd/commands/walletrpc_active.go - CLI client command for PSBT signing
Test files (1 file, excluded from classification)
  • lnwallet/btcwallet/psbt_test.go - Test coverage for multisig finalization

Analysis

This PR modifies critical wallet signing functionality in lnwallet/btcwallet/psbt.go. The changes fix FinalizePsbt to properly handle multisig P2WSH inputs by calling SignPsbt (which uses BIP32 derivation info) before delegating to the base wallet's finalize logic.

Why CRITICAL:

  • Touches lnwallet/* package which handles wallet operations, channel funding, and signing
  • Modifies PSBT finalization logic that could affect fund security if incorrect
  • Involves multisig P2WSH script handling and signature validation
  • Any bugs in signing or finalization could lead to funds being stuck or lost

Review recommendations:

  • Verify the signing order is correct (sign before finalize)
  • Ensure proper error handling for edge cases
  • Confirm the fix doesn't introduce regressions for single-sig PSBTs
  • Validate the test coverage adequately covers the multisig workflow

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

FinalizePsbt delegates to the base btcwallet's FinalizePsbt which uses
FetchInputInfo (UTXO DB lookup) to identify signable inputs. For
multisig P2WSH outputs the wallet doesn't own the script address, so
FetchInputInfo fails, the input is skipped, and finalization is
attempted with insufficient partial signatures.

Fix this by calling SignPsbt (which consults BIP32 derivation info)
before delegating to the base wallet's FinalizePsbt. This ensures that
any inputs with valid BIP32 derivation paths get signed regardless of
whether the UTXO is in the wallet's database.

Add a regression test that creates a 2-of-2 multisig P2WSH, adds an
external cosigner's partial signature, and verifies that FinalizePsbt
successfully signs and finalizes the transaction.

Fixes #10575.
Add a new 'lncli wallet psbt sign' subcommand that exposes the existing
SignPsbt RPC. This command signs PSBT inputs using BIP32 derivation
information without finalizing the transaction, making it useful for
multisig workflows where the user needs to add lnd's signature before
passing the PSBT to another signer or to the finalize command.

Previously, SignPsbt was only available via the gRPC/REST API and had no
lncli equivalent. Users working with multisig PSBTs had to use the API
directly as a workaround for the FinalizePsbt limitation fixed in the
previous commit.
@Roasbeef Roasbeef force-pushed the fix-psbt-finalize-multisig branch from bf9e76f to 6302cf8 Compare February 16, 2026 22:27
@Roasbeef Roasbeef marked this pull request as draft February 16, 2026 22:28
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 correctly fixes an issue with FinalizePsbt for multisig P2WSH inputs by adding a preliminary call to SignPsbt. The change is well-reasoned and accompanied by a thorough regression test. The addition of the lncli wallet psbt sign command is a valuable feature for users performing multisig operations. The overall implementation is solid, with just one minor suggestion to improve adherence to the project's documentation style guide.

Action: actionDecorator(signPsbt),
}

func signPsbt(ctx *cli.Context) error {

Choose a reason for hiding this comment

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

medium

This function is missing a comment explaining its purpose. According to the LND Style Guide (lines 17-19), every function must be commented, with the comment starting with the function name and being a complete sentence.

Suggested change
func signPsbt(ctx *cli.Context) error {
// signPsbt is the action for the `lncli wallet psbt sign` command. It
// parses the funded PSBT from the command line, calls the `SignPsbt` RPC,
// and prints the result.
func signPsbt(ctx *cli.Context) error {
References
  1. The style guide requires every function to have a comment that starts with the function name and describes its purpose in complete sentences. (link)

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.

[bug]: Can't finalize psbt with 2-of-2 multisig p2wsh

2 participants