@@ -595,7 +595,7 @@ impl RandomWalkStrategy {
595595 // Retrieve the direction-specific update via the public ChannelInfo fields.
596596 // as_directed_from already checked both directions are Some, but we break
597597 // defensively rather than unwrap.
598- let update = match if directed. source ( ) == & next_channel. node_one {
598+ let channel_update_info = match if directed. source ( ) == & next_channel. node_one {
599599 next_channel. one_to_two . as_ref ( )
600600 } else {
601601 next_channel. two_to_one . as_ref ( )
@@ -604,15 +604,15 @@ impl RandomWalkStrategy {
604604 None => break ,
605605 } ;
606606
607- if !update . enabled {
607+ if !channel_update_info . enabled {
608608 break ;
609609 }
610610
611611 route_least_htlc_upper_bound =
612- route_least_htlc_upper_bound. min ( update . htlc_maximum_msat ) ;
612+ route_least_htlc_upper_bound. min ( channel_update_info . htlc_maximum_msat ) ;
613613
614614 route_greatest_htlc_lower_bound =
615- route_greatest_htlc_lower_bound. max ( update . htlc_minimum_msat ) ;
615+ route_greatest_htlc_lower_bound. max ( channel_update_info . htlc_minimum_msat ) ;
616616
617617 let next_pubkey = match PublicKey :: try_from ( * next_node_id) {
618618 Ok ( pk) => pk,
@@ -682,25 +682,37 @@ impl RandomWalkStrategy {
682682 let ( _, next_scid, _) = route[ i + 1 ] ;
683683 let next_channel = graph. channel ( next_scid) ?;
684684 let ( directed, _) = next_channel. as_directed_from ( & node_id) ?;
685- let update = match if directed. source ( ) == & next_channel. node_one {
685+ let channel_update_info = match if directed. source ( ) == & next_channel. node_one {
686686 next_channel. one_to_two . as_ref ( )
687687 } else {
688688 next_channel. two_to_one . as_ref ( )
689689 } {
690690 Some ( u) => u,
691691 None => return None ,
692692 } ;
693- let fee = update. fees . base_msat as u64
694- + ( forwarded * update. fees . proportional_millionths as u64 / 1_000_000 ) ;
695- forwarded += fee;
693+ // forwarded is the amount sent over next_channel (before this hop's own fee is
694+ // added on top for the preceding channel), so check it against next_channel's
695+ // own advertised bounds before computing the fee.
696+ if forwarded > channel_update_info. htlc_maximum_msat
697+ || forwarded < channel_update_info. htlc_minimum_msat
698+ {
699+ return None ;
700+ }
701+
702+ // Overflow prevention
703+ let proportional_fee = forwarded
704+ . checked_mul ( channel_update_info. fees . proportional_millionths as u64 )
705+ . map ( |v| v / 1_000_000 ) ?;
706+ let fee = ( channel_update_info. fees . base_msat as u64 ) . checked_add ( proportional_fee) ?;
707+ forwarded = forwarded. checked_add ( fee) ?;
696708
697709 hops. push ( RouteHop {
698710 pubkey,
699711 node_features,
700712 short_channel_id : via_scid,
701713 channel_features,
702714 fee_msat : fee,
703- cltv_expiry_delta : update . cltv_expiry_delta as u32 ,
715+ cltv_expiry_delta : channel_update_info . cltv_expiry_delta as u32 ,
704716 maybe_announced_channel,
705717 } ) ;
706718 }
0 commit comments