Skip to content
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

option_simple_close (features 60/61) #1096

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
89 changes: 89 additions & 0 deletions 02-peer-protocol.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ operation, and closing.
* [Channel Close](#channel-close)
* [Closing Initiation: `shutdown`](#closing-initiation-shutdown)
* [Closing Negotiation: `closing_signed`](#closing-negotiation-closing_signed)
* [Closing Negotiation: `closing_complete` and `closing_sig`](#closing-negotiation-closing_complete-and-closing_sig)
* [Normal Operation](#normal-operation)
* [Forwarding HTLCs](#forwarding-htlcs)
* [`cltv_expiry_delta` Selection](#cltv_expiry_delta-selection)
Expand Down Expand Up @@ -584,6 +585,17 @@ Closing happens in two stages:
| |<-(?)-- closing_signed Fn----| |
+-------+ +-------+

+-------+ +-------+
t-bast marked this conversation as resolved.
Show resolved Hide resolved
| |--(1)----- shutdown ------->| |
| |<-(2)----- shutdown --------| |
| | | |
| | <complete all pending HTLCs> | |
| A | ... | B |
| | | |
| |--(3)-- closing_complete Fee->| |
rustyrussell marked this conversation as resolved.
Show resolved Hide resolved
| |<-(4)-- closing_sig ----------| |
+-------+ +-------+

### Closing Initiation: `shutdown`

Either node (or both) can send a `shutdown` message to initiate closing,
Expand Down Expand Up @@ -776,6 +788,83 @@ satoshis, which is possible if `dust_limit_satoshis` is below 546 satoshis).
No funds are at risk when that happens, but the channel must be force-closed as
the closing transaction will likely never reach miners.

### Closing Negotiation: `closing_complete` and `closing_sig`

Once shutdown is complete, the channel is empty of HTLCs, there are no commitments
for which a revocation is owed, and all updates are included on both commitments,
the final current commitment transactions will have no HTLCs.

Each peer says what fee it will pay, and the other side simply signs that transaction. The only complexity comes from allowing each side to omit its own output should it be uneconomic.
t-bast marked this conversation as resolved.
Show resolved Hide resolved

This process will be repeated every time a `shutdown` message is received, which allows re-negotiation.
t-bast marked this conversation as resolved.
Show resolved Hide resolved

1. type: 40 (`closing_complete`)
2. data:
* [`channel_id`:`channel_id`]
* [`u64`:`fee_satoshis`]
* [`u8`: `has_closer_output`]
t-bast marked this conversation as resolved.
Show resolved Hide resolved
* [`signature`:`signature_with_closee_output`]
t-bast marked this conversation as resolved.
Show resolved Hide resolved
* [`signature`:`signature_without_closee_output`]

1. type: 41 (`closing_sig`)
2. data:
* [`channel_id`:`channel_id`]
* [`u8`: `closee_output`]
t-bast marked this conversation as resolved.
Show resolved Hide resolved
* [`signature`:`signature`]

#### Requirements

Note: the details and requirements for the transaction being signed are in [BOLT 3](03-transactions.md#closing-transaction)).

Both nodes:
- After a `shutdown` has been received, AND no HTLCs remain in either commitment transaction:
- SHOULD send a `closing_complete` message.

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.
- SHOULD set `has_closer_output` to 0 if it considers its own remaining balance to be uneconomic.
- Otherwise MUST set `has_closer_output` to 1.
- If it sets `has_closer_output` to 1:
- MUST set `signature_with_closee_output` to a valid signature of a transaction with both closer and closee outputs.
- MUST set `signature_without_closee_output` to a valid signature of a transaction with only a closer output.
- Otherwise: (`has_closer_output` is 0):
- MUST set `signature_with_closee_output` to a valid signature of a transaction with only the closee output.
- MUST set `signature_without_closee_output` to a valid signature of a transaction with only the null output.
t-bast marked this conversation as resolved.
Show resolved Hide resolved
t-bast marked this conversation as resolved.
Show resolved Hide resolved

The receiver of `closing_complete` (aka. "the closee"):
- if either `signature_with_closee_output` or `signature_without_closee_output` is not valid for the closing transactions specified in [BOLT #3](03-transactions.md#closing-transaction) OR non-compliant with LOW-S-standard rule<sup>[LOWS](https://github.com/bitcoin/bitcoin/pull/6769)</sup>:
- SHOULD send a `warning` and close the connection, or send an
`error` and fail the channel.
- Otherwise:
- MUST select one of the signatures (and thus, transactions) to respond to.
- SHOULD sign and broadcast that transaction.
- SHOULD send `closing_sig`.
t-bast marked this conversation as resolved.
Show resolved Hide resolved

The sender of `closing_sig`:
- if it selected `signature_with_closee_output` to broadcast:
- MUST set `closee_output` to 1.
- MUST set `signature` to a valid signature on that transaction.
- otherwise (it selected `signature_without_closee_output`):
- MUST set `closee_output` to 0.
- MUST set `signature` to a valid signature on that transaction.

The receiver of `closing_sig`:
- SHOULD broadcast the transaction indicated by `closee_output`.

### Rationale

The close protocol is designed to avoid any failure scenarios caused by fee disagreement, since each side offers to pay its own desired fee.

Multiple signatures are given, so each side can choose whether it wants to include its own output. In the case of large fees and tiny channels, where neither side wants its output, the use of an OP_RETURN simply cleans up the dangling unspent transaction output. This is expected to be extremely rare.

Note that there is usually no reason to pay a high fee for rapid processing, since an urgent child could pay the fee on the closing transactions' behalf.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could also mention RBF of the closing transaction here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also I fail to understand how we could ever have a transaction be urgent enough to push for confirmation if it involved burning all of the outputs in an OP_RETURN.


If the closer proposes a transaction which will not relay (either its own output is dust, or the fee rate it proposes is too low), it doesn't harm the closee to sign the transaction.

Similarly, if the closer proposes a high fee, it doesn't harm the closee to sign the transaction, as the closer is paying.

There's a slight game where each side would prefer the other side pay the fee, and proposes a minimal fee. If neither side proposes a fee which will relay, the negotiation can occur again, or the final commitment transaction can be spent. In practice, the opener has an incentive to offer a reasonable closing fee, as they would pay the fee for the commitment transaction, which also costs more to spend.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This discussion of the game theory hints at an issue I've always had with the "opener pays" rule. I do understand the pathological scenario that the rule is meant to avoid (where a malicious node can drain the funds of a victim node by repeatedly opening and abandoning channels to it), but this new proposal creates a perverse incentive.

Olav opens a channel to Kristján. Some time later, Kristján wants the channel closed. Under this new proposal, Kristján's fee-optimal channel-closing strategy would be to transmit a bogus error message to Olav so that Olav will be forced (by protocol convention) to unilaterally close the channel. Thusly, Kristján would obtain an immediately spendable output and would avoid paying any fees.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's always true.

But K can also mutual close at <1 sat per byte.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How can any mutual closing transaction use <1 sat/vB fee rate? The transaction would not propagate.

And you're right that it's always true. It has always irked me. I swear I have seen some cases where nodes to which I have opened channels have sent me error messages for no reason other than to get me to unilaterally close. I think it was a design mistake to have commitment transactions reward the non-closing party with an immediately spendable output. I think commitment transactions should time-lock both outputs to discourage baiting a peer into unilaterally closing.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That will disappear once we have package relay, because at that point commitment transactions will pay no fees. The fees will have to be paid using CPFP on an ephemeral anchor. Also, if you send bogus errors, nodes will start blacklisting you at some point and won't accept new channels from you: this isn't the case today, but will definitely be in the future.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The opener should at least be on the hook for whatever the commitment fee is. Otherwise, as the non-opener, it's cheaper to FC and wait out the time lock. Also, if there's nothing on the non-opener side, is FC the only options since there's nothing on that side to pay the fee.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I want to challenge this idea of "it's cheaper to FC and wait out the time lock". Having money locked up carries opportunity cost of the entire output. Yes you may save in fees, but your outputs are tied up in chain resolution and that is a cost in its own right.

Also, if there's nothing on the non-opener side, is FC the only options since there's nothing on that side to pay the fee.

Why would a node be concerned about aggressively closing a channel that has no capital tied up in it?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Current coop close is ~168 vB (2 x P2WPKH outputs) to ~192 vB (2 x P2TR outputs). Sweeping the timelock is 121-123 vB.. so ~35-50% smaller tx. I agree with the time cost, but if you are closing due to months of inactivity, what's another up to two weeks. But the opener would be doubly screwed since they would pay the FC (+ anchors) and then have to pay to sweep. I supposed the opener can "deter" this by keeping max commit fees low.

Closing channels should be discouraged, but having dead/inactive channel is worse.

In my mind, game theory would have me coop close at a very low fee if the balance is mostly on the other side or FC if it's mostly on my side and I'm not the opener and commit fee is high enough.

Why would a node be concerned about aggressively closing a channel that has no capital tied up in it?

More of a hypothetical.. how does a closer pay if there's little to nothing on their side.

I agree a change to channel closing is needed, but 100% opener to 100% closer is a pretty drastic change. I would like to see the opener using (some of) the commit fee already reserved and/or splitting the fee based on balance.


## Normal Operation

Once both nodes have exchanged `channel_ready` (and optionally [`announcement_signatures`](07-routing-gossip.md#the-announcement_signatures-message)), the channel can be used to make payments via Hashed Time Locked Contracts.
Expand Down
38 changes: 37 additions & 1 deletion 03-transactions.md
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,9 @@ The witness script for the output is:

To spend this via penalty, the remote node uses a witness stack `<revocationsig> 1`, and to collect the output, the local node uses an input with nSequence `to_self_delay` and a witness stack `<local_delayedsig> 0`.

## Closing Transaction
## Classic Closing Transaction

This variant is used for `closing_signed` messages (i.e. where `option_simple_close` is not negotiated).

Note that there are two possible variants for each node.

Expand Down Expand Up @@ -388,6 +390,40 @@ has been used.
There will be at least one output, if the funding amount is greater
than twice `dust_limit_satoshis`.

## Closing Transaction

This variant is used for `closing_complete` and `closing_sig` messages (i.e. where `option_simple_close` is negotiated).

In this case, the node sending `closing_complete` ("the closer") pays the fees, and the sequence is set to 0xFFFFFFFD to allow RBF. The outputs are ordered as detailed in [Transaction Output Ordering](#transaction-output-ordering).

Two closing transactions are always produced: one `with_closee_output` one `without_closee_output` (the non-closer chooses which to accept). `closing_complete` contains `has_closer_output` to indicate whether the closer's output is in the transactions.

* version: 2
* locktime: 0
* txin count: 1
* `txin[0]` outpoint: `txid` and `output_index` from `funding_created` message
* `txin[0]` sequence: 0xFFFFFFFD
* `txin[0]` script bytes: 0
* `txin[0]` witness: `0 <signature_for_pubkey1> <signature_for_pubkey2>`

* txout count: 1 or 2 of the following
* The closer output:
* `txout` amount: the final balance for the closer, minus `closing_complete` `fee_satoshis`, rounded down to whole satoshis.
* `txout` script: as specified in that closer's `scriptpubkey` in its `shutdown` message
* The closee output:
* `txout` amount: the final balance for the closer, rounded down to whole satoshis.
t-bast marked this conversation as resolved.
Show resolved Hide resolved
* `txout` script: as specified in that closee's `scriptpubkey` in its `shutdown` message
* The null output:
* `txout` amount: 0
* `txout` script: `OP_RETURN` (106).

### Requirements

Each node offering a signature:
- MUST round each output down to whole satoshis.
- MUST subtract the fee given by `fee_satoshis` from the closer output.


## Fees

### Fee Calculation
Expand Down
2 changes: 2 additions & 0 deletions 09-features.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ The Context column decodes as follows:
| 46/47 | `option_scid_alias` | Supply channel aliases for routing | IN | | [BOLT #2][bolt02-channel-ready] |
| 48/49 | `option_payment_metadata` | Payment metadata in tlv record | 9 | | [BOLT #11](11-payment-encoding.md#tagged-fields) |
| 50/51 | `option_zeroconf` | Understands zeroconf channel types | IN | `option_scid_alias` | [BOLT #2][bolt02-channel-ready] |
| 60/61 | `option_simple_close` | Simplified closing negotiation | IN | `option_shutdown_anysegwit` | [BOLT #2][bolt02-simple-close] |
rustyrussell marked this conversation as resolved.
Show resolved Hide resolved

## Definitions

Expand Down Expand Up @@ -96,6 +97,7 @@ This work is licensed under a [Creative Commons Attribution 4.0 International Li

[bolt02-retransmit]: 02-peer-protocol.md#message-retransmission
[bolt02-open]: 02-peer-protocol.md#the-open_channel-message
[bolt02-simple-close]: 02-peer-protocol.md#closing-negotiation-closing_complete-and-closing_sig
[bolt03-htlc-tx]: 03-transactions.md#htlc-timeout-and-htlc-success-transactions
[bolt02-shutdown]: 02-peer-protocol.md#closing-initiation-shutdown
[bolt02-channel-ready]: 02-peer-protocol.md#the-channel_ready-message
Expand Down