Merge pull request #1119 from TheBlueMatt/2021-10-less-aggressive-htlc-timeouts
[rust-lightning] / lightning / src / ln / features.rs
index 5d908ee01a4957bd7c85d305043af8e5204523a2..32ba9de758632036942318c756f64708793e1b1a 100644 (file)
 //! [BOLT #9]: https://github.com/lightningnetwork/lightning-rfc/blob/master/09-features.md
 //! [messages]: crate::ln::msgs
 
+use {io, io_extras};
 use prelude::*;
 use core::{cmp, fmt};
+use core::hash::{Hash, Hasher};
 use core::marker::PhantomData;
 
 use bitcoin::bech32;
@@ -89,6 +91,28 @@ mod sealed {
                                        )*
                                ];
                        }
+
+                       impl alloc::fmt::Display for Features<$context> {
+                               fn fmt(&self, fmt: &mut alloc::fmt::Formatter) -> Result<(), alloc::fmt::Error> {
+                                       $(
+                                               $(
+                                                       fmt.write_fmt(format_args!("{}: {}, ", stringify!($required_feature),
+                                                               if <$context as $required_feature>::requires_feature(&self.flags) { "required" }
+                                                               else if <$context as $required_feature>::supports_feature(&self.flags) { "supported" }
+                                                               else { "not supported" }))?;
+                                               )*
+                                               $(
+                                                       fmt.write_fmt(format_args!("{}: {}, ", stringify!($optional_feature),
+                                                               if <$context as $optional_feature>::requires_feature(&self.flags) { "required" }
+                                                               else if <$context as $optional_feature>::supports_feature(&self.flags) { "supported" }
+                                                               else { "not supported" }))?;
+                                               )*
+                                       )*
+                                       fmt.write_fmt(format_args!("unknown flags: {}",
+                                               if self.requires_unknown_bits() { "required" }
+                                               else if self.supports_unknown_bits() { "supported" } else { "none" }))
+                               }
+                       }
                };
        }
 
@@ -124,6 +148,12 @@ mod sealed {
                        ,
                        // Byte 3
                        ,
+                       // Byte 4
+                       ,
+                       // Byte 5
+                       ,
+                       // Byte 6
+                       ,
                ],
                optional_features: [
                        // Byte 0
@@ -134,6 +164,12 @@ mod sealed {
                        BasicMPP,
                        // Byte 3
                        ShutdownAnySegwit,
+                       // Byte 4
+                       ,
+                       // Byte 5
+                       ,
+                       // Byte 6
+                       Keysend,
                ],
        });
        define_context!(ChannelContext {
@@ -158,6 +194,30 @@ mod sealed {
                        BasicMPP,
                ],
        });
+       // This isn't a "real" feature context, and is only used in the channel_type field in an
+       // `OpenChannel` message.
+       define_context!(ChannelTypeContext {
+               required_features: [
+                       // Byte 0
+                       ,
+                       // Byte 1
+                       StaticRemoteKey,
+                       // Byte 2
+                       ,
+                       // Byte 3
+                       ,
+               ],
+               optional_features: [
+                       // Byte 0
+                       ,
+                       // Byte 1
+                       ,
+                       // Byte 2
+                       ,
+                       // Byte 3
+                       ,
+               ],
+       });
 
        /// Defines a feature with the given bits for the specified [`Context`]s. The generated trait is
        /// useful for manipulating feature flags.
@@ -289,7 +349,7 @@ mod sealed {
        define_feature!(9, VariableLengthOnion, [InitContext, NodeContext, InvoiceContext],
                "Feature flags for `var_onion_optin`.", set_variable_length_onion_optional,
                set_variable_length_onion_required);
-       define_feature!(13, StaticRemoteKey, [InitContext, NodeContext],
+       define_feature!(13, StaticRemoteKey, [InitContext, NodeContext, ChannelTypeContext],
                "Feature flags for `option_static_remotekey`.", set_static_remote_key_optional,
                set_static_remote_key_required);
        define_feature!(15, PaymentSecret, [InitContext, NodeContext, InvoiceContext],
@@ -299,6 +359,8 @@ mod sealed {
        define_feature!(27, ShutdownAnySegwit, [InitContext, NodeContext],
                "Feature flags for `opt_shutdown_anysegwit`.", set_shutdown_any_segwit_optional,
                set_shutdown_any_segwit_required);
+       define_feature!(55, Keysend, [NodeContext],
+               "Feature flags for keysend payments.", set_keysend_optional, set_keysend_required);
 
        #[cfg(test)]
        define_feature!(123456789, UnknownFeature, [NodeContext, ChannelContext, InvoiceContext],
@@ -325,6 +387,11 @@ impl<T: sealed::Context> Clone for Features<T> {
                }
        }
 }
+impl<T: sealed::Context> Hash for Features<T> {
+       fn hash<H: Hasher>(&self, hasher: &mut H) {
+               self.flags.hash(hasher);
+       }
+}
 impl<T: sealed::Context> PartialEq for Features<T> {
        fn eq(&self, o: &Self) -> bool {
                self.flags.eq(&o.flags)
@@ -345,11 +412,22 @@ pub type ChannelFeatures = Features<sealed::ChannelContext>;
 /// Features used within an invoice.
 pub type InvoiceFeatures = Features<sealed::InvoiceContext>;
 
+/// Features used within the channel_type field in an OpenChannel message.
+///
+/// A channel is always of some known "type", describing the transaction formats used and the exact
+/// semantics of our interaction with our peer.
+///
+/// Note that because a channel is a specific type which is proposed by the opener and accepted by
+/// the counterparty, only required features are allowed here.
+///
+/// This is serialized differently from other feature types - it is not prefixed by a length, and
+/// thus must only appear inside a TLV where its length is known in advance.
+pub type ChannelTypeFeatures = Features<sealed::ChannelTypeContext>;
+
 impl InitFeatures {
        /// Writes all features present up to, and including, 13.
-       pub(crate) fn write_up_to_13<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
+       pub(crate) fn write_up_to_13<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
                let len = cmp::min(2, self.flags.len());
-               w.size_hint(len + 2);
                (len as u16).write(w)?;
                for i in (0..len).rev() {
                        if i == 0 {
@@ -386,6 +464,40 @@ impl InvoiceFeatures {
        pub(crate) fn to_context<C: sealed::Context>(&self) -> Features<C> {
                self.to_context_internal()
        }
+
+       /// Getting a route for a keysend payment to a private node requires providing the payee's
+       /// features (since they were not announced in a node announcement). However, keysend payments
+       /// don't have an invoice to pull the payee's features from, so this method is provided for use in
+       /// [`Payee::for_keysend`], thus omitting the need for payers to manually construct an
+       /// `InvoiceFeatures` for [`find_route`].
+       ///
+       /// [`Payee::for_keysend`]: crate::routing::router::Payee::for_keysend
+       /// [`find_route`]: crate::routing::router::find_route
+       pub(crate) fn for_keysend() -> InvoiceFeatures {
+               InvoiceFeatures::empty().set_variable_length_onion_optional()
+       }
+}
+
+impl ChannelTypeFeatures {
+       /// Constructs the implicit channel type based on the common supported types between us and our
+       /// counterparty
+       pub(crate) fn from_counterparty_init(counterparty_init: &InitFeatures) -> Self {
+               let mut ret = counterparty_init.to_context_internal();
+               // ChannelTypeFeatures must only contain required bits, so we OR the required forms of all
+               // optional bits and then AND out the optional ones.
+               for byte in ret.flags.iter_mut() {
+                       *byte |= (*byte & 0b10_10_10_10) >> 1;
+                       *byte &= 0b01_01_01_01;
+               }
+               ret
+       }
+
+       /// Constructs a ChannelTypeFeatures with only static_remotekey set
+       pub(crate) fn only_static_remote_key() -> Self {
+               let mut ret = Self::empty();
+               <sealed::ChannelTypeContext as sealed::StaticRemoteKey>::set_required_bit(&mut ret.flags);
+               ret
+       }
 }
 
 impl ToBase32 for InvoiceFeatures {
@@ -499,7 +611,28 @@ impl<T: sealed::Context> Features<T> {
                &self.flags
        }
 
-       pub(crate) fn requires_unknown_bits(&self) -> bool {
+       fn write_be<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
+               for f in self.flags.iter().rev() { // Swap back to big-endian
+                       f.write(w)?;
+               }
+               Ok(())
+       }
+
+       fn from_be_bytes(mut flags: Vec<u8>) -> Features<T> {
+               flags.reverse(); // Swap to little-endian
+               Self {
+                       flags,
+                       mark: PhantomData,
+               }
+       }
+
+       pub(crate) fn supports_any_optional_bits(&self) -> bool {
+               self.flags.iter().any(|&byte| (byte & 0b10_10_10_10) != 0)
+       }
+
+       /// Returns true if this `Features` object contains unknown feature flags which are set as
+       /// "required".
+       pub fn requires_unknown_bits(&self) -> bool {
                // Bitwise AND-ing with all even bits set except for known features will select required
                // unknown features.
                let byte_count = T::KNOWN_FEATURE_MASK.len();
@@ -527,12 +660,6 @@ impl<T: sealed::Context> Features<T> {
                        (byte & unknown_features) != 0
                })
        }
-
-       /// The number of bytes required to represent the feature flags present. This does not include
-       /// the length bytes which are included in the serialized form.
-       pub(crate) fn byte_count(&self) -> usize {
-               self.flags.len()
-       }
 }
 
 impl<T: sealed::DataLossProtect> Features<T> {
@@ -540,6 +667,7 @@ impl<T: sealed::DataLossProtect> Features<T> {
        pub(crate) fn requires_data_loss_protect(&self) -> bool {
                <T as sealed::DataLossProtect>::requires_feature(&self.flags)
        }
+       #[cfg(test)]
        pub(crate) fn supports_data_loss_protect(&self) -> bool {
                <T as sealed::DataLossProtect>::supports_feature(&self.flags)
        }
@@ -641,32 +769,44 @@ impl<T: sealed::ShutdownAnySegwit> Features<T> {
                self
        }
 }
-
-impl<T: sealed::Context> Writeable for Features<T> {
-       fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
-               w.size_hint(self.flags.len() + 2);
-               (self.flags.len() as u16).write(w)?;
-               for f in self.flags.iter().rev() { // Swap back to big-endian
-                       f.write(w)?;
+macro_rules! impl_feature_len_prefixed_write {
+       ($features: ident) => {
+               impl Writeable for $features {
+                       fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
+                               (self.flags.len() as u16).write(w)?;
+                               self.write_be(w)
+                       }
+               }
+               impl Readable for $features {
+                       fn read<R: io::Read>(r: &mut R) -> Result<Self, DecodeError> {
+                               Ok(Self::from_be_bytes(Vec::<u8>::read(r)?))
+                       }
                }
-               Ok(())
        }
 }
-
-impl<T: sealed::Context> Readable for Features<T> {
-       fn read<R: ::std::io::Read>(r: &mut R) -> Result<Self, DecodeError> {
-               let mut flags: Vec<u8> = Readable::read(r)?;
-               flags.reverse(); // Swap to little-endian
-               Ok(Self {
-                       flags,
-                       mark: PhantomData,
-               })
+impl_feature_len_prefixed_write!(InitFeatures);
+impl_feature_len_prefixed_write!(ChannelFeatures);
+impl_feature_len_prefixed_write!(NodeFeatures);
+impl_feature_len_prefixed_write!(InvoiceFeatures);
+
+// Because ChannelTypeFeatures only appears inside of TLVs, it doesn't have a length prefix when
+// serialized. Thus, we can't use `impl_feature_len_prefixed_write`, above, and have to write our
+// own serialization.
+impl Writeable for ChannelTypeFeatures {
+       fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
+               self.write_be(w)
+       }
+}
+impl Readable for ChannelTypeFeatures {
+       fn read<R: io::Read>(r: &mut R) -> Result<Self, DecodeError> {
+               let v = io_extras::read_to_end(r)?;
+               Ok(Self::from_be_bytes(v))
        }
 }
 
 #[cfg(test)]
 mod tests {
-       use super::{ChannelFeatures, InitFeatures, InvoiceFeatures, NodeFeatures};
+       use super::{ChannelFeatures, ChannelTypeFeatures, InitFeatures, InvoiceFeatures, NodeFeatures};
        use bitcoin::bech32::{Base32Len, FromBase32, ToBase32, u5};
 
        #[test]
@@ -777,7 +917,7 @@ mod tests {
        #[test]
        fn convert_to_context_with_unknown_flags() {
                // Ensure the `from` context has fewer known feature bytes than the `to` context.
-               assert!(InvoiceFeatures::known().byte_count() < NodeFeatures::known().byte_count());
+               assert!(InvoiceFeatures::known().flags.len() < NodeFeatures::known().flags.len());
                let invoice_features = InvoiceFeatures::known().set_unknown_feature_optional();
                assert!(invoice_features.supports_unknown_bits());
                let node_features: NodeFeatures = invoice_features.to_context();
@@ -825,4 +965,15 @@ mod tests {
                let features_deserialized = InvoiceFeatures::from_base32(&features_as_u5s).unwrap();
                assert_eq!(features, features_deserialized);
        }
+
+       #[test]
+       fn test_channel_type_mapping() {
+               // If we map an InvoiceFeatures with StaticRemoteKey optional, it should map into a
+               // required-StaticRemoteKey ChannelTypeFeatures.
+               let init_features = InitFeatures::empty().set_static_remote_key_optional();
+               let converted_features = ChannelTypeFeatures::from_counterparty_init(&init_features);
+               assert_eq!(converted_features, ChannelTypeFeatures::only_static_remote_key());
+               assert!(!converted_features.supports_any_optional_bits());
+               assert!(converted_features.requires_static_remote_key());
+       }
 }