@@ -18,7 +18,7 @@ use ln::channelmanager::{HTLCForwardInfo, CLTV_FAR_FAR_AWAY, MIN_CLTV_EXPIRY_DEL
18
18
use ln:: onion_utils;
19
19
use routing:: network_graph:: { NetworkUpdate , RoutingFees } ;
20
20
use routing:: router:: { get_route, PaymentParameters , Route , RouteHint , RouteHintHop } ;
21
- use ln:: features:: { InitFeatures , InvoiceFeatures } ;
21
+ use ln:: features:: { InitFeatures , InvoiceFeatures , NodeFeatures } ;
22
22
use ln:: msgs;
23
23
use ln:: msgs:: { ChannelMessageHandler , ChannelUpdate , OptionalField } ;
24
24
use util:: events:: { Event , MessageSendEvent , MessageSendEventsProvider } ;
@@ -34,6 +34,7 @@ use bitcoin::hashes::sha256::Hash as Sha256;
34
34
use bitcoin:: secp256k1;
35
35
use bitcoin:: secp256k1:: Secp256k1 ;
36
36
use bitcoin:: secp256k1:: key:: { PublicKey , SecretKey } ;
37
+ use bitcoin:: network:: constants:: Network ;
37
38
38
39
use io;
39
40
use prelude:: * ;
@@ -577,6 +578,149 @@ fn test_onion_failure() {
577
578
} , true , Some ( 23 ) , None , None ) ;
578
579
}
579
580
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
+
580
724
macro_rules! get_phantom_route {
581
725
( $nodes: expr, $amt: expr, $channel: expr) => { {
582
726
let secp_ctx = Secp256k1 :: new( ) ;
0 commit comments