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

Closing tx detailed specification #201

Closed
Closed
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 21 additions & 24 deletions 02-peer-protocol.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Copy link
Collaborator

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?

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 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 :(

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.
Copy link
Collaborator

Choose a reason for hiding this comment

The 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
Expand Down
40 changes: 40 additions & 0 deletions 03-transactions.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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
Copy link
Collaborator

Choose a reason for hiding this comment

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

Isn't that version 2?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The 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...

Copy link
Collaborator

Choose a reason for hiding this comment

The 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
Copy link
Collaborator

Choose a reason for hiding this comment

The 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.

Copy link
Collaborator

Choose a reason for hiding this comment

The 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?

Copy link
Collaborator

Choose a reason for hiding this comment

The 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
Copy link
Collaborator

Choose a reason for hiding this comment

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

How about:

Each node offering a signature MUST subtract the fee given by fee_satoshis from
the output to the funder; it MUST then remove any output below its own dust_limit_satoshis, and MAY also eliminate its own output.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The 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
Copy link
Collaborator

Choose a reason for hiding this comment

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

Something is missing here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Oops! yep....


## Fees

### Fee Calculation
Expand Down