// Byte 2
BasicMPP | Wumbo | AnchorsNonzeroFeeHtlcTx | AnchorsZeroFeeHtlcTx,
// Byte 3
- ShutdownAnySegwit,
+ ShutdownAnySegwit | Taproot,
// Byte 4
OnionMessages,
// Byte 5
// Byte 2
BasicMPP | Wumbo | AnchorsNonzeroFeeHtlcTx | AnchorsZeroFeeHtlcTx,
// Byte 3
- ShutdownAnySegwit,
+ ShutdownAnySegwit | Taproot,
// Byte 4
OnionMessages,
// Byte 5
// Byte 2
AnchorsNonzeroFeeHtlcTx | AnchorsZeroFeeHtlcTx,
// Byte 3
- ,
+ Taproot,
// Byte 4
,
// Byte 5
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,
}
/// Returns true if this `Features` object contains required features unknown by `other`.
- pub fn requires_unknown_bits_from(&self, other: &Features<T>) -> bool {
+ pub fn requires_unknown_bits_from(&self, other: &Self) -> 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)| {
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 {
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(());
}
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]