Skip to content

Commit 8a59b6b

Browse files
Add tests for defaulting to creating tlv onions
1 parent ff152ef commit 8a59b6b

File tree

2 files changed

+154
-1
lines changed

2 files changed

+154
-1
lines changed

lightning/src/ln/onion_route_tests.rs

Lines changed: 145 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use ln::channelmanager::{HTLCForwardInfo, CLTV_FAR_FAR_AWAY, MIN_CLTV_EXPIRY_DEL
1818
use ln::onion_utils;
1919
use routing::network_graph::{NetworkUpdate, RoutingFees};
2020
use routing::router::{get_route, PaymentParameters, Route, RouteHint, RouteHintHop};
21-
use ln::features::{InitFeatures, InvoiceFeatures};
21+
use ln::features::{InitFeatures, InvoiceFeatures, NodeFeatures};
2222
use ln::msgs;
2323
use ln::msgs::{ChannelMessageHandler, ChannelUpdate, OptionalField};
2424
use util::events::{Event, MessageSendEvent, MessageSendEventsProvider};
@@ -34,6 +34,7 @@ use bitcoin::hashes::sha256::Hash as Sha256;
3434
use bitcoin::secp256k1;
3535
use bitcoin::secp256k1::Secp256k1;
3636
use bitcoin::secp256k1::key::{PublicKey, SecretKey};
37+
use bitcoin::network::constants::Network;
3738

3839
use io;
3940
use prelude::*;
@@ -577,6 +578,149 @@ fn test_onion_failure() {
577578
}, true, Some(23), None, None);
578579
}
579580

