Skip to content

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

@kallerosenbaum

Description

@kallerosenbaum

Pre-Submission Checklist

  • I have searched the existing issues and believe this is a new bug.
  • I am not asking a question about how to use lnd, but reporting a bug (otherwise open a discussion).

LND Version

0.20.1-beta.rc1

LND Configuration

lnd --listen=0.0.0.0:9735 --rpclisten=0.0.0.0:10009 --alias=xxxxx --color=#FF001C --tlsextradomain=xxxxxx --externalip=xxxxxx --externalip=xxxxxxx --bitcoin.node=bitcoind --bitcoin.mainnet --bitcoind.rpcuser=xxxxxxx --bitcoind.rpcpass=xxxxxxx --bitcoind.rpchost=xxxxxxx --bitcoind.zmqpubrawblock=xxxxxxx --bitcoind.zmqpubrawtx=xxxxxxx --minchansize=1000000 --maxpendingchannels=10 --workers.read=1250 --workers.write=1250 --workers.sig=1250 --stagger-initial-reconnect --wtclient.sweep-fee-rate=70 --bitcoin.feerate=2000 --bitcoin.timelockdelta=200 --bitcoin.basefee=500 --protocol.wumbo-channels --db.bolt.auto-compact --db.bolt.auto-compact-min-age=104h --gc-canceled-invoices-on-the-fly --routing.strictgraphpruning --routerrpc.maxmchistory=0 --coop-close-target-confs=3 --tlscertduration=87600h --tor.active --tor.socks=tor-proxy.tor.svc.cluster.local:9050 --tor.skip-proxy-for-clearnet-targets --backupfilepath=/mnt/lnd_backup/channels.backup --healthcheck.chainbackend.attempts=30

Backend Version

Bitcoin Core 30.0

Backend Configuration

OS/Distribution

.

Bug Details & Steps to Reproduce

I tried to sign a 1-in-1-out PSBT with a 2-of-2 multisig p2wsh input.

lncli wallet psbt finalize cHNidP8BAFICAAAAARGoqtlxeriz2dVxvFjcx4ASlG6/yGGEMG0mPr+jO2RRAAAAAAAAAAAAAaImEgAAAAAAFgAUlQVzS+ZxcaDOAiqxUfZS8be5DmkAAAAAAAEBKywnEgAAAAAAIgAgX2UE9ylf4u3gOfMQcfZI0GjfxO7Tq+tE+P4FYdAqi3siAgM/ZjNgxZyU9C7PX83E32U9yukVV7MNfCA0WZoNZ2rh3UcwRAIgUMgxt6Id2RjgMcfG1zk8okAib8TrkjxJWBPtDU8VpRYCIAHnS/1ZbcdL8kw3Vha6fj0hlo/Cp/1b2r0OWfCQWQLMAQEDBAEAAAABBUdSIQM/ZjNgxZyU9C7PX83E32U9yukVV7MNfCA0WZoNZ2rh3SEDgV6bz0A46b1dVm7dibauioZveelfAlUFvtljSUuU/G5SriIGA4Fem89AOOm9XVZu3Ym2roqGb3npXwJVBb7ZY0lLlPxuGIkMv475AwCAAAAAgAAAAIAAAAAAX0kAAAHMIQOBXpvPQDjpvV1Wbt2Jtq6Khm956V8CVQW+2WNJS5T8bgAA
[lncli] rpc error: code = Unknown desc = error finalizing PSBT: error finalizing PSBT: Unsupported script type

