Skip to content
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

MPP: limit the number of HTLCs based on destination connectivity #3936

Merged
merged 5 commits into from
Sep 10, 2020

Conversation

ZmnSCPxj
Copy link
Collaborator

Fixes: #3926

(probably)

@ZmnSCPxj
Copy link
Collaborator Author

Rebased

@ZmnSCPxj ZmnSCPxj force-pushed the mpp-destination-htlcs branch 2 times, most recently from 2b759af to e4b1970 Compare August 13, 2020 14:00
@ZmnSCPxj
Copy link
Collaborator Author

Currently wondering if I should instead put the new code in a new paymod instead of mixing it with the presplitter.

And additionally make the presplitter less aggressive, say if it would generate more HTLCs than half the payment_max_htlcs it would limit itself to half the payment_max_htlcs, given that we can very easily split later but have no way to re-merge payments.

@ZmnSCPxj
Copy link
Collaborator Author

ZmnSCPxj commented Aug 13, 2020

Turns out the routehints paymod takes over ownership of the invoice routes (and leaves a stale pointer in the invoice structure, how rude), but we need to know the number of invoice routes being maintained, because if the payee is unpublished that is the only indication we have of the incoming channels of the payee and therefore the limit on the destination connectivity.

@whitslack
Copy link
Collaborator

This seems extremely fragile. You're making some wild assumptions about the HTLC capacities of the nodes in the network. You say, "Assume 30, since that is what C-lightning itself uses, and we have probably the lowest such limit among implementations in common use," but 30 HTLCs is a rather high limit. My C-Lightning node has automatically force-closed a channel with only 4 outstanding HTLCs, and it cost me over $5 in chain fees, once all was said and done, so I surely don't want to allow 30 outstanding HTLCs on any channel; that'd be a recipe for going broke. I have set max-concurrent-htlcs=5 to limit my potential losses. If other node operators are adopting the same strategy, then your estimate of 30 HTLCs per channel doesn't hold water. Besides, you're assuming that no other multi-part payments are in progress to the destination node concurrently, but that is unlikely to be true for high-volume destinations.

Shouldn't C-Lightning strive to minimize the number of concurrent HTLCs that any given multi-part payment generates? Each additional HTLC costs additional money (base fee) and carries a non-zero (and rather high) probability of triggering a channel force-closure and costing the user many dollars in chain fees. Your current strategy is just too expensive.

@ZmnSCPxj
Copy link
Collaborator Author

30 here is the maximum we will split later. See ASSUMED_REASONABLE_HTLCS_PER_CHANNEL instead for the limit on the presplit. This is the initial limit on the number of splits, and comes to 30 / 3 = 10. We do the presplit for up to 10 splits per channel, which gives us some slack later for adaptive splitting.

@ZmnSCPxj
Copy link
Collaborator Author

Moved into a new paymod, since @whitslack brings up that maybe we should not really split early, so maybe we might decide to remove presplitter later. Also, toned down the ASSUMED_MAX_HTLCS_PER_CHANNEL.

Copy link
Member

@cdecker cdecker left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is rather less convoluted than what I expected to be honest, the paymod structure seems to be working :-)
I was about to argue that it'd be better if we limit the overall number of HTLCs the presplit modifier is allowed to create (using either the fibonacci series in #3951 or the simpler power of 16 proposal that doesn't have code yet), but since this is a rather nicely self-contained limiter I think we should keep it.

Might come in handy to have another early abort signal.

plugins/libplugin-pay.c Show resolved Hide resolved
plugins/libplugin-pay.c Show resolved Hide resolved
plugins/libplugin-pay.c Outdated Show resolved Hide resolved
@ZmnSCPxj
Copy link
Collaborator Author

ZmnSCPxj commented Aug 25, 2020

I was about to argue that it'd be better if we limit the overall number of HTLCs the presplit modifier is allowed to create

I would argue that this is different from the presplit:

  • The presplit limit is for the expected network connectivity, i.e. the average connectivity of hop nodes.
  • This limit is for the destination connectivity.

We already have a limit for the source connectivity, that is the only limit we have.

We should limit to the lowest of all three limits: source, network, destination.

The source or the destination could be unusually low-connectivity compared to the network, which is why the presplit limit (which represents the expected limit of the network) is different from the destination limit (which we derive from the number of channels we know to the destination).

plugins/libplugin-pay.c Outdated Show resolved Hide resolved
@ZmnSCPxj
Copy link
Collaborator Author

