@@ -16,9 +16,9 @@ use chain::keysinterface::{KeysInterface, Recipient};
1616use ln:: { PaymentHash , PaymentSecret } ;
1717use ln:: channelmanager:: { HTLCForwardInfo , CLTV_FAR_FAR_AWAY , MIN_CLTV_EXPIRY_DELTA , PendingHTLCInfo , PendingHTLCRouting } ;
1818use ln:: onion_utils;
19- use routing:: network_graph:: { NetworkUpdate , RoutingFees } ;
19+ use routing:: network_graph:: { NetworkUpdate , RoutingFees , NodeId } ;
2020use routing:: router:: { get_route, PaymentParameters , Route , RouteHint , RouteHintHop } ;
21- use ln:: features:: { InitFeatures , InvoiceFeatures } ;
21+ use ln:: features:: { InitFeatures , InvoiceFeatures , NodeFeatures } ;
2222use ln:: msgs;
2323use ln:: msgs:: { ChannelMessageHandler , ChannelUpdate , OptionalField } ;
2424use util:: events:: { Event , MessageSendEvent , MessageSendEventsProvider } ;
@@ -34,6 +34,7 @@ use bitcoin::hashes::sha256::Hash as Sha256;
3434use bitcoin:: secp256k1;
3535use bitcoin:: secp256k1:: Secp256k1 ;
3636use bitcoin:: secp256k1:: key:: { PublicKey , SecretKey } ;
37+ use bitcoin:: network:: constants:: Network ;
3738
3839use io;
3940use prelude:: * ;
@@ -577,6 +578,185 @@ 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 when no `NodeAnnouncementInfo`
584+ // `features` for a node in the `network_graph` exists, or when the node isn't in the
585+ // `network_graph`, and no other known `features` for the node exists.
586+ let mut priv_channels_conf = UserConfig :: default ( ) ;
587+ priv_channels_conf. channel_options . announced_channel = false ;
588+ let chanmon_cfgs = create_chanmon_cfgs ( 5 ) ;
589+ let node_cfgs = create_node_cfgs ( 5 , & chanmon_cfgs) ;
590+ let node_chanmgrs = create_node_chanmgrs ( 5 , & node_cfgs, & [ None , None , None , None , Some ( priv_channels_conf) ] ) ;
591+ let mut nodes = create_network ( 5 , & node_cfgs, & node_chanmgrs) ;
592+
593+ create_announced_chan_between_nodes ( & nodes, 0 , 1 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
594+ create_announced_chan_between_nodes ( & nodes, 1 , 2 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
595+ create_announced_chan_between_nodes ( & nodes, 2 , 3 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
596+ create_unannounced_chan_between_nodes_with_value ( & nodes, 3 , 4 , 100000 , 10001 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
597+
598+ let payment_params = PaymentParameters :: from_node_id ( nodes[ 3 ] . node . get_our_node_id ( ) ) ;
599+ let origin_node = & nodes[ 0 ] ;
600+ let network_graph = origin_node. network_graph ;
601+
602+ // Clears all the `NodeAnnouncementInfo` for all nodes of `nodes[0]`'s `network_graph`, so that
603+ // their `features` aren't used when creating the `route`.
604+ network_graph. clear_nodes_announcement_info ( ) ;
605+
606+ let scorer = test_utils:: TestScorer :: with_penalty ( 0 ) ;
607+ let seed = [ 0u8 ; 32 ] ;
608+ let keys_manager = test_utils:: TestKeysInterface :: new ( & seed, Network :: Testnet ) ;
609+ let random_seed_bytes = keys_manager. get_secure_random_bytes ( ) ;
610+ let read_only_network_graph = & network_graph. read_only ( ) ;
611+ let announced_route = get_route (
612+ & origin_node. node . get_our_node_id ( ) , & payment_params, read_only_network_graph,
613+ Some ( & origin_node. node . list_usable_channels ( ) . iter ( ) . collect :: < Vec < _ > > ( ) ) ,
614+ 1000000 , TEST_FINAL_CLTV , origin_node. logger , & scorer, & random_seed_bytes) . unwrap ( ) ;
615+
616+ let hops = & announced_route. paths [ 0 ] ;
617+ // Assert that the hop between `nodes[1]` and `nodes[2]` defaults to supporting variable length
618+ // onions, as `nodes[0]` has no `NodeAnnouncementInfo` `features` for `node[2]`
619+ assert ! ( hops[ 1 ] . node_features. supports_variable_length_onion( ) ) ;
620+ // Assert that the hop between `nodes[2]` and `nodes[3]` defaults to supporting variable length
621+ // onions, as `nodes[0]` has no `NodeAnnouncementInfo` `features` for `node[3]`, and no `InvoiceFeatures`
622+ // for the `payment_params`, which would otherwise have been used.
623+ assert ! ( hops[ 2 ] . node_features. supports_variable_length_onion( ) ) ;
624+ // Note that we do not asset that `hops[0]` (the channel between `nodes[0]` and `nodes[1]`)
625+ // supports variable length onions, as the `InitFeatures` exchanged in the init message when
626+ // between the nodes will be used when creating the route. We therefore do not default to
627+ // supporting variable length onions for that hop, as the `InitFeatures` in this case are
628+ // `InitFeatures::known()`.
629+
630+ let unannounced_chan = & nodes[ 4 ] . node . list_usable_channels ( ) [ 0 ] ;
631+
632+ let last_hop = RouteHint ( vec ! [ RouteHintHop {
633+ src_node_id: nodes[ 3 ] . node. get_our_node_id( ) ,
634+ short_channel_id: unannounced_chan. short_channel_id. unwrap( ) ,
635+ fees: RoutingFees {
636+ base_msat: 0 ,
637+ proportional_millionths: 0 ,
638+ } ,
639+ cltv_expiry_delta: 42 ,
640+ htlc_minimum_msat: None ,
641+ htlc_maximum_msat: None ,
642+ } ] ) ;
643+
644+ let unannounced_chan_params = PaymentParameters :: from_node_id ( nodes[ 4 ] . node . get_our_node_id ( ) ) . with_route_hints ( vec ! [ last_hop] ) ;
645+ let unannounced_route = get_route (
646+ & origin_node. node . get_our_node_id ( ) , & unannounced_chan_params, read_only_network_graph,
647+ Some ( & origin_node. node . list_usable_channels ( ) . iter ( ) . collect :: < Vec < _ > > ( ) ) ,
648+ 10000 , TEST_FINAL_CLTV , origin_node. logger , & scorer, & random_seed_bytes) . unwrap ( ) ;
649+
650+ let unannounced_chan_hop = & unannounced_route. paths [ 0 ] [ 3 ] ;
651+ // Ensure that `nodes[4]` doesn't exist in `nodes[0]`'s `network_graph`, as it's not public.
652+ assert ! ( read_only_network_graph. nodes( ) . get( & NodeId :: from_pubkey( & nodes[ 4 ] . node. get_our_node_id( ) ) ) . is_none( ) ) ;
653+ // Assert that the hop between `nodes[3]` and `nodes[4]` defaults to supporting variable length
654+ // onions, even thouugh nodes[4] as `nodes[0]` doesn't exists in `nodes[0]`'s `network_graph`,
655+ // and no `InvoiceFeatures` for the `payment_params` exists, which would otherwise have been
656+ // used.
657+ assert ! ( unannounced_chan_hop. node_features. supports_variable_length_onion( ) ) ;
658+
659+ let cur_height = nodes[ 0 ] . best_block_info ( ) . 1 + 1 ;
660+ let ( announced_route_payloads, _htlc_msat, _htlc_cltv) = onion_utils:: build_onion_payloads ( & announced_route. paths [ 0 ] , 40000 , & None , cur_height, & None ) . unwrap ( ) ;
661+ let ( unannounced_route_paylods, _htlc_msat, _htlc_cltv) = onion_utils:: build_onion_payloads ( & unannounced_route. paths [ 0 ] , 40000 , & None , cur_height, & None ) . unwrap ( ) ;
662+
663+ for onion_payloads in vec ! [ announced_route_payloads, unannounced_route_paylods] {
664+ for onion_payload in onion_payloads. iter ( ) {
665+ match onion_payload. format {
666+ msgs:: OnionHopDataFormat :: Legacy { ..} => {
667+ panic ! ( "Generated a `msgs::OnionHopDataFormat::Legacy` payload, even though that shouldn't have happend." ) ;
668+ }
669+ _ => { }
670+ }
671+ }
672+ }
673+ }
674+
675+ #[ test]
676+ fn test_do_not_use_default_to_tlv_onions_if_other_features_not_supporting_them_exists ( ) {
677+ // Tests that we do not default to creating tlv onions if any of these features exists when
678+ // creating the specific hop in the route:
679+ // 1. `InitFeatures` to the counterparty node exchanged with the init message to the node, which
680+ // doesn't support variable length onions.
681+ // 2. `NodeFeatures` in the `NodeAnnouncementInfo` of a node in sender node's the
682+ // `network_graph`, which doesn't support variable length onions.
683+ // 3. `InvoiceFeatures` specified by the receiving node, which doesn't support variable length
684+ // onions, when no `NodeAnnouncementInfo` `features` exists for the receiver in the sender's
685+ // `network_graph`.
686+ let chanmon_cfgs = create_chanmon_cfgs ( 4 ) ;
687+ let mut node_cfgs = create_node_cfgs ( 4 , & chanmon_cfgs) ;
688+
689+ // Set `node[1]` config to `InitFeatures::empty()` which return `false` for
690+ // `supports_variable_length_onion()`
691+ let mut node_1_cfg = & mut node_cfgs[ 1 ] ;
692+ node_1_cfg. features = InitFeatures :: empty ( ) ;
693+
694+ let node_chanmgrs = create_node_chanmgrs ( 4 , & node_cfgs, & [ None , None , None , None ] ) ;
695+ let mut nodes = create_network ( 4 , & node_cfgs, & node_chanmgrs) ;
696+
697+ create_announced_chan_between_nodes ( & nodes, 0 , 1 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
698+ create_announced_chan_between_nodes ( & nodes, 1 , 2 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
699+ create_announced_chan_between_nodes ( & nodes, 2 , 3 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
700+
701+ let payment_params = PaymentParameters :: from_node_id ( nodes[ 3 ] . node . get_our_node_id ( ) )
702+ . with_features ( InvoiceFeatures :: empty ( ) ) ;
703+ let origin_node = & nodes[ 0 ] ;
704+ let network_graph = origin_node. network_graph ;
705+ network_graph. clear_nodes_announcement_info ( ) ;
706+ let scorer = test_utils:: TestScorer :: with_penalty ( 0 ) ;
707+ let seed = [ 0u8 ; 32 ] ;
708+ let keys_manager = test_utils:: TestKeysInterface :: new ( & seed, Network :: Testnet ) ;
709+ let random_seed_bytes = keys_manager. get_secure_random_bytes ( ) ;
710+
711+ // Set `NodeAnnouncementInfo` `features` which do not support variable length onions for
712+ // `nodes[2]` in `nodes[0]`'s `network_graph`.
713+ let nodes_2_unsigned_node_announcement = msgs:: UnsignedNodeAnnouncement {
714+ features : NodeFeatures :: empty ( ) ,
715+ timestamp : 20090103 ,
716+ node_id : nodes[ 2 ] . node . get_our_node_id ( ) ,
717+ rgb : [ 32 ; 3 ] ,
718+ alias : [ 16 ; 32 ] ,
719+ addresses : Vec :: new ( ) ,
720+ excess_address_data : Vec :: new ( ) ,
721+ excess_data : Vec :: new ( ) ,
722+ } ;
723+ let _res = network_graph. update_node_from_unsigned_announcement ( & nodes_2_unsigned_node_announcement) ;
724+
725+ let route = get_route (
726+ & origin_node. node . get_our_node_id ( ) , & payment_params, & network_graph. read_only ( ) ,
727+ Some ( & origin_node. node . list_usable_channels ( ) . iter ( ) . collect :: < Vec < _ > > ( ) ) ,
728+ 1000000 , TEST_FINAL_CLTV , origin_node. logger , & scorer, & random_seed_bytes) . unwrap ( ) ;
729+
730+ let hops = & route. paths [ 0 ] ;
731+
732+ // Assert that the hop between `nodes[0]` and `nodes[1]` doesn't support variable length
733+ // onions, as as the `InitFeatures` exchanged (`InitFeatures::empty()`) in the init message
734+ // between the nodes when setting up the channel is used when creating the `route` and that we
735+ // therefore do not default to supporting variable length onions. Despite `nodes[0]` having no
736+ // `NodeAnnouncementInfo` `features` for `node[1]`.
737+ assert ! ( !hops[ 0 ] . node_features. supports_variable_length_onion( ) ) ;
738+ // Assert that the hop between `nodes[1]` and `nodes[2]` uses the `features` from
739+ // `nodes_2_unsigned_node_announcement` that doesn't support variable length onions.
740+ assert ! ( !hops[ 1 ] . node_features. supports_variable_length_onion( ) ) ;
741+ // Assert that the hop between `nodes[2]` and `nodes[3]` uses the `InvoiceFeatures` set to the
742+ // `payment_params`, that doesn't support variable length onions. We therefore do not end up
743+ // defaulting to supporting variable length onions, despite `nodes[0]` having no
744+ // `NodeAnnouncementInfo` `features` for `node[3]`.
745+ assert ! ( !hops[ 2 ] . node_features. supports_variable_length_onion( ) ) ;
746+
747+ let cur_height = nodes[ 0 ] . best_block_info ( ) . 1 + 1 ;
748+ let ( onion_payloads, _htlc_msat, _htlc_cltv) = onion_utils:: build_onion_payloads ( & route. paths [ 0 ] , 40000 , & None , cur_height, & None ) . unwrap ( ) ;
749+
750+ for onion_payload in onion_payloads. iter ( ) {
751+ match onion_payload. format {
752+ msgs:: OnionHopDataFormat :: Legacy { ..} => { }
753+ _ => {
754+ panic ! ( "Should have only have generated `msgs::OnionHopDataFormat::Legacy` payloads" ) ;
755+ }
756+ }
757+ }
758+ }
759+
580760macro_rules! get_phantom_route {
581761 ( $nodes: expr, $amt: expr, $channel: expr) => { {
582762 let secp_ctx = Secp256k1 :: new( ) ;
0 commit comments