|
| 1 | +# Local Resource Conservation |
| 2 | + |
| 3 | +## Table of Contents |
| 4 | +* [Introduction](#introduction) |
| 5 | +* [Overview](#overview) |
| 6 | +* [Local Reputation](#local-reputation) |
| 7 | + * [Recommendations for Reputation Scoring](#recommendations-for-reputation-scoring) |
| 8 | + * [Effective HTLC Fees](#effective-htlc-fees) |
| 9 | + * [Outgoing Channel Revenue](#outgoing-channel-revenue) |
| 10 | + * [Incoming Channel Revenue](#incoming-channel-revenue) |
| 11 | + * [In Flight HTLC Risk](#in-flight-htlc-risk) |
| 12 | +* [Resource Bucketing](#resource-bucketing) |
| 13 | +* [Implementation Notes](#implementation-notes) |
| 14 | + * [Decaying Average](#decaying-average) |
| 15 | + * [Multiple Channels](#multiple-channels) |
| 16 | + |
| 17 | +## Introduction |
| 18 | +Channel jamming is a known denial-of-service attack against the Lightning |
| 19 | +Network. An attacker that controls both ends of a payment route can disrupt |
| 20 | +usage of a channel by sending payments that are destined to fail through a |
| 21 | +target route. Fees are currently only paid to routing nodes on successful |
| 22 | +completion of a payment, so this attack is virtually free - the attacker pays |
| 23 | +only for the costs of running a node, funding channels on-chain and the |
| 24 | +opportunity cost of capital committed to the attack. |
| 25 | + |
| 26 | +A channel can be fully jammed by depleting its available HTLC slots by holding |
| 27 | +`max_accepted_htlcs` or its available liquidity by holding the |
| 28 | +`max_htlc_value_in_flight`. An economically rational attacker will pursue the |
| 29 | +attack method with the lowest cost and highest utility. An attack can exhaust |
| 30 | +the resources along the target route in two ways, though the difference |
| 31 | +between the two behaviors is not rigorously defined: |
| 32 | +* Quick Jamming: sending a continuous stream of payments through a route that |
| 33 | + are quickly resolved, but block all of the liquidity or HTLC slots along the |
| 34 | + route. |
| 35 | +* Slow Jamming: sending a slow stream of payments through a route and only |
| 36 | + failing them at the latest possible timeout, blocking all of the liquidity |
| 37 | + or HTLC slots along the route for the duration. |
| 38 | + |
| 39 | +This document outlines recommendations for implementing local resource |
| 40 | +conservation to mitigate slow jamming attacks. It is part of a hybrid solution |
| 41 | +to mitigating channel jamming, intended to be followed by the introduction of |
| 42 | +unconditional fees to mitigate fast jamming. |
| 43 | + |
| 44 | +## Overview |
| 45 | +Local resource conservation combines the following elements to provide nodes |
| 46 | +with a mechanism to protect themselves against slow-jamming attacks: |
| 47 | + |
| 48 | +* [HTLC Endorsement](#../02-peer-protocol.md#adding-an-htlc-update_add_htlc): |
| 49 | + propagation of a signal along the payment route that indicates whether the |
| 50 | + node sending `update_add_htlc` recommends that the HTLC should be granted |
| 51 | + access to downstream resources (and that it will stake its reputation on the |
| 52 | + fast resolution of the HTLC). |
| 53 | +* [Local Reputation](#local-reputation): local tracking of the historical |
| 54 | + forwarding behavior of channel peers, used to decide whether to grant |
| 55 | + incoming HTLCs full access to local resources and whether to propagate |
| 56 | + endorsement downstream. |
| 57 | +* [Resource Bucketing](#resource-bucketing): reservation of a portion of |
| 58 | + "protected" liquidity and slots for endorsed HTLCs that have been forwarded |
| 59 | + by high reputation nodes. |
| 60 | + |
| 61 | +Sequence: |
| 62 | +* The `update_add_htlc` is sent by an upstream peer. |
| 63 | +* If the sending peer has sufficient local reputation (per the receiving |
| 64 | + peer's view) AND the incoming HTLC was sent with a non-zero `endorsed` TLV: |
| 65 | + * The HTLC will be allowed access to the "protected" bucket, so will have |
| 66 | + full access to the channel's liquidity and slots, |
| 67 | + * The corresponding outgoing HTLC (if present) will be forwarded with |
| 68 | + `endorsed` set to `1`. |
| 69 | +* Otherwise: |
| 70 | + * The HTLC will be limited to the remaining "general" slots and liquidity, |
| 71 | + and will be failed if there are no resources remaining in this bucket. |
| 72 | + * The corresponding outgoing HTLC (if present) will be forwarded with |
| 73 | + `endorsed` set to `0`. |
| 74 | + |
| 75 | +In the steady state when Lightning is being used as expected, there should be |
| 76 | +no need for use of protected resources as channels are not saturated during |
| 77 | +regular operation. Should the network come under attack, honest nodes that |
| 78 | +have built up reputation over time will still be able to utilize protected |
| 79 | +resources to process payments in the network. |
| 80 | + |
| 81 | +## Local Reputation |
| 82 | + |
| 83 | +### Recommendations for Reputation Scoring |
| 84 | +Local reputation can be used by forwarding nodes to decide whether to allocate |
| 85 | +resources to and signal endorsement of a HTLC on the outgoing channel. Nodes MAY |
| 86 | +use any metric of their choosing to classify a peer as having sufficient |
| 87 | +reputation, though a poor choice of reputation scoring metric may affect their |
| 88 | +reputation with their downstream peers. |
| 89 | + |
| 90 | +The goal of this reputation metric is to ensure that the cost to obtain |
| 91 | +sufficient reputation for a HTLC to be endorsed on the outgoing channel is |
| 92 | +greater than the damage that a node can inflict by abusing the access that it |
| 93 | +is granted. This algorithm uses forwarding fees to measure damage, as this value |
| 94 | +is observable within the protocol. It is reasonable to expect an adversary to |
| 95 | +"about turn" - to behave perfectly to build up reputation, then alter their |
| 96 | +behavior to abuse it. For this reason, in-flight HTLCs have a temporary |
| 97 | +negative impact on reputation until they are resolved. |
| 98 | + |
| 99 | +If granted full access to a node's liquidity and slots, the maximum amount of |
| 100 | +damage that can be inflicted on the targeted node is bounded by the largest |
| 101 | +cltv delta from the current block height that it will allow a HTLC to set |
| 102 | +before failing it with [expiry_too_far](../04-onion-routing.md#failure-messages). |
| 103 | +This value is typically 2016 blocks (~2 weeks) at the time of writing. |
| 104 | + |
| 105 | +Upon receipt of `update_add_htlc`, the local node considers the following to |
| 106 | +determine whether the sender is classified as having sufficient reputation: |
| 107 | +* Outgoing channel revenue: the total routing fees over the maximum allowed HTLC |
| 108 | + hold period (~2 weeks) that the outgoing channel has earned the local node, |
| 109 | + considering both incoming and outgoing HTLCs that have used the channel. |
| 110 | +* Incoming channel revenue: the total routing fees that the incoming channel has |
| 111 | + earned the local node, considering only incoming HTLCs on the channel. |
| 112 | +* In-flight HTLCs risk: any endorsed HTLC that the incoming channel has |
| 113 | + in-flight on the requested outgoing channel negatively affect reputation, |
| 114 | + based on the assumption that they will be held until just before their |
| 115 | + expiry height. |
| 116 | + |
| 117 | +On a per-HTLC basis, the local node will classify the sending node's |
| 118 | +reputation for the offered HTLC as follows: |
| 119 | +* if `incoming_channel_revenue - in_flight_risk >= outgoing_channel_revenue`: |
| 120 | + * the sending node is considered to have *sufficient* reputation for the |
| 121 | + offered HTLC. |
| 122 | +* otherwise, the sending node is considered to have *insufficient* reputation |
| 123 | + for the offered HTLC. |
| 124 | + |
| 125 | +The sections that follow provide details of how to calculate the components of |
| 126 | +the inequality. |
| 127 | + |
| 128 | +#### Effective HTLC Fees |
| 129 | +The contribution that the fees paid by a HTLC make to reputation standings is |
| 130 | +adjusted by the amount of time that a HTLC took to resolve. By accounting for |
| 131 | +the "opportunity cost" of HTLCs that are held for longer periods of time, the |
| 132 | +reputation score rewards fast resolving, successful payments and penalizes |
| 133 | +slow resolving payments (regardless of successful resolution). |
| 134 | + |
| 135 | +We define the following parameters: |
| 136 | +* `resolution_period`: the amount of time a HTLC is allowed to resolve in that |
| 137 | + classifies as "good" behavior, expressed in seconds. The recommended default |
| 138 | + is 90 seconds (given that the protocol allows for a 60 second MPP timeout). |
| 139 | +* `resolution_time`: the amount of time elapsed in seconds between a HTLC being |
| 140 | + added to and removed from the local node's commitment transaction. |
| 141 | +* `fees`: the fees that are offered to the local node to forward the HTLC, |
| 142 | + expressed in milli-satoshis. |
| 143 | + |
| 144 | +We define the `opportunity_cost` of the time a HTLC takes to resolve: |
| 145 | +`opportunity_cost`: `ceil ( (resolution_time - resolution_period) / resolution_period) * fees` |
| 146 | + |
| 147 | +Given that `resolution_time` will be > 0 in practice, `opportunity_cost` is 0 |
| 148 | +for HTLCs that resolve within `resolution_period`, and charges the `fees` that |
| 149 | +the HTLC would have earned per period it is held thereafter. This cost accounts |
| 150 | +for the slot and liquidity that could have otherwise been paid for by |
| 151 | +successful, fast resolving HTLCs during the `resolution_time` the HTLC was |
| 152 | +locked in the channel. |
| 153 | + |
| 154 | +Each HTLC's contribution to reputation is expressed by its `effective_fee` |
| 155 | +which is determined by its endorsement, resolution time and outcome: |
| 156 | +* if `endorsed` is non-zero in `update_add_htlc`: |
| 157 | + * if successfully resolved with `update_fulfill_htlc`: |
| 158 | + * `effective_fees` = `fees` - `opportunity_cost` |
| 159 | + * otherwise: |
| 160 | + * `effective_fees` = -`opportunity_cost` |
| 161 | +* otherwise: |
| 162 | + * if successfully resolved AND `resolution_time` <= `resolution_period` |
| 163 | + * `effective_fees` = `fees` |
| 164 | + * otherwise: |
| 165 | + * `effective_fees` = 0 |
| 166 | + |
| 167 | +##### Rationale |
| 168 | +Reputation is negatively affected by slow-resolving HTLCs (regardless of whether |
| 169 | +they are settled or failed) to ensure that reputation scoring reacts to bad |
| 170 | +behavior. HTLCs that resolve within a period of time that is considered |
| 171 | +reasonable do not decrease reputation, as some rate of failure is natural in |
| 172 | +the network. |
| 173 | + |
| 174 | +The resolution of HTLCs with `endorsed` set to `0` do not have a negative |
| 175 | +impact on reputation because the forwarding node made no promises about their |
| 176 | +behavior. They are allowed to build reputation when they resolve successfully |
| 177 | +within the specified `resolution_period` to allow new nodes in the network to |
| 178 | +bootstrap reputation. |
| 179 | + |
| 180 | +#### Outgoing Channel Revenue |
| 181 | +Outgoing channel revenue measures the damage to the local node (ie, the loss in |
| 182 | +forwarding fees) that a slow jamming attack can incur. For an individual |
| 183 | +channel, this is equal to the total revenue forwarded in both directions over |
| 184 | +the maximum allowed HTLC hold time. |
| 185 | + |
| 186 | +We define the following parameters: |
| 187 | +* `outgoing_revenue_window`: the largest cltv delta from the current block |
| 188 | + height that a node will allow a HTLC to set before failing it with |
| 189 | + [expiry_too_far](../04-onion-routing.md#failure-messages), expressed in |
| 190 | + seconds (assuming 10 minute blocks). |
| 191 | + |
| 192 | +We define the `outgoing_channel_revenue`: |
| 193 | +* for each `update_add_htlc` processed on the outgoing channel over the rolling |
| 194 | + window [`now` - `outgoing_revenue_window`; `now`]: |
| 195 | + * if the HTLC has been resolved: |
| 196 | + * `outgoing_channel_revenue` += `fee` |
| 197 | + |
| 198 | +##### Rationale |
| 199 | +We consider bi-directional HTLC forwards on the outgoing channel to properly |
| 200 | +account for the potential loss of a jamming attack - even when fees don't |
| 201 | +accrue on the channel, it is pairwise valuable to the local node. In flight |
| 202 | +HTLCs have no impact on outgoing channel revenue, as their fee contribution is |
| 203 | +unknown. |
| 204 | + |
| 205 | +#### Incoming Channel Revenue |
| 206 | +Incoming channel revenue measures the unforgeable history that the incoming |
| 207 | +channel has built with the local node via payment of forwarding fees. As this |
| 208 | +value aims to capture the contribution of the channel (rather than its value |
| 209 | +to the local node), only incoming HTLCs are considered. |
| 210 | + |
| 211 | +We define the following parameters: |
| 212 | +* `incoming_revenue_multiplier`: a multiplier applied to |
| 213 | + `outgoing_revenue_window` to determine the rolling window over which the |
| 214 | + incoming channel's forwarding history is considered (default 10). |
| 215 | + |
| 216 | +We define the `incoming_channel_revenue`: |
| 217 | +* for each incoming `update_add_htlc` processed on the incoming channel over |
| 218 | + the rolling window [`now` - `outgoing_channel_window` * |
| 219 | + `incoming_channel_multiplier`; `now`]: |
| 220 | + * if the HTLC has been resolved: |
| 221 | + * `incoming_channel_revenue` += `effective_fee(HTLC)` |
| 222 | + |
| 223 | +##### Rationale |
| 224 | +For the incoming channel, only HTLCs that they have forwarded to the local |
| 225 | +node count torwards their unforegable contribution to building reputation, as |
| 226 | +they push fees to the local node. While the incoming channel may be valuable |
| 227 | +as a sink (or predominantly outgoing) channel, the HTLCs that the local node |
| 228 | +has forwarded outwards do not represent fees paid by a potential attacker. |
| 229 | + |
| 230 | +#### In Flight HTLC Risk |
| 231 | +Whenever a HTLC is forwarded, we assume that it will resolve with the worst |
| 232 | +case off-chain resolution time and dock reputation accordingly. This decrease |
| 233 | +will be temporary in the case of fast resolution, and preemptively slash |
| 234 | +reputation in the case where the HTLC is used as part of a slow jamming attack. |
| 235 | + |
| 236 | +We define the following parameters: |
| 237 | +* `height_added`: the block height at which the HTLC was irrevocably committed |
| 238 | + to by the local node. |
| 239 | + |
| 240 | +We define the `outstanding_risk` of in-flight HTLCs: |
| 241 | +* `outstanding_risk` = `fees` * (`cltv_expiry` - `height_added` * 10 * 60) / `resolution_period` |
| 242 | + |
| 243 | +We define the `in_flight_htlc_risk` for an incoming channel sending |
| 244 | +`update_add_htlc`: |
| 245 | +* `in_flight_htlc_risk` = `outstanding_risk(proposed update_add_htlc)` |
| 246 | +* for each HTLC originating on the incoming channel, forwarded over the |
| 247 | + requested outgoing channel: |
| 248 | + * if `endorsed` is non-zero: |
| 249 | + * `in_flight_htlc_risk` += `outstanding_risk(HTLC)` |
| 250 | + |
| 251 | +##### Rationale |
| 252 | +In flight HTLC are included in reputation scoring to account for sudden changes |
| 253 | +in a peer's behavior. Even when sufficient reputation is obtained, each HTLC |
| 254 | +choosing to take advantage of that reputation is treated as if it will be used |
| 255 | +to inflict maximum damage. The expiry height of each incoming in flight HTLC is |
| 256 | +considered so that risk is directly related to the amount of time the HTLC |
| 257 | +could be held in the channel. Ten minute blocks are assumed for simplicity. |
| 258 | + |
| 259 | +## Resource Bucketing |
| 260 | +When making the decision to forward a HTLC on its outgoing channel, a node |
| 261 | +MAY choose to limit its exposure to HTLCs that put it at risk of a denial of |
| 262 | +service attack. |
| 263 | + |
| 264 | +We define the following parameters: |
| 265 | +* `protected_slot_count`: defines the number of HTLC slots that are reserved |
| 266 | + for endorsed HTLCs from peers with sufficient reputation (default: 0.5 * |
| 267 | + remote peer's `max_accepted_htlcs`). |
| 268 | +* `protected_liquidity_portion`: defines the portion of liquidity that is |
| 269 | + reserved for endorsed HTLCs from peers with sufficient reputation (default: |
| 270 | + 0.5). |
| 271 | + |
| 272 | +A node implementing resource bucketing limits exposure on its outgoing channel: |
| 273 | +* MUST choose `protected_slot_count` <= the remote channel peer's |
| 274 | + `max_accepted_htlcs`. |
| 275 | +* MUST choose `protected_liquidity_portion` in [0;1]. |
| 276 | + |
| 277 | +For each `update_add_htlc` proposed by an incoming channel: |
| 278 | +* If `endorsed` is non-zero AND the incoming channel has sufficient local |
| 279 | + reputation for the HTLC (see [Recommendations for Reputation Scoring](#recommendations-for-reputation-scoring)): |
| 280 | + * SHOULD forward the HTLC as usual. |
| 281 | + * SHOULD set `endorsed` to 1 in the outgoing `update_add_htlc`. |
| 282 | +* Otherwise: |
| 283 | + * SHOULD reduce the remote peer's `max_accepted_htlcs` by |
| 284 | + `protected_slot_count` for the purposes of the proposed HTLC. |
| 285 | + * SHOULD reduce the `max_htlc_value_in_flight` by |
| 286 | + `protected_liquidity_portion` * `max_htlc_value_in_flight`. |
| 287 | + * SHOULD set `endorsed` to `0` in the outgoing `update_add_htlc`. |
| 288 | + |
| 289 | +## Implementation Notes |
| 290 | + |
| 291 | +### Decaying Average |
| 292 | +Rolling windows specified in this write up may be implemented as a decaying |
| 293 | +average to minimize the amount of data that needs to be stored per-channel. In |
| 294 | +flight HTLCs can be accounted for separately to this calculation, as the node |
| 295 | +will already have data for these HTLCs available. |
| 296 | + |
| 297 | +Track the following values for each rolling window: |
| 298 | +* `last_update`: stores the timestamp of the last update to the decaying |
| 299 | + average, expressed in seconds. |
| 300 | +* `decaying_average`: stores the value of the decaying average. |
| 301 | +* `decay_rate`: a constant rate of decay based on the rolling window chosen, |
| 302 | + calculated as: `((1/2)^(2/window_length_seconds))`. |
| 303 | + |
| 304 | +To update the `decaying_average` at time `t`: |
| 305 | +* `last_update_diff` = `now` - `last_update`. |
| 306 | +* `decaying_average` = `decaying_average` * `decay_rate` ^ `last_update_diff`. |
| 307 | +* `last_update` = `t`. |
| 308 | + |
| 309 | +When assessing whether a peer has sufficient reputation for a HTLC: |
| 310 | +* MUST update `decaying_average` as described above. |
| 311 | + |
| 312 | +When updating the `decaying_average` to add the `effective_fee` of a newly |
| 313 | +resolved HTLC at timestamp `t`: |
| 314 | +* MUST update `decaying_average` as described above. |
| 315 | +* `decaying_average` = `decaying_average` + `effective_fee` |
| 316 | + |
| 317 | + |
| 318 | +### Bootstrapping Outgoing Channel Revenue |
| 319 | +New channels with no revenue history: |
| 320 | +* MAY choose not to endorse any HTLCs in their first two weeks of operation |
| 321 | + to establish baseline revenue. |
| 322 | +* MAY choose to use `outgoing_channel_revenue` for a similar channel as a |
| 323 | + default starting point for scoring reputation. |
| 324 | + |
| 325 | +### Multiple Channels |
| 326 | +If the local node has multiple channels open with the incoming and outgoing |
| 327 | +peers: |
| 328 | +* MAY consider `incoming_channel_revenue` across all channels with the peer |
| 329 | + when assessing reputation, but MUST include all in-flight HTLCs originating |
| 330 | + from the peer in `in_flight_htlc_risk` if doing so. |
| 331 | +* MAY consider `outgoing_channel_revenue` for all channels with the outgoing |
| 332 | + peer, but SHOULD take care to [bootstrap](#bootstrapping-outgoing-channel-revenue) |
| 333 | + new channels so they do not lower the reputation threshold for existing ones. |
| 334 | +* SHOULD calculate `outgoing_channel_revenue` for the channel that is selected |
| 335 | + for [non-strict-forwarding](../04-onion-routing.md#non-strict-forwarding) |
| 336 | + forwarding. |
0 commit comments