581+
#[test]
582+
fn test_default_to_onion_payload_tlv_format() {
583+
// Tests that we default to creating tlv format onion payloads in the scenario that we have no
584+
// `NodeAnnouncementInfo` `features` for a node in the `network_graph` when creating a route,
585+
// and no other known `features` for the node.
586+
let chanmon_cfgs = create_chanmon_cfgs(4);
587+
let node_cfgs = create_node_cfgs(4, &chanmon_cfgs);
588+
let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs, &[None, None, None, None]);
589+
let mut nodes = create_network(4, &node_cfgs, &node_chanmgrs);
590+
591+
create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
592+
create_announced_chan_between_nodes(&nodes, 1, 2, InitFeatures::known(), InitFeatures::known());
593+
create_announced_chan_between_nodes(&nodes, 2, 3, InitFeatures::known(), InitFeatures::known());
594+
595+
let payment_params = PaymentParameters::from_node_id(nodes[3].node.get_our_node_id());
596+
let origin_node = &nodes[0];
597+
let network_graph = origin_node.network_graph;
598+
599+
// Clears all the `NodeAnnouncementInfo` for all nodes of `nodes[0]`'s `network_graph`, so that
600+
// their `features` aren't used when creating the `route`.
601+
network_graph.clear_nodes_announcement_info();
602+
603+
let scorer = test_utils::TestScorer::with_penalty(0);
604+
let seed = [0u8; 32];
605+
let keys_manager = test_utils::TestKeysInterface::new(&seed, Network::Testnet);
606+
let random_seed_bytes = keys_manager.get_secure_random_bytes();
607+
let route = get_route(
608+
&origin_node.node.get_our_node_id(), &payment_params, &network_graph.read_only(),
609+
Some(&origin_node.node.list_usable_channels().iter().collect::<Vec<_>>()),
610+
1000000, TEST_FINAL_CLTV, origin_node.logger, &scorer, &random_seed_bytes).unwrap();
611+
612+
let hops = &route.paths[0];
613+
// Assert that the hop between `nodes[1]` and `nodes[2]` defaults to supporting variable length
614+
// onions, as `nodes[0]` has no `NodeAnnouncementInfo` `features` for `node[2]`
615+
assert!(hops[1].node_features.supports_variable_length_onion());
616+
// Assert that the hop between `nodes[2]` and `nodes[3]` defaults to supporting variable length
617+
// onions, as `nodes[0]` has no `NodeAnnouncementInfo` `features` for `node[3]`, and no `InvoiceFeatures`
618+
// for the `payment_params`, which would otherwise have been used.
619+
assert!(hops[2].node_features.supports_variable_length_onion());
620+
// Note that we do not asset that `hops[0]` (the channel between `nodes[0]` and `nodes[1]`)
621+
// supports variable length onions, as the `InitFeatures` exchanged in the init message when
622+
// between the nodes will be used when creating the route. We therefore do not default to
623+
// supporting variable length onions for that hop, as the `InitFeatures` in this case are
624+
// `InitFeatures::known()`.
625+
626+
let cur_height = nodes[0].best_block_info().1 + 1;
627+
let (onion_payloads, _htlc_msat, _htlc_cltv) = onion_utils::build_onion_payloads(&route.paths[0], 40000, &None, cur_height, &None).unwrap();
628+
629+
for onion_payload in onion_payloads.iter() {
630+
match onion_payload.format {
631+
msgs::OnionHopDataFormat::Legacy {..} => {
632+
panic!("Generated a `msgs::OnionHopDataFormat::Legacy` payload, even though that shouldn't have happend.");
633+
}
634+
_ => {}
635+
}
636+
}
637+
}
638+
639+
#[test]
640+
fn test_do_not_use_default_to_tlv_onions_if_other_features_not_supporting_them_exists() {
641+
// Tests that we do not default to creating tlv onions if any of these features exists when
642+
// creating the specific hop in the route:
643+
// 1. `InitFeatures` to the counterparty node exchanged with the init message to the node, which
644+
// doesn't support variable length onions.
645+
// 2. `NodeFeatures` in the `NodeAnnouncementInfo` of a node in sender node's the
646+
// `network_graph`, which doesn't support variable length onions.
647+
// 3. `InvoiceFeatures` specified by the receiving node, which doesn't support variable length
648+
// onions, when no `NodeAnnouncementInfo` `features` exists for the receiver in the sender's
649+
// `network_graph`.
650+
let chanmon_cfgs = create_chanmon_cfgs(4);
651+
let mut node_cfgs = create_node_cfgs(4, &chanmon_cfgs);
652+
653+
// Set `node[1]` config to `InitFeatures::empty()` which return `false` for
654+
// `supports_variable_length_onion()`
655+
let mut node_1_cfg = &mut node_cfgs[1];
656+
node_1_cfg.features = InitFeatures::empty();
657+
658+
let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs, &[None, None, None, None]);
659+
let mut nodes = create_network(4, &node_cfgs, &node_chanmgrs);
660+
661+
create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
662+
create_announced_chan_between_nodes(&nodes, 1, 2, InitFeatures::known(), InitFeatures::known());
663+
create_announced_chan_between_nodes(&nodes, 2, 3, InitFeatures::known(), InitFeatures::known());
664+
665+
let payment_params = PaymentParameters::from_node_id(nodes[3].node.get_our_node_id())
666+
.with_features(InvoiceFeatures::empty());
667+
let origin_node = &nodes[0];
668+
let network_graph = origin_node.network_graph;
669+
network_graph.clear_nodes_announcement_info();
670+
let scorer = test_utils::TestScorer::with_penalty(0);
671+
let seed = [0u8; 32];
672+
let keys_manager = test_utils::TestKeysInterface::new(&seed, Network::Testnet);
673+
let random_seed_bytes = keys_manager.get_secure_random_bytes();
674+
675+
// Set `NodeAnnouncementInfo` `features` which do not support variable length onions for
676+
// `nodes[2]` in `nodes[0]`'s `network_graph`.
677+
let nodes_2_unsigned_node_announcement = msgs::UnsignedNodeAnnouncement {
678+
features: NodeFeatures::empty(),
679+
timestamp: 20090103,
680+
node_id: nodes[2].node.get_our_node_id(),
681+
rgb: [32; 3],
682+
alias: [16;32],
683+
addresses: Vec::new(),
684+
excess_address_data: Vec::new(),
685+
excess_data: Vec::new(),
686+
};
687+
let _res = network_graph.update_node_from_unsigned_announcement(&nodes_2_unsigned_node_announcement);
688+
689+
let route = get_route(
690+
&origin_node.node.get_our_node_id(), &payment_params, &network_graph.read_only(),
691+
Some(&origin_node.node.list_usable_channels().iter().collect::<Vec<_>>()),
692+
1000000, TEST_FINAL_CLTV, origin_node.logger, &scorer, &random_seed_bytes).unwrap();
693+
694+
let hops = &route.paths[0];
695+
696+
// Assert that the hop between `nodes[0]` and `nodes[1]` doesn't support variable length
697+
// onions, as as the `InitFeatures` exchanged (`InitFeatures::empty()`) in the init message
698+
// between the nodes when setting up the channel is used when creating the `route` and that we
699+
// therefore do not default to supporting variable length onions. Despite `nodes[0]` having no
700+
// `NodeAnnouncementInfo` `features` for `node[1]`.
701+
assert!(!hops[0].node_features.supports_variable_length_onion());
702+
// Assert that the hop between `nodes[1]` and `nodes[2]` uses the `features` from
703+
// `nodes_2_unsigned_node_announcement` that doesn't support variable length onions.
704+
assert!(!hops[1].node_features.supports_variable_length_onion());
705+
// Assert that the hop between `nodes[2]` and `nodes[3]` uses the `InvoiceFeatures` set to the
706+
// `payment_params`, that doesn't support variable length onions. We therefore do not end up
707+
// defaulting to supporting variable length onions, despite `nodes[0]` having no
708+
// `NodeAnnouncementInfo` `features` for `node[3]`.
709+
assert!(!hops[2].node_features.supports_variable_length_onion());
710+
711+
let cur_height = nodes[0].best_block_info().1 + 1;
712+
let (onion_payloads, _htlc_msat, _htlc_cltv) = onion_utils::build_onion_payloads(&route.paths[0], 40000, &None, cur_height, &None).unwrap();
713+
714+
for onion_payload in onion_payloads.iter() {
715+
match onion_payload.format {
716+
msgs::OnionHopDataFormat::Legacy {..} => {}
717+
_ => {
718+
panic!("Should have only have generated `msgs::OnionHopDataFormat::Legacy` payloads");
719+
}
720+
}
721+
}
722+
}
723+
580724
macro_rules! get_phantom_route {
581725
($nodes: expr, $amt: expr, $channel: expr) => {{
582726
let secp_ctx = Secp256k1::new();

lightning/src/routing/network_graph.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1033,6 +1033,15 @@ impl NetworkGraph {
10331033
}
10341034
}
10351035

1036+
/// Clears the `NodeAnnouncementInfo` field for all nodes in the `NetworkGraph` for testing
1037+
/// purposes.
1038+
#[cfg(test)]
1039+
pub fn clear_nodes_announcement_info(&self) {
1040+
for node in self.nodes.write().unwrap().iter_mut(){
1041+
node.1.announcement_info = None;
1042+
}
1043+
}
1044+
10361045
/// For an already known node (from channel announcements), update its stored properties from a
10371046
/// given node announcement.
10381047
///

0 commit comments

Comments
 (0)