From f7d151dd503b846284aee40336b626ff35e074bb Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Tue, 4 Jul 2017 13:23:13 +0930 Subject: [PATCH 1/5] BOLT 2: move closing tx definition to BOLT #3, and insist recipient check fee The recipient should check the fee is valid, otherwise we might get fun overflow games. So might as well check that it's better than the previous offer (as the sender is already required to do). Changing BOLT #3 to define the mutual close tx is next patch. Signed-off-by: Rusty Russell --- 02-peer-protocol.md | 45 +++++++++++++++++++++------------------------ 1 file changed, 21 insertions(+), 24 deletions(-) diff --git a/02-peer-protocol.md b/02-peer-protocol.md index 529597d88..08673e61c 100644 --- a/02-peer-protocol.md +++ b/02-peer-protocol.md @@ -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. 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 From ff17597aaad4cf099a212339c01af631b7621022 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Tue, 4 Jul 2017 13:28:37 +0930 Subject: [PATCH 2/5] BOLT 3: define closing transaction. The only surprise here (maybe?) is that we use the commitment number encoding. I think that makes sense, but it was unspecified before. Signed-off-by: Rusty Russell --- 03-transactions.md | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/03-transactions.md b/03-transactions.md index 48737b781..350c8c3e4 100644 --- a/03-transactions.md +++ b/03-transactions.md @@ -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 ` 1` and to collect the output the local node uses an input with nSequence `to_self_delay` and a witness stack ` 0` +## Closing Transaction + +Note that there are two possible variants for each node. + +* version: 2 +* 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 ` +* txout count: 0, 1 or 2 + * `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. + +### Requirements + +Each node offering MUST subtract the fee given by `fee_satoshis` from +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 + ## Fees ### Fee Calculation From 04d318a86ffd22bf69cb2ea9edd5c2cb20198517 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Tue, 11 Jul 2017 10:49:33 +0930 Subject: [PATCH 3/5] fixup! BOLT 3: define closing transaction. Version fix as pointed out by @roasbeef --- 03-transactions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/03-transactions.md b/03-transactions.md index 350c8c3e4..59c0bd061 100644 --- a/03-transactions.md +++ b/03-transactions.md @@ -239,7 +239,7 @@ To spend this via penalty, the remote node uses a witness stack ` Note that there are two possible variants for each node. -* version: 2 +* version: 1 * locktime: 0 * txin count: 1 * `txin[0]` outpoint: `txid` and `output_index` from `funding_created` message From e3d9051b76109d826e96c35e5d54512efc70a931 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Mon, 24 Jul 2017 20:49:18 +0930 Subject: [PATCH 4/5] fixup! BOLT 3: define closing transaction. --- 03-transactions.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/03-transactions.md b/03-transactions.md index 59c0bd061..584920c94 100644 --- a/03-transactions.md +++ b/03-transactions.md @@ -252,10 +252,8 @@ Note that there are two possible variants for each node. ### Requirements -Each node offering MUST subtract the fee given by `fee_satoshis` from -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. +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. ### Rationale @@ -272,7 +270,8 @@ 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 will be at least one output if `dust_limit_satoshis` is greater +than twice the funding amount. ## Fees From 45eacb51c4faea12167d5131245edc0db3139a01 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Sat, 29 Jul 2017 13:26:17 +0930 Subject: [PATCH 5/5] fixup: avoid state in closing_signed retransmission Suggested-by: Roasbeef Signed-off-by: Rusty Russell --- 02-peer-protocol.md | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/02-peer-protocol.md b/02-peer-protocol.md index 08673e61c..7a8f93fce 100644 --- a/02-peer-protocol.md +++ b/02-peer-protocol.md @@ -424,14 +424,13 @@ 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 +Otherwise, 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 +[BOLT #3](03-transactions.md#fee-calculation), and 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. +`fee_satoshis`, unless it has reconnected since then. If the receiver agrees with the fee, it SHOULD reply with a `closing_signed` with the same `fee_satoshis` value, otherwise it @@ -441,8 +440,9 @@ and its previously-sent `fee_satoshis`. #### Rationale 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. +progress, even if only by a single satoshi at a time. To avoid +keeping state and handle the corner case where fees have shifted +between reconnections, negotiation restarts 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 @@ -991,7 +991,7 @@ same `update_` messages as previously sent. On reconnection if the node has sent a previous `shutdown` it MUST retransmit it, and if the node has sent a previous `closing_signed` it -MUST then retransmit the last `closing_signed`. +MUST send another `closing_signed`. ### Rationale @@ -1009,7 +1009,9 @@ because there are also occasions where a node can simply forget the channel altogether. There is similarly no acknowledgment for `closing_signed`, or -`shutdown`, so they are also retransmitted on reconnection. +`shutdown`, so they are also retransmitted on reconnection. In the +case of `closing_signed`, negotation restarts on reconnection, so it +need not be an exact retransmission. The handling of updates is similarly atomic: if the commit is not acknowledged (or wasn't sent) the updates are re-sent. However, we