mirror of
https://github.com/lightning/bolts.git
synced 2025-03-15 12:20:07 +01:00
Add strict shutdown
exchange for taproot channels
It was previously unclear whether a node could send `shutdown` and `closing_complete` immediately after that whenever RBF-ing their previous closing transaction. While this worked for non-taproot channels, it doesn't allow a clean exchange of fresh musig2 nonces for taproot channels. We now require that whenever a node wants to start a new signing round, `shutdown` must be sent *and* received before sending `closing_complete`.
This commit is contained in:
parent
8efb63eb61
commit
37fa862a82
1 changed files with 30 additions and 15 deletions
|
@ -1530,29 +1530,32 @@ Closing happens in two stages:
|
||||||
| | | |
|
| | | |
|
||||||
| | shutdown(scriptA2) | |
|
| | shutdown(scriptA2) | |
|
||||||
| |----------------------------->| |
|
| |----------------------------->| |
|
||||||
|
| | shutdown(scriptB1) | | (*) Bob doesn't update his script
|
||||||
|
| |<-----------------------------| |
|
||||||
| | closing_complete | |
|
| | closing_complete | |
|
||||||
| |----------------------------->| |
|
| |----------------------------->| |
|
||||||
| | closing_sig | |
|
| | closing_sig | |
|
||||||
| |<-----------------------------| |
|
| |<-----------------------------| |
|
||||||
| | | |
|
| | | |
|
||||||
| | <Both update their script> | | (*) This is a concurrent update
|
| | <Bob updates his script> | |
|
||||||
|
| | | |
|
||||||
|
| | shutdown(scriptB2) | |
|
||||||
|
| |<-----------------------------| |
|
||||||
|
| | shutdown(scriptA2) | |
|
||||||
|
| |----------------------------->| |
|
||||||
|
| | closing_complete | |
|
||||||
|
| | <-------------------| |
|
||||||
|
| | | |
|
||||||
|
| | <Alice updates her script> | | (*) This is a concurrent update while Bob is sending closing_complete
|
||||||
| | | |
|
| | | |
|
||||||
| | shutdown(scriptA3) | |
|
| | shutdown(scriptA3) | |
|
||||||
| |-------------------> | |
|
| |-------------------> | |
|
||||||
| | closing_complete | |
|
|
||||||
| |-------------------> | |
|
|
||||||
| | shutdown(scriptB2) | |
|
|
||||||
| | <-------------------| |
|
|
||||||
| | closing_complete | |
|
|
||||||
| | <-------------------| |
|
|
||||||
| | shutdown(scriptA3) | |
|
|
||||||
| | ------------------->| |
|
|
||||||
| | closing_complete | |
|
|
||||||
| | ------------------->| | (*) B doesn't answer with closing_sig because A's sig doesn't use scriptB2
|
|
||||||
| | shutdown(scriptB2) | |
|
|
||||||
| |<------------------- | |
|
|
||||||
| | closing_complete | |
|
| | closing_complete | |
|
||||||
| |<------------------- | | (*) A doesn't answer with closing_sig because B's sig doesn't use scriptA3
|
| |<------------------- | | (*) A doesn't answer with closing_sig because B's sig doesn't use scriptA3
|
||||||
|
| | shutdown(scriptA3) | |
|
||||||
|
| | ------------------->| |
|
||||||
|
| | shutdown(scriptB2) | | (*) B answers A's shutdown with his own shutdown, without any changes
|
||||||
|
| |<-----------------------------| |
|
||||||
| | closing_complete | |
|
| | closing_complete | |
|
||||||
| |----------------------------->| | (*) A now uses scriptB2 and scriptA3 for closing_complete
|
| |----------------------------->| | (*) A now uses scriptB2 and scriptA3 for closing_complete
|
||||||
| | closing_complete | |
|
| | closing_complete | |
|
||||||
|
@ -1806,8 +1809,11 @@ Note: the details and requirements for the transaction being signed are in [BOLT
|
||||||
An output is *dust* if the amount is less than the [Bitcoin Core Dust Thresholds](03-transactions.md#dust-limits).
|
An output is *dust* if the amount is less than the [Bitcoin Core Dust Thresholds](03-transactions.md#dust-limits).
|
||||||
|
|
||||||
Both nodes:
|
Both nodes:
|
||||||
- After a `shutdown` has been received, AND no HTLCs remain in either commitment transaction:
|
- After a `shutdown` has been sent and received, AND no HTLCs remain in either commitment transaction:
|
||||||
- SHOULD send a `closing_complete` message.
|
- SHOULD send a `closing_complete` message.
|
||||||
|
- When receiving `shutdown` again, if it did not send `shutdown` first:
|
||||||
|
- MUST respond with `shutdown`.
|
||||||
|
- MAY send `closing_complete` afterwards.
|
||||||
|
|
||||||
The sender of `closing_complete` (aka. "the closer"):
|
The sender of `closing_complete` (aka. "the closer"):
|
||||||
- MUST set `fee_satoshis` to a fee less than or equal to its outstanding balance, rounded down to whole satoshis.
|
- MUST set `fee_satoshis` to a fee less than or equal to its outstanding balance, rounded down to whole satoshis.
|
||||||
|
@ -1828,6 +1834,10 @@ The sender of `closing_complete` (aka. "the closer"):
|
||||||
- SHOULD NOT set `closer_and_closee_outputs`.
|
- SHOULD NOT set `closer_and_closee_outputs`.
|
||||||
- Otherwise:
|
- Otherwise:
|
||||||
- MUST set both `closer_output_only` and `closer_and_closee_outputs`.
|
- MUST set both `closer_output_only` and `closer_and_closee_outputs`.
|
||||||
|
- If it wants to send another `closing_complete` (e.g. with a different `fee_satoshis`):
|
||||||
|
- MUST send `shutdown` first.
|
||||||
|
- MUST receive `shutdown` from the remote node in response.
|
||||||
|
- MUST use the `scriptpubkey`s from those `shutdown` messages.
|
||||||
|
|
||||||
The receiver of `closing_complete` (aka. "the closee"):
|
The receiver of `closing_complete` (aka. "the closee"):
|
||||||
- If `fee_satoshis` is greater than the closer's outstanding balance:
|
- If `fee_satoshis` is greater than the closer's outstanding balance:
|
||||||
|
@ -1885,7 +1895,12 @@ there's a race where you could receive `closing_complete` for the previous outpu
|
||||||
signature won't validate. In this case, ignoring the `closing_complete` is the correct behaviour,
|
signature won't validate. In this case, ignoring the `closing_complete` is the correct behaviour,
|
||||||
as the new `shutdown` will trigger a new `closing_complete` with the correct signature. This
|
as the new `shutdown` will trigger a new `closing_complete` with the correct signature. This
|
||||||
assumption that we only remember the last-sent of any message is why so many cases of bad
|
assumption that we only remember the last-sent of any message is why so many cases of bad
|
||||||
signatures are simply ignored.
|
signatures are simply ignored.
|
||||||
|
|
||||||
|
When sending a new `shutdown`, we must receive a new `shutdown` from the remote node before
|
||||||
|
sending `closing_complete`. This is necessary to be compatible with future taproot channels
|
||||||
|
that use musig2 and need to exchange random nonces every time a transaction spending the channel
|
||||||
|
output is signed.
|
||||||
|
|
||||||
If the closer proposes a transaction which will not relay (an output is dust, or the fee rate it
|
If the closer proposes a transaction which will not relay (an output is dust, or the fee rate it
|
||||||
proposes is too low), it doesn't harm the closee to sign the transaction.
|
proposes is too low), it doesn't harm the closee to sign the transaction.
|
||||||
|
|
Loading…
Add table
Reference in a new issue