Expose chan type in `Event::OpenChannelRequest` & `ChannelDetails`
authorMatt Corallo <git@bluematt.me>
Wed, 16 Feb 2022 04:21:29 +0000 (04:21 +0000)
committerMatt Corallo <git@bluematt.me>
Sun, 27 Mar 2022 17:12:17 +0000 (17:12 +0000)
As we add new supported channel types, inbound channels which use
new features may cause backwards-compatibility issues for clients.
If a new channel is opened using new features while a client still
wishes to ensure support for downgrading to a previous version of
LDK, that new channel may cause the `ChannelManager` to fail
deserialization due to unsupported feature flags.

By exposing the channel type flags to the user in channel requests,
users wishing to support downgrading to previous versions of LDK
can reject channels which use channel features which previous
versions of LDK do not understand.

fuzz/src/router.rs
lightning/src/ln/channel.rs
lightning/src/ln/channelmanager.rs
lightning/src/routing/router.rs
lightning/src/util/events.rs

index 5494b26c7a300e5cb99d1056cd9054a9d626a8ac..bff177b19091b47b6b7f2184e1e826240d63a838 100644 (file)
@@ -215,6 +215,7 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
                                                                        forwarding_info: None,
                                                                },
                                                                funding_txo: Some(OutPoint { txid: bitcoin::Txid::from_slice(&[0; 32]).unwrap(), index: 0 }),
+                                                               channel_type: None,
                                                                short_channel_id: Some(scid),
                                                                inbound_scid_alias: None,
                                                                channel_value_satoshis: slice_to_be64(get_slice!(8)),
index 71e0ea121a929f2533c3af47714a50264e83b962..e1f292b76736b987c0e375d863f594c3beaf40d4 100644 (file)
@@ -4232,6 +4232,11 @@ impl<Signer: Sign> Channel<Signer> {
                self.user_id
        }
 
+       /// Gets the channel's type
+       pub fn get_channel_type(&self) -> &ChannelTypeFeatures {
+               &self.channel_type
+       }
+
        /// Guaranteed to be Some after both FundingLocked messages have been exchanged (and, thus,
        /// is_usable() returns true).
        /// Allowed in any state (including after shutdown)
index f3913c5167c8ebc70d0b1cfadb20568908555133..87f894190dac5492dc0d788738699972e009c9fb 100644 (file)
@@ -42,7 +42,7 @@ use chain::transaction::{OutPoint, TransactionData};
 // construct one themselves.
 use ln::{PaymentHash, PaymentPreimage, PaymentSecret};
 use ln::channel::{Channel, ChannelError, ChannelUpdateStatus, UpdateFulfillCommitFetch};
-use ln::features::{InitFeatures, NodeFeatures};
+use ln::features::{ChannelTypeFeatures, InitFeatures, NodeFeatures};
 use routing::router::{PaymentParameters, Route, RouteHop, RoutePath, RouteParameters};
 use ln::msgs;
 use ln::msgs::NetAddress;
@@ -1200,6 +1200,10 @@ pub struct ChannelDetails {
        /// Note that, if this has been set, `channel_id` will be equivalent to
        /// `funding_txo.unwrap().to_channel_id()`.
        pub funding_txo: Option<OutPoint>,
+       /// The features which this channel operates with. See individual features for more info.
+       ///
+       /// `None` until negotiation completes and the channel type is finalized.
+       pub channel_type: Option<ChannelTypeFeatures>,
        /// The position of the funding transaction in the chain. None if the funding transaction has
        /// not yet been confirmed and the channel fully opened.
        ///
@@ -1922,6 +1926,9 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
                                                forwarding_info: channel.counterparty_forwarding_info(),
                                        },
                                        funding_txo: channel.get_funding_txo(),
+                                       // Note that accept_channel (or open_channel) is always the first message, so
+                                       // `have_received_message` indicates that type negotiation has completed.
+                                       channel_type: if channel.have_received_message() { Some(channel.get_channel_type().clone()) } else { None },
                                        short_channel_id: channel.get_short_channel_id(),
                                        inbound_scid_alias: channel.latest_inbound_scid_alias(),
                                        channel_value_satoshis: channel.get_value_satoshis(),
@@ -4315,6 +4322,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
                                                        counterparty_node_id: counterparty_node_id.clone(),
                                                        funding_satoshis: msg.funding_satoshis,
                                                        push_msat: msg.push_msat,
+                                                       channel_type: channel.get_channel_type().clone(),
                                                }
                                        );
                                }
@@ -6054,6 +6062,7 @@ impl_writeable_tlv_based!(ChannelCounterparty, {
 impl_writeable_tlv_based!(ChannelDetails, {
        (1, inbound_scid_alias, option),
        (2, channel_id, required),
+       (3, channel_type, option),
        (4, counterparty, required),
        (6, funding_txo, option),
        (8, short_channel_id, option),
index 62cbda9a76ddd097710d897537e11f104c1ec408..34d4cd32fa18672903295ed54addaa1d173fbfa6 100644 (file)
@@ -1667,6 +1667,7 @@ mod tests {
                                forwarding_info: None,
                        },
                        funding_txo: Some(OutPoint { txid: bitcoin::Txid::from_slice(&[0; 32]).unwrap(), index: 0 }),
+                       channel_type: None,
                        short_channel_id,
                        inbound_scid_alias: None,
                        channel_value_satoshis: 0,
@@ -5363,6 +5364,7 @@ mod benches {
                        funding_txo: Some(OutPoint {
                                txid: bitcoin::Txid::from_slice(&[0; 32]).unwrap(), index: 0
                        }),
+                       channel_type: None,
                        short_channel_id: Some(1),
                        inbound_scid_alias: None,
                        channel_value_satoshis: 10_000_000,
index 3b90015cab901bd0ba72586ffad37dd65d3be711..ef2fc0fd9c72c740c4503621813bdb8ab960b6bc 100644 (file)
@@ -17,6 +17,7 @@
 use chain::keysinterface::SpendableOutputDescriptor;
 use ln::channelmanager::PaymentId;
 use ln::channel::FUNDING_CONF_DEADLINE_BLOCKS;
+use ln::features::ChannelTypeFeatures;
 use ln::msgs;
 use ln::msgs::DecodeError;
 use ln::{PaymentPreimage, PaymentHash, PaymentSecret};
@@ -429,6 +430,10 @@ pub enum Event {
                funding_satoshis: u64,
                /// Our starting balance in the channel if the request is accepted, in milli-satoshi.
                push_msat: u64,
+               /// The features that this channel will operate with. If you reject the channel, a
+               /// well-behaved counterparty may automatically re-attempt the channel with a new set of
+               /// feature flags.
+               channel_type: ChannelTypeFeatures,
        },
 }