@@ -45,14 +45,16 @@ use crate::blinded_path::BlindedPath;
4545use crate :: events:: { Event , MessageSendEventsProvider , PaymentPurpose } ;
4646use crate :: ln:: channelmanager:: { PaymentId , RecentPaymentDetails , Retry , self } ;
4747use crate :: ln:: functional_test_utils:: * ;
48- use crate :: ln:: msgs:: { ChannelMessageHandler , Init , OnionMessage , OnionMessageHandler } ;
48+ use crate :: ln:: msgs:: { ChannelMessageHandler , Init , NodeAnnouncement , OnionMessage , OnionMessageHandler , RoutingMessageHandler , SocketAddress , UnsignedGossipMessage , UnsignedNodeAnnouncement } ;
4949use crate :: offers:: invoice:: Bolt12Invoice ;
5050use crate :: offers:: invoice_error:: InvoiceError ;
5151use crate :: offers:: invoice_request:: InvoiceRequest ;
5252use crate :: offers:: parse:: Bolt12SemanticError ;
5353use crate :: onion_message:: messenger:: PeeledOnion ;
5454use crate :: onion_message:: offers:: OffersMessage ;
5555use crate :: onion_message:: packet:: ParsedOnionMessageContents ;
56+ use crate :: routing:: gossip:: { NodeAlias , NodeId } ;
57+ use crate :: sign:: { NodeSigner , Recipient } ;
5658
5759use crate :: prelude:: * ;
5860
@@ -98,6 +100,37 @@ fn disconnect_peers<'a, 'b, 'c>(node_a: &Node<'a, 'b, 'c>, peers: &[&Node<'a, 'b
98100 }
99101}
100102
103+ fn announce_node_address < ' a , ' b , ' c > (
104+ node : & Node < ' a , ' b , ' c > , peers : & [ & Node < ' a , ' b , ' c > ] , address : SocketAddress ,
105+ ) {
106+ let features = node. onion_messenger . provided_node_features ( )
107+ | node. gossip_sync . provided_node_features ( ) ;
108+ let rgb = [ 0u8 ; 3 ] ;
109+ let announcement = UnsignedNodeAnnouncement {
110+ features,
111+ timestamp : 1000 ,
112+ node_id : NodeId :: from_pubkey ( & node. keys_manager . get_node_id ( Recipient :: Node ) . unwrap ( ) ) ,
113+ rgb,
114+ alias : NodeAlias ( [ 0u8 ; 32 ] ) ,
115+ addresses : vec ! [ address] ,
116+ excess_address_data : Vec :: new ( ) ,
117+ excess_data : Vec :: new ( ) ,
118+ } ;
119+ let signature = node. keys_manager . sign_gossip_message (
120+ UnsignedGossipMessage :: NodeAnnouncement ( & announcement)
121+ ) . unwrap ( ) ;
122+
123+ let msg = NodeAnnouncement {
124+ signature,
125+ contents : announcement
126+ } ;
127+
128+ node. gossip_sync . handle_node_announcement ( & msg) . unwrap ( ) ;
129+ for peer in peers {
130+ peer. gossip_sync . handle_node_announcement ( & msg) . unwrap ( ) ;
131+ }
132+ }
133+
101134fn route_bolt12_payment < ' a , ' b , ' c > (
102135 node : & Node < ' a , ' b , ' c > , path : & [ & Node < ' a , ' b , ' c > ] , invoice : & Bolt12Invoice
103136) {
@@ -178,6 +211,58 @@ fn extract_invoice_error<'a, 'b, 'c>(
178211 }
179212}
180213
214+ /// Checks that blinded paths without Tor-only nodes are preferred when constructing an offer.
215+ #[ test]
216+ fn prefers_non_tor_nodes_in_blinded_paths ( ) {
217+ let mut accept_forward_cfg = test_default_channel_config ( ) ;
218+ accept_forward_cfg. accept_forwards_to_priv_channels = true ;
219+
220+ let mut features = channelmanager:: provided_init_features ( & accept_forward_cfg) ;
221+ features. set_onion_messages_optional ( ) ;
222+ features. set_route_blinding_optional ( ) ;
223+
224+ let chanmon_cfgs = create_chanmon_cfgs ( 6 ) ;
225+ let node_cfgs = create_node_cfgs ( 6 , & chanmon_cfgs) ;
226+
227+ * node_cfgs[ 1 ] . override_init_features . borrow_mut ( ) = Some ( features) ;
228+
229+ let node_chanmgrs = create_node_chanmgrs (
230+ 6 , & node_cfgs, & [ None , Some ( accept_forward_cfg) , None , None , None , None ]
231+ ) ;
232+ let nodes = create_network ( 6 , & node_cfgs, & node_chanmgrs) ;
233+
234+ create_unannounced_chan_between_nodes_with_value ( & nodes, 0 , 1 , 10_000_000 , 1_000_000_000 ) ;
235+ create_unannounced_chan_between_nodes_with_value ( & nodes, 2 , 3 , 10_000_000 , 1_000_000_000 ) ;
236+ create_announced_chan_between_nodes_with_value ( & nodes, 1 , 2 , 10_000_000 , 1_000_000_000 ) ;
237+ create_announced_chan_between_nodes_with_value ( & nodes, 1 , 4 , 10_000_000 , 1_000_000_000 ) ;
238+ create_announced_chan_between_nodes_with_value ( & nodes, 1 , 5 , 10_000_000 , 1_000_000_000 ) ;
239+ create_announced_chan_between_nodes_with_value ( & nodes, 2 , 4 , 10_000_000 , 1_000_000_000 ) ;
240+ create_announced_chan_between_nodes_with_value ( & nodes, 2 , 5 , 10_000_000 , 1_000_000_000 ) ;
241+
242+ // Add an extra channel so that more than one of Bob's peers have MIN_PEER_CHANNELS.
243+ create_announced_chan_between_nodes_with_value ( & nodes, 4 , 5 , 10_000_000 , 1_000_000_000 ) ;
244+
245+ let ( alice, bob, charlie, david) = ( & nodes[ 0 ] , & nodes[ 1 ] , & nodes[ 2 ] , & nodes[ 3 ] ) ;
246+ let bob_id = bob. node . get_our_node_id ( ) ;
247+ let charlie_id = charlie. node . get_our_node_id ( ) ;
248+
249+ disconnect_peers ( alice, & [ charlie, david, & nodes[ 4 ] , & nodes[ 5 ] ] ) ;
250+ disconnect_peers ( david, & [ bob, & nodes[ 4 ] , & nodes[ 5 ] ] ) ;
251+
252+ let tor = SocketAddress :: OnionV2 ( [ 255 , 254 , 253 , 252 , 251 , 250 , 249 , 248 , 247 , 246 , 38 , 7 ] ) ;
253+ announce_node_address ( charlie, & [ alice, bob, david, & nodes[ 4 ] , & nodes[ 5 ] ] , tor) ;
254+
255+ let offer = bob. node
256+ . create_offer_builder ( "coffee" . to_string ( ) ) . unwrap ( )
257+ . amount_msats ( 10_000_000 )
258+ . build ( ) . unwrap ( ) ;
259+ assert_ne ! ( offer. signing_pubkey( ) , bob_id) ;
260+ assert ! ( !offer. paths( ) . is_empty( ) ) ;
261+ for path in offer. paths ( ) {
262+ assert_ne ! ( path. introduction_node_id, charlie_id) ;
263+ }
264+ }
265+
181266/// Checks that an offer can be paid through blinded paths and that ephemeral pubkeys are used
182267/// rather than exposing a node's pubkey.
183268#[ test]
0 commit comments