@@ -72,21 +72,22 @@ pub struct Route {
72
72
}
73
73
74
74
impl 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`.
78
79
pub fn get_total_fees ( & self ) -> u64 {
79
80
// Do not count last hop of each path since that's the full value of the payment
80
81
return self . paths . iter ( )
81
- . flat_map ( |path| path. split_last ( ) . unwrap ( ) . 1 )
82
+ . flat_map ( |path| path. split_last ( ) . map ( | ( _ , path_prefix ) | path_prefix ) . unwrap_or ( & [ ] ) )
82
83
. map ( |hop| & hop. fee_msat )
83
84
. sum ( ) ;
84
85
}
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.
86
88
pub fn get_total_amount ( & self ) -> u64 {
87
89
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. fee_msat ) . unwrap_or ( 0 ) )
90
91
. sum ( ) ;
91
92
}
92
93
}
@@ -4226,17 +4227,17 @@ mod tests {
4226
4227
RouteHop {
4227
4228
pubkey: PublicKey :: from_slice( & hex:: decode( "02eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619" ) . unwrap( ) [ ..] ) . unwrap( ) ,
4228
4229
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
4230
4231
} ,
4231
4232
RouteHop {
4232
4233
pubkey: PublicKey :: from_slice( & hex:: decode( "0324653eac434488002cc06bbfb7f10fe18991e35f9fe4302dbea6d2353dc0ab1c" ) . unwrap( ) [ ..] ) . unwrap( ) ,
4233
4234
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
4235
4236
} ,
4236
4237
RouteHop {
4237
4238
pubkey: PublicKey :: from_slice( & hex:: decode( "027f31ebc5462c1fdce1b737ecff52d37d75dea43ce11c74d25aa297165faa2007" ) . unwrap( ) [ ..] ) . unwrap( ) ,
4238
4239
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
4240
4241
} ,
4241
4242
] ] ,
4242
4243
} ;
@@ -4252,23 +4253,23 @@ mod tests {
4252
4253
RouteHop {
4253
4254
pubkey: PublicKey :: from_slice( & hex:: decode( "02eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619" ) . unwrap( ) [ ..] ) . unwrap( ) ,
4254
4255
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
4256
4257
} ,
4257
4258
RouteHop {
4258
4259
pubkey: PublicKey :: from_slice( & hex:: decode( "0324653eac434488002cc06bbfb7f10fe18991e35f9fe4302dbea6d2353dc0ab1c" ) . unwrap( ) [ ..] ) . unwrap( ) ,
4259
4260
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
4261
4262
} ,
4262
4263
] , vec![
4263
4264
RouteHop {
4264
4265
pubkey: PublicKey :: from_slice( & hex:: decode( "02eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619" ) . unwrap( ) [ ..] ) . unwrap( ) ,
4265
4266
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
4267
4268
} ,
4268
4269
RouteHop {
4269
4270
pubkey: PublicKey :: from_slice( & hex:: decode( "0324653eac434488002cc06bbfb7f10fe18991e35f9fe4302dbea6d2353dc0ab1c" ) . unwrap( ) [ ..] ) . unwrap( ) ,
4270
4271
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
4272
4273
} ,
4273
4274
] ] ,
4274
4275
} ;
@@ -4277,6 +4278,17 @@ mod tests {
4277
4278
assert_eq ! ( route. get_total_amount( ) , 300 ) ;
4278
4279
}
4279
4280
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
+
4280
4292
#[ cfg( not( feature = "no-std" ) ) ]
4281
4293
pub ( super ) fn random_init_seed ( ) -> u64 {
4282
4294
// Because the default HashMap in std pulls OS randomness, we can use it as a (bad) RNG.
0 commit comments