Skip to content

Commit 194367f

Browse files
authored
Merge pull request #94 from TheBlueMatt/2018-07-duplicate_hash
Handle duplicate payment_hash send_payment()s
2 parents c75d07f + e0c75ca commit 194367f

File tree

1 file changed

+18
-8
lines changed

1 file changed

+18
-8
lines changed

src/ln/channelmanager.rs

+18-8
Original file line numberDiff line numberDiff line change
@@ -636,6 +636,12 @@ impl ChannelManager {
636636
/// Sends a payment along a given route.
637637
/// Value parameters are provided via the last hop in route, see documentation for RouteHop
638638
/// 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.
639645
/// See-also docs on Channel::send_htlc_and_commit.
640646
/// May generate a SendHTLCs event on success, which should be relayed.
641647
pub fn send_payment(&self, route: Route, payment_hash: [u8; 32]) -> Result<(), HandleError> {
@@ -662,29 +668,33 @@ impl ChannelManager {
662668
let onion_packet = ChannelManager::construct_onion_packet(onion_payloads, onion_keys, &payment_hash)?;
663669

664670
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+
666674
let id = match channel_state.short_to_id.get(&route.hops.first().unwrap().short_channel_id) {
667675
None => return Err(HandleError{err: "No channel available with first hop!", action: None}),
668676
Some(id) => id.clone()
669677
};
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+
670684
let res = {
671685
let chan = channel_state.by_id.get_mut(&id).unwrap();
672686
if chan.get_their_node_id() != route.hops.first().unwrap().pubkey {
673687
return Err(HandleError{err: "Node ID mismatch on first hop!", action: None});
674688
}
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)?
676690
};
677691

678692
let first_hop_node_id = route.hops.first().unwrap().pubkey;
679693

680-
if channel_state.claimable_htlcs.insert(payment_hash, PendingOutboundHTLC::OutboundRoute {
694+
claimable_htlc_entry.or_insert(PendingOutboundHTLC::OutboundRoute {
681695
route,
682696
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+
});
688698

689699
match res {
690700
Some(msgs) => (first_hop_node_id, msgs),

0 commit comments

Comments
 (0)