@@ -2111,6 +2111,8 @@ fn add_random_cltv_offset(route: &mut Route, payment_params: &PaymentParameters,
2111
2111
let network_nodes = network_graph. nodes ( ) ;
2112
2112
2113
2113
for path in route. paths . iter_mut ( ) {
2114
+ if path. blinded_tail . as_ref ( ) . map_or ( false , |tail| tail. hops . len ( ) > 1 ) { continue }
2115
+
2114
2116
let mut shadow_ctlv_expiry_delta_offset: u32 = 0 ;
2115
2117
2116
2118
// Remember the last three nodes of the random walk and avoid looping back on them.
@@ -2179,6 +2181,10 @@ fn add_random_cltv_offset(route: &mut Route, payment_params: &PaymentParameters,
2179
2181
shadow_ctlv_expiry_delta_offset = cmp:: min ( shadow_ctlv_expiry_delta_offset, max_path_offset) ;
2180
2182
2181
2183
// Add 'shadow' CLTV offset to the final hop
2184
+ if let Some ( tail) = path. blinded_tail . as_mut ( ) {
2185
+ tail. final_cltv_expiry_delta = tail. final_cltv_expiry_delta
2186
+ . checked_add ( shadow_ctlv_expiry_delta_offset) . unwrap_or ( tail. final_cltv_expiry_delta ) ;
2187
+ }
2182
2188
if let Some ( last_hop) = path. hops . last_mut ( ) {
2183
2189
last_hop. cltv_expiry_delta = last_hop. cltv_expiry_delta
2184
2190
. checked_add ( shadow_ctlv_expiry_delta_offset) . unwrap_or ( last_hop. cltv_expiry_delta ) ;
@@ -5871,6 +5877,54 @@ mod tests {
5871
5877
assert_eq ! ( * inflight_htlcs. 0 . get( & ( 42 , true ) ) . unwrap( ) , 301 ) ;
5872
5878
assert_eq ! ( * inflight_htlcs. 0 . get( & ( 43 , false ) ) . unwrap( ) , 201 ) ;
5873
5879
}
5880
+
5881
+ #[ test]
5882
+ fn blinded_path_cltv_shadow_offset ( ) {
5883
+ // Don't add a shadow offset to blinded paths with more than 1 hop.
5884
+ let blinded_path = BlindedPath {
5885
+ introduction_node_id : ln_test_utils:: pubkey ( 43 ) ,
5886
+ blinding_point : ln_test_utils:: pubkey ( 44 ) ,
5887
+ blinded_hops : vec ! [
5888
+ BlindedHop { blinded_node_id: ln_test_utils:: pubkey( 45 ) , encrypted_payload: Vec :: new( ) } ,
5889
+ BlindedHop { blinded_node_id: ln_test_utils:: pubkey( 46 ) , encrypted_payload: Vec :: new( ) }
5890
+ ] ,
5891
+ } ;
5892
+ let mut route = Route { paths : vec ! [ Path {
5893
+ hops: vec![ RouteHop {
5894
+ pubkey: ln_test_utils:: pubkey( 42 ) ,
5895
+ node_features: NodeFeatures :: empty( ) ,
5896
+ short_channel_id: 42 ,
5897
+ channel_features: ChannelFeatures :: empty( ) ,
5898
+ fee_msat: 100 ,
5899
+ cltv_expiry_delta: 0 ,
5900
+ } ,
5901
+ RouteHop {
5902
+ pubkey: blinded_path. introduction_node_id,
5903
+ node_features: NodeFeatures :: empty( ) ,
5904
+ short_channel_id: 43 ,
5905
+ channel_features: ChannelFeatures :: empty( ) ,
5906
+ fee_msat: 1 ,
5907
+ cltv_expiry_delta: 0 ,
5908
+ }
5909
+ ] ,
5910
+ blinded_tail: Some ( BlindedTail {
5911
+ hops: blinded_path. blinded_hops,
5912
+ blinding_point: blinded_path. blinding_point,
5913
+ final_cltv_expiry_delta: 0 ,
5914
+ final_value_msat: 200 ,
5915
+ } ) ,
5916
+ } ] , payment_params : None } ;
5917
+
5918
+ let payment_params = PaymentParameters :: from_node_id ( ln_test_utils:: pubkey ( 47 ) , 18 ) ;
5919
+ let ( _, network_graph, _, _, _) = build_line_graph ( ) ;
5920
+ add_random_cltv_offset ( & mut route, & payment_params, & network_graph. read_only ( ) , & [ 0 ; 32 ] ) ;
5921
+ assert_eq ! ( route. paths[ 0 ] . blinded_tail. as_ref( ) . unwrap( ) . final_cltv_expiry_delta, 0 ) ;
5922
+
5923
+ // Add a shadow offset if we're sending to a 1-hop blinded path.
5924
+ route. paths [ 0 ] . blinded_tail . as_mut ( ) . unwrap ( ) . hops . pop ( ) ;
5925
+ add_random_cltv_offset ( & mut route, & payment_params, & network_graph. read_only ( ) , & [ 0 ; 32 ] ) ;
5926
+ assert_eq ! ( route. paths[ 0 ] . blinded_tail. as_ref( ) . unwrap( ) . final_cltv_expiry_delta, 40 ) ;
5927
+ }
5874
5928
}
5875
5929
5876
5930
#[ cfg( all( test, not( feature = "no-std" ) ) ) ]
0 commit comments