Merge pull request #2396 from tnull/2023-07-fix-github-actions
[rust-lightning] / lightning / src / ln / features.rs
index 82242c71d059600eb82c5ace9cd2ccb7fb012ea3..ca6ea70b61da7312de22b1e28749a51cb3f28941 100644 (file)
 //!     (see [BOLT-2](https://github.com/lightning/bolts/blob/master/02-peer-protocol.md) for more information).
 //! - `OnionMessages` - requires/supports forwarding onion messages
 //!     (see [BOLT-7](https://github.com/lightning/bolts/pull/759/files) for more information).
-//!     TODO: update link
+//     TODO: update link
 //! - `ChannelType` - node supports the channel_type field in open/accept
 //!     (see [BOLT-2](https://github.com/lightning/bolts/blob/master/02-peer-protocol.md) for more information).
 //! - `SCIDPrivacy` - supply channel aliases for routing
 //!     (see [BOLT-2](https://github.com/lightning/bolts/blob/master/02-peer-protocol.md) for more information).
+//! - `PaymentMetadata` - include additional data in invoices which is passed to recipients in the
+//!      onion.
+//!      (see [BOLT-11](https://github.com/lightning/bolts/blob/master/11-payment-encoding.md) for
+//!      more).
+//! - `ZeroConf` - supports accepting HTLCs and using channels prior to funding confirmation
+//!      (see
+//!      [BOLT-2](https://github.com/lightning/bolts/blob/master/02-peer-protocol.md#the-channel_ready-message)
+//!      for more info).
 //! - `Keysend` - send funds to a node without an invoice
 //!     (see the [`Keysend` feature assignment proposal](https://github.com/lightning/bolts/issues/605#issuecomment-606679798) for more information).
 //! - `AnchorsZeroFeeHtlcTx` - requires/supports that commitment transactions include anchor outputs
-//!   and HTLC transactions are pre-signed with zero fee (see
-//!   [BOLT-3](https://github.com/lightning/bolts/blob/master/03-transactions.md) for more
-//!   information).
+//!     and HTLC transactions are pre-signed with zero fee (see
+//!     [BOLT-3](https://github.com/lightning/bolts/blob/master/03-transactions.md) for more
+//!     information).
+//!
+//! LDK knows about the following features, but does not support them:
+//! - `AnchorsNonzeroFeeHtlcTx` - the initial version of anchor outputs, which was later found to be
+//!     vulnerable (see this
+//!     [mailing list post](https://lists.linuxfoundation.org/pipermail/lightning-dev/2020-September/002796.html)
+//!     for more information).
 //!
 //! [BOLT #9]: https://github.com/lightning/bolts/blob/master/09-features.md
 //! [messages]: crate::ln::msgs
@@ -63,6 +77,7 @@
 use crate::{io, io_extras};
 use crate::prelude::*;
 use core::{cmp, fmt};
+use core::borrow::Borrow;
 use core::hash::{Hash, Hasher};
 use core::marker::PhantomData;
 
