Skip to content

Replace PublicKey with [u8; 33] in NetworkGraph #1107

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

Merged

Conversation

dunxen
Copy link
Contributor

@dunxen dunxen commented Oct 5, 2021

Closes #960

@dunxen dunxen marked this pull request as draft October 5, 2021 06:40
@dunxen
Copy link
Contributor Author

dunxen commented Oct 5, 2021

Going to take this out of draft once I've fixed the linting and fuzzing.

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.

This is awesome, excited to see benchmark results once bench compiles :)

@dunxen dunxen force-pushed the 2021-10-swap-pubkey-for-bytearray branch from e60d06f to 01e67a4 Compare October 5, 2021 20:49
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, current bench shows a pretty substantial gain in read_network_graph (1.7 seconds to 1.1 seconds on GH Actions) but a very substantial regression in route performance (89ms to 500ms on GH Actions), I believe due to calls to serialize or from_slice in the tight inner loop, see comment.

@dunxen
Copy link
Contributor Author

dunxen commented Oct 6, 2021

I believe due to calls to serialize or from_slice in the tight inner loop, see comment.

I'm also going to minimise serialize() in the rest of get_route() as much as possible.

@dunxen dunxen force-pushed the 2021-10-swap-pubkey-for-bytearray branch from 01e67a4 to c36d6e7 Compare October 6, 2021 08:58
@dunxen
Copy link
Contributor Author

dunxen commented Oct 6, 2021

Seems to fix for earlier Rust versions not supporting const generics, I'll need to use another way to compare NodeIds without introducing more allocations or other overhead.

Edit: Sort of wrong assumption here. It works on 1.47. Rust versions 1.51 and later just use const generics. Would have worked if these were Schnorr pubkeys lol. I'll provide the impl for [T; 33], then I'll promote the PR from draft to ready.

Edit 2: Darn, doesn't seem like I can do this until rust-lang/rust#31844 anyway. And I'm not sure if we'd manage to do it via conditional compilation.

@dunxen
Copy link
Contributor Author

dunxen commented Oct 6, 2021

Just comparing here

#1079

test ln::channelmanager::bench::bench_sends               ... bench:   7,765,229 ns/iter (+/- 1,232,859)
test routing::network_graph::benches::read_network_graph  ... bench: 2,303,387,362 ns/iter (+/- 80,066,866)
test routing::network_graph::benches::write_network_graph ... bench: 152,065,789 ns/iter (+/- 7,420,318)
test routing::router::benches::generate_mpp_routes        ... bench: 104,163,061 ns/iter (+/- 64,813,214)
test routing::router::benches::generate_routes            ... bench:  97,599,490 ns/iter (+/- 69,822,412)

vs c36d6e7

test ln::channelmanager::bench::bench_sends               ... bench:   7,565,717 ns/iter (+/- 1,752,280)
test routing::network_graph::benches::read_network_graph  ... bench: 1,407,918,285 ns/iter (+/- 124,747,638)
test routing::network_graph::benches::write_network_graph ... bench: 134,930,617 ns/iter (+/- 10,801,383)
test routing::router::benches::generate_mpp_routes        ... bench:  42,800,183 ns/iter (+/- 28,587,831)
test routing::router::benches::generate_routes            ... bench:  42,839,538 ns/iter (+/- 33,412,245)

The write performance is not a huge improvement (expected this probably) but read and routes are nice.

@TheBlueMatt
Copy link
Collaborator

Seems to fix for earlier Rust versions not supporting const generics, I'll need to use another way to compare NodeIds without introducing more allocations or other overhead.

I think the way to do this is to replace NodeId type alias with pub struct NodeId([u8; 33]) and then you'll be able to impl core::cmp::PartialOrd for NodeId directly.

@TheBlueMatt
Copy link
Collaborator

The rest of the patch looks good, I think.

@dunxen dunxen force-pushed the 2021-10-swap-pubkey-for-bytearray branch from c36d6e7 to 2a3c25a Compare October 6, 2021 20:50
@dunxen dunxen marked this pull request as ready for review October 6, 2021 21:16
@codecov
Copy link

codecov bot commented Oct 6, 2021

Codecov Report

Merging #1107 (e9059e0) into main (6582aae) will decrease coverage by 0.01%.
The diff coverage is 82.75%.

❗ Current head e9059e0 differs from pull request most recent head fce631c. Consider uploading reports for the commit fce631c to get more accurate results
Impacted file tree graph

@@            Coverage Diff             @@
##             main    #1107      +/-   ##
==========================================
- Coverage   90.67%   90.65%   -0.02%     
==========================================
  Files          66       65       -1     
  Lines       34608    34621      +13     
