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

Create normal/phantom invoice with description hash #1361

Merged

Conversation

luizParreira
Copy link
Contributor

@luizParreira luizParreira commented Mar 13, 2022

Closes #1280

@luizParreira
Copy link
Contributor Author

@TheBlueMatt I implemented the first try on supporting description_hash. On my implementation, I created 2 variant functions create_phantom_invoice_with_description_hash and create_invoice_from_channelmanager_with_description_hash, both of which receive a normal description that is hashed within the function. I was not sure if this would be better than just receiving the description_hash directly. Please, let me know what you think. :)

@codecov-commenter
Copy link

codecov-commenter commented Mar 13, 2022

Codecov Report

Merging #1361 (2ce3832) into main (c244c78) will increase coverage by 0.01%.
The diff coverage is 97.67%.

❗ Current head 2ce3832 differs from pull request most recent head 925e296. Consider uploading reports for the commit 925e296 to get more accurate results

@@            Coverage Diff             @@
##             main    #1361      +/-   ##
==========================================
+ Coverage   90.73%   90.74%   +0.01%     
==========================================
  Files          73       73              
  Lines       40808    40885      +77     
  Branches    40808    40885      +77     
==========================================
+ Hits        37027    37102      +75     
- Misses       3781     3783       +2     
Impacted Files Coverage Δ
lightning-invoice/src/utils.rs 96.79% <97.67%> (+0.25%) ⬆️
lightning/src/util/events.rs 33.09% <0.00%> (-0.36%) ⬇️
lightning/src/ln/functional_tests.rs 97.06% <0.00%> (-0.02%) ⬇️
lightning/src/routing/router.rs 92.40% <0.00%> (+0.03%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update c244c78...925e296. Read the comment docs.

@luizParreira luizParreira force-pushed the rust-lightning/issues/1280 branch 3 times, most recently from 55e696f to 813a965 Compare March 14, 2022 10:22
Copy link
Contributor

@ViktorTigerstrom ViktorTigerstrom left a comment

Choose a reason for hiding this comment

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

In general this looks quite good in terms of solving the issue from what I can see :)

However, please avoid mixing code reformatting with code changes as this PR currently does. Else it becomes hard to see what is actual code changes, and what is only code reformatting. It also complicates using git log/blame in the future, to find out why certain code was changed. If your IDE auto formats the code, I would recommend that you disable that feature, and only make it hint reformatting tips.
If you really want to include the reformatting, I'd recommend that you at least push it into a separate PR/commit.

InvoiceDescription::Hash(hash) => InvoiceBuilder::new(network).description_hash(hash.0),
};

let mut invoice = invoice
Copy link
Contributor

Choose a reason for hiding this comment

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

The code below here in this function is code reformatting.

InvoiceDescription::Hash(hash) => InvoiceBuilder::new(network).description_hash(hash.0),
};

let mut invoice = invoice
Copy link
Contributor

Choose a reason for hiding this comment

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

The code below here in this function is mostly code reformatting.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In this case, I am also avoiding the route_hints double loop and am setting the invoice's private_route as we loop through the channels.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah I see! That specific optimization will conflict with #1325, but if you prefer keeping it, whichever PR gets merged after the other could just resolve that :)

@luizParreira luizParreira force-pushed the rust-lightning/issues/1280 branch 3 times, most recently from 7789ea7 to 66a33fa Compare March 14, 2022 16:24
@luizParreira
Copy link
Contributor Author

@ViktorTigerstrom Thank you very much for the review. I managed to fix all of your points. Let me know if there is any other improvement you think I should make.

@luizParreira luizParreira force-pushed the rust-lightning/issues/1280 branch from 66a33fa to 8c27b47 Compare March 14, 2022 16:28
@ViktorTigerstrom
Copy link
Contributor

Great, that looks much better :)! Some quick fixes I recommend that you fix are:

  • Use tabs rather than spaces, which the rest of the project does
  • Try looking at how the rest of the project formats calls/argument passing to functions like create_announced_chan_between_nodes_with_value, handle_channel_update and similar to make the code more consistent with the rest of the project :)

Copy link
Collaborator

@TheBlueMatt TheBlueMatt left a comment

