-
Notifications
You must be signed in to change notification settings - Fork 492
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
Closing tx detailed specification #201
Changes from 3 commits
f7d151d
ff17597
04d318a
e3d9051
45eacb5
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 |
---|---|---|
|
@@ -414,38 +414,35 @@ The sender SHOULD set the initial `fee_satoshis` according to its | |
estimate of cost of inclusion in a block. | ||
|
||
The sender MUST set `signature` to the Bitcoin signature of the close | ||
transaction with the node responsible for paying the bitcoin fee | ||
paying `fee_satoshis`, then removing any output which is below | ||
its own `dust_limit_satoshis`. The sender MAY then also eliminate its own | ||
output from the mutual close transaction. | ||
transaction as specified in [BOLT #3](03-transactions.md#closing-transaction). | ||
|
||
The receiver MUST check `signature` is valid for either the close | ||
transaction with the given `fee_satoshis` as detailed above and its | ||
own `dust_limit_satoshis` OR that same transaction with the sender's | ||
output eliminated, and MUST fail the connection if it is not. | ||
The receiver MUST check `signature` is valid for either variant of close | ||
transaction specified in [BOLT #3](03-transactions.md#closing-transaction), | ||
and MUST fail the connection if it is not. | ||
|
||
If `fee_satoshis` is equal to its previously sent `fee_satoshis`, the receiver | ||
SHOULD close the connection and SHOULD sign and broadcast the final closing | ||
transaction. | ||
|
||
Otherwise, if this is the first `closing_signed` received, the | ||
recipient MUST fail the connection if `fee_satoshis` is greater than | ||
the base fee of the final commitment transaction as calculated in | ||
[BOLT #3](03-transactions.md#fee-calculation). Otherwise the | ||
recipient SHOULD fail the connection if `fee_satoshis` is not strictly | ||
between its last-sent `fee_satoshis` and its previously-received | ||
`fee_satoshis`, unless it is equal to the previously-received | ||
`fee_satoshis` and it has reconnected since then. | ||
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. In line with my comment on #199 (which is related to this PR as well), why are we requiring nodes remember the prior close negotiation state between re-connects. It may be the case that fees have gone down significantly since the prior negotiation, and both nodes would be massively overpaying (or the other way around). If we instead allow nodes to forget any negotiation upon re-connect then this allows them to have more completely control over the fees that they're paying. From another angle, it seems that auto-attempt-to-re-close-on-re-connect may not even be a behavior that we desire. Days (even weeks) may pass between re-connects, it may not necessarily be the case that if a user wished to cooperatively close out the channel 3 days ago, that they still wish to do so upon re-connect (whenever that is). |
||
|
||
If the receiver agrees with the fee, it SHOULD reply with a | ||
`closing_signed` with the same `fee_satoshis` value, otherwise it | ||
SHOULD propose a value strictly between the received `fee_satoshis` | ||
MUST propose a value strictly between the received `fee_satoshis` | ||
and its previously-sent `fee_satoshis`. | ||
|
||
Once a node has sent or received a `closing_signed` with matching | ||
`fee_satoshis` it SHOULD close the connection and SHOULD sign and | ||
broadcast the final closing transaction. | ||
|
||
#### Rationale | ||
|
||
There is a possibility of irreparable differences on closing if one | ||
node considers the other's output too small to allow propagation on | ||
the bitcoin network (aka "dust"), and that other node instead | ||
considers that output to be too valuable to discard. This is why each | ||
side uses its own `dust_limit_satoshis`, and the result can be a | ||
signature validation failure, if they disagree on what the closing | ||
transaction should look like. | ||
|
||
However, if one side chooses to eliminate its own output, there's no | ||
reason for the other side to fail the closing protocol, so this is | ||
explicitly allowed. | ||
The "strictly between" requirements ensure that we make forward | ||
progress, even if only by a single satoshi at a time, but we have | ||
to allow for retransmission on reconnection. | ||
|
||
Note that there is limited risk if the closing transaction is | ||
delayed, and it will be broadcast very soon, so there is usually no | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,6 +15,7 @@ This details the exact format of on-chain transactions, which both sides need to | |
* [Received HTLC Outputs](#received-htlc-outputs) | ||
* [Trimmed Outputs](#trimmed-outputs) | ||
* [HTLC-Timeout and HTLC-Success Transactions](#htlc-timeout-and-htlc-success-transactions) | ||
* [Closing Transaction](#closing-transaction) | ||
* [Fees](#fees) | ||
* [Fee Calculation](#fee-calculation) | ||
* [Fee Payment](#fee-payment) | ||
|
@@ -234,6 +235,45 @@ 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 | ||
|
||
Note that there are two possible variants for each node. | ||
|
||
* version: 1 | ||
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. Isn't that version 2? 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. @Roasbeef said version 1, since version 2 only needed for CLTV, which we don't need here. I don't really mind... 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. Using version 1 here allow us to blend in a bit more with regular (non contract) traffic (assuming an eventual saturation of transactions spending segwit inputs). |
||
* locktime: 0 | ||
* txin count: 1 | ||
* `txin[0]` outpoint: `txid` and `output_index` from `funding_created` message | ||
* `txin[0]` sequence: 0xFFFFFFFF | ||
* `txin[0]` script bytes: 0 | ||
* `txin[0]` witness: `0 <signature_for_key1> <signature_for_key2>` | ||
* txout count: 0, 1 or 2 | ||
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. In what case would having no transaction outputs be warranted or valid? |
||
* `txout` amount: final balance to be paid to one node (minus `fee_satoshis` from `closing_signed` if this peer funded the channel) | ||
* `txout` script: as specified in that node's `scriptpubkey` in its `shutdown` message. | ||
|
||
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. BIP 69 should be used here as well. I'm assuming y'all already do so? 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. yes |
||
### Requirements | ||
|
||
Each node offering MUST subtract the fee given by `fee_satoshis` from | ||
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. How about:
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. Yes, that's better, |
||
the output to the funder. Each node MUST then remove any output below | ||
the `dust_limit_satoshis` of the node offering `closing_signed`, and | ||
MAY also eliminate its own output. | ||
|
||
### Rationale | ||
|
||
There is a possibility of irreparable differences on closing if one | ||
node considers the other's output too small to allow propagation on | ||
the bitcoin network (aka "dust"), and that other node instead | ||
considers that output to be too valuable to discard. This is why each | ||
side uses its own `dust_limit_satoshis`, and the result can be a | ||
signature validation failure, if they disagree on what the closing | ||
transaction should look like. | ||
|
||
However, if one side chooses to eliminate its own output, there's no | ||
reason for the other side to fail the closing protocol, so this is | ||
explicitly allowed. The signature will indicate which variant | ||
has been used. | ||
|
||
It is assumed that `dust_limit_satoshis` is greater than the funding | ||
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. Something is missing here? 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. Oops! yep.... |
||
|
||
## Fees | ||
|
||
### Fee Calculation | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this doesn't work in case of a reconnection, where both parties re-send their last
closing_signed
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's why the sentence ends:
... unless it is equal to the previously-received
fee_satoshis
and it has reconnected since then.It's a bit awkward, I agree :(