@@ -636,6 +636,12 @@ impl ChannelManager {
636
636
/// Sends a payment along a given route.
637
637
/// Value parameters are provided via the last hop in route, see documentation for RouteHop
638
638
/// fields for more info.
639
+ /// Note that if the payment_hash already exists elsewhere (eg you're sending a duplicative
640
+ /// payment), we don't do anything to stop you! We always try to ensure that if the provided
641
+ /// next hop knows the preimage to payment_hash they can claim an additional amount as
642
+ /// specified in the last hop in the route! Thus, you should probably do your own
643
+ /// payment_preimage tracking (which you should already be doing as they represent "proof of
644
+ /// payment") and prevent double-sends yourself.
639
645
/// See-also docs on Channel::send_htlc_and_commit.
640
646
/// May generate a SendHTLCs event on success, which should be relayed.
641
647
pub fn send_payment ( & self , route : Route , payment_hash : [ u8 ; 32 ] ) -> Result < ( ) , HandleError > {
@@ -662,29 +668,33 @@ impl ChannelManager {
662
668
let onion_packet = ChannelManager :: construct_onion_packet ( onion_payloads, onion_keys, & payment_hash) ?;
663
669
664
670
let ( first_hop_node_id, ( update_add, commitment_signed, chan_monitor) ) = {
665
- let mut channel_state = self . channel_state . lock ( ) . unwrap ( ) ;
671
+ let mut channel_state_lock = self . channel_state . lock ( ) . unwrap ( ) ;
672
+ let channel_state = channel_state_lock. borrow_parts ( ) ;
673
+
666
674
let id = match channel_state. short_to_id . get ( & route. hops . first ( ) . unwrap ( ) . short_channel_id ) {
667
675
None => return Err ( HandleError { err : "No channel available with first hop!" , action : None } ) ,
668
676
Some ( id) => id. clone ( )
669
677
} ;
678
+
679
+ let claimable_htlc_entry = channel_state. claimable_htlcs . entry ( payment_hash. clone ( ) ) ;
680
+ if let hash_map:: Entry :: Occupied ( _) = claimable_htlc_entry {
681
+ return Err ( HandleError { err : "Already had pending HTLC with the same payment_hash" , action : None } ) ;
682
+ }
683
+
670
684
let res = {
671
685
let chan = channel_state. by_id . get_mut ( & id) . unwrap ( ) ;
672
686
if chan. get_their_node_id ( ) != route. hops . first ( ) . unwrap ( ) . pubkey {
673
687
return Err ( HandleError { err : "Node ID mismatch on first hop!" , action : None } ) ;
674
688
}
675
- chan. send_htlc_and_commit ( htlc_msat, payment_hash. clone ( ) , htlc_cltv, onion_packet) ?
689
+ chan. send_htlc_and_commit ( htlc_msat, payment_hash, htlc_cltv, onion_packet) ?
676
690
} ;
677
691
678
692
let first_hop_node_id = route. hops . first ( ) . unwrap ( ) . pubkey ;
679
693
680
- if channel_state . claimable_htlcs . insert ( payment_hash , PendingOutboundHTLC :: OutboundRoute {
694
+ claimable_htlc_entry . or_insert ( PendingOutboundHTLC :: OutboundRoute {
681
695
route,
682
696
session_priv,
683
- } ) . is_some ( ) {
684
- // TODO: We need to track these better, we're not generating these, so a
685
- // third-party might make this happen:
686
- panic ! ( "payment_hash was repeated! Don't let this happen" ) ;
687
- }
697
+ } ) ;
688
698
689
699
match res {
690
700
Some ( msgs) => ( first_hop_node_id, msgs) ,
0 commit comments