-
Notifications
You must be signed in to change notification settings - Fork 525
Funding Timeout Recovery proposal #854
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,179 @@ | ||
| # Funding Timeout Recovery | ||
|
|
||
| > "So long, and thanks for all the sigs" | ||
| > -- Hitchhikers guide to Lightning | ||
|
|
||
|
|
||
| ## Problem description | ||
|
|
||
| Due to circumstances it may take considerable time for a funding | ||
| transaction to confirm, e.g., the funder chose to attach a fee that is | ||
| too low to guarantee timely confirmation. This means the channel | ||
| funding may not complete for quite some time, and the specification | ||
| thus allows the fundee to forget the channel after 2016 blocks: | ||
|
|
||
| > - SHOULD forget the channel if it does not see the correct funding | ||
| > transaction after a timeout of 2016 blocks. | ||
|
|
||
| Since this leaves the funder in a situation where they are forced | ||
| to use the commitment transaction, and since the commitment | ||
| transaction is using an overestimated feerate, this could end up | ||
| costing the funder more than strictly necessary, and the specification | ||
| suggests avoiding this situation thus: | ||
|
|
||
| > If the fundee forgets the channel before it was confirmed, the | ||
| > funder will need to broadcast the commitment transaction to get his | ||
| > funds back and open a new channel. To avoid this, the funder should | ||
| > ensure the funding transaction confirms in the next 2016 blocks. | ||
|
|
||
| However, despite a funder's best efforts to estimate the funding | ||
| transaction fee correctly, the estimation may still fail to guarantee | ||
| timely confirmation. | ||
|
|
||
| This proposal describes a method for a channel to be closed | ||
| collaboratively, without going through the commitment transaction with | ||
| overestimated feerate, and without encumbering the funder's funds with | ||
| the unilateral close timeout. | ||
|
|
||
|
|
||
| ## Overview | ||
|
|
||
| Upon agreeing to open a new channel with a peer, the fundee generates | ||
| a new bitcoin private key `funding_privkey` (corresponding to the | ||
| `funding_pubkey`) that is used to sign off on the funds in the channel | ||
| once the funding is complete, i.e., the funding transaction is | ||
| confirmed. This *funding_pubkey* is used exclusively when signing off | ||
| on changes to the channel, no unrelated funds are ever secured using | ||
| this private key. | ||
|
|
||
| The fundee may therefore sign a collaborative close transaction with | ||
| the `funding_privkey` at any time, as long as they remember not to | ||
| sign any future commitment transactions. Thus the fundee may provide a | ||
| blanked signature for a commitment transaction using `sighash_none`, | ||
| signing off whatever the funder intends to do with the funding | ||
| outpoint. This frees the parties from having to negotiate a closing | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I feel a little bit dumb asking this but would this idea not also work for a regular mutual close? The fees are paid by the funder and this would remove the necessity to have the negotiation of closing fees via
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. sighash none would allow the other party to only include an output for himself, it think you mean a sighash single, but that would be clearly visible on chain that a lightning channel was closed, this doesn't matter with announced ones (just search the txid on an LN explorer) but it does with private channels |
||
| transaction fee, since the funder can simply change the outputs on the | ||
| closing transaction without invalidating the fundee's signature. | ||
|
|
||
| The fundee receives the blank signature as part of an error message | ||
| when attempting to re-establish a connection, allowing them to build a | ||
| closing transaction, with arbitrary outputs, e.g., not encumbering the | ||
| funder's return output with a timeout. | ||
|
|
||
This comment was marked as abuse.
Sorry, something went wrong. |
||
|
|
||
| ## Implementation | ||
|
|
||
| This proposal is only applicable to single-funded channels, as | ||
| dual-funded channels do not suffer from this issue. | ||
|
|
||
| The fundee may forget a channel if it hasn't been confirmed after | ||
| 2016, however it may chose to retain a minimal stub of the channel to | ||
| help the funder recover the funds gracefully in case the funding | ||
| transaction eventually confirms. In order to do so it must retain the | ||
| following information: | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Of course this is less information than a regular channel but it still wont forget the channel opening attempt completely. So How is that an improvement? |
||
|
|
||
| - The `channel_id` that was exchanged during the funding | ||
| sub-protocol. | ||
| - Information used to derive the `funding_privkey`. | ||
| - The `funding_outpoint` from the `funding_created` message. | ||
| - The funder's `funding_pubkey`. | ||
|
|
||
| This information is required in order to construct a valid closing | ||
| transaction without any outputs. The outputs will later be modifiable | ||
| by the funder, and committed to by their own signature. The fundee | ||
| signs the closing transaction with `sighash_none` to allow these | ||
This comment was marked as abuse.
Sorry, something went wrong. |
||
| changes by the funder. | ||
|
|
||
| A stub MUST NOT be created if the funding transaction confirmed before | ||
| the fundee decided to forget the channel and mark it as closed / | ||
| forgotten. | ||
|
|
||
| Upon forgetting the channel, the fundee has to store the above | ||
| information locally in order to retrieve it when required. The fundee | ||
| MUST mark the channel as closed, preventing them from signing off on | ||
| any future changes, and any re-establishment attempt of the channel | ||
| MUST result in an immediate error being returned. | ||
|
|
||
| The following steps encompass the funding timeout recovery: | ||
|
|
||
| 1. Upon reconnecting the funder sends a `channel_reestablish` message | ||
| as usual. | ||
| 2. Upon receiving the `channel_reestablish` the fundee notices that | ||
| it has forgotten the channel, but it has a funding timeout | ||
| recovery stub matching the `channel_id`. | ||
| 3. The fundee create a closing transaction from the channel stub, | ||
| with `nSequence=0xfffffffd`, sign it with the private key matching | ||
| `fundee_privkey`. | ||
| 4. The signature is sent as part of the `error` message (see Error | ||
| Details change below), as TLV type XXX. | ||
| 5. The funder receives the signature and verifies that it matches the | ||
This comment was marked as abuse.
Sorry, something went wrong.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good point, but I guess that's pretty much implied, isn't it? |
||
| expected close transaction. | ||
| 6. The funder completes the close transaction with the desired | ||
| outputs, the fundee signature, and its own signature. | ||
| 7. The close transaction is broadcast, completing the close operation. | ||
|
cdecker marked this conversation as resolved.
|
||
|
|
||
| Notice that since the signature from the fundee is a `sighash_none` | ||
| signature, it doesn't get invalidated when changing the outputs. This | ||
| allows the funder to chose any desired feerate. In addition setting | ||
| the `nSequence=0xfffffffd` opts into RBF, allowing the funder to bump | ||
| the feerate if desired. | ||
|
|
||
|
|
||
| ## Extension: Funding Transaction Alias | ||
|
|
||
| Under some circumstances it may happen that the funding transaction is | ||
| malleated, and the funding outpoint is no longer the same as | ||
| advertised during the negotiation. In this case any commitment | ||
| transaction negotiated during the opening will also be invalid, and | ||
| the funds are stuck in limbo. | ||
This comment was marked as abuse.
Sorry, something went wrong.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yea, what's the exact purpose of this - is it just to allow RBF? In that case isn't it simpler to open a fresh channel?
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Its main purpose is to prevent some users from losing funds because they decided to RBF-bump the funding transaction using external tools. We had one user that took the funding transaction, added it into electrum and used it to bump the funding transaction, without knowing that this would make the channel completely unusable, and unable to recover the funds, since the commitment transaction was now detached from the funding. We know that other implementations have had similar issues in the past, so we'd like to have a builtin way of fixing this if the counterparty is collaborative. This is a gentleman's agreement to help recover funds in this case, but it is not a guarantee that it works, since a malicious peer may just as well try to extort the funder. It should be clear that the funder is at fault here, since he malleated the funding tx, but having a mechanism of helping them recover is nice :-)
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this should be described in the rational for the Alias |
||
|
|
||
| To solve this issue, the funder can provide an alias, i.e., the | ||
| malleated outpoint as part of the re-establish. Upon receiving a | ||
| re-establish with an alias the fundee MAY mark the channel as closed, | ||
| derives the necessary information (detailed above), but replaces the | ||
| `funding_outpoint` with the one from the re-establish message and | ||
| returns the generated signature as part of the `error` message. | ||
|
|
||
|
|
||
| ## Safety | ||
|
|
||
| The `funding_privkey` is assumed to be unique for every channel. If | ||
| this is the case then any signature the fundee provides can only ever | ||
| be applied to transactions relating to the channel, i.e., signing a | ||
| commitment or close transaction for that channel. It is possible with | ||
| the extension for a funder to receive a signature for an arbitrary | ||
| output, however given the above constraint, it must be either the | ||
| funding output for the channel, or the signature doesn't match the | ||
| output's spending requirement as it's bound to another public-key or | ||
| script. | ||
|
|
||
|
|
||
| ## Required Changes | ||
|
|
||
| The following changes are required to existing messages. | ||
|
|
||
|
|
||
| ### Error Details | ||
|
|
||
| The `error` message is extended with a TLV stream at the end to | ||
| include details about the error. This proposal uses this to return the | ||
| blank signature from the fundee to the funder if they forgot the | ||
| channel. | ||
|
|
||
|
|
||
| ### Re-establish TLV | ||
|
|
||
| Only required for the funding transaction alias extension. The | ||
| `channel_reestablish` message is extended with a TLV stream at the end | ||
| to include optional fields. This proposal adds the optional | ||
| `funding_transaction_alias` TLV type to be added in this stream. | ||
|
|
||
|
|
||
| ## Open Questions | ||
|
|
||
| - [ ] The specification appears to not require `funding_pubkey` to be | ||
| unique to the channel. Is anyone reusing their it? Can we | ||
| require it to be unique? | ||
This comment was marked as abuse.
Sorry, something went wrong.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We also use unique per-channel secrets in eclair, it makes sense to require it to be unique.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks like KEYOLO is also an option then, I added #866 as a counter-proposal using the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sounds good. I'm adding an explicit doc in lightning-signer that the channel nonce should not be reused if supplied, and we do generate a unique one if it is not supplied. The generated keys are not in the BIP32 hierarchy, so should not collide with layer-1 keys. |
||
| - [ ] Do we want to piggyback the signature on the error message or | ||
This comment was marked as abuse.
Sorry, something went wrong.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can always extend this using TLVs, to include a collaboration fee (do we want to formalize extortion???) and whatever else we want, having that flexibility and re-using the message we already have are not mutually exclusive imho. What I like about the error message is that it is atomic, either we get an error along with all the information required to react to it, or we don't. If we split across multiple messages we might get the error, but not the extra information, or we might get the extra information first, not know what to do with it, and only then the error. |
||
| shall we add a new message that preceeds the error message? | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The only use case I am seeing is to request a Funding Transaction Alias but that seems a bit complicated from a communication flow perspective. |
||
| - [ ] Additional safety checks: `next_commitment_number` must be 1. | ||
Uh oh!
There was an error while loading. Please reload this page.