TL;DR: We had a user promise the wrong txid for a funding tx[1]. This of course requires remote cooperation to get their funds back. This lead me to a temporary solution, but Christian suggested a more wideranging one.
The problem ----------- With single-sided[2] funding, the opener gives the txid and outnum of the funding tx. It gets the signature for the first (noop) commitment tx, and then broadcasts the funding tx. If it screwed up, because they RBF the funding tx, or other subtle problems, they cannot access their funds. After some time, the remote node will give up and forget the channel. The hack -------- I have added feature 104/105 as OPT_SHUTDOWN_WRONG_FUNDING, and added a TLV stream to the shutdown message, with 100 `wrong_funding` providing an alternate funding txid and outnum.[3] If the recipient supports it (config setting is called 'experimental-shutdown-wrong-funding'), they make sure the channel is unused (next commitment and next revocation numbers both 1), and that the sender was the opener[4]. They then use these values as the input for the shutdown negotiation, and continue like normal. This is great, as it doesn't require interaction for the rescue. Limitations ----------- The peer will forget the channel 2016 blocks after proposal (we don't actually delete it from the db, but it would require some fishing as we don't load it into memory). So you have to figure out what went wrong and fix it in a timely manner. We are considering a stub state for old channels to allow some limited interaction with such dead channels, but it's not implemented for now. We want this for reestablish rexmit anyway. This also doesn't help the case of "I accidentally all my funds to the channel 2of2 address"[5], since we don't allow variation of the amount, and we only allow a single shutdown flow. Improvements ------------ Christian has been thinking in parallel, and suggested we send a signature for the last tx in the reestablish message. That would allow them to recreate the last valid transaction themselves if they wanted to, but wouldn't help this case. Or more, we could sign anything they ask for dead channels (in our case, 100 deep, all txs completely resolved, or 2016 later with no funding seen). More radically, I suggested we could actually give them our private key in this case, which would allow late post-hoc rescue of any strangeness they did. Christian and I checked: we use hardened derivation and so it's fairly harmless. This last possibility would allow nice tooling around this rescue feature, but revealing a secret key is not something I would do lightly.[6] Thoughts? Thanks! Rusty. [1] We have a fundchannel_start / fundchannel_complete API, but the latter takes *TXID* rather than a whole PSBT. Calculating the txid is non-trivial (P2SH-wrapped inputs!), and of course this presents a giant footgun, as users simply use the TXID of the global tx and it *sometimes* works. API is changing before release![7] [2] Dual-funding avoids this entire problem by co-constructing the funding tx, rather than presenting the txid/outnum as a fait accompli. Even if one side doesn't contribute, they calculate the funding txid themselves. [3] https://github.com/ElementsProject/lightning/pull/4421 [4] We disable `wrong_funding` for dual-opened-negotiated channels too. [5] t-bast said someone did this. I think I died a little inside. [6] `option_boating_accident_as_a_service`? [7] For the love of God, GO ALL IN ON PSBT and don't do hybrid APIs like this. Rusty is dumb. Don't be like Rusty. _______________________________________________ Lightning-dev mailing list Lightning-dev@lists.linuxfoundation.org https://lists.linuxfoundation.org/mailman/listinfo/lightning-dev