@@ -126,7 +141,7 @@ mod sealed {
                // Byte 1
                VariableLengthOnion | StaticRemoteKey | PaymentSecret,
                // Byte 2
-               BasicMPP | Wumbo | AnchorsZeroFeeHtlcTx,
+               BasicMPP | Wumbo | AnchorsNonzeroFeeHtlcTx | AnchorsZeroFeeHtlcTx,
                // Byte 3
                ShutdownAnySegwit,
                // Byte 4
@@ -142,7 +157,7 @@ mod sealed {
                // Byte 1
                VariableLengthOnion | StaticRemoteKey | PaymentSecret,
                // Byte 2
-               BasicMPP | Wumbo | AnchorsZeroFeeHtlcTx,
+               BasicMPP | Wumbo | AnchorsNonzeroFeeHtlcTx | AnchorsZeroFeeHtlcTx,
                // Byte 3
                ShutdownAnySegwit,
                // Byte 4
@@ -188,7 +203,7 @@ mod sealed {
                // Byte 1
                StaticRemoteKey,
                // Byte 2
-               AnchorsZeroFeeHtlcTx,
+               AnchorsNonzeroFeeHtlcTx | AnchorsZeroFeeHtlcTx,
                // Byte 3
                ,
                // Byte 4
@@ -267,6 +282,7 @@ mod sealed {
                                        }
 
                                        flags[Self::BYTE_OFFSET] |= Self::REQUIRED_MASK;
+                                       flags[Self::BYTE_OFFSET] &= !Self::OPTIONAL_MASK;
                                }
 
                                /// Sets the feature's optional (odd) bit in the given flags.
@@ -369,6 +385,9 @@ mod sealed {
        define_feature!(19, Wumbo, [InitContext, NodeContext],
                "Feature flags for `option_support_large_channel` (aka wumbo channels).", set_wumbo_optional, set_wumbo_required,
                supports_wumbo, requires_wumbo);
+       define_feature!(21, AnchorsNonzeroFeeHtlcTx, [InitContext, NodeContext, ChannelTypeContext],
+               "Feature flags for `option_anchors_nonzero_fee_htlc_tx`.", set_anchors_nonzero_fee_htlc_tx_optional,
+               set_anchors_nonzero_fee_htlc_tx_required, supports_anchors_nonzero_fee_htlc_tx, requires_anchors_nonzero_fee_htlc_tx);
        define_feature!(23, AnchorsZeroFeeHtlcTx, [InitContext, NodeContext, ChannelTypeContext],
                "Feature flags for `option_anchors_zero_fee_htlc_tx`.", set_anchors_zero_fee_htlc_tx_optional,
                set_anchors_zero_fee_htlc_tx_required, supports_anchors_zero_fee_htlc_tx, requires_anchors_zero_fee_htlc_tx);
@@ -393,6 +412,7 @@ mod sealed {
        define_feature!(55, Keysend, [NodeContext],
                "Feature flags for keysend payments.", set_keysend_optional, set_keysend_required,
                supports_keysend, requires_keysend);
+       // Note: update the module-level docs when a new feature bit is added!
 
        #[cfg(test)]
        define_feature!(123456789, UnknownFeature,
@@ -412,13 +432,21 @@ pub struct Features<T: sealed::Context> {
        mark: PhantomData<T>,
 }
 
-impl <T: sealed::Context> Features<T> {
-       pub(crate) fn or(mut self, o: Self) -> Self {
-               let total_feature_len = cmp::max(self.flags.len(), o.flags.len());
+impl<T: sealed::Context, Rhs: Borrow<Self>> core::ops::BitOrAssign<Rhs> for Features<T> {
+       fn bitor_assign(&mut self, rhs: Rhs) {
+               let total_feature_len = cmp::max(self.flags.len(), rhs.borrow().flags.len());
                self.flags.resize(total_feature_len, 0u8);
-               for (byte, o_byte) in self.flags.iter_mut().zip(o.flags.iter()) {
-                       *byte |= *o_byte;
+               for (byte, rhs_byte) in self.flags.iter_mut().zip(rhs.borrow().flags.iter()) {
+                       *byte |= *rhs_byte;
                }
+       }
+}
+
+impl<T: sealed::Context> core::ops::BitOr for Features<T> {
+       type Output = Self;
+
+       fn bitor(mut self, o: Self) -> Self {
+               self |= o;
                self
        }
 }
@@ -441,6 +469,16 @@ impl<T: sealed::Context> PartialEq for Features<T> {
                self.flags.eq(&o.flags)
        }
 }
+impl<T: sealed::Context> PartialOrd for Features<T> {
+       fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
+               self.flags.partial_cmp(&other.flags)
+       }
+}
+impl<T: sealed::Context + Eq> Ord for Features<T> {
+       fn cmp(&self, other: &Self) -> cmp::Ordering {
+               self.flags.cmp(&other.flags)
+       }
+}
 impl<T: sealed::Context> fmt::Debug for Features<T> {
        fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
                self.flags.fmt(fmt)
@@ -513,15 +551,29 @@ impl InvoiceFeatures {
        /// [`PaymentParameters::for_keysend`], thus omitting the need for payers to manually construct an
        /// `InvoiceFeatures` for [`find_route`].
        ///
+       /// MPP keysend is not widely supported yet, so we parameterize support to allow the user to
+       /// choose whether their router should find multi-part routes.
+       ///
        /// [`PaymentParameters::for_keysend`]: crate::routing::router::PaymentParameters::for_keysend
        /// [`find_route`]: crate::routing::router::find_route
-       pub(crate) fn for_keysend() -> InvoiceFeatures {
+       pub(crate) fn for_keysend(allow_mpp: bool) -> InvoiceFeatures {
                let mut res = InvoiceFeatures::empty();
                res.set_variable_length_onion_optional();
+               if allow_mpp {
+                       res.set_basic_mpp_optional();
+               }
                res
        }
 }
 
+impl Bolt12InvoiceFeatures {
+       /// Converts `Bolt12InvoiceFeatures` to `Features<C>`. Only known `Bolt12InvoiceFeatures` relevant
+       /// to context `C` are included in the result.
+       pub(crate) fn to_context<C: sealed::Context>(&self) -> Features<C> {
+               self.to_context_internal()
+       }
+}
+
 impl ChannelTypeFeatures {
        // Maps the relevant `InitFeatures` to `ChannelTypeFeatures`. Any unknown features to
        // `ChannelTypeFeatures` are not included in the result.
@@ -542,6 +594,14 @@ impl ChannelTypeFeatures {
                <sealed::ChannelTypeContext as sealed::StaticRemoteKey>::set_required_bit(&mut ret.flags);
                ret
        }
+
+       /// Constructs a ChannelTypeFeatures with anchors support
+       pub(crate) fn anchors_zero_htlc_fee_and_dependencies() -> Self {
+               let mut ret = Self::empty();
+               <sealed::ChannelTypeContext as sealed::StaticRemoteKey>::set_required_bit(&mut ret.flags);
+               <sealed::ChannelTypeContext as sealed::AnchorsZeroFeeHtlcTx>::set_required_bit(&mut ret.flags);
+               ret
+       }
 }
 
 impl ToBase32 for InvoiceFeatures {
@@ -667,6 +727,25 @@ impl<T: sealed::Context> Features<T> {
                self.flags.iter().any(|&byte| (byte & 0b10_10_10_10) != 0)
        }
 
+       /// Returns true if this `Features` object contains required features unknown by `other`.
+       pub fn requires_unknown_bits_from(&self, other: &Features<T>) -> bool {
+               // Bitwise AND-ing with all even bits set except for known features will select required
+               // unknown features.
+               self.flags.iter().enumerate().any(|(i, &byte)| {
+                       const REQUIRED_FEATURES: u8 = 0b01_01_01_01;
+                       const OPTIONAL_FEATURES: u8 = 0b10_10_10_10;
+                       let unknown_features = if i < other.flags.len() {
+                               // Form a mask similar to !T::KNOWN_FEATURE_MASK only for `other`
+                               !(other.flags[i]
+                                       | ((other.flags[i] >> 1) & REQUIRED_FEATURES)
+                                       | ((other.flags[i] << 1) & OPTIONAL_FEATURES))
+                       } else {
+                               0b11_11_11_11
+                       };
+                       (byte & (REQUIRED_FEATURES & unknown_features)) != 0
+               })
+       }
+
        /// Returns true if this `Features` object contains unknown feature flags which are set as
        /// "required".
        pub fn requires_unknown_bits(&self) -> bool {
@@ -715,6 +794,50 @@ impl<T: sealed::Context> Features<T> {
                }
                true
        }
+
+       /// Sets a required custom feature bit. Errors if `bit` is outside the custom range as defined
+       /// by [bLIP 2] or if it is a known `T` feature.
+       ///
+       /// Note: Required bits are even. If an odd bit is given, then the corresponding even bit will
+       /// be set instead (i.e., `bit - 1`).
+       ///
+       /// [bLIP 2]: https://github.com/lightning/blips/blob/master/blip-0002.md#feature-bits
+       pub fn set_required_custom_bit(&mut self, bit: usize) -> Result<(), ()> {
+               self.set_custom_bit(bit - (bit % 2))
+       }
+
+       /// Sets an optional custom feature bit. Errors if `bit` is outside the custom range as defined
+       /// by [bLIP 2] or if it is a known `T` feature.
+       ///
+       /// Note: Optional bits are odd. If an even bit is given, then the corresponding odd bit will be
+       /// set instead (i.e., `bit + 1`).
+       ///
+       /// [bLIP 2]: https://github.com/lightning/blips/blob/master/blip-0002.md#feature-bits
+       pub fn set_optional_custom_bit(&mut self, bit: usize) -> Result<(), ()> {
+               self.set_custom_bit(bit + (1 - (bit % 2)))
+       }
+
+       fn set_custom_bit(&mut self, bit: usize) -> Result<(), ()> {
+               if bit < 256 {
+                       return Err(());
+               }
+
+               let byte_offset = bit / 8;
+               let mask = 1 << (bit - 8 * byte_offset);
+               if byte_offset < T::KNOWN_FEATURE_MASK.len() {
+                       if (T::KNOWN_FEATURE_MASK[byte_offset] & mask) != 0 {
+                               return Err(());
+                       }
+               }
+
+               if self.flags.len() <= byte_offset {
+                       self.flags.resize(byte_offset + 1, 0u8);
+               }
+
+               self.flags[byte_offset] |= mask;
+
+               Ok(())
+       }
 }
 
 impl<T: sealed::UpfrontShutdownScript> Features<T> {
@@ -781,6 +904,7 @@ impl_feature_len_prefixed_write!(InitFeatures);
 impl_feature_len_prefixed_write!(ChannelFeatures);
 impl_feature_len_prefixed_write!(NodeFeatures);
 impl_feature_len_prefixed_write!(InvoiceFeatures);
+impl_feature_len_prefixed_write!(Bolt12InvoiceFeatures);
 impl_feature_len_prefixed_write!(BlindedHopFeatures);
 
 // Some features only appear inside of TLVs, so they don't have a length prefix when serialized.
@@ -840,24 +964,61 @@ mod tests {
                assert!(features.supports_unknown_bits());
        }
 
+       #[test]
+       fn requires_unknown_bits_from() {
+               let mut features1 = InitFeatures::empty();
+               let mut features2 = InitFeatures::empty();
+               assert!(!features1.requires_unknown_bits_from(&features2));
+               assert!(!features2.requires_unknown_bits_from(&features1));
+
+               features1.set_data_loss_protect_required();
+               assert!(features1.requires_unknown_bits_from(&features2));
+               assert!(!features2.requires_unknown_bits_from(&features1));
+
+               features2.set_data_loss_protect_optional();
+               assert!(!features1.requires_unknown_bits_from(&features2));
+               assert!(!features2.requires_unknown_bits_from(&features1));
+
+               features2.set_gossip_queries_required();
+               assert!(!features1.requires_unknown_bits_from(&features2));
+               assert!(features2.requires_unknown_bits_from(&features1));
+
+               features1.set_gossip_queries_optional();
+               assert!(!features1.requires_unknown_bits_from(&features2));
+               assert!(!features2.requires_unknown_bits_from(&features1));
+
+               features1.set_variable_length_onion_required();
+               assert!(features1.requires_unknown_bits_from(&features2));
+               assert!(!features2.requires_unknown_bits_from(&features1));
+
+               features2.set_variable_length_onion_optional();
+               assert!(!features1.requires_unknown_bits_from(&features2));
+               assert!(!features2.requires_unknown_bits_from(&features1));
+
+               features1.set_basic_mpp_required();
+               features2.set_wumbo_required();
+               assert!(features1.requires_unknown_bits_from(&features2));
+               assert!(features2.requires_unknown_bits_from(&features1));
+       }
+
        #[test]
        fn convert_to_context_with_relevant_flags() {
                let mut init_features = InitFeatures::empty();
                // Set a bunch of features we use, plus initial_routing_sync_required (which shouldn't get
                // converted as it's only relevant in an init context).
                init_features.set_initial_routing_sync_required();
-               init_features.set_data_loss_protect_optional();
+               init_features.set_data_loss_protect_required();
                init_features.set_variable_length_onion_required();
                init_features.set_static_remote_key_required();
                init_features.set_payment_secret_required();
                init_features.set_basic_mpp_optional();
                init_features.set_wumbo_optional();
+               init_features.set_anchors_zero_fee_htlc_tx_optional();
                init_features.set_shutdown_any_segwit_optional();
                init_features.set_onion_messages_optional();
                init_features.set_channel_type_optional();
                init_features.set_scid_privacy_optional();
                init_features.set_zero_conf_optional();
-               init_features.set_anchors_zero_fee_htlc_tx_optional();
 
                assert!(init_features.initial_routing_sync());
                assert!(!init_features.supports_upfront_shutdown_script());
@@ -866,15 +1027,15 @@ mod tests {
                let node_features: NodeFeatures = init_features.to_context();
                {
                        // Check that the flags are as expected:
-                       // - option_data_loss_protect
+                       // - option_data_loss_protect (req)
                        // - var_onion_optin (req) | static_remote_key (req) | payment_secret(req)
-                       // - basic_mpp | wumbo
+                       // - basic_mpp | wumbo | anchors_zero_fee_htlc_tx
                        // - opt_shutdown_anysegwit
                        // - onion_messages
                        // - option_channel_type | option_scid_alias
                        // - option_zeroconf
                        assert_eq!(node_features.flags.len(), 7);
-                       assert_eq!(node_features.flags[0], 0b00000010);
+                       assert_eq!(node_features.flags[0], 0b00000001);
                        assert_eq!(node_features.flags[1], 0b01010001);
                        assert_eq!(node_features.flags[2], 0b10001010);
                        assert_eq!(node_features.flags[3], 0b00001000);
@@ -916,6 +1077,36 @@ mod tests {
                assert!(features.supports_payment_secret());
        }
 
+       #[test]
+       fn set_custom_bits() {
+               let mut features = InvoiceFeatures::empty();
+               features.set_variable_length_onion_optional();
+               assert_eq!(features.flags[1], 0b00000010);
+
+               assert!(features.set_optional_custom_bit(255).is_err());
+               assert!(features.set_required_custom_bit(256).is_ok());
+               assert!(features.set_required_custom_bit(258).is_ok());
+               assert_eq!(features.flags[31], 0b00000000);
+               assert_eq!(features.flags[32], 0b00000101);
+
+               let known_bit = <sealed::InvoiceContext as sealed::PaymentSecret>::EVEN_BIT;
+               let byte_offset = <sealed::InvoiceContext as sealed::PaymentSecret>::BYTE_OFFSET;
+               assert_eq!(byte_offset, 1);
+               assert_eq!(features.flags[byte_offset], 0b00000010);
+               assert!(features.set_required_custom_bit(known_bit).is_err());
+               assert_eq!(features.flags[byte_offset], 0b00000010);
+
+               let mut features = InvoiceFeatures::empty();
+               assert!(features.set_optional_custom_bit(256).is_ok());
+               assert!(features.set_optional_custom_bit(259).is_ok());
+               assert_eq!(features.flags[32], 0b00001010);
+
+               let mut features = InvoiceFeatures::empty();
+               assert!(features.set_required_custom_bit(257).is_ok());
+               assert!(features.set_required_custom_bit(258).is_ok());
+               assert_eq!(features.flags[32], 0b00000101);
+       }
+
        #[test]
        fn encodes_features_without_length() {
                let features = OfferFeatures::from_le_bytes(vec![1, 2, 3, 4, 5, 42, 100, 101]);