//! (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).
//!
//! LDK knows about the following features, but does not support them:
//! - `AnchorsNonzeroFeeHtlcTx` - the initial version of anchor outputs, which was later found to be
// Byte 2
BasicMPP | Wumbo | AnchorsNonzeroFeeHtlcTx | AnchorsZeroFeeHtlcTx,
// Byte 3
- ShutdownAnySegwit,
+ RouteBlinding | ShutdownAnySegwit | Taproot,
// Byte 4
OnionMessages,
// Byte 5
// Byte 2
BasicMPP | Wumbo | AnchorsNonzeroFeeHtlcTx | AnchorsZeroFeeHtlcTx,
// Byte 3
- ShutdownAnySegwit,
+ RouteBlinding | ShutdownAnySegwit | Taproot,
// Byte 4
OnionMessages,
// Byte 5
// Byte 2
AnchorsNonzeroFeeHtlcTx | AnchorsZeroFeeHtlcTx,
// Byte 3
- ,
+ Taproot,
// Byte 4
,
// Byte 5
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);
+ 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);
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,
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.
///
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(());
}
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();
// 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
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);
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]