Advance self blinded payment paths
[rust-lightning] / lightning / src / ln / features.rs
index d10c3a71927b254854fd11869f1d9cbaedf7cb35..51c608c1a6b47231762bbb35627032dcf33d19bc 100644 (file)
 //!     (see [BOLT-4](https://github.com/lightning/bolts/blob/master/04-onion-routing.md#basic-multi-part-payments) for more information).
 //! - `Wumbo` - requires/supports that a node create large channels. Called `option_support_large_channel` in the spec.
 //!     (see [BOLT-2](https://github.com/lightning/bolts/blob/master/02-peer-protocol.md#the-open_channel-message) 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).
+//! - `RouteBlinding` - requires/supports that a node can relay payments over blinded paths
+//!     (see [BOLT-4](https://github.com/lightning/bolts/blob/master/04-onion-routing.md#route-blinding) for more information).
 //! - `ShutdownAnySegwit` - requires/supports that future segwit versions are allowed in `shutdown`
 //!     (see [BOLT-2](https://github.com/lightning/bolts/blob/master/02-peer-protocol.md) for more information).
 //! - `OnionMessages` - requires/supports forwarding onion messages
 //!      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).
+//! - `Trampoline` - supports receiving and forwarding Trampoline payments
+//!     (see the [`Trampoline` feature proposal](https://github.com/lightning/bolts/pull/836) 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
 //! [BOLT #9]: https://github.com/lightning/bolts/blob/master/09-features.md
 //! [messages]: crate::ln::msgs
 
-use crate::{io, io_extras};
+#[allow(unused_imports)]
 use crate::prelude::*;
+
+use crate::{io, io_extras};
 use core::{cmp, fmt};
 use core::borrow::Borrow;
 use core::hash::{Hash, Hasher};
 use core::marker::PhantomData;
 
-use bitcoin::bech32;
-use bitcoin::bech32::{Base32Len, FromBase32, ToBase32, u5, WriteBase32};
+use bech32::{Base32Len, FromBase32, ToBase32, u5, WriteBase32};
 use crate::ln::msgs::DecodeError;
 use crate::util::ser::{Readable, WithoutLength, Writeable, Writer};
 
 mod sealed {
+       #[allow(unused_imports)]
        use crate::prelude::*;
        use crate::ln::features::Features;
 
@@ -143,13 +149,15 @@ mod sealed {
                // Byte 2
                BasicMPP | Wumbo | AnchorsNonzeroFeeHtlcTx | AnchorsZeroFeeHtlcTx,
                // Byte 3
-               ShutdownAnySegwit | Taproot,
+               RouteBlinding | ShutdownAnySegwit | Taproot,
                // Byte 4
                OnionMessages,
                // Byte 5
                ChannelType | SCIDPrivacy,
                // Byte 6
                ZeroConf,
+               // Byte 7
+               Trampoline,
        ]);
        define_context!(NodeContext, [
                // Byte 0
@@ -159,13 +167,15 @@ mod sealed {
                // Byte 2
                BasicMPP | Wumbo | AnchorsNonzeroFeeHtlcTx | AnchorsZeroFeeHtlcTx,
                // Byte 3
-               ShutdownAnySegwit | Taproot,
+               RouteBlinding | ShutdownAnySegwit | Taproot,
                // Byte 4
                OnionMessages,
                // Byte 5
                ChannelType | SCIDPrivacy,
                // Byte 6
                ZeroConf | Keysend,
+               // Byte 7
+               Trampoline,
        ]);
        define_context!(ChannelContext, []);
        define_context!(Bolt11InvoiceContext, [
@@ -183,6 +193,8 @@ mod sealed {
                ,
                // Byte 6
                PaymentMetadata,
+               // Byte 7
+               Trampoline,
        ]);
        define_context!(OfferContext, []);
        define_context!(InvoiceRequestContext, []);
@@ -391,6 +403,9 @@ mod sealed {
        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);
+       define_feature!(25, RouteBlinding, [InitContext, NodeContext],
+               "Feature flags for `option_route_blinding`.", set_route_blinding_optional,
+               set_route_blinding_required, supports_route_blinding, requires_route_blinding);
        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);
@@ -415,6 +430,9 @@ mod sealed {
        define_feature!(55, Keysend, [NodeContext],
                "Feature flags for keysend payments.", set_keysend_optional, set_keysend_required,
                supports_keysend, requires_keysend);
+       define_feature!(57, Trampoline, [InitContext, NodeContext, Bolt11InvoiceContext],
+               "Feature flags for Trampoline routing.", set_trampoline_routing_optional, set_trampoline_routing_required,
+               supports_trampoline_routing, requires_trampoline_routing);
        // Note: update the module-level docs when a new feature bit is added!
 
        #[cfg(test)]
@@ -424,6 +442,9 @@ mod sealed {
                set_unknown_feature_required, supports_unknown_test_feature, requires_unknown_test_feature);
 }
 
+const ANY_REQUIRED_FEATURES_MASK: u8 = 0b01_01_01_01;
+const ANY_OPTIONAL_FEATURES_MASK: u8 = 0b10_10_10_10;
+
 /// Tracks the set of features which a node implements, templated by the context in which it
 /// appears.
 ///
@@ -464,12 +485,24 @@ 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);
+               let mut nonzero_flags = &self.flags[..];
+               while nonzero_flags.last() == Some(&0) {
+                       nonzero_flags = &nonzero_flags[..nonzero_flags.len() - 1];
+               }
+               nonzero_flags.hash(hasher);
        }
 }
 impl<T: sealed::Context> PartialEq for Features<T> {
        fn eq(&self, o: &Self) -> bool {
-               self.flags.eq(&o.flags)
+               let mut o_iter = o.flags.iter();
+               let mut self_iter = self.flags.iter();
+               loop {
+                       match (o_iter.next(), self_iter.next()) {
+                               (Some(o), Some(us)) => if o != us { return false },
+                               (Some(b), None) | (None, Some(b)) => if *b != 0 { return false },
+                               (None, None) => return true,
+                       }
+               }
        }
 }
 impl<T: sealed::Context> PartialOrd for Features<T> {
@@ -585,8 +618,8 @@ impl ChannelTypeFeatures {
                // 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;
+                       *byte |= (*byte & ANY_OPTIONAL_FEATURES_MASK) >> 1;
+                       *byte &= ANY_REQUIRED_FEATURES_MASK;
                }
                ret
        }
