1
0
mirror of https://github.com/lightning/bolts.git synced 2024-11-19 01:50:03 +01:00

BOLT 2: Details of HTLC Timeouts, ie. cltv_expiry_delta.

Complete rewrite, including a routing example and the new
min_final_cltv expirt.  I hope this makes it clear.

(Thanks to everyone who reviewed and gave feedback; you rock!)

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2017-10-02 20:19:26 +10:30 committed by Olaoluwa Osuntokun
parent d1fbfd30f8
commit 58d4d9bca3
3 changed files with 185 additions and 43 deletions

View File

@ -16,7 +16,7 @@ operation, and closing.
* [Closing negotiation: `closing_signed`](#closing-negotiation-closing_signed)
* [Normal Operation](#normal-operation)
* [Forwarding HTLCs](#forwarding-htlcs)
* [Risks With HTLC Timeouts](#risks-with-htlc-timeouts)
* [`cltv_expiry_delta` Selection](#cltv_expiry_delta-selection)
* [Adding an HTLC: `update_add_htlc`](#adding-an-htlc-update_add_htlc)
* [Removing an HTLC: `update_fulfill_htlc`, `update_fail_htlc` and `update_fail_malformed_htlc`](#removing-an-htlc-update_fulfill_htlc-update_fail_htlc-and-update_fail_malformed_htlc)
* [Committing Updates So Far: `commitment_signed`](#committing-updates-so-far-commitment_signed)
@ -508,7 +508,7 @@ the incoming HTLC has been irrevocably committed.
A node MUST NOT fail an incoming HTLC (`update_fail_htlc`) for which it has committed
to an outgoing HTLC, until the removal of the outgoing HTLC is irrevocably committed, or the outgoing on-chain HTLC output has been spent via the HTLC-timeout transaction with sufficient depth.
A node MUST fail an incoming HTLC (`update_fail_htlc`) once its `cltv_expiry` has been reached.
A node MUST fail an incoming HTLC (`update_fail_htlc`) once its `cltv_expiry` has been reached, or if `cltv_expiry` - `current_height` < `cltv_expiry_delta` for the outgoing channel.
A node MUST fulfill an incoming HTLC for which it has committed to an outgoing HTLC,
as soon as it receives `update_fulfill_htlc` for the outgoing HTLC, or has discovered the `payment_preimage` from an on-chain HTLC spend.
@ -520,61 +520,113 @@ Fulfilling an HTLC is different: knowledge of the preimage is by definition irre
so we should fulfill the incoming HTLC as soon as we can to reduce latency.
### Risks With HTLC Timeouts
### `cltv_expiry_delta` Selection
Once an HTLC has timed out where it could either be fulfilled or timed-out;
Once an HTLC has timed out it could either be fulfilled or timed-out;
care must be taken around this transition both for offered and received HTLCs.
As a result of forwarding an HTLC from node A to node C, B will end up having an incoming
HTLC from A and an outgoing HTLC to C. B will make sure that the incoming HTLC has a greater
timeout than the outgoing HTLC, so that B can get refunded from C sooner than it has to refund
A if the payment does not complete.
Consider the following scenario, where A sends an HTLC to B, who
forwards to C, who delivers the goods as soon as the payment is
received.
For example, node A might offer node B an HTLC with a timeout of 3 days, and node B might
offer node C the same HTLC with a timeout of 2 days:
1. C needs to be sure that the HTLC from B cannot time out, even if B becomes
unresponsive; i.e. C can fulfill the incoming HTLC on-chain before B can
time it out on-chain.
```
3 days timeout 2 days timeout
A ------------------> B ------------------> C
```
2. B needs to be sure that if C fulfills the HTLC from B, it can fulfill the
incoming HTLC from A. i.e. B can get the preimage from C and fulfill incoming the
HTLC on-chain before A can time it out on-chain.
The difference in timeouts is called `cltv_expiry_delta` in
[BOLT #7](07-routing-gossip.md).
The critical settings here are the `cltv_expiry_delta` in
[BOLT #7](07-routing-gossip.md#the-channel_update-message), and the
related
[`min_final_cltv_expiry` in BOLT #11](11-payment-encoding.md#tagged-fields).
`cltv_expiry_delta` is the minimum difference in HTLC CLTV timeouts in
the forwarding case (B) and `min_final_ctlv_expiry` is the minimum difference
between HTLC CLTV timeout and the current block height for the
terminal case (C).
This difference is important: after 2 days B can try to
remove the offer to C even if C is unresponsive, by broadcasting the
commitment transaction it has with C and spending the HTLC output.
Even though C might race to try to use its payment preimage at that point to
also spend the HTLC, it should be resolved well before the 3 day
deadline so B can either redeem the HTLC off A or close it.
Note that if this value is too low for a channel, the risk is only to
the node *accepting* the HTLC, not the node offering it. For this
reason, the `cltv_expiry_delta` for the *outgoing* channel is used as
the delta across a node.
We can derive the worst-case number of blocks between outgoing and
incoming HTLC resolution, given a few assumptions:
If the timing is too close, there is a risk of "one-sided redemption",
where the payment preimage received from an offered HTLC is too late
to be used for an incoming HTLC, leaving the node with unexpected
liability.
* A worst-case reorganization depth `R` blocks
* A grace-period `G` blocks after HTLC timeout before we give up on
an unresponsive peer and drop to chain.
* A number of blocks `S` between transaction broadcast and the
transaction being included in a block.
The worst case is for a forwarding node (B) which takes the longest
possible time to spot the outgoing HTLC fulfillment, and then takes
the longest possible time to redeem it on-chain:
Thus the effective timeout of the HTLC is the `cltv_expiry`, plus some
additional delay for the transaction which redeems the HTLC output to
be irreversibly committed to the blockchain.
1. The B->C HTLC times out at block `N`, and B waits `G` blocks until
it gives up waiting for C. B or C commits to the blockchain,
and B spends HTLC, which takes `S` blocks to be included.
2. Bad case: C wins the race (just) and fulfills the HTLC, B only sees
that transaction when it sees block `N+G+S+1`.
3. Worst case: There's reorganization `R` deep in which C wins and
fulfills. B only sees transaction at `N+G+S+R`.
4. B now needs to fulfill the incoming A->B HTLC, but A is unresponsive: B waits `G` more
blocks before giving up waiting for A. A or B commits to the blockchain.
5. Bad case: B sees A's commitment transaction in block `N+G+S+R+G+1`, and has
to spend the HTLC output, which takes `S` blocks to be mined.
6. Worst case: There's another reorganization `R` deep which A uses to
spend the commitment transaction, so B sees A's commitment
transaction in block `N+G+S+R+G+R`, and has to spend the HTLC output, which
takes `S` blocks to be mined.
7. B's HTLC spend needs to be at least `R` deep before it times out,
otherwise another reorganization could allow A to timeout the
transaction.
Thus the worst case is `3R+2G+2S` assuming `R` is at least 1. Note that the
chances of three reorganizations in which the other node wins all of them is
low for `R` of 2 or more. Since we use high fees (and HTLC spends can use
almost arbitrary fees) `S` should be small, though given that block times are
irregular and empty blocks still occur, `S = 2` should be considered a
minimum. Similarly, the grace period `G` can be low (1 or 2), as nodes are
required to timeout or fulfill as soon as possible; but too low increases the
risk of unnecessary channel closure due to networking delays.
There are four values we need to derive:
1. The `cltv_expiry_delta` for channels. `3R+2G+2S`; if in doubt, a
`cltv_expiry_delta` of 12 is reasonable (R=2, G=1, S=2).
2. For HTLCs we offer: the timeout deadline when we have to fail the channel
and time it out on-chain. This is `G` blocks after the HTLC
`cltv_expiry`; 1 block is reasonable.
3. For HTLCs we accept and have a preimage: the fulfillment deadline when we
have to fail the channel and fulfill the HTLC onchain before its
`cltv_expiry`. This is steps 4-7 above, which means a deadline of `2R+G+S`
blocks before `cltv_expiry`; 7 blocks is reasonable.
4. The minimum `cltv_expiry` we will accept for terminal payments: the
worst case for the terminal node C lower at `2R+G+S` blocks (steps
1-3 above don't apply). The default in
[BOLT 11](11-payment-encoding.md) is 9, which is slightly more
conservative than the 6 this calculation suggests.
The fulfillment risk is similar: if a node C fulfills an HTLC after
its timeout, B might broadcast the commitment transaction and
immediately broadcast the HTLC timeout transaction. In this scenario,
B would gain knowledge of the preimage without paying C.
#### Requirements
A node MUST estimate the deadline for successful redemption for each
HTLC. A node MUST NOT offer a HTLC after this deadline, and
MUST fail the channel if an HTLC which it offered is in either node's
current commitment transaction past this deadline.
A node MUST estimate a timeout deadline for each HTLC it offers. A node MUST
NOT offer an HTLC with a timeout deadline before its `cltv_expiry`, and MUST
fail the channel if an HTLC which it offered is in either node's current
commitment transaction past this timeout deadline.
A node MUST estimate a fulfillment deadline for each HTLC it is attempting to
fulfill. A node MUST fail (and not forward) an HTLC whose fulfillment
deadline is already past, and MUST fail the connection if a HTLC it has
fulfilled is in either node's current commitment transaction past this
fulfillment deadline.
A node MUST NOT fulfill an HTLC after this deadline, and MUST fail the
connection if a HTLC it has fulfilled is in either node's current
commitment transaction past this deadline.
### Adding an HTLC: `update_add_htlc`
@ -743,7 +795,7 @@ using the `failure_code` given and setting the data to
#### Rationale
A node which doesn't time out HTLCs risks channel failure (see
"Risks With HTLC Timeouts").
[`cltv_expiry_delta` Selection](#cltv_expiry_delta-selection).
A node which sends `update_fulfill_htlc` before the sender is also
committed to the HTLC risks losing funds.

View File

@ -146,7 +146,7 @@ Field Description:
* `outgoing_cltv_value` - The CLTV value that the _outgoing_ HTLC carrying
the packet should have.
cltv_expiry - cltv_expiry_delta = outgoing_cltv_value
cltv_expiry - cltv_expiry_delta >= outgoing_cltv_value
Inclusion of this field allows a node to both authenticate the information
specified by the original sender and the parameters of the HTLC forwarded,
@ -557,7 +557,7 @@ outgoing channel:
* [`2`:`len`]
* [`len`:`channel_update`]
If the cltv-expiry is too near, we tell them the the current channel
If the `cltv_expiry` is too near, we tell them the the current channel
setting for the outgoing channel:
1. type: UPDATE|14 (`expiry_too_soon`)

View File

@ -448,6 +448,96 @@ Other more advanced considerations involve diversity of routes to
avoid single points of failure and detection, and channel balance
of local channels.
### Routing Example
Consider four nodes:
```
B
/ \
/ \
A C
\ /
\ /
D
```
Each advertises the following `cltv_expiry_delta` on its end of every
channel:
1. A: 10 blocks
2. B: 20 blocks
3. C: 30 blocks
4. D: 40 blocks
C also uses a`min_final_cltv_expiry` of 9 (the default) when requesting
payments.
Also, each node has the same fee scheme which it uses for each of its
channels:
1. A: 100 base + 1000 millionths
1. B: 200 base + 2000 millionths
1. C: 300 base + 3000 millionths
1. D: 400 base + 4000 millionths
The network will see eight `channel_update` messages:
1. A->B: `cltv_expiry_delta` = 10, `fee_base_msat` = 100, `fee_proportional_millionths` = 1000
1. A->D: `cltv_expiry_delta` = 10, `fee_base_msat` = 100, `fee_proportional_millionths` = 1000
1. B->A: `cltv_expiry_delta` = 20, `fee_base_msat` = 200, `fee_proportional_millionths` = 2000
1. D->A: `cltv_expiry_delta` = 40, `fee_base_msat` = 400, `fee_proportional_millionths` = 4000
1. B->C: `cltv_expiry_delta` = 20, `fee_base_msat` = 200, `fee_proportional_millionths` = 2000
1. D->C: `cltv_expiry_delta` = 40, `fee_base_msat` = 400, `fee_proportional_millionths` = 4000
1. C->B: `cltv_expiry_delta` = 30, `fee_base_msat` = 300, `fee_proportional_millionths` = 3000
1. C->D: `cltv_expiry_delta` = 30, `fee_base_msat` = 300, `fee_proportional_millionths` = 3000
If B were to send 4,999,999 millisatoshi directly to C, it wouldn't
charge itself a fee nor add its own `cltv_expiry_delta`, so it would
use C's requested `min_final_cltv_expiry` of 9. We also assume it adds a
"shadow route" to give an extra CLTV of 42. It could also add extra
cltv deltas at other hops, as these values are a minimum, but we don't
here for simplicity:
* `amount_msat`: 4999999
* `cltv_expiry`: current-block-height + 9 + 42
* `onion_routing_packet`:
* `amt_to_forward` = 4999999
* `outgoing_cltv_value` = current-block-height + 9 + 42
If A were to send an 4,999,999 millisatoshi to C via B, it needs to
pay B the fee it specified in the B->C `channel_update`, calculated as
per [HTLC Fees](#htlc_fees):
200 + 4999999 * 2000 / 1000000 = 10199
Similarly, it would need to add the `cltv_expiry` from B->C's
`channel_update` (20), plus C's requested `min_final_cltv_expiry` (9), plus 42 for the
"shadow route". Thus the `update_add_htlc` message from A to B would
be:
* `amount_msat`: 5010198
* `cltv_expiry`: current-block-height + 20 + 9 + 42
* `onion_routing_packet`:
* `amt_to_forward` = 4999999
* `outgoing_cltv_value` = current-block-height + 9 + 42
The `update_add_htlc` from B to C would be the same as the B->C direct
payment above.
Finally, if for some reason A chose the more expensive route via D, it
would send the following `update_add_htlc` to D:
* `amount_msat`: 5020398
* `cltv_expiry`: current-block-height + 40 + 9 + 42
* `onion_routing_packet`:
* `amt_to_forward` = 4999999
* `outgoing_cltv_value` = current-block-height + 9 + 42
And the `update_add_htlc` from D to C would be the same as the B->C
direct payment again.
## References
![Creative Commons License](https://i.creativecommons.org/l/by/4.0/88x31.png "License CC-BY")