Choose a reason for hiding this comment

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

Nice this looks pretty great. As @ViktorTigerstrom mentioned, could you replace spaces here with tabs, otherwise I'm basically happy with this. Note it'll conflict with #1325 which is probably about ready to land, so I'll let you and @ViktorTigerstrom hash out who has to rebase on which and the merge order.

InitFeatures::known(),
);
nodes[0]
.node
Copy link
Collaborator

Choose a reason for hiding this comment

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

I know this is the rustfmt way and many rust projects use this kind of super-vertical layout, but I find it completely unreadable (and its the primary reason we don't use rustfmt here and I believe the primary reason rust-bitcoin doesn't use it either). If possible, could you condense lines a bit so that its easier for the eye to scan between statements? Only break lines if the line is reaching 100 chars in length, roughly.

@luizParreira luizParreira force-pushed the rust-lightning/issues/1280 branch from 8c27b47 to 7cef6b6 Compare March 16, 2022 17:04
@luizParreira
Copy link
Contributor Author

@TheBlueMatt @ViktorTigerstrom I tried to remove most of the line breaks and make the code layout more horizontal. Please, let me know if there is anything else you would like me to improve :)

@TheBlueMatt
Copy link
Collaborator

Thanks! Sadly this needs rebase since we landed #1325 but otherwise it looks basically good to me.

@luizParreira luizParreira force-pushed the rust-lightning/issues/1280 branch from 7cef6b6 to e618f7b Compare March 16, 2022 17:39
@luizParreira
Copy link
Contributor Author

@TheBlueMatt Rebase done :)

{
_create_phantom_invoice::<Signer, K>(
amt_msat,
InvoiceDescription::Hash(&crate::Sha256(Hash::hash(description.as_bytes()))),
Copy link
Collaborator

Choose a reason for hiding this comment

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

Oh, actually, sorry, can we just take the hash itself as the argument? That's strictly more generic.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You mean receive the Sha256 struct as a param to create_phantom_invoice_with_description_hash, instead of the desccription as as String? 🤔

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yea.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@@ -1015,4 +1201,82 @@ mod test {
}
assert!(chan_ids_to_match.is_empty(), "Unmatched short channel ids: {:?}", chan_ids_to_match);
}
#[test]
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: there's still a lot of spaces instead of tabs in the file in the tests here :).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@TheBlueMatt My bad, I forgot to fix the spaces issue. Is it ok now? On my editor it seems to be on tabs size 4 🤔

@luizParreira luizParreira force-pushed the rust-lightning/issues/1280 branch from e618f7b to 411d827 Compare March 16, 2022 17:50
Copy link
Contributor

@ViktorTigerstrom ViktorTigerstrom left a comment

Choose a reason for hiding this comment

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

The rebase looks good! Just some quick recommendations.

Also, unfortunately there's still spaces instead of tabs in all of functions and tests you've added. In some functions/tests, there's a mix between both tabs and spaces. You should set your editor to specifically use tabs, not 4 spaces for indentations.

@@ -1015,4 +1201,81 @@ mod test {
}
assert!(chan_ids_to_match.is_empty(), "Unmatched short channel ids: {:?}", chan_ids_to_match);
}