@@ -731,7 +764,7 @@ impl<T: sealed::Context> Features<T> {
        }
 
        pub(crate) fn supports_any_optional_bits(&self) -> bool {
-               self.flags.iter().any(|&byte| (byte & 0b10_10_10_10) != 0)
+               self.flags.iter().any(|&byte| (byte & ANY_OPTIONAL_FEATURES_MASK) != 0)
        }
 
        /// Returns true if this `Features` object contains required features unknown by `other`.
@@ -739,20 +772,30 @@ impl<T: sealed::Context> Features<T> {
                // 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
+                       let unknown_features = unset_features_mask_at_position(other, i);
+                       (byte & (ANY_REQUIRED_FEATURES_MASK & unknown_features)) != 0
                })
        }
 
+       pub(crate) fn required_unknown_bits_from(&self, other: &Self) -> Vec<usize> {
+               let mut unknown_bits = Vec::new();
+
+               // Bitwise AND-ing with all even bits set except for known features will select required
+               // unknown features.
+               self.flags.iter().enumerate().for_each(|(i, &byte)| {
+                       let unknown_features = unset_features_mask_at_position(other, i);
+                       if byte & unknown_features != 0 {
+                               for bit in (0..8).step_by(2) {
+                                       if ((byte & unknown_features) >> bit) & 1 == 1 {
+                                               unknown_bits.push(i * 8 + bit);
+                                       }
+                               }
+                       }
+               });
+
+               unknown_bits
+       }
+
        /// Returns true if this `Features` object contains unknown feature flags which are set as
        /// "required".
        pub fn requires_unknown_bits(&self) -> bool {
@@ -760,13 +803,12 @@ impl<T: sealed::Context> Features<T> {
                // 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
+                       (byte & (ANY_REQUIRED_FEATURES_MASK & unknown_features)) != 0
                })
        }
 
@@ -915,6 +957,13 @@ impl<T: sealed::AnchorsZeroFeeHtlcTx> Features<T> {
        }
 }
 
