Skip to content

Add TLVs required for splicing taproot channels - #1324

Open
t-bast wants to merge 2 commits into
lightning:masterfrom
t-bast:taproot-splicing
Open

t-bast wants to merge 2 commits into
lightning:masterfrom
t-bast:taproot-splicing

Conversation

@t-bast

@t-bast t-bast commented Mar 5, 2026 •

Copy link
Copy Markdown
Collaborator

We add support for splicing and dual-funding taproot channels. Each commit adds a specific feature that leverages taproot and splicing:

@Roasbeef Roasbeef left a comment

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.

Nice to have this follow up!

Comment thread 02-peer-protocol.md
t-bast added 2 commits June 1, 2026 14:12
When sending `tx_add_input`, we previously required transmitting the
entire transaction being spent to prevent malleability issues where
attackers replace a `p2wpkh` input by a `p2pkh` input after signing.

When both participants of the interactive-tx protocol sign a taproot
input, this malleability issue disappears. We thus allow transmitting
only the utxo amount and script in that case. For simplicity, we only
allow this when splicing a taproot channels (where both participants
sign the previous funding output) or when *all* inputs are using
taproot (we could be less strict, but being too smart here may risk
losing funds, so we err on the cautious side).
We add musig2 nonce fields in various `interactive-tx` messages to allow
using taproot channels with dual funding and splicing.
@t-bast
t-bast force-pushed the taproot-splicing branch from c577054 to d96fc95 Compare June 1, 2026 12:12
@t-bast
t-bast marked this pull request as ready for review June 1, 2026 12:13
@t-bast t-bast mentioned this pull request Jun 1, 2026
11 of 19 tasks
@t-bast t-bast mentioned this pull request Jul 16, 2026
12 of 19 tasks
@t-bast t-bast mentioned this pull request Aug 12, 2026
5 of 18 tasks
@t-bast t-bast mentioned this pull request Aug 27, 2026
15 of 22 tasks
@Roasbeef Roasbeef mentioned this pull request Oct 19, 2026
14 of 25 tasks

@Roasbeef Roasbeef left a comment

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.

Took another pass at this. The overall shape looks right to me, but the musig2 nonce lifecycle needs a few more requirements before implementations can line up on it. Roughly in order of importance:

1. Nonce freshness and reuse

Nothing here says the funding_nonce and commit_nonces must be freshly generated for each negotiation, including each RBF attempt of a splice. Nothing says a node must never produce two different partial signatures with the same secret nonce either. With RBF in the picture, that's the easy way to leak the funding key: sign the shared input of attempt 1, then reuse the nonce for attempt 2 and sign a different message. I'd add something like:

  - MUST generate a fresh `funding_nonce` (and `commit_nonces`) for every
    interactive-tx session, including each RBF attempt.
  - MUST NOT create more than one partial signature with a given secret nonce.

2. Reconnecting between tx_complete and tx_signatures

If peers disconnect after exchanging tx_complete but before a node has sent its tx_signatures, that node still has to produce its partial signature for the shared input after reconnecting. channel_reestablish only gains current_commit_nonce, so there's no way to exchange new funding nonces. Implementations are left with two choices: persist the secret nonce across restarts (which makes the reuse in (1) much easier to hit), or get stuck. I think channel_reestablish also needs a fresh funding nonce from each side when next_funding is set and tx_signatures hasn't been sent, with the partial signature made over those. If a node already sent tx_signatures, it should retransmit the exact same partial signature it sent before rather than re-signing.

3. Which tx_complete carries the nonces

tx_complete is sent several times in a session (every time a peer has nothing more to add), and the splice requirement only says "MUST include ... in funding_nonce" without naming the message. It should say which instance counts, e.g. the nonces MUST be included in every tx_complete and the receiver uses the ones from the final, consecutive tx_complete. Otherwise one side may sign with a nonce the other side thinks was superseded.

4. Dual-funding isn't covered

The description says this adds support for dual-funding taproot channels as well, but every new requirement is scoped to "When splicing a taproot channel". The open_channel2 flow gets no requirement for commit_nonces, so there's nothing that says where the first commitment's verification nonces come from in a dual-funded taproot open.

5. When prevtx may be omitted

The sender rule is "If the transaction splices an existing taproot channel or only uses taproot inputs". The first disjunct allows omitting prevtx in a taproot splice that also has segwit v0 inputs, which the tx_complete check then rejects. The second can't be known when tx_add_input is sent, as the peer may still add inputs. Since tx_complete is the real enforcement point, the sender rule could just be "MAY omit prevtx for a taproot input", with the rationale explaining that the session fails if any input isn't taproot.

"Taproot input" also isn't defined, while the tx_add_input check accepts any witness v1 to v16 program of 2 to 40 bytes. A v2 input passes tx_add_input but presumably isn't "taproot" for tx_complete. I'd define it once as OP_1 followed by a 32-byte push and use that in both places.

It'd also help to spell out the safety argument in the rationale. Omitting prevtx is fine because every signature in the transaction is BIP 341 with a sighash that commits to all prevout amounts and scripts, so a peer that lies in prevtx_details only makes our own signatures invalid. That also implies nodes MUST NOT use SIGHASH_ANYONECANPAY for their inputs here.

6. Smaller things

  • With prevtx_len set to 0, a tx_add_input with both shared_input_txid and prevtx_details set isn't rejected.
  • The duplicate check for prevtx_details should compare outpoints (prevtx_txid, prevtx_vout) against every previously added input, including ones that were added with a full prevtx.
  • shared_input_partial_signature carries a public_nonce, which is redundant with the funding_nonce from tx_complete. Either drop it (32 bytes), or require the receiver to fail if it doesn't match the nonce from tx_complete.
  • Typos: "Ommitting" (and the existing "ommitted"), and "scriptpubKey".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants