@@ -45,7 +45,7 @@ use crate::ln::features::{ChannelFeatures, ChannelTypeFeatures, InitFeatures, No
45
45
#[ cfg( any( feature = "_test_utils" , test) ) ]
46
46
use crate :: ln:: features:: InvoiceFeatures ;
47
47
use crate :: routing:: gossip:: NetworkGraph ;
48
- use crate :: routing:: router:: { DefaultRouter , InFlightHtlcs , PaymentParameters , Route , RouteHop , RouteParameters , RoutePath , Router } ;
48
+ use crate :: routing:: router:: { BlindedTail , DefaultRouter , InFlightHtlcs , Path , PaymentParameters , Route , RouteHop , RouteParameters , Router } ;
49
49
use crate :: routing:: scoring:: ProbabilisticScorer ;
50
50
use crate :: ln:: msgs;
51
51
use crate :: ln:: onion_utils;
@@ -280,7 +280,7 @@ impl_writeable_tlv_based_enum!(SentHTLCId,
280
280
pub ( crate ) enum HTLCSource {
281
281
PreviousHopData ( HTLCPreviousHopData ) ,
282
282
OutboundRoute {
283
- path : Vec < RouteHop > ,
283
+ path : Path ,
284
284
session_priv : SecretKey ,
285
285
/// Technically we can recalculate this from the route, but we cache it here to avoid
286
286
/// doing a double-pass on route when we get a failure back
@@ -313,7 +313,7 @@ impl core::hash::Hash for HTLCSource {
313
313
impl HTLCSource {
314
314
pub fn dummy ( ) -> Self {
315
315
HTLCSource :: OutboundRoute {
316
- path : Vec :: new ( ) ,
316
+ path : Path { hops : Vec :: new ( ) , blinded_tail : None } ,
317
317
session_priv : SecretKey :: from_slice ( & [ 1 ; 32 ] ) . unwrap ( ) ,
318
318
first_hop_htlc_msat : 0 ,
319
319
payment_id : PaymentId ( [ 2 ; 32 ] ) ,
@@ -2513,16 +2513,16 @@ where
2513
2513
}
2514
2514
2515
2515
#[ cfg( test) ]
2516
- pub ( crate ) fn test_send_payment_along_path ( & self , path : & Vec < RouteHop > , payment_hash : & PaymentHash , payment_secret : & Option < PaymentSecret > , total_value : u64 , cur_height : u32 , payment_id : PaymentId , keysend_preimage : & Option < PaymentPreimage > , session_priv_bytes : [ u8 ; 32 ] ) -> Result < ( ) , APIError > {
2516
+ pub ( crate ) fn test_send_payment_along_path ( & self , path : & Path , payment_hash : & PaymentHash , payment_secret : & Option < PaymentSecret > , total_value : u64 , cur_height : u32 , payment_id : PaymentId , keysend_preimage : & Option < PaymentPreimage > , session_priv_bytes : [ u8 ; 32 ] ) -> Result < ( ) , APIError > {
2517
2517
let _lck = self . total_consistency_lock . read ( ) . unwrap ( ) ;
2518
2518
self . send_payment_along_path ( path, payment_hash, payment_secret, total_value, cur_height, payment_id, keysend_preimage, session_priv_bytes)
2519
2519
}
2520
2520
2521
- fn send_payment_along_path ( & self , path : & Vec < RouteHop > , payment_hash : & PaymentHash , payment_secret : & Option < PaymentSecret > , total_value : u64 , cur_height : u32 , payment_id : PaymentId , keysend_preimage : & Option < PaymentPreimage > , session_priv_bytes : [ u8 ; 32 ] ) -> Result < ( ) , APIError > {
2521
+ fn send_payment_along_path ( & self , path : & Path , payment_hash : & PaymentHash , payment_secret : & Option < PaymentSecret > , total_value : u64 , cur_height : u32 , payment_id : PaymentId , keysend_preimage : & Option < PaymentPreimage > , session_priv_bytes : [ u8 ; 32 ] ) -> Result < ( ) , APIError > {
2522
2522
// The top-level caller should hold the total_consistency_lock read lock.
2523
2523
debug_assert ! ( self . total_consistency_lock. try_write( ) . is_err( ) ) ;
2524
2524
2525
- log_trace ! ( self . logger, "Attempting to send payment for path with next hop {}" , path. first ( ) . unwrap ( ) . short_channel_id ) ;
2525
+ log_trace ! ( self . logger, "Attempting to send payment for path with next hop {}" , path. first_hop_scid ( ) ) ;
2526
2526
let prng_seed = self . entropy_source . get_secure_random_bytes ( ) ;
2527
2527
let session_priv = SecretKey :: from_slice ( & session_priv_bytes[ ..] ) . expect ( "RNG is busted" ) ;
2528
2528
@@ -2535,7 +2535,7 @@ where
2535
2535
let onion_packet = onion_utils:: construct_onion_packet ( onion_payloads, onion_keys, prng_seed, payment_hash) ;
2536
2536
2537
2537
let err: Result < ( ) , _ > = loop {
2538
- let ( counterparty_node_id, id) = match self . short_to_chan_info . read ( ) . unwrap ( ) . get ( & path. first ( ) . unwrap ( ) . short_channel_id ) {
2538
+ let ( counterparty_node_id, id) = match self . short_to_chan_info . read ( ) . unwrap ( ) . get ( & path. first_hop_scid ( ) ) {
2539
2539
None => return Err ( APIError :: ChannelUnavailable { err : "No channel available with first hop!" . to_owned ( ) } ) ,
2540
2540
Some ( ( cp_id, chan_id) ) => ( cp_id. clone ( ) , chan_id. clone ( ) ) ,
2541
2541
} ;
@@ -2587,7 +2587,7 @@ where
2587
2587
return Ok ( ( ) ) ;
2588
2588
} ;
2589
2589
2590
- match handle_error ! ( self , err, path. first ( ) . unwrap ( ) . pubkey ) {
2590
+ match handle_error ! ( self , err, path. first_hop_node_id ( ) ) {
2591
2591
Ok ( _) => unreachable ! ( ) ,
2592
2592
Err ( e) => {
2593
2593
Err ( APIError :: ChannelUnavailable { err : e. err } )
@@ -6902,23 +6902,25 @@ impl Readable for HTLCSource {
6902
6902
let mut payment_id = None ;
6903
6903
let mut payment_secret = None ;
6904
6904
let mut payment_params: Option < PaymentParameters > = None ;
6905
+ let mut blinded_tail: Option < BlindedTail > = None ;
6905
6906
read_tlv_fields ! ( reader, {
6906
6907
( 0 , session_priv, required) ,
6907
6908
( 1 , payment_id, option) ,
6908
6909
( 2 , first_hop_htlc_msat, required) ,
6909
6910
( 3 , payment_secret, option) ,
6910
6911
( 4 , path, vec_type) ,
6911
6912
( 5 , payment_params, ( option: ReadableArgs , 0 ) ) ,
6913
+ ( 6 , blinded_tail, option) ,
6912
6914
} ) ;
6913
6915
if payment_id. is_none ( ) {
6914
6916
// For backwards compat, if there was no payment_id written, use the session_priv bytes
6915
6917
// instead.
6916
6918
payment_id = Some ( PaymentId ( * session_priv. 0 . unwrap ( ) . as_ref ( ) ) ) ;
6917
6919
}
6918
- if path. is_none ( ) || path. as_ref ( ) . unwrap ( ) . is_empty ( ) {
6920
+ let path = path. unwrap_or ( Vec :: new ( ) ) ;
6921
+ if path. is_empty ( ) && blinded_tail. is_none ( ) {
6919
6922
return Err ( DecodeError :: InvalidValue ) ;
6920
6923
}
6921
- let path = path. unwrap ( ) ;
6922
6924
if let Some ( params) = payment_params. as_mut ( ) {
6923
6925
if params. final_cltv_expiry_delta == 0 {
6924
6926
params. final_cltv_expiry_delta = path. last ( ) . unwrap ( ) . cltv_expiry_delta ;
@@ -6927,7 +6929,7 @@ impl Readable for HTLCSource {
6927
6929
Ok ( HTLCSource :: OutboundRoute {
6928
6930
session_priv : session_priv. 0 . unwrap ( ) ,
6929
6931
first_hop_htlc_msat,
6930
- path,
6932
+ path : Path { hops : path , blinded_tail } ,
6931
6933
payment_id : payment_id. unwrap ( ) ,
6932
6934
payment_secret,
6933
6935
} )
@@ -6949,8 +6951,9 @@ impl Writeable for HTLCSource {
6949
6951
( 1 , payment_id_opt, option) ,
6950
6952
( 2 , first_hop_htlc_msat, required) ,
6951
6953
( 3 , payment_secret, option) ,
6952
- ( 4 , * path, vec_type) ,
6954
+ ( 4 , path. hops , vec_type) ,
6953
6955
( 5 , None :: <PaymentParameters >, option) , // payment_params in LDK versions prior to 0.0.115
6956
+ ( 6 , path. blinded_tail, option) ,
6954
6957
} ) ;
6955
6958
}
6956
6959
HTLCSource :: PreviousHopData ( ref field) => {
@@ -7612,12 +7615,12 @@ where
7612
7615
if id_to_peer. get ( & monitor. get_funding_txo ( ) . 0 . to_channel_id ( ) ) . is_none ( ) {
7613
7616
for ( htlc_source, ( htlc, _) ) in monitor. get_pending_or_resolved_outbound_htlcs ( ) {
7614
7617
if let HTLCSource :: OutboundRoute { payment_id, session_priv, path, payment_secret, .. } = htlc_source {
7615
- if path. is_empty ( ) {
7618
+ if path. len ( ) == 0 {
7616
7619
log_error ! ( args. logger, "Got an empty path for a pending payment" ) ;
7617
7620
return Err ( DecodeError :: InvalidValue ) ;
7618
7621
}
7619
7622
7620
- let path_amt = path. last ( ) . unwrap ( ) . fee_msat ;
7623
+ let path_amt = path. final_value_msat ( ) ;
7621
7624
let mut session_priv_bytes = [ 0 ; 32 ] ;
7622
7625
session_priv_bytes[ ..] . copy_from_slice ( & session_priv[ ..] ) ;
7623
7626
match pending_outbounds. pending_outbound_payments . lock ( ) . unwrap ( ) . entry ( payment_id) {
@@ -7627,7 +7630,7 @@ where
7627
7630
if newly_added { "Added" } else { "Had" } , path_amt, log_bytes!( session_priv_bytes) , log_bytes!( htlc. payment_hash. 0 ) ) ;
7628
7631
} ,
7629
7632
hash_map:: Entry :: Vacant ( entry) => {
7630
- let path_fee = path. get_path_fees ( ) ;
7633
+ let path_fee = path. fee_msat ( ) ;
7631
7634
entry. insert ( PendingOutboundPayment :: Retryable {
7632
7635
retry_strategy : None ,
7633
7636
attempts : PaymentAttempts :: new ( ) ,
@@ -8130,15 +8133,15 @@ mod tests {
8130
8133
Event :: PaymentPathSuccessful { payment_id : ref actual_payment_id, ref payment_hash, ref path } => {
8131
8134
assert_eq ! ( payment_id, * actual_payment_id) ;
8132
8135
assert_eq ! ( our_payment_hash, * payment_hash. as_ref( ) . unwrap( ) ) ;
8133
- assert_eq ! ( route. paths[ 0 ] , * path) ;
8136
+ assert_eq ! ( route. paths[ 0 ] . hops , * path) ;
8134
8137
} ,
8135
8138
_ => panic ! ( "Unexpected event" ) ,
8136
8139
}
8137
8140
match events[ 2 ] {
8138
8141
Event :: PaymentPathSuccessful { payment_id : ref actual_payment_id, ref payment_hash, ref path } => {
8139
8142
assert_eq ! ( payment_id, * actual_payment_id) ;
8140
8143
assert_eq ! ( our_payment_hash, * payment_hash. as_ref( ) . unwrap( ) ) ;
8141
- assert_eq ! ( route. paths[ 0 ] , * path) ;
8144
+ assert_eq ! ( route. paths[ 0 ] . hops , * path) ;
8142
8145
} ,
8143
8146
_ => panic ! ( "Unexpected event" ) ,
8144
8147
}
@@ -8342,12 +8345,12 @@ mod tests {
8342
8345
let ( mut route, payment_hash, _, _) = get_route_and_payment_hash ! ( & nodes[ 0 ] , nodes[ 3 ] , 100000 ) ;
8343
8346
let path = route. paths [ 0 ] . clone ( ) ;
8344
8347
route. paths . push ( path) ;
8345
- route. paths [ 0 ] [ 0 ] . pubkey = nodes[ 1 ] . node . get_our_node_id ( ) ;
8346
- route. paths [ 0 ] [ 0 ] . short_channel_id = chan_1_id;
8347
- route. paths [ 0 ] [ 1 ] . short_channel_id = chan_3_id;
8348
- route. paths [ 1 ] [ 0 ] . pubkey = nodes[ 2 ] . node . get_our_node_id ( ) ;
8349
- route. paths [ 1 ] [ 0 ] . short_channel_id = chan_2_id;
8350
- route. paths [ 1 ] [ 1 ] . short_channel_id = chan_4_id;
8348
+ route. paths [ 0 ] . hops [ 0 ] . pubkey = nodes[ 1 ] . node . get_our_node_id ( ) ;
8349
+ route. paths [ 0 ] . hops [ 0 ] . short_channel_id = chan_1_id;
8350
+ route. paths [ 0 ] . hops [ 1 ] . short_channel_id = chan_3_id;
8351
+ route. paths [ 1 ] . hops [ 0 ] . pubkey = nodes[ 2 ] . node . get_our_node_id ( ) ;
8352
+ route. paths [ 1 ] . hops [ 0 ] . short_channel_id = chan_2_id;
8353
+ route. paths [ 1 ] . hops [ 1 ] . short_channel_id = chan_4_id;
8351
8354
8352
8355
match nodes[ 0 ] . node . send_payment ( & route, payment_hash, & None , PaymentId ( payment_hash. 0 ) ) . unwrap_err ( ) {
8353
8356
PaymentSendFailure :: ParameterError ( APIError :: APIMisuseError { ref err } ) => {
0 commit comments