@@ -11,9 +11,12 @@ use bitcoin::blockdata::script::Builder;
1111use  bitcoin:: blockdata:: transaction:: TxOut ; 
1212use  bitcoin:: hash_types:: BlockHash ; 
1313
14+ use  lightning:: blinded_path:: { BlindedHop ,  BlindedPath } ; 
1415use  lightning:: chain:: transaction:: OutPoint ; 
1516use  lightning:: ln:: channelmanager:: { self ,  ChannelDetails ,  ChannelCounterparty } ; 
17+ use  lightning:: ln:: features:: { BlindedHopFeatures ,  Bolt12InvoiceFeatures } ; 
1618use  lightning:: ln:: msgs; 
19+ use  lightning:: offers:: invoice:: BlindedPayInfo ; 
1720use  lightning:: routing:: gossip:: { NetworkGraph ,  RoutingFees } ; 
1821use  lightning:: routing:: utxo:: { UtxoFuture ,  UtxoLookup ,  UtxoLookupError ,  UtxoResult } ; 
1922use  lightning:: routing:: router:: { find_route,  PaymentParameters ,  RouteHint ,  RouteHintHop ,  RouteParameters } ; 
@@ -197,6 +200,91 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
197200	let  mut  node_pks = HashSet :: new ( ) ; 
198201	let  mut  scid = 42 ; 
199202
203+ 	macro_rules!  first_hops { 
204+ 		( $first_hops_vec:  expr)  => { 
205+ 			match  get_slice!( 1 ) [ 0 ]  { 
206+ 				0  => None , 
207+ 				count => { 
208+ 					for  _ in 0 ..count { 
209+ 						scid += 1 ; 
210+ 						let  rnid = node_pks. iter( ) . skip( u16 :: from_be_bytes( get_slice!( 2 ) . try_into( ) . unwrap( ) )  as  usize  % node_pks. len( ) ) . next( ) . unwrap( ) ; 
211+ 						let  capacity = u64 :: from_be_bytes( get_slice!( 8 ) . try_into( ) . unwrap( ) ) ; 
212+ 						$first_hops_vec. push( ChannelDetails  { 
213+ 							channel_id:  [ 0 ;  32 ] , 
214+ 							counterparty:  ChannelCounterparty  { 
215+ 								node_id:  * rnid, 
216+ 								features:  channelmanager:: provided_init_features( & UserConfig :: default ( ) ) , 
217+ 								unspendable_punishment_reserve:  0 , 
218+ 								forwarding_info:  None , 
219+ 								outbound_htlc_minimum_msat:  None , 
220+ 								outbound_htlc_maximum_msat:  None , 
221+ 							} , 
222+ 							funding_txo:  Some ( OutPoint  {  txid:  bitcoin:: Txid :: from_slice( & [ 0 ;  32 ] ) . unwrap( ) ,  index:  0  } ) , 
223+ 							channel_type:  None , 
224+ 							short_channel_id:  Some ( scid) , 
225+ 							inbound_scid_alias:  None , 
226+ 							outbound_scid_alias:  None , 
227+ 							channel_value_satoshis:  capacity, 
228+ 							user_channel_id:  0 ,  inbound_capacity_msat:  0 , 
229+ 							unspendable_punishment_reserve:  None , 
230+ 							confirmations_required:  None , 
231+ 							confirmations:  None , 
232+ 							force_close_spend_delay:  None , 
233+ 							is_outbound:  true ,  is_channel_ready:  true , 
234+ 							is_usable:  true ,  is_public:  true , 
235+ 							balance_msat:  0 , 
236+ 							outbound_capacity_msat:  capacity. saturating_mul( 1000 ) , 
237+ 							next_outbound_htlc_limit_msat:  capacity. saturating_mul( 1000 ) , 
238+ 							next_outbound_htlc_minimum_msat:  0 , 
239+ 							inbound_htlc_minimum_msat:  None , 
240+ 							inbound_htlc_maximum_msat:  None , 
241+ 							config:  None , 
242+ 							feerate_sat_per_1000_weight:  None , 
243+ 							channel_shutdown_state:  Some ( channelmanager:: ChannelShutdownState :: NotShuttingDown ) , 
244+ 						} ) ; 
245+ 					} 
246+ 					Some ( & $first_hops_vec[ ..] ) 
247+ 				} , 
248+ 			} 
249+ 		} 
250+ 	} 
251+ 
252+ 	macro_rules!  last_hops { 
253+ 		( $last_hops:  expr)  => { 
254+ 			let  count = get_slice!( 1 ) [ 0 ] ; 
255+ 			for  _ in 0 ..count { 
256+ 				scid += 1 ; 
257+ 				let  rnid = node_pks. iter( ) . skip( slice_to_be16( get_slice!( 2 ) ) as  usize  % node_pks. len( ) ) . next( ) . unwrap( ) ; 
258+ 				$last_hops. push( RouteHint ( vec![ RouteHintHop  { 
259+ 					src_node_id:  * rnid, 
260+ 					short_channel_id:  scid, 
261+ 					fees:  RoutingFees  { 
262+ 						base_msat:  slice_to_be32( get_slice!( 4 ) ) , 
263+ 						proportional_millionths:  slice_to_be32( get_slice!( 4 ) ) , 
264+ 					} , 
265+ 					cltv_expiry_delta:  slice_to_be16( get_slice!( 2 ) ) , 
266+ 					htlc_minimum_msat:  Some ( slice_to_be64( get_slice!( 8 ) ) ) , 
267+ 					htlc_maximum_msat:  None , 
268+ 				} ] ) ) ; 
269+ 			} 
270+ 		} 
271+ 	} 
272+ 
273+ 	macro_rules!  find_routes { 
274+ 		( $first_hops:  expr,  $node_pks:  expr,  $route_params:  expr)  => { 
275+ 			let  scorer = ProbabilisticScorer :: new( ProbabilisticScoringDecayParameters :: default ( ) ,  & net_graph,  & logger) ; 
276+ 			let  random_seed_bytes:  [ u8 ;  32 ]  = [ get_slice!( 1 ) [ 0 ] ;  32 ] ; 
277+ 			for  target in $node_pks { 
278+ 				let  final_value_msat = slice_to_be64( get_slice!( 8 ) ) ; 
279+ 				let  final_cltv_expiry_delta = slice_to_be32( get_slice!( 4 ) ) ; 
280+ 				let  route_params = $route_params( final_value_msat,  final_cltv_expiry_delta,  target) ; 
281+ 				let  _ = find_route( & our_pubkey,  & route_params,  & net_graph, 
282+ 					$first_hops. map( |c| c. iter( ) . collect:: <Vec <_>>( ) ) . as_ref( ) . map( |a| a. as_slice( ) ) , 
283+ 					& logger,  & scorer,  & ProbabilisticScoringFeeParameters :: default ( ) ,  & random_seed_bytes) ; 
284+ 			} 
285+ 		} 
286+ 	} 
287+ 
200288	loop  { 
201289		match  get_slice ! ( 1 ) [ 0 ]  { 
202290			0  => { 
@@ -230,86 +318,61 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
230318				net_graph. channel_failed_permanent ( short_channel_id) ; 
231319			} , 
232320			_ if  node_pks. is_empty ( )  => { } , 
233- 			_  => { 
321+ 			x  if  x <  250  => { 
234322				let  mut  first_hops_vec = Vec :: new ( ) ; 
235- 				let  first_hops = match  get_slice ! ( 1 ) [ 0 ]  { 
236- 					0  => None , 
237- 					count => { 
238- 						for  _ in  0 ..count { 
239- 							scid += 1 ; 
240- 							let  rnid = node_pks. iter ( ) . skip ( u16:: from_be_bytes ( get_slice ! ( 2 ) . try_into ( ) . unwrap ( ) )  as  usize  % node_pks. len ( ) ) . next ( ) . unwrap ( ) ; 
241- 							let  capacity = u64:: from_be_bytes ( get_slice ! ( 8 ) . try_into ( ) . unwrap ( ) ) ; 
242- 							first_hops_vec. push ( ChannelDetails  { 
243- 								channel_id :  [ 0 ;  32 ] , 
244- 								counterparty :  ChannelCounterparty  { 
245- 									node_id :  * rnid, 
246- 									features :  channelmanager:: provided_init_features ( & UserConfig :: default ( ) ) , 
247- 									unspendable_punishment_reserve :  0 , 
248- 									forwarding_info :  None , 
249- 									outbound_htlc_minimum_msat :  None , 
250- 									outbound_htlc_maximum_msat :  None , 
251- 								} , 
252- 								funding_txo :  Some ( OutPoint  {  txid :  bitcoin:: Txid :: from_slice ( & [ 0 ;  32 ] ) . unwrap ( ) ,  index :  0  } ) , 
253- 								channel_type :  None , 
254- 								short_channel_id :  Some ( scid) , 
255- 								inbound_scid_alias :  None , 
256- 								outbound_scid_alias :  None , 
257- 								channel_value_satoshis :  capacity, 
258- 								user_channel_id :  0 ,  inbound_capacity_msat :  0 , 
259- 								unspendable_punishment_reserve :  None , 
260- 								confirmations_required :  None , 
261- 								confirmations :  None , 
262- 								force_close_spend_delay :  None , 
263- 								is_outbound :  true ,  is_channel_ready :  true , 
264- 								is_usable :  true ,  is_public :  true , 
265- 								balance_msat :  0 , 
266- 								outbound_capacity_msat :  capacity. saturating_mul ( 1000 ) , 
267- 								next_outbound_htlc_limit_msat :  capacity. saturating_mul ( 1000 ) , 
268- 								next_outbound_htlc_minimum_msat :  0 , 
269- 								inbound_htlc_minimum_msat :  None , 
270- 								inbound_htlc_maximum_msat :  None , 
271- 								config :  None , 
272- 								feerate_sat_per_1000_weight :  None , 
273- 								channel_shutdown_state :  Some ( channelmanager:: ChannelShutdownState :: NotShuttingDown ) , 
274- 							} ) ; 
275- 						} 
276- 						Some ( & first_hops_vec[ ..] ) 
277- 					} , 
278- 				} ; 
323+ 				// Use macros here and in the blinded match arm to ensure values are fetched from the fuzz 
324+ 				// input in the same order, for better coverage. 
325+ 				let  first_hops = first_hops ! ( first_hops_vec) ; 
279326				let  mut  last_hops = Vec :: new ( ) ; 
280- 				{ 
281- 					let  count = get_slice ! ( 1 ) [ 0 ] ; 
282- 					for  _ in  0 ..count { 
283- 						scid += 1 ; 
284- 						let  rnid = node_pks. iter ( ) . skip ( slice_to_be16 ( get_slice ! ( 2 ) ) as  usize  % node_pks. len ( ) ) . next ( ) . unwrap ( ) ; 
285- 						last_hops. push ( RouteHint ( vec ! [ RouteHintHop  { 
286- 							src_node_id:  * rnid, 
287- 							short_channel_id:  scid, 
288- 							fees:  RoutingFees  { 
289- 								base_msat:  slice_to_be32( get_slice!( 4 ) ) , 
290- 								proportional_millionths:  slice_to_be32( get_slice!( 4 ) ) , 
291- 							} , 
292- 							cltv_expiry_delta:  slice_to_be16( get_slice!( 2 ) ) , 
293- 							htlc_minimum_msat:  Some ( slice_to_be64( get_slice!( 8 ) ) ) , 
294- 							htlc_maximum_msat:  None , 
295- 						} ] ) ) ; 
296- 					} 
297- 				} 
298- 				let  scorer = ProbabilisticScorer :: new ( ProbabilisticScoringDecayParameters :: default ( ) ,  & net_graph,  & logger) ; 
299- 				let  random_seed_bytes:  [ u8 ;  32 ]  = [ get_slice ! ( 1 ) [ 0 ] ;  32 ] ; 
300- 				for  target in  node_pks. iter ( )  { 
301- 					let  final_value_msat = slice_to_be64 ( get_slice ! ( 8 ) ) ; 
302- 					let  final_cltv_expiry_delta = slice_to_be32 ( get_slice ! ( 4 ) ) ; 
303- 					let  route_params = RouteParameters  { 
304- 						payment_params :  PaymentParameters :: from_node_id ( * target,  final_cltv_expiry_delta) 
327+ 				last_hops ! ( last_hops) ; 
328+ 				find_routes ! ( first_hops,  node_pks. iter( ) ,  |final_amt,  final_delta,  target:  & PublicKey | { 
329+ 					RouteParameters  { 
330+ 						payment_params:  PaymentParameters :: from_node_id( * target,  final_delta) 
305331							. with_route_hints( last_hops. clone( ) ) . unwrap( ) , 
306- 						final_value_msat, 
307- 					} ; 
308- 					let  _ = find_route ( & our_pubkey,  & route_params,  & net_graph, 
309- 						first_hops. map ( |c| c. iter ( ) . collect :: < Vec < _ > > ( ) ) . as_ref ( ) . map ( |a| a. as_slice ( ) ) , 
310- 						& logger,  & scorer,  & ProbabilisticScoringFeeParameters :: default ( ) ,  & random_seed_bytes) ; 
311- 				} 
332+ 						final_value_msat:  final_amt, 
333+ 					} 
334+ 				} ) ; 
312335			} , 
336+ 			x => { 
337+ 				let  mut  first_hops_vec = Vec :: new ( ) ; 
338+ 				let  first_hops = first_hops ! ( first_hops_vec) ; 
339+ 				let  mut  last_hops_unblinded = Vec :: new ( ) ; 
340+ 				last_hops ! ( last_hops_unblinded) ; 
341+ 				let  dummy_pk = PublicKey :: from_slice ( & [ 2 ;  33 ] ) . unwrap ( ) ; 
342+ 				let  last_hops:  Vec < ( BlindedPayInfo ,  BlindedPath ) >  = last_hops_unblinded. into_iter ( ) . map ( |hint| { 
343+ 					let  hop = & hint. 0 [ 0 ] ; 
344+ 					let  payinfo = BlindedPayInfo  { 
345+ 						fee_base_msat :  hop. fees . base_msat , 
346+ 						fee_proportional_millionths :  hop. fees . proportional_millionths , 
347+ 						htlc_minimum_msat :  hop. htlc_minimum_msat . unwrap ( ) , 
348+ 						htlc_maximum_msat :  hop. htlc_minimum_msat . unwrap ( ) . saturating_mul ( 100 ) , 
349+ 						cltv_expiry_delta :  hop. cltv_expiry_delta , 
350+ 						features :  BlindedHopFeatures :: empty ( ) , 
351+ 					} ; 
352+ 					let  num_blinded_hops = x % 250 ; 
353+ 					let  mut  blinded_hops = Vec :: new ( ) ; 
354+ 					for  _ in  0 ..num_blinded_hops { 
355+ 						blinded_hops. push ( BlindedHop  { 
356+ 							blinded_node_id :  dummy_pk, 
357+ 							encrypted_payload :  Vec :: new ( ) 
358+ 						} ) ; 
359+ 					} 
360+ 					( payinfo,  BlindedPath  { 
361+ 						introduction_node_id :  hop. src_node_id , 
362+ 						blinding_point :  dummy_pk, 
363+ 						blinded_hops, 
364+ 					} ) 
365+ 				} ) . collect ( ) ; 
366+ 				let  mut  features = Bolt12InvoiceFeatures :: empty ( ) ; 
367+ 				features. set_basic_mpp_optional ( ) ; 
368+ 				find_routes ! ( first_hops,  vec![ dummy_pk] . iter( ) ,  |final_amt,  _,  _| { 
369+ 					RouteParameters  { 
370+ 						payment_params:  PaymentParameters :: blinded( last_hops. clone( ) ) 
371+ 							. with_bolt12_features( features. clone( ) ) . unwrap( ) , 
372+ 						final_value_msat:  final_amt, 
373+ 					} 
374+ 				} ) ; 
375+ 			} 
313376		} 
314377	} 
315378} 
0 commit comments