BDR: Linearizing secp256k1 deps
[rust-lightning] / lightning / src / ln / channelmanager.rs
index 6835522241bc0337238821b9549e1a969a69c016..78cf5987afd80d03334847dc07705a5cca3bbdb7 100644 (file)
@@ -14,21 +14,21 @@ use bitcoin::blockdata::constants::genesis_block;
 use bitcoin::network::constants::Network;
 use bitcoin::util::hash::BitcoinHash;
 
-use bitcoin_hashes::{Hash, HashEngine};
-use bitcoin_hashes::hmac::{Hmac, HmacEngine};
-use bitcoin_hashes::sha256::Hash as Sha256;
-use bitcoin_hashes::sha256d::Hash as Sha256dHash;
-use bitcoin_hashes::cmp::fixed_time_eq;
+use bitcoin::hashes::{Hash, HashEngine};
+use bitcoin::hashes::hmac::{Hmac, HmacEngine};
+use bitcoin::hashes::sha256::Hash as Sha256;
+use bitcoin::hashes::sha256d::Hash as Sha256dHash;
+use bitcoin::hashes::cmp::fixed_time_eq;
 
-use secp256k1::key::{SecretKey,PublicKey};
-use secp256k1::Secp256k1;
-use secp256k1::ecdh::SharedSecret;
-use secp256k1;
+use bitcoin::secp256k1::key::{SecretKey,PublicKey};
+use bitcoin::secp256k1::Secp256k1;
+use bitcoin::secp256k1::ecdh::SharedSecret;
+use bitcoin::secp256k1;
 
 use chain::chaininterface::{BroadcasterInterface,ChainListener,FeeEstimator};
 use chain::transaction::OutPoint;
 use ln::channel::{Channel, ChannelError};
-use ln::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, ChannelMonitorUpdateErr, ManyChannelMonitor, CLTV_CLAIM_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS, ANTI_REORG_DELAY, HTLC_FAIL_BACK_BUFFER};
+use ln::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, ChannelMonitorUpdateErr, ManyChannelMonitor, HTLC_FAIL_BACK_BUFFER, CLTV_CLAIM_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS, ANTI_REORG_DELAY};
 use ln::features::{InitFeatures, NodeFeatures};
 use ln::router::{Route, RouteHop};
 use ln::msgs;
@@ -1039,7 +1039,11 @@ impl<ChanSigner: ChannelKeys, M: Deref, T: Deref, K: Deref, F: Deref> ChannelMan
 
                                // OUR PAYMENT!
                                // final_expiry_too_soon
-                               if (msg.cltv_expiry as u64) < self.latest_block_height.load(Ordering::Acquire) as u64 + (CLTV_CLAIM_BUFFER + LATENCY_GRACE_PERIOD_BLOCKS) as u64 {
+                               // We have to have some headroom to broadcast on chain if we have the preimage, so make sure we have at least
+                               // HTLC_FAIL_BACK_BUFFER blocks to go.
+                               // Also, ensure that, in the case of an unknown payment hash, our payment logic has enough time to fail the HTLC backward
+                               // before our onchain logic triggers a channel closure (see HTLC_FAIL_BACK_BUFFER rational).
+                               if (msg.cltv_expiry as u64) <= self.latest_block_height.load(Ordering::Acquire) as u64 + HTLC_FAIL_BACK_BUFFER as u64 + 1 {
                                        return_err!("The final CLTV expiry is too soon to handle", 17, &[0;0]);
                                }
                                // final_incorrect_htlc_amount
@@ -1163,13 +1167,20 @@ impl<ChanSigner: ChannelKeys, M: Deref, T: Deref, K: Deref, F: Deref> ChannelMan
                                                break Some(("Forwarding node has tampered with the intended HTLC values or origin node has an obsolete cltv_expiry_delta", 0x1000 | 13, Some(self.get_channel_update(chan).unwrap())));
                                        }
                                        let cur_height = self.latest_block_height.load(Ordering::Acquire) as u32 + 1;
