XXX: BAD WIP
authorMatt Corallo <git@bluematt.me>
Sat, 13 Nov 2021 21:28:49 +0000 (21:28 +0000)
committerMatt Corallo <git@bluematt.me>
Tue, 21 Dec 2021 00:16:55 +0000 (00:16 +0000)
lightning/src/ln/channel.rs
lightning/src/ln/channelmanager.rs

index bda7d341108f5e7f6055a292146e3a88fd892127..746222506701b865b6d1c14caf77ef58b7d55ab2 100644 (file)
@@ -2430,7 +2430,10 @@ panic!();
 
        fn check_state_for_htlc_msg(&self) -> Result<(), ChannelError> {
                if (self.channel_state & (ChannelState::ChannelFunded as u32)) != (ChannelState::ChannelFunded as u32) {
-                       return Err(ChannelError::Close("Got HTLC message when channel was not in an operational state".to_owned()));
+                       let early_funding_locked_state = ChannelState::FundingSent as u32 | ChannelState::OurFundingLocked as u32;
+                       if self.channel_state & early_funding_locked_state != early_funding_locked_state {
+                               return Err(ChannelError::Close("Got HTLC message when channel was not in an operational state".to_owned()));
+                       }
                }
                if self.channel_state & (ChannelState::PeerDisconnected as u32) == ChannelState::PeerDisconnected as u32 {
                        return Err(ChannelError::Close("Peer sent HTLC message when we needed a channel_reestablish".to_owned()));
@@ -4282,6 +4285,7 @@ panic!();
 
        /// Returns true if this channel is fully established and not known to be closing.
        /// Allowed in any state (including after shutdown)
+       #[inline]
        pub fn is_usable(&self) -> bool {
                let mask = ChannelState::ChannelFunded as u32 | BOTH_SIDES_SHUTDOWN_MASK;
                (self.channel_state & mask) == (ChannelState::ChannelFunded as u32) && !self.monitor_pending_funding_locked
@@ -4290,10 +4294,26 @@ panic!();
        /// Returns true if this channel is currently available for use. This is a superset of
        /// is_usable() and considers things like the channel being temporarily disabled.
        /// Allowed in any state (including after shutdown)
+       #[inline]
        pub fn is_live(&self) -> bool {
                self.is_usable() && (self.channel_state & (ChannelState::PeerDisconnected as u32) == 0)
        }
 
+       /// Returns true if this channel is currently available for receiving inbound payments *to us*.
+       /// This may be true even if [`is_usable`] (or [`is_live`]) is *not* true, if our counterparty
+       /// is willing to forward payments to us with 0 confirmations on the funding transaction.
+       /// Note that payments received on this channel MUST NOT be forwarded unless we've marked the
+       /// channel trusted or [`is_usable`] is also true.
+       /// Allowed in any state (including after shutdown)
+       pub fn is_receivable(&self) -> bool {
+               let non_live_state_reqd = ChannelState::TheirFundingLocked as u32 | ChannelState::ChannelState::FundingSent as u32;
+               self.is_live() || (
+                       (self.channel_state & BOTH_SIDES_SHUTDOWN_MASK) == 0 &&
+                       (self.channel_state & ChannelState::PeerDisconnected as u32) == 0 &&
+                       (self.channel_state & non_live_state_reqd) == non_live_state_reqd
+               )
+       }
+
        /// Returns true if this channel has been marked as awaiting a monitor update to move forward.
        /// Allowed in any state (including after shutdown)
        pub fn is_awaiting_monitor_update(&self) -> bool {
index b1ea5b2ea8222ee5cfd65545c2a97ef079eb2a54..60eb5605b64772722eb97f662b58c531c8613c52 100644 (file)
@@ -1274,6 +1274,7 @@ pub struct ChannelDetails {
        ///
        /// This is a strict superset of `is_funding_locked`.
        pub is_usable: bool,
+       pub is_receivable: bool,
        /// True if this channel is (or will be) publicly-announced.
        pub is_public: bool,
 }
@@ -1828,7 +1829,8 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
                                        force_close_spend_delay: channel.get_counterparty_selected_contest_delay(),
                                        is_outbound: channel.is_outbound(),
                                        is_funding_locked: channel.is_usable(),
-                                       is_usable: channel.is_live(),
+                                       is_outbound_usable: channel.is_live(),
+                                       is_inbound_usable: channel.is_live(),
                                        is_public: channel.should_announce(),
                                });
                        }
@@ -1861,6 +1863,19 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
                self.list_channels_with_filter(|&(_, ref channel)| channel.is_live())
        }
 
+       /// Gets the list of channels on which we can receive a payment to us, in random order. Useful
+       /// to generate a list of route hints when generating an invoice.
+       ///
+       /// These are guaranteed to have their [`ChannelDetails::is_receivable`] value set to true, see the
+       /// documentation for [`ChannelDetails::is_receivable`] for more info on exactly what the criteria
+       /// are.
+       pub fn list_receivable_channels(&self) -> Vec<ChannelDetails> {
+               // Note we use is_live here instead of usable which leads to somewhat confused
+               // internal/external nomenclature, but that's ok cause that's probably what the user
+               // really wanted anyway.
+               self.list_channels_with_filter(|&(_, ref channel)| channel.is_receivable())
+       }
+
        /// Helper function that issues the channel close events
        fn issue_channel_close_events(&self, channel: &Channel<Signer>, closure_reason: ClosureReason) {
                let mut pending_events_lock = self.pending_events.lock().unwrap();