Skip to content

Conversation

rustyrussell
Copy link
Contributor

This is useful for implementing an LSP, where you want to open a zero conf channel, and only broadcast the actual funding tx once they've sent enough to make it worthwhile.

The first few patches actually fix an unrelated bug I realized when looking at this: if we crash, nothing broadcasts the funding transactions again. If bitcoind doesn't keep it, or if it didn't make it to bitcoind, the transaction will never reach the blockchain.

The flow is:

  • fundchannel_start
  • fundchannel_complete withhold=true
  • Either sendpsbt (resets withhold to false), or close channel (immediately closes channel without any txs).

This can definitely happen with zeroconf and the about-to-be-implemented withheld=True:

```
lightningd-1 2025-09-12T13:17:50.848Z **BROKEN** 022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59-chan#1: Illegal gossip state transition: CGOSSIP_WAITING_FOR_SCID->CGOSSIP_CHANNEL_UNANNOUNCED_DYING
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Interestingly, @niftynei added a funding_psbt column to the db in 2020,
but we don't use it (it was removed early 2021 with the "inflight"
architecture).  So we don't need to add a new column, just plumb it
back in.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Fixed: Protocol: we now re-transmit unseen funding transactions on startup, for more robustness.
…e sendpsbt.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Added: JSON-RPC: `psbt` field in `funding` in listpeerchannels, and `funding_psbt` in listclosedchannels.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
…re-send.

This covers the other corner case, where we crash before actually
signing and sending the PSBT.  We can spot this because the channel is
in AWAITING_LOCKIN and we have a PSBT, but it's not signed yet.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Normally we don't care, but if we're withholding it, keep it around
so we can sign & broadcast later.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
…els.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Added: JSON-RPC: `listpeerchannels` `funding` object `withheld` flag, and `listclosedchannels` `funding_withheld` flags, indicating fundchannel_complete was called with the `withheld` parameter true.
…ithheld channel.

There's no funding tx to spend.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
…art.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This is just a polite way of telling us that if we close, don't bother broadcasting
since we didn't broadcast the funding tx.

Changelog-Added: JSON-RPC: `fundchannel_complete` new parameter `withhold` (default false).
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
@rustyrussell rustyrussell added this to the v25.12 milestone Sep 12, 2025
@rustyrussell rustyrussell requested a review from nepet September 12, 2025 15:27
@nepet
Copy link
Collaborator

nepet commented Oct 7, 2025

Looks good to me so far. I'll build the "Client-Trusts-LSP" mode for the LSP on top of this PR to see if it contains everything we need once #8569 got merged.

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