The PSBT is generated by chantools zombierecovery (more details in the discussion at ElementsProject/lightning#8892) and later enhanced by me with keypath information retreived from lncli wallet addresses list and master fingerprint extracted from the xprv. The decoded version looks like this:

{
  "tx": {
    "txid": "6089b76456a4223a1e261a4248ccbd41ce25d950f8b2f306768a0fe8e2c38285",
    "hash": "6089b76456a4223a1e261a4248ccbd41ce25d950f8b2f306768a0fe8e2c38285",
    "version": 2,
    "size": 82,
    "vsize": 82,
    "weight": 328,
    "locktime": 0,
    "vin": [
      {
        "txid": "51643ba3bf3e266d308461c8bf6e941280c7dc58bc71d5d9b3b87a71d9aaa811",
        "vout": 0,
        "scriptSig": {
          "asm": "",
          "hex": ""
        },
        "sequence": 0
      }
    ],
    "vout": [
      {
        "value": 0.01189538,
        "n": 0,
        "scriptPubKey": {
          "asm": "0 9505734be67171a0ce022ab151f652f1b7b90e69",
          "desc": "addr(bc1qj5zhxjlxw9c6pnsz92c4rajj7xmmjrnfxj37ay)#mvr2ajxa",
          "hex": "00149505734be67171a0ce022ab151f652f1b7b90e69",
          "address": "bc1qj5zhxjlxw9c6pnsz92c4rajj7xmmjrnfxj37ay",
          "type": "witness_v0_keyhash"
        }
      }
    ]
  },
  "global_xpubs": [
  ],
  "psbt_version": 0,
  "proprietary": [
  ],
  "unknown": {
  },
  "inputs": [
    {
      "witness_utxo": {
        "amount": 0.01189676,
        "scriptPubKey": {
          "asm": "0 5f6504f7295fe2ede039f31071f648d068dfc4eed3abeb44f8fe0561d02a8b7b",
          "desc": "addr(bc1qtajsfaeftl3wmcpe7vg8rajg6p5dl38w6w47k38clczkr5p23dasgkgwfj)#kvgjt6dq",
          "hex": "00205f6504f7295fe2ede039f31071f648d068dfc4eed3abeb44f8fe0561d02a8b7b",
          "address": "bc1qtajsfaeftl3wmcpe7vg8rajg6p5dl38w6w47k38clczkr5p23dasgkgwfj",
          "type": "witness_v0_scripthash"
        }
      },
      "partial_signatures": {
        "033f663360c59c94f42ecf5fcdc4df653dcae91557b30d7c2034599a0d676ae1dd": "3044022050c831b7a21dd918e031c7c6d7393ca240226fc4eb923c495813ed0d4f15a516022001e74bfd596dc74bf24c375616ba7e3d21968fc2a7fd5bdabd0e59f0905902cc01"
      },
      "sighash": "ALL",
      "witness_script": {
        "asm": "2 033f663360c59c94f42ecf5fcdc4df653dcae91557b30d7c2034599a0d676ae1dd 03815e9bcf4038e9bd5d566edd89b6ae8a866f79e95f025505bed963494b94fc6e 2 OP_CHECKMULTISIG",
        "hex": "5221033f663360c59c94f42ecf5fcdc4df653dcae91557b30d7c2034599a0d676ae1dd2103815e9bcf4038e9bd5d566edd89b6ae8a866f79e95f025505bed963494b94fc6e52ae",
        "type": "multisig"
      },
      "bip32_derivs": [
        {
          "pubkey": "03815e9bcf4038e9bd5d566edd89b6ae8a866f79e95f025505bed963494b94fc6e",
          "master_fingerprint": "890cbf8e",
          "path": "m/1017h/0h/0h/0/18783"
        }
      ],
      "unknown": {
        "cc": "03815e9bcf4038e9bd5d566edd89b6ae8a866f79e95f025505bed963494b94fc6e"
      }
    }
  ],
  "outputs": [
    {
    }
  ],
  "fee": 0.00000138
}

If I run this typescript code with the xprv of the lnd node it works.

import { Psbt } from 'bitcoinjs-lib';
import BIP32Factory from 'bip32';
import * as ecc from 'tiny-secp256k1';
const bip32 = BIP32Factory(ecc);

const xprv = process.env.XPRV!;
const node = bip32.fromBase58(xprv);
const unsignedPsbtBase64 = 'cHNidP8BAFICAAAAARGoqtlxeriz2dVxvFjcx4ASlG6/yGGEMG0mPr+jO2RRAAAAAAAAAAAAAaImEgAAAAAAFgAUlQVzS+ZxcaDOAiqxUfZS8be5DmkAAAAAAAEBKywnEgAAAAAAIgAgX2UE9ylf4u3gOfMQcfZI0GjfxO7Tq+tE+P4FYdAqi3siAgM/ZjNgxZyU9C7PX83E32U9yukVV7MNfCA0WZoNZ2rh3UcwRAIgUMgxt6Id2RjgMcfG1zk8okAib8TrkjxJWBPtDU8VpRYCIAHnS/1ZbcdL8kw3Vha6fj0hlo/Cp/1b2r0OWfCQWQLMAQEDBAEAAAABBUdSIQM/ZjNgxZyU9C7PX83E32U9yukVV7MNfCA0WZoNZ2rh3SEDgV6bz0A46b1dVm7dibauioZveelfAlUFvtljSUuU/G5SrgHMIQOBXpvPQDjpvV1Wbt2Jtq6Khm956V8CVQW+2WNJS5T8bgAA';
const unsignedPsbt = Psbt.fromBase64(unsignedPsbtBase64);
const fingerprint = node.fingerprint;
unsignedPsbt.updateInput(0, {
    bip32Derivation: [{
        path: 'm/1017\'/0\'/0\'/0/18783',
        pubkey: Buffer.from('03815e9bcf4038e9bd5d566edd89b6ae8a866f79e95f025505bed963494b94fc6e', 'hex'),
        masterFingerprint: fingerprint
    }]
});
const signedPsbt = unsignedPsbt.signAllInputsHD(node);
const signedBase64 = signedPsbt.toBase64();
console.log('signedBase64', signedBase64);

I also tried to sign the psbt with chantools, but that failed too:

#  ./chantools zombierecovery signoffer --rootkey=xprvXXXXXXXXXXXXXXX --psbt cHNidP8BAFICAAAAARGoqtlxeriz2dVxvFjcx4ASlG6/yGGEMG0mPr+jO2RRAAAAAAAAAAAAAaImEgAAAAAAFgAUlQVzS+ZxcaDOAiqxUfZS8be5DmkAAAAAAAEBKywnEgAAAAAAIgAgX2UE9ylf4u3gOfMQcfZI0GjfxO7Tq+tE+P4FYdAqi3siAgM/ZjNgxZyU9C7PX83E32U9yukVV7MNfCA0WZoNZ2rh3UcwRAIgUMgxt6Id2RjgMcfG1zk8okAib8TrkjxJWBPtDU8VpRYCIAHnS/1ZbcdL8kw3Vha6fj0hlo/Cp/1b2r0OWfCQWQLMAQEDBAEAAAABBUdSIQM/ZjNgxZyU9C7PX83E32U9yukVV7MNfCA0WZoNZ2rh3SEDgV6bz0A46b1dVm7dibauioZveelfAlUFvtljSUuU/G5SriIGA4Fem89AOOm9XVZu3Ym2roqGb3npXwJVBb7ZY0lLlPxuGIkMv475AwCAAAAAgAAAAIAAAAAAX0kAAAHMIQOBXpvPQDjpvV1Wbt2Jtq6Khm956V8CVQW+2WNJS5T8bgAA
2026-02-13 07:25:46.423 [INF] CHAN: chantools version v0.14.1 commit 
The PSBT contains the following proposal:

        Close 1 channels: 
        Channel 0 (51643ba3bf3e266d308461c8bf6e941280c7dc58bc71d5d9b3b87a71d9aaa811:0), capacity 1189676 sats

        Send 1189538 sats to address bc1qj5zhxjlxw9c6pnsz92c4rajj7xmmjrnfxj37ay

        Total fees: 138 sats

Do you want to continue?
Press <enter> to continue and sign the transaction or <ctrl+c> to abort: 
Error: could not find local multisig key: no matching pubkeys found
Usage:
  chantools zombierecovery signoffer [flags]

Examples:
chantools zombierecovery signoffer \
        --psbt <offered_psbt_base64>

Flags:
      --apiurl string        API URL to use for publishing the final transaction (must be esplora compatible) (default "https://api.node-recovery.com")
      --bip39                read a classic BIP39 seed and passphrase from the terminal instead of asking for lnd seed format or providing the --rootkey flag
  -h, --help                 help for signoffer
      --hsm_secret string    the hex encoded HSM secret to use for deriving the multisig keys for a CLN node; obtain by running 'xxd -p -c32 ~/.lightning/bitcoin/hsm_secret'
      --psbt string          the base64 encoded PSBT that the other party sent as an offer to rescue funds
      --publish              if set, the final PSBT will be published to the network after signing, otherwise it will just be printed to stdout
      --remote_peer string   the hex encoded remote peer node identity key, only required when running 'signoffer' on the CLN side
      --rootkey string       BIP32 HD root key of the wallet to use for signing the offer; leave empty to prompt for lnd 24 word aezeed
      --walletdb string      read the seed/master root key to use for signing the offer from an lnd wallet.db file instead of asking for a seed or providing the --rootkey flag

Global Flags:
      --nologfile   If set, no log file will be created. This is useful for testing purposes where we don't want to create a log file.
  -r, --regtest     Indicates if regtest parameters should be used
  -s, --signet      Indicates if the public signet parameters should be used
  -t, --testnet     Indicates if testnet parameters should be used

could not find local multisig key: no matching pubkeys found

Expected Behavior

I would expect LND to happily sign the PSBT. Or at least that chantools would.

Debug Information

No response

Environment

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions