X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;ds=sidebyside;f=lightning%2Fsrc%2Fln%2Fchannelmanager.rs;h=cfa2da06fd17bddb9167f14ec9b2efed6a51d7ff;hb=5425b2b77e690a08a604c6d26fbd0f8a1667f045;hp=6cf07ab4c86fa20c77ee0c75f6d4a2a2eea39c3b;hpb=c47acd76e8e60b65335a1bd1b9bbb53ddd43e496;p=rust-lightning diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index 6cf07ab4..cfa2da06 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -69,6 +69,7 @@ use core::ops::Deref; #[cfg(any(test, feature = "std"))] use std::time::Instant; +use util::crypto::sign; mod inbound_payment { use alloc::string::ToString; @@ -441,6 +442,7 @@ struct ClaimableHTLC { cltv_expiry: u32, value: u64, onion_payload: OnionPayload, + timer_ticks: u8, } /// A payment identifier used to uniquely identify a payment to LDK. @@ -886,6 +888,8 @@ impl PendingOutboundPayment { /// issues such as overly long function definitions. Note that the ChannelManager can take any /// type that implements KeysInterface for its keys manager, but this type alias chooses the /// concrete type of the KeysManager. +/// +/// (C-not exported) as Arcs don't make sense in bindings pub type SimpleArcChannelManager = ChannelManager, Arc, Arc, Arc, Arc>; /// SimpleRefChannelManager is a type alias for a ChannelManager reference, and is the reference @@ -896,6 +900,8 @@ pub type SimpleArcChannelManager = ChannelManager = ChannelManager; /// Manager which keeps track of a number of channels and sends messages to the appropriate @@ -1148,6 +1154,9 @@ const CHECK_CLTV_EXPIRY_SANITY_2: u32 = MIN_CLTV_EXPIRY_DELTA as u32 - LATENCY_G /// pending HTLCs in flight. pub(crate) const PAYMENT_EXPIRY_BLOCKS: u32 = 3; +/// The number of ticks of [`ChannelManager::timer_tick_occurred`] until expiry of incomplete MPPs +pub(crate) const MPP_TIMEOUT_TICKS: u8 = 3; + /// Information needed for constructing an invoice route hint for this channel. #[derive(Clone, Debug, PartialEq)] pub struct CounterpartyForwardingInfo { @@ -1218,6 +1227,9 @@ pub struct ChannelDetails { /// counterparty will recognize the alias provided here in place of the [`short_channel_id`] /// when they see a payment to be routed to us. /// + /// Our counterparty may choose to rotate this value at any time, though will always recognize + /// previous values for inbound payment forwarding. + /// /// [`short_channel_id`]: Self::short_channel_id pub inbound_scid_alias: Option, /// The value, in satoshis, of this channel as appears in the funding output @@ -1306,9 +1318,12 @@ pub struct ChannelDetails { } impl ChannelDetails { - /// Gets the SCID which should be used to identify this channel for inbound payments. This - /// should be used for providing invoice hints or in any other context where our counterparty - /// will forward a payment to us. + /// Gets the current SCID which should be used to identify this channel for inbound payments. + /// This should be used for providing invoice hints or in any other context where our + /// counterparty will forward a payment to us. + /// + /// This is either the [`ChannelDetails::inbound_scid_alias`], if set, or the + /// [`ChannelDetails::short_channel_id`]. See those for more information. pub fn get_inbound_payment_scid(&self) -> Option { self.inbound_scid_alias.or(self.short_channel_id) } @@ -3068,7 +3083,7 @@ impl ChannelMana excess_data: Vec::new(), }; let msghash = hash_to_message!(&Sha256dHash::hash(&announcement.encode()[..])[..]); - let node_announce_sig = self.secp_ctx.sign(&msghash, &self.our_network_key); + let node_announce_sig = sign(&self.secp_ctx, &msghash, &self.our_network_key); let mut channel_state_lock = self.channel_state.lock().unwrap(); let channel_state = &mut *channel_state_lock; @@ -3342,6 +3357,7 @@ impl ChannelMana phantom_shared_secret, }, value: amt_to_forward, + timer_ticks: 0, cltv_expiry, onion_payload, }; @@ -3636,6 +3652,7 @@ impl ChannelMana let new_feerate = self.fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Normal); let mut handle_errors = Vec::new(); + let mut timed_out_mpp_htlcs = Vec::new(); { let mut channel_state_lock = self.channel_state.lock().unwrap(); let channel_state = &mut *channel_state_lock; @@ -3684,6 +3701,32 @@ impl ChannelMana true }); + + channel_state.claimable_htlcs.retain(|payment_hash, htlcs| { + if htlcs.is_empty() { + // This should be unreachable + debug_assert!(false); + return false; + } + if let OnionPayload::Invoice(ref final_hop_data) = htlcs[0].onion_payload { + // Check if we've received all the parts we need for an MPP (the value of the parts adds to total_msat). + // In this case we're not going to handle any timeouts of the parts here. + if final_hop_data.total_msat == htlcs.iter().fold(0, |total, htlc| total + htlc.value) { + return true; + } else if htlcs.into_iter().any(|htlc| { + htlc.timer_ticks += 1; + return htlc.timer_ticks >= MPP_TIMEOUT_TICKS + }) { + timed_out_mpp_htlcs.extend(htlcs.into_iter().map(|htlc| (htlc.prev_hop.clone(), payment_hash.clone()))); + return false; + } + } + true + }); + } + + for htlc_source in timed_out_mpp_htlcs.drain(..) { + self.fail_htlc_backwards_internal(self.channel_state.lock().unwrap(), HTLCSource::PreviousHopData(htlc_source.0), &htlc_source.1, HTLCFailReason::Reason { failure_code: 23, data: Vec::new() }); } for (err, counterparty_node_id) in handle_errors.drain(..) { @@ -4310,8 +4353,13 @@ impl ChannelMana /// /// The `temporary_channel_id` parameter indicates which inbound channel should be accepted. /// - /// [`Event::OpenChannelRequest`]: crate::util::events::Event::OpenChannelRequest - pub fn accept_inbound_channel(&self, temporary_channel_id: &[u8; 32]) -> Result<(), APIError> { + /// For inbound channels, the `user_channel_id` parameter will be provided back in + /// [`Event::ChannelClosed::user_channel_id`] to allow tracking of which events correspond + /// with which `accept_inbound_channel` call. + /// + /// [`Event::OpenChannelRequest`]: events::Event::OpenChannelRequest + /// [`Event::ChannelClosed::user_channel_id`]: events::Event::ChannelClosed::user_channel_id + pub fn accept_inbound_channel(&self, temporary_channel_id: &[u8; 32], user_channel_id: u64) -> Result<(), APIError> { let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(&self.total_consistency_lock, &self.persistence_notifier); let mut channel_state_lock = self.channel_state.lock().unwrap(); @@ -4323,7 +4371,7 @@ impl ChannelMana } channel_state.pending_msg_events.push(events::MessageSendEvent::SendAcceptChannel { node_id: channel.get().get_counterparty_node_id(), - msg: channel.get_mut().accept_inbound_channel(), + msg: channel.get_mut().accept_inbound_channel(user_channel_id), }); } hash_map::Entry::Vacant(_) => { @@ -4364,7 +4412,7 @@ impl ChannelMana if !self.default_configuration.manually_accept_inbound_channels { channel_state.pending_msg_events.push(events::MessageSendEvent::SendAcceptChannel { node_id: counterparty_node_id.clone(), - msg: channel.accept_inbound_channel(), + msg: channel.accept_inbound_channel(0), }); } else { let mut pending_events = self.pending_events.lock().unwrap(); @@ -5549,6 +5597,12 @@ where let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(&self.total_consistency_lock, &self.persistence_notifier); self.do_chain_event(Some(height), |channel| channel.transactions_confirmed(&block_hash, height, txdata, self.genesis_hash.clone(), self.get_our_node_id(), &self.logger) .map(|(a, b)| (a, Vec::new(), b))); + + let last_best_block_height = self.best_block.read().unwrap().height(); + if height < last_best_block_height { + let timestamp = self.highest_seen_timestamp.load(Ordering::Acquire); + self.do_chain_event(Some(last_best_block_height), |channel| channel.best_block_updated(last_best_block_height, timestamp as u32, self.genesis_hash.clone(), self.get_our_node_id(), &self.logger)); + } } fn best_block_updated(&self, header: &BlockHeader, height: u32) { @@ -5938,6 +5992,7 @@ impl &events::MessageSendEvent::SendChannelRangeQuery { .. } => false, &events::MessageSendEvent::SendShortIdsQuery { .. } => false, &events::MessageSendEvent::SendReplyChannelRange { .. } => false, + &events::MessageSendEvent::SendGossipTimestampFilter { .. } => false, } }); } @@ -6296,6 +6351,7 @@ impl Readable for ClaimableHTLC { }; Ok(Self { prev_hop: prev_hop.0.unwrap(), + timer_ticks: 0, value, onion_payload, cltv_expiry, @@ -7370,8 +7426,8 @@ mod tests { let payer_pubkey = nodes[0].node.get_our_node_id(); let payee_pubkey = nodes[1].node.get_our_node_id(); - nodes[0].node.peer_connected(&payee_pubkey, &msgs::Init { features: InitFeatures::known() }); - nodes[1].node.peer_connected(&payer_pubkey, &msgs::Init { features: InitFeatures::known() }); + nodes[0].node.peer_connected(&payee_pubkey, &msgs::Init { features: InitFeatures::known(), remote_network_address: None }); + nodes[1].node.peer_connected(&payer_pubkey, &msgs::Init { features: InitFeatures::known(), remote_network_address: None }); let _chan = create_chan_between_nodes(&nodes[0], &nodes[1], InitFeatures::known(), InitFeatures::known()); let route_params = RouteParameters { @@ -7414,8 +7470,8 @@ mod tests { let payer_pubkey = nodes[0].node.get_our_node_id(); let payee_pubkey = nodes[1].node.get_our_node_id(); - nodes[0].node.peer_connected(&payee_pubkey, &msgs::Init { features: InitFeatures::known() }); - nodes[1].node.peer_connected(&payer_pubkey, &msgs::Init { features: InitFeatures::known() }); + nodes[0].node.peer_connected(&payee_pubkey, &msgs::Init { features: InitFeatures::known(), remote_network_address: None }); + nodes[1].node.peer_connected(&payer_pubkey, &msgs::Init { features: InitFeatures::known(), remote_network_address: None }); let _chan = create_chan_between_nodes(&nodes[0], &nodes[1], InitFeatures::known(), InitFeatures::known()); let route_params = RouteParameters { @@ -7580,8 +7636,8 @@ pub mod bench { }); let node_b_holder = NodeHolder { node: &node_b }; - node_a.peer_connected(&node_b.get_our_node_id(), &Init { features: InitFeatures::known() }); - node_b.peer_connected(&node_a.get_our_node_id(), &Init { features: InitFeatures::known() }); + node_a.peer_connected(&node_b.get_our_node_id(), &Init { features: InitFeatures::known(), remote_network_address: None }); + node_b.peer_connected(&node_a.get_our_node_id(), &Init { features: InitFeatures::known(), remote_network_address: None }); node_a.create_channel(node_b.get_our_node_id(), 8_000_000, 100_000_000, 42, None).unwrap(); node_b.handle_open_channel(&node_a.get_our_node_id(), InitFeatures::known(), &get_event_msg!(node_a_holder, MessageSendEvent::SendOpenChannel, node_b.get_our_node_id())); node_a.handle_accept_channel(&node_b.get_our_node_id(), InitFeatures::known(), &get_event_msg!(node_b_holder, MessageSendEvent::SendAcceptChannel, node_a.get_our_node_id()));