#[test]
fn test_create_invoice_with_description_hash() {
Copy link
Contributor

@ViktorTigerstrom ViktorTigerstrom Mar 16, 2022

Choose a reason for hiding this comment

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

I'd personally place this test with the other tests that doesn't require std, just so it becomes clearer what's actually loaded under which configuration. I suggest you place it after the test_from_channelmanager test.

Copy link
Contributor Author

Choose a reason for hiding this comment

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


#[test]
#[cfg(feature = "std")]
fn create_phantom_invoice_with_description_hash() {
Copy link
Contributor

Choose a reason for hiding this comment

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

Same here, I suggest that you place this right after the do_test_multi_node_receive test.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@luizParreira luizParreira force-pushed the rust-lightning/issues/1280 branch 2 times, most recently from 5c7c5b4 to d1f4536 Compare March 16, 2022 18:48
@luizParreira
Copy link
Contributor Author

@ViktorTigerstrom @TheBlueMatt I believe now I am properly formatting with tabs :)

@luizParreira luizParreira force-pushed the rust-lightning/issues/1280 branch from d1f4536 to 2ce3832 Compare March 16, 2022 19:33
Copy link
Collaborator

@TheBlueMatt TheBlueMatt left a comment

Choose a reason for hiding this comment

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

Left a few comments on examples of places where I think the formatting needlessly leads to reviewers/readers having no context - the classic issue with rustfmt's poor formatting. Could you take a pass through and remove newlines that don't improve readability (feel free to add blank lines to break up hunks if the code looks too dense).

amt_msat: Option<u64>, description: String, payment_hash: PaymentHash, payment_secret:
PaymentSecret, phantom_route_hints: Vec<PhantomRouteHints>, keys_manager: K, network: Currency
) -> Result<Invoice, SignOrCreationError<()>> where K::Target: KeysInterface {
amt_msat: Option<u64>,
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm also really not a huge fan of making this layout super vertical just to call a utility method.

Some(payment_amt), description_hash, payment_hash, payment_secret, route_hints,
&nodes[1].keys_manager, Currency::BitcoinTestnet,
)
.unwrap();
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why did you \n here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No particular reason. Removed with 24ed8af

/// that the payment secret is valid when the invoice is paid.
/// Use this variant if you want to pass the `description_hash` to the invoice.
pub fn create_invoice_from_channelmanager_with_description_hash<
Signer: Sign,
Copy link
Collaborator

Choose a reason for hiding this comment

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

Same here - we're now 21 LoC to list 5 arguments, with two or three of these suddenly even large terminals have no context for what's going on..this is a great example of why rustfmt is unreadable. Can you condense these somewhat (I know some of the existing code was this way)

&nodes[1].node, nodes[1].keys_manager, Currency::BitcoinTestnet, Some(10_000),
description_hash, Duration::from_secs(1234567),
)
.unwrap();
Copy link
Collaborator

Choose a reason for hiding this comment

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

same here - why \n?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No particular reason. Removed with 24ed8af

.unwrap();
assert_eq!(invoice.amount_pico_btc(), Some(100_000));
assert_eq!(
invoice.min_final_cltv_expiry(),
Copy link
Collaborator

Choose a reason for hiding this comment

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

No need to break this into multiple lines, the line written out isn't very long.

MIN_FINAL_CLTV_EXPIRY as u64
);
assert_eq!(
invoice.description(),
Copy link
Collaborator

Choose a reason for hiding this comment

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

I don't see a reason why this needs to be on a new line.

@luizParreira luizParreira force-pushed the rust-lightning/issues/1280 branch from 2ce3832 to 5852bbe Compare March 18, 2022 13:24
@luizParreira
Copy link
Contributor Author

@TheBlueMatt Fixed your code-style comments. Anything else?

@luizParreira luizParreira force-pushed the rust-lightning/issues/1280 branch from 5852bbe to 24ed8af Compare March 18, 2022 13:34
Copy link
Contributor

@ViktorTigerstrom ViktorTigerstrom left a comment

Choose a reason for hiding this comment

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

Starting to look really good :)! Just left a few comments of further cleanup that can be made, and also improvements to the code formatting that I think you should implement to make the code more consistent with the rest of the project, even though lines will exceed 100 chars.

