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

pay optimizations round 1 #4404

Merged
merged 9 commits into from
Mar 11, 2021
Merged

pay optimizations round 1 #4404

merged 9 commits into from
Mar 11, 2021

Conversation

cdecker
Copy link
Member

@cdecker cdecker commented Feb 26, 2021

This started out as a quick fix for #4299, but while debugging I
stumbled over a couple of easy optimizations:

  • Keysend no longer requires featurebit 55 to be signaled by the
    destination, instead requiring only TLV. This is because apparently
    keysend is not formally proposed to the spec, and the featurebit is
    not reserved. We now will report a more meaningful error message if
    the recipient returns an INVALID_ONION_PAYLOAD error.
  • We now filter routehints whose entrypoints we cannot reach, since
    there is no point in trying them if we can't even get to the
    entrypoint. This considers two different scenarios: entrypoint is
    unknown and entrypoint is unreachable.
  • Added payment_abort to set a top-level error message in the pay
    result, which should make it easier for modifiers to be helpful and
    give a human-readable error message.

I have some more improvements planned, but this seemed like a good
initial candidate set.

@cdecker
Copy link
Member Author

cdecker commented Feb 27, 2021

It seems the test I added is flaky, I'll have a look before undrafting it again.

@cdecker cdecker marked this pull request as draft February 27, 2021 12:20
@cdecker cdecker force-pushed the no55 branch 2 times, most recently from 3822c35 to ae8b311 Compare March 2, 2021 12:17
@rustyrussell rustyrussell added this to the v0.9.4 milestone Mar 3, 2021
@cdecker cdecker marked this pull request as ready for review March 3, 2021 17:51
plugins/pay.c Outdated
Comment on lines 2007 to 2009
is_b12 = strlen(b11str) > 3 &&
(strstarts(b11str, "lni") || strstarts(b11str, "lno") ||
strstarts(b11str, "lnr"));
Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm, I think it's clearer to use two fail ptrs (esp since this test doesn't work correctly for upper case, and I worry about it breaking if we allow lightning:// prefixes etc)?

Then prefer to the bolt11 failstr if both fail. Later we can apply some kind of heuristic like this if necessary (maybe create a helper like looks_like_bolt12_invoice())?

Copy link
Contributor

Choose a reason for hiding this comment

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

Untested:

diff --git a/common/bolt12.c b/common/bolt12.c
index 9cff0ab88..174c66430 100644
--- a/common/bolt12.c
+++ b/common/bolt12.c
@@ -289,6 +289,11 @@ struct tlv_invoice *invoice_decode_nosig(const tal_t *ctx,
 	return invoice;
 }
 
+bool smells_like_bolt12_invoice(const char *str)
+{
+	return strstarts(str, "lni1") || strstarts(str, "LNI1");
+}
+
 static void add_days(struct tm *tm, u32 number)
 {
 	tm->tm_mday += number;
diff --git a/common/bolt12.h b/common/bolt12.h
index 797c5b64b..e9edd9da2 100644
--- a/common/bolt12.h
+++ b/common/bolt12.h
@@ -99,6 +99,9 @@ struct tlv_invoice *invoice_decode_nosig(const tal_t *ctx,
 					 const struct chainparams *must_be_chain,
 					 char **fail);
 
+/* For better error msgs when we get a bolt11 or bolt12. */
+bool smells_like_bolt12_invoice(const char *str);
+
 /* Check a bolt12-style signature. */
 bool bolt12_check_signature(const struct tlv_field *fields,
 			    const char *messagename,

As pointed out by @cfromknecht [1] there was no formal standardization of
the featurebit, and lnd would try a keysend whenever TLV was supported
by the recipient. This mimics that behavior by checking only that TLV
is enabled.

Changelog-Fixes: keysend: We now attempt to send with keysend even if the node hasn't explicitly opted in by setting a featurebit.

[1] ElementsProject#4299 (comment)
Changelog-Fixed: pay: `pay` was reporting in-flight parts as failed
The main responsibility of this new function is to mark a payment
process as terminated and set a reasonable error message, that will be
displayed to the caller. We also skip the remaining modifiers since
they might end up clobbering the message.
@cdecker cdecker force-pushed the no55 branch 3 times, most recently from 9f6aef4 to b8a7d30 Compare March 9, 2021 11:13
We would happily spin on attempts that are doomed to fail because we
don't know the entrypoint. Next up: remove routehints whose
entrypoints are known but unreachable.
Changelog-Added: pay: `pay` will now remove routehints that are unusable due to the entrypoint being unknown or unreachable.
We were not aborting if we had routehints, even though all routehints
may have been filtered out.

Changelog-Fixed: pay: `pay` will now abort early if the destination is not reachable directly nor via routehints.
We were automatically falling back to bolt12 decoding, clobbering the
fail message. Ultimately resulting in confusing error
messages (expected prefix lni but got lnbtrc). Now we first determine
which decoding we're trying to do, and then only decode accordingly.

Changelog-Fixed: pay: Report the correct decoding error if bolt11 parsing fails.
The functions just look at the hrp, so they're not guaranteed to guess
right, but for this case it's sufficient.
@cdecker
Copy link
Member Author

cdecker commented Mar 9, 2021

After a quick detour decoding both and then deciding on which failure was set, I noticed that we'd be masquerading b12 failures with a generic b11 "wrong prefix" error. So I went and added the bolt12_has_*_prefix functions to be able to tell them apart from b11 strings, and now it seems to work.

@rustyrussell
Copy link
Contributor

Ack 858d473

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.

2 participants