Skip to content

Commit

Permalink
multi: add resource bucketing for HTLC slots and liquidity
Browse files Browse the repository at this point in the history
  • Loading branch information
carlaKC committed May 15, 2023
1 parent a049b79 commit ec6eb65
Show file tree
Hide file tree
Showing 2 changed files with 127 additions and 1 deletion.
11 changes: 10 additions & 1 deletion 02-peer-protocol.md
Original file line number Diff line number Diff line change
Expand Up @@ -995,7 +995,10 @@ is destined, is described in [BOLT #4](04-onion-routing.md).
1. type: 0 (`blinding_point`)
2. data:
* [`point`:`blinding`]

1. type: 1 (`endorsed`)
2. data:
* [`byte`:`endorsed`]

#### Requirements

A sending node:
Expand Down Expand Up @@ -1033,6 +1036,10 @@ A sending node:
- MUST increase the value of `id` by 1 for each successive offer.
- if it is relaying a payment inside a blinded route:
- MUST set `blinding_point` (see [Route Blinding](04-onion-routing.md#route-blinding))
- if it is the original source of the HTLC:
- SHOULD set `endorsed` to `1`.
- otherwise:
- SHOULD set `endorsed` as described in [Bolt 4](04-onion-routing.md#resource-bucketing).

`id` MUST NOT be reset to 0 after the update is complete (i.e. after `revoke_and_ack` has
been received). It MUST continue incrementing instead.
Expand All @@ -1059,6 +1066,8 @@ A receiving node:
`error` and fail the channel.
- if `blinding_point` is provided:
- MUST use the corresponding blinded private key to decrypt the `onion_routing_packet` (see [Route Blinding](04-onion-routing.md#route-blinding))
- if `endorsed` is provided:
- SHOULD interpret `endorsed` as described in [Bolt 4](04-onion-routing.md#resource-bucketing).

The `onion_routing_packet` contains an obfuscated list of hops and instructions for each hop along the path.
It commits to the HTLC by setting the `payment_hash` as associated data, i.e. includes the `payment_hash` in the computation of HMACs.
Expand Down
117 changes: 117 additions & 0 deletions 04-onion-routing.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ A node:
* [Route Blinding](#route-blinding)
* [Accepting and Forwarding a Payment](#accepting-and-forwarding-a-payment)
* [Non-strict Forwarding](#non-strict-forwarding)
* [Resource Bucketing](#resource-bucketing)
* [Payload for the Last Node](#payload-for-the-last-node)
* [Shared Secret](#shared-secret)
* [Blinding Ephemeral Keys](#blinding-ephemeral-keys)
Expand All @@ -62,6 +63,7 @@ A node:
* [Returning Errors](#returning-errors)
* [Failure Messages](#failure-messages)
* [Receiving Failure Codes](#receiving-failure-codes)
* [Recommendations for Reputation](#recommendations-for-reputation)
* [Test Vector](#test-vector)
* [Returning Errors](#returning-errors)
* [References](#references)
Expand Down Expand Up @@ -635,6 +637,35 @@ Alternatively, implementations may choose to apply non-strict forwarding only to
like-policy channels to ensure their expected fee revenue does not deviate by
using an alternate channel.

## Resource Bucketing

When making the decision to forward a payment on its outgoing channel, a node
MAY choose to limit its exposure to HTLCs that put it at risk of a denial of
service attack.
* `unknown_allocation_slots`: defines the number of HTLC slots allocated to
unknown traffic (default: 50% of remote peer's `max_accepted_htlcs`).
* `unknown_allocation_liquidity`: defines the amount of the channel balance
that is allocated to unknown traffic (default: 50% of remote peer's
`max_htlc_value_in_flight_msat`.

A node implementing resource bucketing limits exposure on its outgoing channel:
- MUST choose `unknown_allocation_slots` <= the remote channel peer's
`max_accepted_htlcs`.
- MUST choose `unknown_allocation_liquidity` <= the remote channel peer's
`max_htlc_value_in_flight_msat`.
- If `endorsed` is set to 1 in the incoming `update_add_htlc` AND the HTLC
is from a node that the forwarding node considers to have good local
reputation (see [Recommendations for Reputation](#recommendations-for-reputation)):
- SHOULD proceed with forwarding the HTLC.
- SHOULD set `endorsed` to 1 in the outgoing `update_add_htlc`.
- Otherwise, the HTLC is classified as `unknown`:
- If `unknown_allocation_slots` HTLC slots are occupied by other `unknown` HTLCs:
- SHOULD return `temporary_channel_failure` as specified in [Failure Messages](#failure-messages).
- If `unknown_allocation_liquidity` satoshis of liquidity are locked in
other `unknown` HTLCs:
- SHOULD return `temporary_channel_failure` as specified in [Failure Messages](#failure-messages).
- SHOULD set `endorsed` to 0 in the outgoing `update_add_htlc`.

## Payload for the Last Node

When building the route, the origin node MUST use a payload for
Expand Down Expand Up @@ -1407,6 +1438,92 @@ The _origin node_:
- MAY use the data specified in the various failure types for debugging
purposes.

## Recommendations for Reputation

Local reputation is used by forwarding nodes to decide whether to endorse a HTLC
on their outgoing link. Nodes MAY use any metric of their choosing to classify
a peer as having "good" reputation, though a poor choice of reputation scoring
metric will affect their downstream reputation.

Peers build reputation by forwarding successful HTLCs that resolve quickly, and
lose reputation if they endorse failing or slow-resolving HTLCs. Reputation is
only _negatively_ affected if an endorsed HTLC resolves undesirably, to holds
nodes accountable for their endorsement signal while still allowing them to
forward unendorsed HTLCs that they are not certain about.

HTLC resolution time is assessed relative to a threshold that the node
considers to be a reasonable amount of time for a HTLC to resolve:
- `resolution_period`: the amount of time a HTLC is allowed to resolve in that
is classified as "good" behavior (default: 10 seconds).
- `resolution_time`: the time elapsed between `update_add_htlc` and its
resolution (`update_fulfill_hltc` / `update_fail_hltc` /
`update_fail_malformed_htlc`).

Each HTLC's contribution to reputation is expressed by its `effective_fees`
which capture the fees that it paid and the opportunity cost that its
`resolution_time` incurred:
- `fees`: the fees paid by a forwarded HTLC (as described in [BOLT #7](07-routing-gossip.md#htlc-fees),
equal to 0 if the HTLC was failed).

For some reasonable `resolution_period`, the opportunity cost of a HTLC is
charged per `resolution_period` that it takes to resolve:

`opportunity_cost = ceil ( (resolution_time - resolution_period) / resolution_period) * fees`

Given that `resolution_time` will be > 0 in practice, `opportunity_cost` is 0
for HTLCs that resolve within `resolution_period`, and charges the `fees` that
the HTLC would have earned per period it is held thereafter. This cost accounts
for the slot and liquidity that could have otherwise been paid for by
successful, fast resolving HTLCs during the `resolution_time` the HTLC was
locked in the channel.

For every incoming HLTC a peer has forwarded through a node, its `effective_fees`
are calculated as follows:
- if `endorsed` = 1 in `update_add_htlc`:
- `effective_fees` = `fees` - `opportunity_cost`
- otherwise:
- if successfully resolved AND `resolution_time` <= `resolution_period`
- `effective_fees` = `fees`
- otherwise:
- `effective_fees` = 0

The `effective_fees` that a peer has paid our node are compared to our total
routing revenue to classify a peer's reputation as "good" or "neutral". This
relates the fees that must be paid to earn "good" reputation to the damage that
can be done by abusing it.

Routing revenue is assessed over a sliding window, so that reputation
classification is related to the node's current routing activity. Nodes MAY
choose a window per their preferences - shorter windows being more reactive to
recent routing patterns, and longer windows aggregating trends over time.

- `routing_window`: the period of time in which total routing revenue is
assessed (default: 10 minutes * the maximum number of blocks in the future a
HTLC's expiry height can fall before the node will send `expiry_too_far`, as
outlined in [Failure Messages](#failure-messages)).
- `routing_revenue`: the sum of all fees paid to the node to forward HTLCs
over the interval [ `now` - `routing_window` ; `now` ].

The total `effective_fees` that an individual peer has generated are assessed
over a longer period of time to assess its reputation relative to the routing
activity of the node (represented by `routing_revenue`).

- `reputation_window`: the period of time over which the node's `effective_fees`
are calculated to assess its reputation (recommended default = 10 * `routing_window`).
- `reputation_revenue`: the total `effective_fees` of HTLCs forwarded by the peer
over the interval [ `now` - `reputation_window` ; `now` ].

A peer is classified as having "good" local reputation iff `reputation_revenue` >= `routing_revenue`,
otherwise the peer's reputation is classified as "neutral".

### Rationale
If a HTLC is endorsed by a peer they have signaled that they expect the HTLC
to resolve honestly, so will be held accountable for the manner in which they
resolve. By contrast, if a HTLC was not endorsed by the upstream peer, it
should not have a negative impact on reputation. In the case where one of
these "unknown" HTLCs succeeds within the reasonable resolution threshold, the
peer is still credited with fees because the HTLC resolved desirably.

# Test Vector

## Returning Errors
Expand Down

0 comments on commit ec6eb65

Please sign in to comment.