Cache the total points tracked in our historical liquidity data
[rust-lightning] / lightning / src / ln / features.rs
index 5de383b1f4469273207441892a90d1d2c063494d..28710c343649e813f5e9581f9fad5fa618c4430b 100644 (file)
@@ -143,7 +143,7 @@ mod sealed {
                // Byte 2
                BasicMPP | Wumbo | AnchorsNonzeroFeeHtlcTx | AnchorsZeroFeeHtlcTx,
                // Byte 3
-               ShutdownAnySegwit,
+               ShutdownAnySegwit | Taproot,
                // Byte 4
                OnionMessages,
                // Byte 5
@@ -159,7 +159,7 @@ mod sealed {
                // Byte 2
                BasicMPP | Wumbo | AnchorsNonzeroFeeHtlcTx | AnchorsZeroFeeHtlcTx,
                // Byte 3
-               ShutdownAnySegwit,
+               ShutdownAnySegwit | Taproot,
                // Byte 4
                OnionMessages,
                // Byte 5
@@ -205,7 +205,7 @@ mod sealed {
                // Byte 2
                AnchorsNonzeroFeeHtlcTx | AnchorsZeroFeeHtlcTx,
                // Byte 3
-               ,
+               Taproot,
                // Byte 4
                ,
                // Byte 5
@@ -394,6 +394,9 @@ mod sealed {
        define_feature!(27, ShutdownAnySegwit, [InitContext, NodeContext],
                "Feature flags for `opt_shutdown_anysegwit`.", set_shutdown_any_segwit_optional,
                set_shutdown_any_segwit_required, supports_shutdown_anysegwit, requires_shutdown_anysegwit);
+       define_feature!(31, Taproot, [InitContext, NodeContext, ChannelTypeContext],
+               "Feature flags for `option_taproot`.", set_taproot_optional,
+               set_taproot_required, supports_taproot, requires_taproot);
        define_feature!(39, OnionMessages, [InitContext, NodeContext],
                "Feature flags for `option_onion_messages`.", set_onion_messages_optional,
                set_onion_messages_required, supports_onion_messages, requires_onion_messages);
@@ -715,7 +718,11 @@ impl<T: sealed::Context> Features<T> {
                Ok(())
        }
 
-       fn from_be_bytes(mut flags: Vec<u8>) -> Features<T> {
+       /// Create a [`Features`] given a set of flags, in big-endian. This is in byte order from
+       /// most on-the-wire encodings.
+       ///
+       /// This is not exported to bindings users as we don't support export across multiple T
+       pub fn from_be_bytes(mut flags: Vec<u8>) -> Features<T> {
                flags.reverse(); // Swap to little-endian
                Self {
                        flags,
@@ -751,16 +758,23 @@ impl<T: sealed::Context> Features<T> {
        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();
-               self.flags.iter().enumerate().any(|(i, &byte)| {
-                       let required_features = 0b01_01_01_01;
-                       let unknown_features = if i < byte_count {
-                               !T::KNOWN_FEATURE_MASK[i]
-                       } else {
-                               0b11_11_11_11
-                       };
-                       (byte & (required_features & unknown_features)) != 0
-               })
+               let mut known_chunks = T::KNOWN_FEATURE_MASK.chunks(8);
+               for chunk in self.flags.chunks(8) {
+                       let mut flag_bytes = [0; 8];
+                       flag_bytes[..chunk.len()].copy_from_slice(&chunk);
+                       let flag_int = u64::from_le_bytes(flag_bytes);
+
+                       let known_chunk = known_chunks.next().unwrap_or(&[0; 0]);
+                       let mut known_bytes = [0; 8];
+                       known_bytes[..known_chunk.len()].copy_from_slice(&known_chunk);
+                       let known_int = u64::from_le_bytes(known_bytes);
+
+                       const REQ_MASK: u64 = 0x55555555_55555555;
+                       if flag_int & (REQ_MASK & !known_int) != 0 {
+                               return true;
+                       }
+               }
+               false
        }
 
        pub(crate) fn supports_unknown_bits(&self) -> bool {
@@ -795,6 +809,35 @@ impl<T: sealed::Context> Features<T> {
                true
        }
 
+       /// Sets a required feature bit. Errors if `bit` is outside the feature range as defined
+       /// by [BOLT 9].
+       ///
+       /// Note: Required bits are even. If an odd bit is given, then the corresponding even bit will
+       /// be set instead (i.e., `bit - 1`).
+       ///
+       /// [BOLT 9]: https://github.com/lightning/bolts/blob/master/09-features.md
+       pub fn set_required_feature_bit(&mut self, bit: usize) -> Result<(), ()> {
+               self.set_feature_bit(bit - (bit % 2))
+       }
+
+       /// Sets an optional feature bit. Errors if `bit` is outside the feature range as defined
+       /// by [BOLT 9].
+       ///
+       /// Note: Optional bits are odd. If an even bit is given, then the corresponding odd bit will be
+       /// set instead (i.e., `bit + 1`).
+       ///
+       /// [BOLT 9]: https://github.com/lightning/bolts/blob/master/09-features.md
+       pub fn set_optional_feature_bit(&mut self, bit: usize) -> Result<(), ()> {
+               self.set_feature_bit(bit + (1 - (bit % 2)))
+       }
+
+       fn set_feature_bit(&mut self, bit: usize) -> Result<(), ()> {
+               if bit > 255 {
+                       return Err(());
+               }
+               self.set_bit(bit, false)
+       }
+
        /// 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.
        ///
@@ -821,10 +864,13 @@ impl<T: sealed::Context> Features<T> {
                if bit < 256 {
                        return Err(());
                }
+               self.set_bit(bit, true)
+       }
 
+       fn set_bit(&mut self, bit: usize, custom: bool) -> Result<(), ()> {
                let byte_offset = bit / 8;
                let mask = 1 << (bit - 8 * byte_offset);
-               if byte_offset < T::KNOWN_FEATURE_MASK.len() {
+               if byte_offset < T::KNOWN_FEATURE_MASK.len() && custom {
                        if (T::KNOWN_FEATURE_MASK[byte_offset] & mask) != 0 {
                                return Err(());
                        }
@@ -1075,6 +1121,13 @@ mod tests {
                assert!(!features.requires_basic_mpp());
                assert!(features.requires_payment_secret());
                assert!(features.supports_payment_secret());
+
+               // Set flags manually
+               let mut features = NodeFeatures::empty();
+               assert!(features.set_optional_feature_bit(55).is_ok());
+               assert!(features.supports_keysend());
+               assert!(features.set_optional_feature_bit(255).is_ok());
+               assert!(features.set_required_feature_bit(256).is_err());
        }
 
        #[test]