Comment on lines 207 to 209
pub fn create_invoice_from_channelmanager_with_description_hash<Signer: Sign, M: Deref, T: Deref,
K: Deref, F: Deref, L: Deref,
>(
Copy link
Contributor

@ViktorTigerstrom ViktorTigerstrom Mar 18, 2022

Choose a reason for hiding this comment

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

I think you should make this into a single line, even though it's over 100 chars to make it more consistent with the rest of the project.

Comment on lines 234 to 236
pub fn create_invoice_from_channelmanager_with_description_hash_and_duration_since_epoch<
Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref,
>(
Copy link
Contributor

Choose a reason for hiding this comment

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

Same here, make this into a single line.

Comment on lines 883 to 886
let invoice = ::utils::create_phantom_invoice_with_description_hash::<
EnforcingSigner,
&test_utils::TestKeysInterface,
>(
Copy link
Contributor

Choose a reason for hiding this comment

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

Make this into a single line.

Comment on lines 864 to 873
let chan_0_1 = create_announced_chan_between_nodes_with_value(
&nodes, 0, 1, 100000, 10001, InitFeatures::known(), InitFeatures::known(),
);
nodes[0].node.handle_channel_update(&nodes[1].node.get_our_node_id(), &chan_0_1.1);
nodes[1].node.handle_channel_update(&nodes[0].node.get_our_node_id(), &chan_0_1.0);
let chan_0_2 = create_announced_chan_between_nodes_with_value(
&nodes, 0, 2, 100000, 10001, InitFeatures::known(), InitFeatures::known(),
);
nodes[0].node.handle_channel_update(&nodes[2].node.get_our_node_id(), &chan_0_2.1);
nodes[2].node.handle_channel_update(&nodes[0].node.get_our_node_id(), &chan_0_2.0);
Copy link
Contributor

@ViktorTigerstrom ViktorTigerstrom Mar 18, 2022

Choose a reason for hiding this comment

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

Sorry for not picking up on this earlier, but there's actually no need for you to create these channels in order to create the invoice for this test. So you can just remove them to make the test more focused :). Also while you're at it, you might as well remove the extra unused node created in test_create_invoice_with_description_hash and create_phantom_invoice_with_description_hash to avoid any confusion.

@luizParreira luizParreira force-pushed the rust-lightning/issues/1280 branch 2 times, most recently from 439c6ed to 925e296 Compare March 18, 2022 18:01
@luizParreira
Copy link
Contributor Author

luizParreira commented Mar 18, 2022

@ViktorTigerstrom Fixed your points on 7714393

TheBlueMatt
TheBlueMatt previously approved these changes Mar 18, 2022
Copy link
Collaborator

@TheBlueMatt TheBlueMatt left a comment

Choose a reason for hiding this comment

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

LGTM! Thanks for tacking some of the style stuff, two trivial nits, but no need to rush to fix them unless there's other stuff to fix or you feel like it.

@ViktorTigerstrom
Copy link
Contributor

@ViktorTigerstrom Fixed your points on 7714393

Great!

@jkczyz
Copy link
Contributor

jkczyz commented Mar 18, 2022

Rather than have a handful of functions with long names and parameter lists, should we consider having one function that takes an InvoiceBuilder?

@ViktorTigerstrom
Copy link
Contributor

ViktorTigerstrom commented Mar 18, 2022

Rather than have a handful of functions with long names and parameter lists, should we consider having one function that takes an InvoiceBuilder?

If that's something we'd like to implement, I could work on that in a follow up if you'd like, to not bloat this PR.

@TheBlueMatt
Copy link
Collaborator

Yea, passing an InvoiceBuilder instead of a function would be nice, but its kinda an awkward API to communicate to the user exactly what is or is not required to be set before calling the function. More importantly, the InvoiceBuidler API isn't something we can describe in the bindings, so its currently not exported :(.

@jkczyz
Copy link
Contributor

jkczyz commented Mar 18, 2022

Hmmm... yeah, bindings would be a problem. Would be nice to at least have the phantom and non-phantom versions take an InvoiceDescription enum instead of having a version for each variant, but looks like we don't export that either. 🙁

}

#[cfg(feature = "std")]
/// Utility to create an invoice that can be paid to one of multiple nodes, or a "phantom invoice."
Copy link
Contributor

Choose a reason for hiding this comment

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

Perhaps better to reference the other docs rather than repeating them here. But could be left to a follow-up.

@TheBlueMatt
Copy link
Collaborator

Would be nice to at least have the phantom and non-phantom versions take an InvoiceDescription enum instead of having a version for each variant, but looks like we don't export that either.

Yea, there's probably an easy-ish way to do something like that, the issue with it currently is its really an enum-holding-references type, which we can't map, but we can create a second enum that isn't holding a reference which would let us do this.

@TheBlueMatt
Copy link
Collaborator

Figure its worth landing as-is, we can condense the functions as a follow-up, or not, its not like its bad in its current state.

@TheBlueMatt TheBlueMatt merged commit 5ed2985 into lightningdevkit:main Mar 18, 2022
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.

create_invoice_from_channelmanager variant with description hash support
5 participants