-
Notifications
You must be signed in to change notification settings - Fork 407
Default to BOLT 4 tlv payload format onions #1414
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
Default to BOLT 4 tlv payload format onions #1414
Conversation
lightning/src/routing/router.rs
Outdated
@@ -1132,7 +1134,7 @@ where L::Target: Logger { | |||
let features = if let Some(node_info) = $node.announcement_info.as_ref() { | |||
&node_info.features | |||
} else { | |||
&empty_node_features | |||
&variable_length_onion_optional_features |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just want to clarify that I couldn't manage to create a test scenario where changing this specific line created a different result in terms of which payload format we create. Though I think it makes sense to change this line.
Codecov Report
@@ Coverage Diff @@
## main #1414 +/- ##
==========================================
+ Coverage 90.82% 90.84% +0.02%
==========================================
Files 73 74 +1
Lines 41266 41375 +109
Branches 41266 41375 +109
==========================================
+ Hits 37480 37589 +109
Misses 3786 3786
Continue to review full report at Codecov.
|
89b9a42
to
8a59b6b
Compare
Cleaned up some documentation. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't believe this modifies the default for last-hop hints which do not appear in the network graph at all. This is the most common use for this. See the NodeFeatures::empty()
call on L1317 in router.rs
Ah thanks, I'll update with converge of that case as soon as I can! |
lightning/src/routing/router.rs
Outdated
let mut variable_length_onion_optional_features = NodeFeatures::empty(); | ||
variable_length_onion_optional_features.set_variable_length_onion_optional(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let mut variable_length_onion_optional_features = NodeFeatures::empty(); | |
variable_length_onion_optional_features.set_variable_length_onion_optional(); | |
let mut onion_optional_features = NodeFeatures::empty(); | |
onion_optional_features.set_variable_length_onion_optional(); |
I'm a super fan of the explicative variable name, but I think that here the variable is too long? Mabey onion_optional_features
is better?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@vincenzopalazzo True, thanks a lot for the feedback! I opted for onion_format_optional_features
in the latest version I pushed, to find some middle ground without losing too much meaning. But I'll change to onion_optional_features
if you think that's still too long :)
lightning/src/routing/router.rs
Outdated
@@ -1132,7 +1134,7 @@ where L::Target: Logger { | |||
let features = if let Some(node_info) = $node.announcement_info.as_ref() { | |||
&node_info.features | |||
} else { | |||
&empty_node_features | |||
&variable_length_onion_optional_features |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
&variable_length_onion_optional_features | |
&onion_optional_features |
lightning/src/routing/router.rs
Outdated
@@ -1330,7 +1332,7 @@ where L::Target: Logger { | |||
if let Some(node_info) = node.announcement_info.as_ref() { | |||
ordered_hops.last_mut().unwrap().1 = node_info.features.clone(); | |||
} else { | |||
ordered_hops.last_mut().unwrap().1 = NodeFeatures::empty(); | |||
ordered_hops.last_mut().unwrap().1 = variable_length_onion_optional_features.clone(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ordered_hops.last_mut().unwrap().1 = variable_length_onion_optional_features.clone(); | |
ordered_hops.last_mut().unwrap().1 = onion_optional_features.clone(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Basically lgtm, need to review the tests still, can you squash the fixup commits?
b713196
to
18557ce
Compare
Fixed some documentation and updated the commit message. Sorry about that. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Largely look good but still need to review the tests while you address the comments.
lightning/src/routing/router.rs
Outdated
@@ -2958,7 +2964,7 @@ mod tests { | |||
assert_eq!(route.paths[0][3].short_channel_id, last_hops[0].0[1].short_channel_id); | |||
assert_eq!(route.paths[0][3].fee_msat, 100); | |||
assert_eq!(route.paths[0][3].cltv_expiry_delta, 42); | |||
assert_eq!(route.paths[0][3].node_features.le_flags(), &Vec::<u8>::new()); // We dont pass flags in from invoices yet | |||
assert_eq!(route.paths[0][3].node_features.le_flags(), &vec![0, 2]); // We dont pass flags in from invoices yet |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use default_onion_format_flags
?
lightning/src/routing/router.rs
Outdated
let mut onion_format_optional_features = NodeFeatures::empty(); | ||
onion_format_optional_features.set_variable_length_onion_optional(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd say use a method for this so it can be reused in the tests and name the variable default_node_features
. No need to have the name talk about the feature itself. FWIW, I think we lose some meaning by dropping the "variable length" part of it, but we can avoid that by just using a generic name.
lightning/src/routing/router.rs
Outdated
fn default_onion_format_flags() -> Vec<u8> { | ||
vec![0, 2] | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could drop this in favor of using the previously suggested method and calling le_flags
on the result.
Thanks for the feedback @jkczyz! Addressed it in the latest commit. I've also realized that I should maybe expand my test to include routing through an unannounced node that isn't the target node, to cover that case as well. I'll add that if you think that it's of value to cover that case in the tests. |
/// | ||
/// Default features are: | ||
/// * variable_length_onion_optional | ||
fn default_node_features() -> NodeFeatures { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Decided to also name this function to default_node_features
, so that it possibly can be extended with more features in the future. I also considered if it would make more sense to add this as part of the NodeFeatures
type itself, but figured that it probably belongs to the router context.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like this refactoring :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be nice to use some of our macros to simplify the tests (I commented with two specific ones, but similar changes apply in test_do_not_use_default_to_tlv_onions_if_other_features_not_supporting_them_exists
as well. Otherwise LGTM.
let scorer = test_utils::TestScorer::with_penalty(0); | ||
let seed = [0u8; 32]; | ||
let keys_manager = test_utils::TestKeysInterface::new(&seed, Network::Testnet); | ||
let random_seed_bytes = keys_manager.get_secure_random_bytes(); | ||
let read_only_network_graph = &network_graph.read_only(); | ||
let announced_route = get_route( | ||
&origin_node.node.get_our_node_id(), &payment_params, read_only_network_graph, | ||
Some(&origin_node.node.list_usable_channels().iter().collect::<Vec<_>>()), | ||
1000000, TEST_FINAL_CLTV, origin_node.logger, &scorer, &random_seed_bytes).unwrap(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let scorer = test_utils::TestScorer::with_penalty(0); | |
let seed = [0u8; 32]; | |
let keys_manager = test_utils::TestKeysInterface::new(&seed, Network::Testnet); | |
let random_seed_bytes = keys_manager.get_secure_random_bytes(); | |
let read_only_network_graph = &network_graph.read_only(); | |
let announced_route = get_route( | |
&origin_node.node.get_our_node_id(), &payment_params, read_only_network_graph, | |
Some(&origin_node.node.list_usable_channels().iter().collect::<Vec<_>>()), | |
1000000, TEST_FINAL_CLTV, origin_node.logger, &scorer, &random_seed_bytes).unwrap(); | |
let (announced_route, _, _, _) = get_route_and_payment_hash!(origin_node, nodes[3], 1_000_000); |
let unannounced_chan_params = PaymentParameters::from_node_id(nodes[4].node.get_our_node_id()).with_route_hints(vec![last_hop]); | ||
let unannounced_route = get_route( | ||
&origin_node.node.get_our_node_id(), &unannounced_chan_params, read_only_network_graph, | ||
Some(&origin_node.node.list_usable_channels().iter().collect::<Vec<_>>()), | ||
10000, TEST_FINAL_CLTV, origin_node.logger, &scorer, &random_seed_bytes).unwrap(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let unannounced_chan_params = PaymentParameters::from_node_id(nodes[4].node.get_our_node_id()).with_route_hints(vec![last_hop]); | |
let unannounced_route = get_route( | |
&origin_node.node.get_our_node_id(), &unannounced_chan_params, read_only_network_graph, | |
Some(&origin_node.node.list_usable_channels().iter().collect::<Vec<_>>()), | |
10000, TEST_FINAL_CLTV, origin_node.logger, &scorer, &random_seed_bytes).unwrap(); | |
let (unannounced_route, _, _, _) = get_route_and_payment_hash!(nodes[0], nodes[4], last_hop, 10_000, TEST_FINAL_CLTV); |
Hmmm the current version of the I therefore pushed the changes in a fixup commit, which I'll squash or drop depending on if you think the modifications are ok. |
Oops, right, good point. I do still prefer the fixup change here - less code duplication for stuff that we end up changing kinda often means way less painful changes later on. |
let payment_params = $crate::routing::router::PaymentParameters::from_node_id($recv_node.node.get_our_node_id()) | ||
.with_features($crate::ln::features::InvoiceFeatures::known()) | ||
.with_route_hints($last_hops); | ||
$crate::get_route_and_payment_hash!($send_node, $recv_node, payment_params, $recv_value, $cltv, true) | ||
}}; | ||
($send_node: expr, $recv_node: expr, $payment_params: expr, $recv_value: expr, $cltv: expr, true /* with specified payment_params */) => {{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be possible to just have this pattern (without the last true
) and have uses of the previous pattern pass in the full PaymentParameters
? I think there's only a few places in priv_short_conf_tests.rs
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok sure, I'll fix that ASAP!
Default to creating tlv onions for nodes for which we haven't received any features through node announcements or which aren't in the `network_graph`, and where no other features are known such as invoice features nor features in the init msg for nodes we have channels to.
697bda8
to
a0c4d1b
Compare
Addressed the latest feedback and squashed the commits! Note that I pushed the change of the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good. Just some nits on the tests.
// onions, as `nodes[0]` has no `NodeAnnouncementInfo` `features` for `node[3]`, and no `InvoiceFeatures` | ||
// for the `payment_params`, which would otherwise have been used. | ||
assert!(hops[2].node_features.supports_variable_length_onion()); | ||
// Note that we do not asset that `hops[0]` (the channel between `nodes[0]` and `nodes[1]`) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: s/asset/assert
// for the `payment_params`, which would otherwise have been used. | ||
assert!(hops[2].node_features.supports_variable_length_onion()); | ||
// Note that we do not asset that `hops[0]` (the channel between `nodes[0]` and `nodes[1]`) | ||
// supports variable length onions, as the `InitFeatures` exchanged in the init message when |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove "when"
/// purposes. | ||
#[cfg(test)] | ||
pub fn clear_nodes_announcement_info(&self) { | ||
for node in self.nodes.write().unwrap().iter_mut(){ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: add space before brace
// Tests that we do not default to creating tlv onions if any of these features exists when | ||
// creating the specific hop in the route: | ||
// 1. `InitFeatures` to the counterparty node exchanged with the init message to the node, which | ||
// doesn't support variable length onions. | ||
// 2. `NodeFeatures` in the `NodeAnnouncementInfo` of a node in sender node's the | ||
// `network_graph`, which doesn't support variable length onions. | ||
// 3. `InvoiceFeatures` specified by the receiving node, which doesn't support variable length | ||
// onions, when no `NodeAnnouncementInfo` `features` exists for the receiver in the sender's | ||
// `network_graph`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The language could be simplified here by moving the "doesn't support variable length onions" part out of each item and said once preceding the list.
// creating the specific hop in the route: | ||
// 1. `InitFeatures` to the counterparty node exchanged with the init message to the node, which | ||
// doesn't support variable length onions. | ||
// 2. `NodeFeatures` in the `NodeAnnouncementInfo` of a node in sender node's the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
drop trailing "the"
} | ||
|
||
#[test] | ||
fn test_do_not_use_default_to_tlv_onions_if_other_features_not_supporting_them_exists() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To name somewhat similar to the previous test, how about: test_do_not_default_to_onion_payload_tlv_format_when_unsupported
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
a0c4d1b
to
c72ae67
Compare
Thanks for the feedback @jkczyz! Addressed and squashed it with the last commit :) |
Closes #1393.
Default to creating BOLT 4 tlv payload format onions for nodes for which we haven't received any features through node announcements, and where no other features are known such as invoice features nor features in the init msg for nodes we
have channel(s) to.
If there is a more convenient way in our testing utils to create a network of nodes, where the nodes to not announce their features through
NodeAnnouncement
s, instead of the test config function I created I'll of course change to that :)!Happy to address any feedback!