@@ -173,6 +173,22 @@ struct ClaimableHTLC {
173
173
onion_payload : OnionPayload ,
174
174
}
175
175
176
+ /// A payment identifier used to correlate an MPP payment's per-path HTLC sources internally.
177
+ #[ derive( Hash , Copy , Clone , PartialEq , Eq , Debug ) ]
178
+ pub ( crate ) struct MppId ( pub [ u8 ; 32 ] ) ;
179
+
180
+ impl Writeable for MppId {
181
+ fn write < W : Writer > ( & self , w : & mut W ) -> Result < ( ) , io:: Error > {
182
+ self . 0 . write ( w)
183
+ }
184
+ }
185
+
186
+ impl Readable for MppId {
187
+ fn read < R : Read > ( r : & mut R ) -> Result < Self , DecodeError > {
188
+ let buf: [ u8 ; 32 ] = Readable :: read ( r) ?;
189
+ Ok ( MppId ( buf) )
190
+ }
191
+ }
176
192
/// Tracks the inbound corresponding to an outbound HTLC
177
193
#[ derive( Clone , PartialEq ) ]
178
194
pub ( crate ) enum HTLCSource {
@@ -183,6 +199,7 @@ pub(crate) enum HTLCSource {
183
199
/// Technically we can recalculate this from the route, but we cache it here to avoid
184
200
/// doing a double-pass on route when we get a failure back
185
201
first_hop_htlc_msat : u64 ,
202
+ mpp_id : MppId ,
186
203
} ,
187
204
}
188
205
#[ cfg( test) ]
@@ -192,6 +209,7 @@ impl HTLCSource {
192
209
path : Vec :: new ( ) ,
193
210
session_priv : SecretKey :: from_slice ( & [ 1 ; 32 ] ) . unwrap ( ) ,
194
211
first_hop_htlc_msat : 0 ,
212
+ mpp_id : MppId ( [ 2 ; 32 ] ) ,
195
213
}
196
214
}
197
215
}
@@ -1820,7 +1838,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
1820
1838
}
1821
1839
1822
1840
// Only public for testing, this should otherwise never be called direcly
1823
- pub ( crate ) fn send_payment_along_path ( & self , path : & Vec < RouteHop > , payment_hash : & PaymentHash , payment_secret : & Option < PaymentSecret > , total_value : u64 , cur_height : u32 , keysend_preimage : & Option < PaymentPreimage > ) -> Result < ( ) , APIError > {
1841
+ pub ( crate ) fn send_payment_along_path ( & self , path : & Vec < RouteHop > , payment_hash : & PaymentHash , payment_secret : & Option < PaymentSecret > , total_value : u64 , cur_height : u32 , mpp_id : MppId , keysend_preimage : & Option < PaymentPreimage > ) -> Result < ( ) , APIError > {
1824
1842
log_trace ! ( self . logger, "Attempting to send payment for path with next hop {}" , path. first( ) . unwrap( ) . short_channel_id) ;
1825
1843
let prng_seed = self . keys_manager . get_secure_random_bytes ( ) ;
1826
1844
let session_priv_bytes = self . keys_manager . get_secure_random_bytes ( ) ;
@@ -1857,6 +1875,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
1857
1875
path: path. clone( ) ,
1858
1876
session_priv: session_priv. clone( ) ,
1859
1877
first_hop_htlc_msat: htlc_msat,
1878
+ mpp_id,
1860
1879
} , onion_packet, & self . logger) , channel_state, chan)
1861
1880
} {
1862
1881
Some ( ( update_add, commitment_signed, monitor_update) ) => {
@@ -1956,6 +1975,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
1956
1975
let mut total_value = 0 ;
1957
1976
let our_node_id = self . get_our_node_id ( ) ;
1958
1977
let mut path_errs = Vec :: with_capacity ( route. paths . len ( ) ) ;
1978
+ let mpp_id = MppId ( self . keys_manager . get_secure_random_bytes ( ) ) ;
1959
1979
' path_check: for path in route. paths . iter ( ) {
1960
1980
if path. len ( ) < 1 || path. len ( ) > 20 {
1961
1981
path_errs. push ( Err ( APIError :: RouteError { err : "Path didn't go anywhere/had bogus size" } ) ) ;
@@ -1977,7 +1997,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
1977
1997
let cur_height = self . best_block . read ( ) . unwrap ( ) . height ( ) + 1 ;
1978
1998
let mut results = Vec :: new ( ) ;
1979
1999
for path in route. paths . iter ( ) {
1980
- results. push ( self . send_payment_along_path ( & path, & payment_hash, payment_secret, total_value, cur_height, & keysend_preimage) ) ;
2000
+ results. push ( self . send_payment_along_path ( & path, & payment_hash, payment_secret, total_value, cur_height, mpp_id , & keysend_preimage) ) ;
1981
2001
}
1982
2002
let mut has_ok = false ;
1983
2003
let mut has_err = false ;
@@ -4911,14 +4931,60 @@ impl Readable for ClaimableHTLC {
4911
4931
}
4912
4932
}
4913
4933
4914
- impl_writeable_tlv_based_enum ! ( HTLCSource ,
4915
- ( 0 , OutboundRoute ) => {
4916
- ( 0 , session_priv, required) ,
4917
- ( 2 , first_hop_htlc_msat, required) ,
4918
- ( 4 , path, vec_type) ,
4919
- } , ;
4920
- ( 1 , PreviousHopData )
4921
- ) ;
4934
+ impl Readable for HTLCSource {
4935
+ fn read < R : Read > ( reader : & mut R ) -> Result < Self , DecodeError > {
4936
+ let id: u8 = Readable :: read ( reader) ?;
4937
+ match id {
4938
+ 0 => {
4939
+ let mut session_priv: :: util:: ser:: OptionDeserWrapper < SecretKey > = :: util:: ser:: OptionDeserWrapper ( None ) ;
4940
+ let mut first_hop_htlc_msat: u64 = 0 ;
4941
+ let mut path = Some ( Vec :: new ( ) ) ;
4942
+ let mut mpp_id = None ;
4943
+ read_tlv_fields ! ( reader, {
4944
+ ( 0 , session_priv, required) ,
4945
+ ( 1 , mpp_id, option) ,
4946
+ ( 2 , first_hop_htlc_msat, required) ,
4947
+ ( 4 , path, vec_type) ,
4948
+ } ) ;
4949
+ if mpp_id. is_none ( ) {
4950
+ // For backwards compat, if there was no mpp_id written, use the session_priv bytes
4951
+ // instead.
4952
+ mpp_id = Some ( MppId ( * session_priv. 0 . unwrap ( ) . as_ref ( ) ) ) ;
4953
+ }
4954
+ Ok ( HTLCSource :: OutboundRoute {
4955
+ session_priv : session_priv. 0 . unwrap ( ) ,
4956
+ first_hop_htlc_msat : first_hop_htlc_msat,
4957
+ path : path. unwrap ( ) ,
4958
+ mpp_id : mpp_id. unwrap ( ) ,
4959
+ } )
4960
+ }
4961
+ 1 => Ok ( HTLCSource :: PreviousHopData ( Readable :: read ( reader) ?) ) ,
4962
+ _ => Err ( DecodeError :: UnknownRequiredFeature ) ,
4963
+ }
4964
+ }
4965
+ }
4966
+
4967
+ impl Writeable for HTLCSource {
4968
+ fn write < W : Writer > ( & self , writer : & mut W ) -> Result < ( ) , :: io:: Error > {
4969
+ match self {
4970
+ HTLCSource :: OutboundRoute { ref session_priv, ref first_hop_htlc_msat, ref path, mpp_id } => {
4971
+ 0u8 . write ( writer) ?;
4972
+ let mpp_id_opt = Some ( mpp_id) ;
4973
+ write_tlv_fields ! ( writer, {
4974
+ ( 0 , session_priv, required) ,
4975
+ ( 1 , mpp_id_opt, option) ,
4976
+ ( 2 , first_hop_htlc_msat, required) ,
4977
+ ( 4 , path, vec_type) ,
4978
+ } ) ;
4979
+ }
4980
+ HTLCSource :: PreviousHopData ( ref field) => {
4981
+ 1u8 . write ( writer) ?;
4982
+ field. write ( writer) ?;
4983
+ }
4984
+ }
4985
+ Ok ( ( ) )
4986
+ }
4987
+ }
4922
4988
4923
4989
impl_writeable_tlv_based_enum ! ( HTLCFailReason ,
4924
4990
( 0 , LightningError ) => {
@@ -5364,7 +5430,7 @@ mod tests {
5364
5430
use bitcoin:: hashes:: sha256:: Hash as Sha256 ;
5365
5431
use core:: time:: Duration ;
5366
5432
use ln:: { PaymentPreimage , PaymentHash , PaymentSecret } ;
5367
- use ln:: channelmanager:: PaymentSendFailure ;
5433
+ use ln:: channelmanager:: { MppId , PaymentSendFailure } ;
5368
5434
use ln:: features:: { InitFeatures , InvoiceFeatures } ;
5369
5435
use ln:: functional_test_utils:: * ;
5370
5436
use ln:: msgs;
@@ -5515,10 +5581,11 @@ mod tests {
5515
5581
let net_graph_msg_handler = & nodes[ 0 ] . net_graph_msg_handler ;
5516
5582
let route = get_route ( & nodes[ 0 ] . node . get_our_node_id ( ) , & net_graph_msg_handler. network_graph , & nodes[ 1 ] . node . get_our_node_id ( ) , Some ( InvoiceFeatures :: known ( ) ) , None , & Vec :: new ( ) , 100_000 , TEST_FINAL_CLTV , & logger) . unwrap ( ) ;
5517
5583
let ( payment_preimage, our_payment_hash, payment_secret) = get_payment_preimage_hash ! ( & nodes[ 1 ] ) ;
5584
+ let mpp_id = MppId ( [ 42 ; 32 ] ) ;
5518
5585
// Use the utility function send_payment_along_path to send the payment with MPP data which
5519
5586
// indicates there are more HTLCs coming.
5520
5587
let cur_height = CHAN_CONFIRM_DEPTH + 1 ; // route_payment calls send_payment, which adds 1 to the current height. So we do the same here to match.
5521
- nodes[ 0 ] . node . send_payment_along_path ( & route. paths [ 0 ] , & our_payment_hash, & Some ( payment_secret) , 200_000 , cur_height, & None ) . unwrap ( ) ;
5588
+ nodes[ 0 ] . node . send_payment_along_path ( & route. paths [ 0 ] , & our_payment_hash, & Some ( payment_secret) , 200_000 , cur_height, mpp_id , & None ) . unwrap ( ) ;
5522
5589
check_added_monitors ! ( nodes[ 0 ] , 1 ) ;
5523
5590
let mut events = nodes[ 0 ] . node . get_and_clear_pending_msg_events ( ) ;
5524
5591
assert_eq ! ( events. len( ) , 1 ) ;
@@ -5548,7 +5615,7 @@ mod tests {
5548
5615
expect_payment_failed ! ( nodes[ 0 ] , our_payment_hash, true ) ;
5549
5616
5550
5617
// Send the second half of the original MPP payment.
5551
- nodes[ 0 ] . node . send_payment_along_path ( & route. paths [ 0 ] , & our_payment_hash, & Some ( payment_secret) , 200_000 , cur_height, & None ) . unwrap ( ) ;
5618
+ nodes[ 0 ] . node . send_payment_along_path ( & route. paths [ 0 ] , & our_payment_hash, & Some ( payment_secret) , 200_000 , cur_height, mpp_id , & None ) . unwrap ( ) ;
5552
5619
check_added_monitors ! ( nodes[ 0 ] , 1 ) ;
5553
5620
let mut events = nodes[ 0 ] . node . get_and_clear_pending_msg_events ( ) ;
5554
5621
assert_eq ! ( events. len( ) , 1 ) ;
0 commit comments