@@ -72,21 +72,22 @@ pub struct Route {
7272}
7373
7474impl Route {
75- /// Returns the total amount of fees paid on this Route.
76- /// This doesn't include any extra payment made to the recipient,
77- /// which can happen in excess of the amount passed to `get_route`'s `final_value_msat`.
75+ /// Returns the total amount of fees paid on this [`Route`].
76+ ///
77+ /// This doesn't include any extra payment made to the recipient, which can happen in excess of
78+ /// the amount passed to [``get_route``]'s `final_value_msat`.
7879 pub fn get_total_fees ( & self ) -> u64 {
7980 // Do not count last hop of each path since that's the full value of the payment
8081 return self . paths . iter ( )
81- . flat_map ( |path| path. split_last ( ) . unwrap ( ) . 1 )
82+ . flat_map ( |path| path. split_last ( ) . map ( |path_pfx| path_pfx . 1 ) . unwrap_or ( & [ ] ) )
8283 . map ( |hop| & hop. fee_msat )
8384 . sum ( ) ;
8485 }
85- /// Returns the total amount paid on this Route, excluding the fees.
86+
87+ /// Returns the total amount paid on this [`Route`], excluding the fees.
8688 pub fn get_total_amount ( & self ) -> u64 {
8789 return self . paths . iter ( )
88- . map ( |path| path. split_last ( ) . unwrap ( ) . 0 )
89- . map ( |hop| & hop. fee_msat )
90+ . map ( |path| path. split_last ( ) . map ( |hop| hop. 0 . fee_msat ) . unwrap_or ( 0 ) )
9091 . sum ( ) ;
9192 }
9293}
@@ -4226,17 +4227,17 @@ mod tests {
42264227 RouteHop {
42274228 pubkey: PublicKey :: from_slice( & hex:: decode( "02eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619" ) . unwrap( ) [ ..] ) . unwrap( ) ,
42284229 channel_features: ChannelFeatures :: empty( ) , node_features: NodeFeatures :: empty( ) ,
4229- short_channel_id: 0 , fee_msat: 100 , cltv_expiry_delta: 0 // Test vectors are garbage and not generateble from a RouteHop, we fill in payloads manually
4230+ short_channel_id: 0 , fee_msat: 100 , cltv_expiry_delta: 0
42304231 } ,
42314232 RouteHop {
42324233 pubkey: PublicKey :: from_slice( & hex:: decode( "0324653eac434488002cc06bbfb7f10fe18991e35f9fe4302dbea6d2353dc0ab1c" ) . unwrap( ) [ ..] ) . unwrap( ) ,
42334234 channel_features: ChannelFeatures :: empty( ) , node_features: NodeFeatures :: empty( ) ,
4234- short_channel_id: 0 , fee_msat: 150 , cltv_expiry_delta: 0 // Test vectors are garbage and not generateble from a RouteHop, we fill in payloads manually
4235+ short_channel_id: 0 , fee_msat: 150 , cltv_expiry_delta: 0
42354236 } ,
42364237 RouteHop {
42374238 pubkey: PublicKey :: from_slice( & hex:: decode( "027f31ebc5462c1fdce1b737ecff52d37d75dea43ce11c74d25aa297165faa2007" ) . unwrap( ) [ ..] ) . unwrap( ) ,
42384239 channel_features: ChannelFeatures :: empty( ) , node_features: NodeFeatures :: empty( ) ,
4239- short_channel_id: 0 , fee_msat: 225 , cltv_expiry_delta: 0 // Test vectors are garbage and not generateble from a RouteHop, we fill in payloads manually
4240+ short_channel_id: 0 , fee_msat: 225 , cltv_expiry_delta: 0
42404241 } ,
42414242 ] ] ,
42424243 } ;
@@ -4252,23 +4253,23 @@ mod tests {
42524253 RouteHop {
42534254 pubkey: PublicKey :: from_slice( & hex:: decode( "02eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619" ) . unwrap( ) [ ..] ) . unwrap( ) ,
42544255 channel_features: ChannelFeatures :: empty( ) , node_features: NodeFeatures :: empty( ) ,
4255- short_channel_id: 0 , fee_msat: 100 , cltv_expiry_delta: 0 // Test vectors are garbage and not generateble from a RouteHop, we fill in payloads manually
4256+ short_channel_id: 0 , fee_msat: 100 , cltv_expiry_delta: 0
42564257 } ,
42574258 RouteHop {
42584259 pubkey: PublicKey :: from_slice( & hex:: decode( "0324653eac434488002cc06bbfb7f10fe18991e35f9fe4302dbea6d2353dc0ab1c" ) . unwrap( ) [ ..] ) . unwrap( ) ,
42594260 channel_features: ChannelFeatures :: empty( ) , node_features: NodeFeatures :: empty( ) ,
4260- short_channel_id: 0 , fee_msat: 150 , cltv_expiry_delta: 0 // Test vectors are garbage and not generateble from a RouteHop, we fill in payloads manually
4261+ short_channel_id: 0 , fee_msat: 150 , cltv_expiry_delta: 0
42614262 } ,
42624263 ] , vec![
42634264 RouteHop {
42644265 pubkey: PublicKey :: from_slice( & hex:: decode( "02eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619" ) . unwrap( ) [ ..] ) . unwrap( ) ,
42654266 channel_features: ChannelFeatures :: empty( ) , node_features: NodeFeatures :: empty( ) ,
4266- short_channel_id: 0 , fee_msat: 100 , cltv_expiry_delta: 0 // Test vectors are garbage and not generateble from a RouteHop, we fill in payloads manually
4267+ short_channel_id: 0 , fee_msat: 100 , cltv_expiry_delta: 0
42674268 } ,
42684269 RouteHop {
42694270 pubkey: PublicKey :: from_slice( & hex:: decode( "0324653eac434488002cc06bbfb7f10fe18991e35f9fe4302dbea6d2353dc0ab1c" ) . unwrap( ) [ ..] ) . unwrap( ) ,
42704271 channel_features: ChannelFeatures :: empty( ) , node_features: NodeFeatures :: empty( ) ,
4271- short_channel_id: 0 , fee_msat: 150 , cltv_expiry_delta: 0 // Test vectors are garbage and not generateble from a RouteHop, we fill in payloads manually
4272+ short_channel_id: 0 , fee_msat: 150 , cltv_expiry_delta: 0
42724273 } ,
42734274 ] ] ,
42744275 } ;
@@ -4277,6 +4278,17 @@ mod tests {
42774278 assert_eq ! ( route. get_total_amount( ) , 300 ) ;
42784279 }
42794280
4281+ #[ test]
4282+ fn total_empty_route_no_panic ( ) {
4283+ // In an earlier version of `Route::get_total_fees` and `Route::get_total_amount`, they
4284+ // would both panic if the route was completely empty. We test to ensure they return 0
4285+ // here, even though its somewhat nonsensical as a route.
4286+ let route = Route { paths : Vec :: new ( ) } ;
4287+
4288+ assert_eq ! ( route. get_total_fees( ) , 0 ) ;
4289+ assert_eq ! ( route. get_total_amount( ) , 0 ) ;
4290+ }
4291+
42804292 #[ cfg( not( feature = "no-std" ) ) ]
42814293 pub ( super ) fn random_init_seed ( ) -> u64 {
42824294 // Because the default HashMap in std pulls OS randomness, we can use it as a (bad) RNG.
0 commit comments