-                                       // We want to have at least LATENCY_GRACE_PERIOD_BLOCKS to fail prior to going on chain CLAIM_BUFFER blocks before expiration
-                                       if msg.cltv_expiry <= cur_height + CLTV_CLAIM_BUFFER + LATENCY_GRACE_PERIOD_BLOCKS as u32 { // expiry_too_soon
+                                       // Theoretically, channel counterparty shouldn't send us a HTLC expiring now, but we want to be robust wrt to counterparty
+                                       // packet sanitization (see HTLC_FAIL_BACK_BUFFER rational)
+                                       if msg.cltv_expiry <= cur_height + HTLC_FAIL_BACK_BUFFER as u32 { // expiry_too_soon
                                                break Some(("CLTV expiry is too close", 0x1000 | 14, Some(self.get_channel_update(chan).unwrap())));
                                        }
                                        if msg.cltv_expiry > cur_height + CLTV_FAR_FAR_AWAY as u32 { // expiry_too_far
                                                break Some(("CLTV expiry is too far in the future", 21, None));
                                        }
+                                       // In theory, we would be safe against unitentional channel-closure, if we only required a margin of LATENCY_GRACE_PERIOD_BLOCKS.
+                                       // But, to be safe against policy reception, we use a longuer delay.
+                                       if (*outgoing_cltv_value) as u64 <= (cur_height + HTLC_FAIL_BACK_BUFFER) as u64 {
+                                               break Some(("Outgoing CLTV value is too soon", 0x1000 | 14, Some(self.get_channel_update(chan).unwrap())));
+                                       }
+
                                        break None;
                                }
                                {
@@ -2962,23 +2973,32 @@ impl<ChanSigner: ChannelKeys, M: Deref + Sync + Send, T: Deref + Sync + Send, K:
                        let short_to_id = &mut channel_state.short_to_id;
                        let pending_msg_events = &mut channel_state.pending_msg_events;
                        channel_state.by_id.retain(|_, channel| {
-                               let chan_res = channel.block_connected(header, height, txn_matched, indexes_of_txn_matched);
-                               if let Ok(Some(funding_locked)) = chan_res {
-                                       pending_msg_events.push(events::MessageSendEvent::SendFundingLocked {
-                                               node_id: channel.get_their_node_id(),
-                                               msg: funding_locked,
-                                       });
-                                       if let Some(announcement_sigs) = self.get_announcement_sigs(channel) {
-                                               log_trace!(self, "Sending funding_locked and announcement_signatures for {}", log_bytes!(channel.channel_id()));
-                                               pending_msg_events.push(events::MessageSendEvent::SendAnnouncementSignatures {
+                               let res = channel.block_connected(header, height, txn_matched, indexes_of_txn_matched);
+                               if let Ok((chan_res, mut timed_out_pending_htlcs)) = res {
+                                       for (source, payment_hash) in timed_out_pending_htlcs.drain(..) {
+                                               let chan_update = self.get_channel_update(&channel).map(|u| u.encode_with_len()).unwrap(); // Cannot add/recv HTLCs before we have a short_id so unwrap is safe
+                                               timed_out_htlcs.push((source, payment_hash,  HTLCFailReason::Reason {
+                                                       failure_code: 0x1000 | 14, // expiry_too_soon, or at least it is now
+                                                       data: chan_update,
+                                               }));
+                                       }
+                                       if let Some(funding_locked) = chan_res {
+                                               pending_msg_events.push(events::MessageSendEvent::SendFundingLocked {
                                                        node_id: channel.get_their_node_id(),
-                                                       msg: announcement_sigs,
+                                                       msg: funding_locked,
                                                });
-                                       } else {
-                                               log_trace!(self, "Sending funding_locked WITHOUT announcement_signatures for {}", log_bytes!(channel.channel_id()));
+                                               if let Some(announcement_sigs) = self.get_announcement_sigs(channel) {
+                                                       log_trace!(self, "Sending funding_locked and announcement_signatures for {}", log_bytes!(channel.channel_id()));
+                                                       pending_msg_events.push(events::MessageSendEvent::SendAnnouncementSignatures {
+                                                               node_id: channel.get_their_node_id(),
+                                                               msg: announcement_sigs,
+                                                       });
+                                               } else {
+                                                       log_trace!(self, "Sending funding_locked WITHOUT announcement_signatures for {}", log_bytes!(channel.channel_id()));
+                                               }
+                                               short_to_id.insert(channel.get_short_channel_id().unwrap(), channel.channel_id());
                                        }
-                                       short_to_id.insert(channel.get_short_channel_id().unwrap(), channel.channel_id());
-                               } else if let Err(e) = chan_res {
+                               } else if let Err(e) = res {
                                        pending_msg_events.push(events::MessageSendEvent::HandleError {
                                                node_id: channel.get_their_node_id(),
                                                action: msgs::ErrorAction::SendErrorMessage { msg: e },
@@ -3049,8 +3069,6 @@ impl<ChanSigner: ChannelKeys, M: Deref + Sync + Send, T: Deref + Sync + Send, K:
                }
 
                for (source, payment_hash, reason) in timed_out_htlcs.drain(..) {
-                       // Call it incorrect_or_unknown_payment_details as the issue, ultimately, is that the
-                       // user failed to provide us a preimage within the cltv_expiry time window.
                        self.fail_htlc_backwards_internal(self.channel_state.lock().unwrap(), source, &payment_hash, reason);
                }
                self.latest_block_height.store(height as usize, Ordering::Release);