+impl<T: sealed::RouteBlinding> Features<T> {
+       #[cfg(test)]
+       pub(crate) fn clear_route_blinding(&mut self) {
+               <T as sealed::RouteBlinding>::clear_bits(&mut self.flags);
+       }
+}
+
 #[cfg(test)]
 impl<T: sealed::UnknownFeature> Features<T> {
        pub(crate) fn unknown() -> Self {
@@ -980,10 +1029,21 @@ impl<T: sealed::Context> Readable for WithoutLength<Features<T>> {
        }
 }
 
+pub(crate) fn unset_features_mask_at_position<T: sealed::Context>(other: &Features<T>, index: usize) -> u8 {
+       if index < other.flags.len() {
+               // Form a mask similar to !T::KNOWN_FEATURE_MASK only for `other`
+               !(other.flags[index]
+                       | ((other.flags[index] >> 1) & ANY_REQUIRED_FEATURES_MASK)
+                       | ((other.flags[index] << 1) & ANY_OPTIONAL_FEATURES_MASK))
+       } else {
+               0b11_11_11_11
+       }
+}
+
 #[cfg(test)]
 mod tests {
        use super::{ChannelFeatures, ChannelTypeFeatures, InitFeatures, Bolt11InvoiceFeatures, NodeFeatures, OfferFeatures, sealed};
-       use bitcoin::bech32::{Base32Len, FromBase32, ToBase32, u5};
+       use bech32::{Base32Len, FromBase32, ToBase32, u5};
        use crate::util::ser::{Readable, WithoutLength, Writeable};
 
        #[test]
@@ -996,11 +1056,24 @@ mod tests {
                features.set_unknown_feature_required();
                assert!(features.requires_unknown_bits());
                assert!(features.supports_unknown_bits());
+               assert_eq!(features.required_unknown_bits_from(&ChannelFeatures::empty()), vec![123456788]);
 
                let mut features = ChannelFeatures::empty();
                features.set_unknown_feature_optional();
                assert!(!features.requires_unknown_bits());
                assert!(features.supports_unknown_bits());
+               assert_eq!(features.required_unknown_bits_from(&ChannelFeatures::empty()), vec![]);
+
+               let mut features = ChannelFeatures::empty();
+               features.set_unknown_feature_required();
+               features.set_custom_bit(123456786).unwrap();
+               assert!(features.requires_unknown_bits());
+               assert!(features.supports_unknown_bits());
+               assert_eq!(features.required_unknown_bits_from(&ChannelFeatures::empty()), vec![123456786, 123456788]);
+
+               let mut limiter = ChannelFeatures::empty();
+               limiter.set_unknown_feature_optional();
+               assert_eq!(features.required_unknown_bits_from(&limiter), vec![123456786]);
        }
 
        #[test]
@@ -1053,6 +1126,7 @@ mod tests {
                init_features.set_basic_mpp_optional();
                init_features.set_wumbo_optional();
                init_features.set_anchors_zero_fee_htlc_tx_optional();
+               init_features.set_route_blinding_optional();
                init_features.set_shutdown_any_segwit_optional();
                init_features.set_onion_messages_optional();
                init_features.set_channel_type_optional();
@@ -1068,8 +1142,8 @@ mod tests {
                        // Check that the flags are as expected:
                        // - option_data_loss_protect (req)
                        // - var_onion_optin (req) | static_remote_key (req) | payment_secret(req)
-                       // - basic_mpp | wumbo | anchors_zero_fee_htlc_tx
-                       // - opt_shutdown_anysegwit
+                       // - basic_mpp | wumbo | option_anchors_zero_fee_htlc_tx
+                       // - option_route_blinding | opt_shutdown_anysegwit
                        // - onion_messages
                        // - option_channel_type | option_scid_alias
                        // - option_zeroconf
@@ -1077,7 +1151,7 @@ mod tests {
                        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);
+                       assert_eq!(node_features.flags[3], 0b00001010);
                        assert_eq!(node_features.flags[4], 0b10000000);
                        assert_eq!(node_features.flags[5], 0b10100000);
                        assert_eq!(node_features.flags[6], 0b00001000);
@@ -1209,4 +1283,26 @@ mod tests {
                assert!(!converted_features.supports_any_optional_bits());
                assert!(converted_features.requires_static_remote_key());
        }
+
+       #[test]
+       #[cfg(feature = "std")]
+       fn test_excess_zero_bytes_ignored() {
+               // Checks that `Hash` and `PartialEq` ignore excess zero bytes, which may appear due to
+               // feature conversion or because a peer serialized their feature poorly.
+               use std::collections::hash_map::DefaultHasher;
+               use std::hash::{Hash, Hasher};
+
+               let mut zerod_features = InitFeatures::empty();
+               zerod_features.flags = vec![0];
+               let empty_features = InitFeatures::empty();
+               assert!(empty_features.flags.is_empty());
+
+               assert_eq!(zerod_features, empty_features);
+
+               let mut zerod_hash = DefaultHasher::new();
+               zerod_features.hash(&mut zerod_hash);
+               let mut empty_hash = DefaultHasher::new();
+               empty_features.hash(&mut empty_hash);
+               assert_eq!(zerod_hash.finish(), empty_hash.finish());
+       }
 }