==========================================
+ Hits        31381    31387       +6     
- Misses       3227     3234       +7     
Impacted Files Coverage Δ
lightning/src/routing/network_graph.rs 91.22% <74.50%> (-0.32%) ⬇️
lightning/src/routing/router.rs 96.04% <89.23%> (+<0.01%) ⬆️
lightning/src/ln/channelmanager.rs 84.87% <0.00%> (-0.01%) ⬇️
lightning/src/ln/mod.rs 90.00% <0.00%> (ø)
lightning/src/ln/payment_tests.rs
lightning/src/ln/functional_tests.rs 97.40% <0.00%> (+0.01%) ⬆️

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 6582aae...fce631c. Read the comment docs.

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.

Basically LGTM, note you'll have to squash for CI to pass.

@dunxen
Copy link
Contributor Author

dunxen commented Oct 6, 2021

Basically LGTM, note you'll have to squash for CI to pass.

The one time I forget to squash before pushing 🥲

@dunxen dunxen force-pushed the 2021-10-swap-pubkey-for-bytearray branch 2 times, most recently from bede58e to 5e204d2 Compare October 7, 2021 05:07
@dunxen dunxen force-pushed the 2021-10-swap-pubkey-for-bytearray branch from 5e204d2 to 059bf1a Compare October 8, 2021 15:55
@dunxen dunxen force-pushed the 2021-10-swap-pubkey-for-bytearray branch from 059bf1a to fce631c Compare October 8, 2021 16:38
@@ -4409,9 +4413,9 @@ mod tests {
'load_endpoints: for _ in 0..10 {
loop {
seed = seed.overflowing_mul(0xdeadbeef).0;
let src = nodes.keys().skip(seed % nodes.len()).next().unwrap();
let src = &PublicKey::from_slice(nodes.keys().skip(seed % nodes.len()).next().unwrap().as_slice()).unwrap();
Copy link
Contributor

Choose a reason for hiding this comment

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

How about impl From<NodeId> for PublicKey (and vice-versa)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, I did consider that right after I pushed the last change. It'll clean things up quite a bit, I agree 🙂

Copy link
Contributor

Choose a reason for hiding this comment

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

I don't believe we can implement From for a struct outside our crate. There's a workaround with using a tuple struct wrapping the PublicKey. But also note that the conversion functions consume the struct being converted, so in many cases we'd have to make a copy since we only have a reference, which I think we'd want to avoid.

Copy link
Collaborator

@TheBlueMatt TheBlueMatt Oct 8, 2021

Choose a reason for hiding this comment

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

We also can't implement From<NodeId> for PublicKey because its not infallible, it'd have to be TryFrom, at which point its arguably a similar amount of code to read (and I strongly prefer to see from_slice over try_from, because its much more explicit for the same thing).

Copy link
Contributor

Choose a reason for hiding this comment

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

@jkczyz since NodeId is in this crate From<T> for NodeId can always be implemented for any T we want. Also since Rust 1.41 From<NodeId> for T is possible. In older versions at least impl Into<T> for NodeId.

Also From and Into can be implemented for references, so copying should be non-issue.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think we can leave it as is for now then?

Copy link
Contributor Author

@dunxen dunxen Oct 8, 2021

Choose a reason for hiding this comment

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

Is there going to be a bump in MSRV soon or are we trying to avoid that? I agree things look fine as is right now but would be nice to be able to implement From / TryFrom for external structs for maybe other things in future?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Is there going to be a bump in MSRV soon or are we trying to avoid that?

Unlikely - we generally try to ensure you can compile LDK using commonly-available Rust toolchains. Distros don't usually ship rust updates except when they have to (ie when a new Firefox ESR comes out and they have to bump to meet the Firefox MSRV).

Copy link
Contributor

Choose a reason for hiding this comment

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

@Kixunil Happy to review any follow-ups if this is possible within our MSRV constraints.

Copy link
Contributor

Choose a reason for hiding this comment

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

I don't care much, just note that Debian oldstable contains Rust 1.41, which is sufficient to solve the From issue. Debian Bullseye has 1.48 which can even support modern Tokio. Debian stable is probably the most conservative distro that's actually widely used, so doesn't seem too bad to me.

@TheBlueMatt TheBlueMatt merged commit 843d25d into lightningdevkit:main Oct 8, 2021
@dunxen dunxen deleted the 2021-10-swap-pubkey-for-bytearray branch October 9, 2021 06:14
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.

Swap NetworkGraph PublicKeys for [u8; 33]
4 participants