@@ -1903,6 +1903,9 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
1903
1903
// for now more than 10 paths likely carries too much one-path failure.
1904
1904
return Err ( PaymentSendFailure :: ParameterError ( APIError :: RouteError { err : "Sending over more than 10 paths is not currently supported" } ) ) ;
1905
1905
}
1906
+ if payment_secret. is_none ( ) && route. paths . len ( ) > 1 {
1907
+ return Err ( PaymentSendFailure :: ParameterError ( APIError :: APIMisuseError { err : "Payment secret is required for multi-path payments" . to_string ( ) } ) ) ;
1908
+ }
1906
1909
let mut total_value = 0 ;
1907
1910
let our_node_id = self . get_our_node_id ( ) ;
1908
1911
let mut path_errs = Vec :: with_capacity ( route. paths . len ( ) ) ;
@@ -1957,9 +1960,13 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
1957
1960
/// would be able to guess -- otherwise, an intermediate node may claim the payment and it will
1958
1961
/// never reach the recipient.
1959
1962
///
1963
+ /// See [`send_payment`] documentation for more details on the return value of this function.
1964
+ ///
1960
1965
/// Similar to regular payments, you MUST NOT reuse a `payment_preimage` value. See
1961
1966
/// [`send_payment`] for more information about the risks of duplicate preimage usage.
1962
1967
///
1968
+ /// Note that `route` must have exactly one path.
1969
+ ///
1963
1970
/// [`send_payment`]: Self::send_payment
1964
1971
pub fn send_spontaneous_payment ( & self , route : & Route , payment_preimage : Option < PaymentPreimage > ) -> Result < PaymentHash , PaymentSendFailure > {
1965
1972
let preimage = match payment_preimage {
@@ -5212,11 +5219,13 @@ mod tests {
5212
5219
use bitcoin:: hashes:: sha256:: Hash as Sha256 ;
5213
5220
use core:: time:: Duration ;
5214
5221
use ln:: { PaymentPreimage , PaymentHash , PaymentSecret } ;
5222
+ use ln:: channelmanager:: PaymentSendFailure ;
5215
5223
use ln:: features:: { InitFeatures , InvoiceFeatures } ;
5216
5224
use ln:: functional_test_utils:: * ;
5217
5225
use ln:: msgs;
5218
5226
use ln:: msgs:: ChannelMessageHandler ;
5219
5227
use routing:: router:: { get_keysend_route, get_route} ;
5228
+ use util:: errors:: APIError ;
5220
5229
use util:: events:: { Event , MessageSendEvent , MessageSendEventsProvider } ;
5221
5230
use util:: test_utils;
5222
5231
@@ -5604,6 +5613,39 @@ mod tests {
5604
5613
5605
5614
nodes[ 1 ] . logger . assert_log_contains ( "lightning::ln::channelmanager" . to_string ( ) , "We don't support MPP keysend payments" . to_string ( ) , 1 ) ;
5606
5615
}
5616
+
5617
+ #[ test]
5618
+ fn test_multi_hop_missing_secret ( ) {
5619
+ let chanmon_cfgs = create_chanmon_cfgs ( 4 ) ;
5620
+ let node_cfgs = create_node_cfgs ( 4 , & chanmon_cfgs) ;
5621
+ let node_chanmgrs = create_node_chanmgrs ( 4 , & node_cfgs, & [ None , None , None , None ] ) ;
5622
+ let nodes = create_network ( 4 , & node_cfgs, & node_chanmgrs) ;
5623
+
5624
+ let chan_1_id = create_announced_chan_between_nodes ( & nodes, 0 , 1 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) . 0 . contents . short_channel_id ;
5625
+ let chan_2_id = create_announced_chan_between_nodes ( & nodes, 0 , 2 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) . 0 . contents . short_channel_id ;
5626
+ let chan_3_id = create_announced_chan_between_nodes ( & nodes, 1 , 3 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) . 0 . contents . short_channel_id ;
5627
+ let chan_4_id = create_announced_chan_between_nodes ( & nodes, 2 , 3 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) . 0 . contents . short_channel_id ;
5628
+ let logger = test_utils:: TestLogger :: new ( ) ;
5629
+
5630
+ // Marshall an MPP route.
5631
+ let ( _, payment_hash, _) = get_payment_preimage_hash ! ( & nodes[ 3 ] ) ;
5632
+ let net_graph_msg_handler = & nodes[ 0 ] . net_graph_msg_handler ;
5633
+ let mut route = get_route ( & nodes[ 0 ] . node . get_our_node_id ( ) , & net_graph_msg_handler. network_graph . read ( ) . unwrap ( ) , & nodes[ 3 ] . node . get_our_node_id ( ) , Some ( InvoiceFeatures :: known ( ) ) , None , & [ ] , 100000 , TEST_FINAL_CLTV , & logger) . unwrap ( ) ;
5634
+ let path = route. paths [ 0 ] . clone ( ) ;
5635
+ route. paths . push ( path) ;
5636
+ route. paths [ 0 ] [ 0 ] . pubkey = nodes[ 1 ] . node . get_our_node_id ( ) ;
5637
+ route. paths [ 0 ] [ 0 ] . short_channel_id = chan_1_id;
5638
+ route. paths [ 0 ] [ 1 ] . short_channel_id = chan_3_id;
5639
+ route. paths [ 1 ] [ 0 ] . pubkey = nodes[ 2 ] . node . get_our_node_id ( ) ;
5640
+ route. paths [ 1 ] [ 0 ] . short_channel_id = chan_2_id;
5641
+ route. paths [ 1 ] [ 1 ] . short_channel_id = chan_4_id;
5642
+
5643
+ match nodes[ 0 ] . node . send_payment ( & route, payment_hash, & None ) . unwrap_err ( ) {
5644
+ PaymentSendFailure :: ParameterError ( APIError :: APIMisuseError { ref err } ) => {
5645
+ assert ! ( regex:: Regex :: new( r"Payment secret is required for multi-path payments" ) . unwrap( ) . is_match( err) ) } ,
5646
+ _ => panic ! ( "unexpected error" )
5647
+ }
5648
+ }
5607
5649
}
5608
5650
5609
5651
#[ cfg( all( any( test, feature = "_test_utils" ) , feature = "unstable" ) ) ]
0 commit comments