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

BOLT 04: document non-strict forwarding #503

Merged
merged 1 commit into from Nov 29, 2018

Conversation

Projects
None yet
5 participants
@cfromknecht
Contributor

cfromknecht commented Nov 10, 2018

This PR documents the allowance of non-strict
forwarding, permitting forwarding nodes to select
between any available outgoing channel with the peer
that would otherwise be specified by the
short_channel_id in the onion packet.

It also includes recommendations for fee schedules
when using non-strict forwarding, either by using
a uniform fee schedule with a peer or only
considering like-policied channels, to ensure the
channel is truly equivalent in terms of fee revenue
for the forwarder.

04-onion-routing: document non-strict forwarding
This commit documents the allowance of non-strict
forwarding, permitting forwarding nodes to select
between any available outgoing channel with the peer
that would otherwise be specified by the
short_channel_id in the onion packet.

It also includes recommendations for fee schedules
when using non-strict forwarding, either by using
a uniform fee schedule with a peer or only
considering like-policied channels, to ensure the
channel is truly equivalent in terms of fee revenue
for the forwarder.

@cfromknecht cfromknecht changed the title from 04-onion-routing: document non-strict forwarding to BOLT 04: document non-strict forwarding Nov 10, 2018

### Recommendation
Implementations using non-strict forwarding should consider applying the same

This comment has been minimized.

@pm47

pm47 Nov 12, 2018

Collaborator

I think we should also recommend sending errors for the initially requested short_channel_id (at least until we allow sending multiple channel_update). This makes it transparent for the sender: either the payment succeeds using a different channel and it isn't even aware of what happened, or there is an error and it gets an error for the channel it asked.

There are other corner cases, like what if we return an error for an unannounced channel?

The way we implemented it in eclair is that we may try different channels, but always end with the one that was requested and return that last error.

This comment has been minimized.

@joostjager

joostjager Nov 13, 2018

I think it can be worth distinguishing between three cases where non-strict forwarding fails:

  1. The htlc does not satisfy the requested channel's policy.
  2. The htlc does satisfy the requested channel's policy (the payment failed for a different reason like insufficient balance) and there is no other channel to B that would be able to carry the payment at this time (for example when none of the channels has enough balance for the requested amount).
  3. The htlc does satisfy the requested channel's policy and there are one or more other channels to B that would be able to carry the payment at this time if their policy would have been satisfied.

In case 1, the sender's graph is not up to date. It is probably best to return a channel_update for the requested channel so the sender can try again.

In case 2, returning a channel_update for the requested channel is unnecessary, because the sender is already aware of the current policy. If optional in the failure message, leave it out to save bytes.

In case 3, returning a channel_update for the requested channel is unnecessary, because the sender is already aware of the current policy. But we could choose to re-purpose the channel_update to signal a policy that would allow forwarding (assuming that nothing changes in the mean time).

The forwarding node could iterate over all its channels to B that have enough balance for the requested amount and determine the best channel for the sender. "Best" is based on a tradeoff between fee and timelock, similar to what is used during path finding. A channel_update is returned for the best channel. This behaviour could be signaled with a node feature bit, so that senders know how to interpret a channel_update for a channel other than the requested channel. It allows them to find a successful route faster and increases the chance for the forwarding node to earn a fee.

A forwarding node could also try to earn more by signaling a more expensive channel, but it may be that the sender then first tries other routes, potentially leaving the forwarding node with empty hands.

In case the best channel is a private channel, the forwarding node could send back a channel_update for a public channel that has a policy that is 'compatible' (equal or higher fees and/or cltv delta) with the private channel. It doesn't matter if this public channel doesn't have enough balance, because non-strict forwarding will also be applied on the next attempt.

This comment has been minimized.

@pm47

pm47 Nov 13, 2018

Collaborator

If optional in the failure message, leave it out to save bytes.

It wouldn't really save bytes because the data is padded to 256B anyway.

But we could choose to re-purpose the channel_update to signal a policy that would allow forwarding (assuming that nothing changes in the mean time).

A proposal made during the summit was that we should allow returning multiple channel_update. The more I think about it though, the more I'm convinced that if supporting non-strict forwarding, a per-node policy is the only thing that really makes sense. That simply removes your 3rd point and weird corner cases (private channels and incentive issues). Anyway I think @cfromknecht intended to specify shorter term recommendations, without changing the onion's format.

This comment has been minimized.

@joostjager

joostjager Nov 13, 2018

Point taken on padding.