Rebased (especially with paymod_log), converted max_htlcs to u32. I still think separating the code out is good encapsulation, even if it currently only has one caller. The why string is required as well, as this is the justification we have to limit the number of HTLCs we will try.

@rustyrussell rustyrussell added this to the v0.9.1 milestone Sep 7, 2020
@cdecker
Copy link
Member

cdecker commented Sep 9, 2020

Rebased on top of master. LGTM 👍

ACK db979fe

rustyrussell added a commit to rustyrussell/lightning that referenced this pull request Sep 10, 2020
As revealed by the failure of tests in ElementsProject#3936, where we ended up trying
to send a partial payment using legacy style, we are not handling
style properly.

1. BOLT9 has features, so we can *know* that the destination supports
   MPP.  We may not have seen a node_announcement.
2. We can't assume that nodes inside routehints support TLV.
3. We can't assume direct peers support TLV.

The keysend code tried to fix this up, so I'm not sure that this caused
the issue in ElementsProject#3968, though.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
As revealed by the failure of tests in ElementsProject#3936, where we ended up trying
to send a partial payment using legacy style, we are not handling
style properly.

1. BOLT9 has features, so we can *know* that the destination supports
   MPP.  We may not have seen a node_announcement.
2. We can't assume that nodes inside routehints support TLV.
3. We can't assume direct peers support TLV.

The keysend code tried to fix this up, so I'm not sure that this caused
the issue in ElementsProject#3968, though.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Fixed: `pay` will now make reliable multi-part payments to nodes it doesn't have a node_announcement for.
…hints paymod mutates it.

The routehints paymod shares the storage of the array d->routehints and
p->invoice->routes, but once it operates, it possibly leaves it as a stale
pointer to memory it used to have.

Since other paymods may be interested in the invoice details, including
the routehints in the invoice, we should ensure the p->invoice->routes
remains valid whenever we try mutating that array.
… of HTLCs based on payee connectivity.

Fixes: ElementsProject#3926

(probably)

Changelog-Fixed: pay: Also limit the number of splits if the payee seems to have a low number of channels that can enter it, given the max-concurrent-htlcs limit.
@rustyrussell
Copy link
Contributor

Rebased onto #4035

rustyrussell added a commit to rustyrussell/lightning that referenced this pull request Sep 10, 2020
As revealed by the failure of tests in ElementsProject#3936, where we ended up trying
to send a partial payment using legacy style, we are not handling
style properly.

1. BOLT9 has features, so we can *know* that the destination supports
   MPP.  We may not have seen a node_announcement.
2. We can't assume that nodes inside routehints support TLV.
3. We can't assume direct peers support TLV.

The keysend code tried to fix this up, so I'm not sure that this caused
the issue in ElementsProject#3968, though.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Fixed: `pay` will now make reliable multi-part payments to nodes it doesn't have a node_announcement for.
@rustyrussell rustyrussell mentioned this pull request Sep 10, 2020
@cdecker
Copy link
Member

cdecker commented Sep 10, 2020

ACK 08a22b7

rustyrussell added a commit that referenced this pull request Sep 10, 2020
As revealed by the failure of tests in #3936, where we ended up trying
to send a partial payment using legacy style, we are not handling
style properly.

1. BOLT9 has features, so we can *know* that the destination supports
   MPP.  We may not have seen a node_announcement.
2. We can't assume that nodes inside routehints support TLV.
3. We can't assume direct peers support TLV.

The keysend code tried to fix this up, so I'm not sure that this caused
the issue in #3968, though.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Fixed: `pay` will now make reliable multi-part payments to nodes it doesn't have a node_announcement for.
@rustyrussell rustyrussell merged commit 0eb1e7e into ElementsProject:master Sep 10, 2020
vibhaa pushed a commit to spider-pcn/lightning that referenced this pull request Mar 24, 2021
As revealed by the failure of tests in ElementsProject#3936, where we ended up trying
to send a partial payment using legacy style, we are not handling
style properly.

1. BOLT9 has features, so we can *know* that the destination supports
   MPP.  We may not have seen a node_announcement.
2. We can't assume that nodes inside routehints support TLV.
3. We can't assume direct peers support TLV.

The keysend code tried to fix this up, so I'm not sure that this caused
the issue in ElementsProject#3968, though.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Fixed: `pay` will now make reliable multi-part payments to nodes it doesn't have a node_announcement for.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

MPP pay splits into too many subpayments
4 participants