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

Reply via email to