I can also see this all going towards a per-node policy. Indeed, the goal of the 3rd point is a short term improvement to the current behaviour without changing the onion format.

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.

This comment has been minimized.

@joostjager

joostjager Nov 13, 2018

Like-policy here means any policy that is satisfied by the incoming htlc? (not just equal policies)

### Recommendation
Implementations using non-strict forwarding should consider applying the same

This comment has been minimized.

@joostjager

joostjager Nov 13, 2018

I think it can be worth distinguishing between three cases where non-strict forwarding fails:

  1. The htlc does not satisfy the requested channel's policy.
  2. The htlc does satisfy the requested channel's policy (the payment failed for a different reason like insufficient balance) and there is no other channel to B that would be able to carry the payment at this time (for example when none of the channels has enough balance for the requested amount).
  3. The htlc does satisfy the requested channel's policy and there are one or more other channels to B that would be able to carry the payment at this time if their policy would have been satisfied.

In case 1, the sender's graph is not up to date. It is probably best to return a channel_update for the requested channel so the sender can try again.

In case 2, returning a channel_update for the requested channel is unnecessary, because the sender is already aware of the current policy. If optional in the failure message, leave it out to save bytes.

In case 3, returning a channel_update for the requested channel is unnecessary, because the sender is already aware of the current policy. But we could choose to re-purpose the channel_update to signal a policy that would allow forwarding (assuming that nothing changes in the mean time).

The forwarding node could iterate over all its channels to B that have enough balance for the requested amount and determine the best channel for the sender. "Best" is based on a tradeoff between fee and timelock, similar to what is used during path finding. A channel_update is returned for the best channel. This behaviour could be signaled with a node feature bit, so that senders know how to interpret a channel_update for a channel other than the requested channel. It allows them to find a successful route faster and increases the chance for the forwarding node to earn a fee.

A forwarding node could also try to earn more by signaling a more expensive channel, but it may be that the sender then first tries other routes, potentially leaving the forwarding node with empty hands.

In case the best channel is a private channel, the forwarding node could send back a channel_update for a public channel that has a policy that is 'compatible' (equal or higher fees and/or cltv delta) with the private channel. It doesn't matter if this public channel doesn't have enough balance, because non-strict forwarding will also be applied on the next attempt.

@joostjager

This comment has been minimized.

joostjager commented Nov 15, 2018

Consider adding a global feature bit to signal that a node forwards non-strictly and that it is therefore not necessary to try all like-policy channels to the same node.

@renepickhardt

This comment has been minimized.

renepickhardt commented Nov 16, 2018

I understand this will increase the complexity but I am wondering weather it would make sense to allow for local base AMP at this point. Let us assume I am supposed to forward 0.1 BTC I have two channels to the same node each with 0.15 BTC capacity and 0.075 on my side of the channel.
In that case This proposal will not help since I can't use ether of the channels.

How ever if the node was allowed to fragment the payment to make a base AMP for only the next hope (as far as I understand not compatible with our current Base AMP proposal (c.f.: #511 since the next hope is not the final node and we can also not alter the rest of the onion package to be cloned for two paths)

still if locally we were able to fragment it would be nice.

in particular the fragmentation could be extended. Let us assume I have only one chanel with capacity of 0.15 and are supposed to forward 0.1 BTC but my balance says 0.075. In that case I could make a local AMP to the next hop with .05 BTC and try myself to find another route with 0.05 to forward to the next hope on a best effort base. This would actually mean that while routing nodes that run into capacity issues will try to locally solve the issue.

One issue with this suggestion is that There are probably not enough fees to send part of the htlcs to be forwarded through a different path. This issue could probably be mitigated by putting higher fees at every onion hop if fragmentation was allowed. (similar issues exist with htlc time delays for the entire package)

I guess that a complete local "allow fragmentation and best effort routing protocol will involve to many changes. I still think that In the case described above where I have 2 channels and I could do a local split where as by selecting either channel I could not forward the payment would be a nice and feasible addtion to what we have agreed on in Australia.

@joostjager

This comment has been minimized.

joostjager commented Nov 20, 2018

Consider adding a global feature bit to signal that a node forwards non-strictly and that it is therefore not necessary to try all like-policy channels to the same node.

It appears that all implementations forward non-strictly, so that would make a feature bit obsolete.

@rustyrussell rustyrussell added this to the v1.0 milestone Nov 26, 2018

@rustyrussell rustyrussell merged commit 7163c52 into lightningnetwork:master Nov 29, 2018

1 check passed

continuous-integration/travis-ci/pr The Travis CI build passed
Details
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment