1 //! Lightning exposes sets of supported operations through "feature flags". This module includes
2 //! types to store those feature flags and query for specific flags.
5 use std::result::Result;
6 use std::marker::PhantomData;
8 use ln::msgs::DecodeError;
9 use util::ser::{Readable, Writeable, Writer};
11 mod sealed { // You should just use the type aliases instead.
12 pub struct InitContext {}
13 pub struct NodeContext {}
14 pub struct ChannelContext {}
16 /// An internal trait capturing the various feature context types
18 impl Context for InitContext {}
19 impl Context for NodeContext {}
20 impl Context for ChannelContext {}
22 pub trait DataLossProtect: Context {}
23 impl DataLossProtect for InitContext {}
24 impl DataLossProtect for NodeContext {}
26 pub trait InitialRoutingSync: Context {}
27 impl InitialRoutingSync for InitContext {}
29 pub trait UpfrontShutdownScript: Context {}
30 impl UpfrontShutdownScript for InitContext {}
31 impl UpfrontShutdownScript for NodeContext {}
33 pub trait VariableLengthOnion: Context {}
34 impl VariableLengthOnion for InitContext {}
35 impl VariableLengthOnion for NodeContext {}
37 pub trait PaymentSecret: Context {}
38 impl PaymentSecret for InitContext {}
39 impl PaymentSecret for NodeContext {}
41 pub trait BasicMPP: Context {}
42 impl BasicMPP for InitContext {}
43 impl BasicMPP for NodeContext {}
46 /// Tracks the set of features which a node implements, templated by the context in which it
48 pub struct Features<T: sealed::Context> {
49 /// Note that, for convinience, flags is LITTLE endian (despite being big-endian on the wire)
54 impl<T: sealed::Context> Clone for Features<T> {
55 fn clone(&self) -> Self {
57 flags: self.flags.clone(),
62 impl<T: sealed::Context> PartialEq for Features<T> {
63 fn eq(&self, o: &Self) -> bool {
64 self.flags.eq(&o.flags)
67 impl<T: sealed::Context> fmt::Debug for Features<T> {
68 fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
73 /// A feature message as it appears in an init message
74 pub type InitFeatures = Features<sealed::InitContext>;
75 /// A feature message as it appears in a node_announcement message
76 pub type NodeFeatures = Features<sealed::NodeContext>;
77 /// A feature message as it appears in a channel_announcement message
78 pub type ChannelFeatures = Features<sealed::ChannelContext>;
81 /// Create a Features with the features we support
82 pub fn supported() -> InitFeatures {
84 flags: vec![2 | 1 << 3 | 1 << 5, 1 << (9-8) | 1 << (15 - 8), 1 << (17 - 8*2)],
89 /// Writes all features present up to, and including, 13.
90 pub(crate) fn write_up_to_13<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
91 let len = cmp::min(2, self.flags.len());
93 (len as u16).write(w)?;
94 for i in (0..len).rev() {
96 self.flags[i].write(w)?;
98 // On byte 1, we want up-to-and-including-bit-13, 0-indexed, which is
99 // up-to-and-including-bit-5, 0-indexed, on this byte:
100 (self.flags[i] & 0b00_11_11_11).write(w)?;
106 /// or's another InitFeatures into this one.
107 pub(crate) fn or(mut self, o: InitFeatures) -> InitFeatures {
108 let total_feature_len = cmp::max(self.flags.len(), o.flags.len());
109 self.flags.resize(total_feature_len, 0u8);
110 for (byte, o_byte) in self.flags.iter_mut().zip(o.flags.iter()) {
117 impl ChannelFeatures {
118 /// Create a Features with the features we support
119 #[cfg(not(feature = "fuzztarget"))]
120 pub(crate) fn supported() -> ChannelFeatures {
126 #[cfg(feature = "fuzztarget")]
127 pub fn supported() -> ChannelFeatures {
134 /// Takes the flags that we know how to interpret in an init-context features that are also
135 /// relevant in a channel-context features and creates a channel-context features from them.
136 pub(crate) fn with_known_relevant_init_flags(_init_ctx: &InitFeatures) -> Self {
137 // There are currently no channel flags defined that we understand.
138 Self { flags: Vec::new(), mark: PhantomData, }
143 /// Create a Features with the features we support
144 #[cfg(not(feature = "fuzztarget"))]
145 pub(crate) fn supported() -> NodeFeatures {
147 flags: vec![2 | 1 << 5, 1 << (9 - 8) | 1 << (15 - 8), 1 << (17 - 8*2)],
151 #[cfg(feature = "fuzztarget")]
152 pub fn supported() -> NodeFeatures {
154 flags: vec![2 | 1 << 5, 1 << (9 - 8) | 1 << (15 - 8), 1 << (17 - 8*2)],
159 /// Takes the flags that we know how to interpret in an init-context features that are also
160 /// relevant in a node-context features and creates a node-context features from them.
161 /// Be sure to blank out features that are unknown to us.
162 pub(crate) fn with_known_relevant_init_flags(init_ctx: &InitFeatures) -> Self {
163 let mut flags = Vec::new();
164 for (i, feature_byte)in init_ctx.flags.iter().enumerate() {
166 // Blank out initial_routing_sync (feature bits 2/3), gossip_queries (6/7),
167 // gossip_queries_ex (10/11), option_static_remotekey (12/13), and
168 // option_support_large_channel (16/17)
169 0 => flags.push(feature_byte & 0b00110011),
170 1 => flags.push(feature_byte & 0b11000011),
171 2 => flags.push(feature_byte & 0b00000011),
175 Self { flags, mark: PhantomData, }
179 impl<T: sealed::Context> Features<T> {
180 /// Create a blank Features with no features set
181 pub fn empty() -> Features<T> {
189 /// Create a Features given a set of flags, in LE.
190 pub fn from_le_bytes(flags: Vec<u8>) -> Features<T> {
198 /// Gets the underlying flags set, in LE.
199 pub fn le_flags(&self) -> &Vec<u8> {
203 pub(crate) fn requires_unknown_bits(&self) -> bool {
204 self.flags.iter().enumerate().any(|(idx, &byte)| {
206 // Unknown bits are even bits which we don't understand, we list ones which we do
208 // unknown, upfront_shutdown_script, unknown (actually initial_routing_sync, but it
209 // is only valid as an optional feature), and data_loss_protect:
210 0 => (byte & 0b01000100),
211 // payment_secret, unknown, unknown, var_onion_optin:
212 1 => (byte & 0b00010100),
213 // unknown, unknown, unknown, basic_mpp:
214 2 => (byte & 0b01010100),
215 // fallback, all even bits set:
216 _ => (byte & 0b01010101),
221 pub(crate) fn supports_unknown_bits(&self) -> bool {
222 self.flags.iter().enumerate().any(|(idx, &byte)| {
224 // unknown, upfront_shutdown_script, initial_routing_sync (is only valid as an
225 // optional feature), and data_loss_protect:
226 0 => (byte & 0b11000100),
227 // payment_secret, unknown, unknown, var_onion_optin:
228 1 => (byte & 0b00111100),
229 // unknown, unknown, unknown, basic_mpp:
230 2 => (byte & 0b11111100),
236 /// The number of bytes required to represent the feature flags present. This does not include
237 /// the length bytes which are included in the serialized form.
238 pub(crate) fn byte_count(&self) -> usize {
243 pub(crate) fn set_require_unknown_bits(&mut self) {
244 let newlen = cmp::max(3, self.flags.len());
245 self.flags.resize(newlen, 0u8);
246 self.flags[2] |= 0x40;
250 pub(crate) fn clear_require_unknown_bits(&mut self) {
251 let newlen = cmp::max(3, self.flags.len());
252 self.flags.resize(newlen, 0u8);
253 self.flags[2] &= !0x40;
254 if self.flags.len() == 3 && self.flags[2] == 0 {
255 self.flags.resize(2, 0u8);
257 if self.flags.len() == 2 && self.flags[1] == 0 {
258 self.flags.resize(1, 0u8);
263 impl<T: sealed::DataLossProtect> Features<T> {
264 pub(crate) fn supports_data_loss_protect(&self) -> bool {
265 self.flags.len() > 0 && (self.flags[0] & 3) != 0
269 impl<T: sealed::UpfrontShutdownScript> Features<T> {
270 pub(crate) fn supports_upfront_shutdown_script(&self) -> bool {
271 self.flags.len() > 0 && (self.flags[0] & (3 << 4)) != 0
274 pub(crate) fn unset_upfront_shutdown_script(&mut self) {
275 self.flags[0] &= !(1 << 5);
279 impl<T: sealed::VariableLengthOnion> Features<T> {
280 pub(crate) fn supports_variable_length_onion(&self) -> bool {
281 self.flags.len() > 1 && (self.flags[1] & 3) != 0
285 impl<T: sealed::InitialRoutingSync> Features<T> {
286 pub(crate) fn initial_routing_sync(&self) -> bool {
287 self.flags.len() > 0 && (self.flags[0] & (1 << 3)) != 0
289 pub(crate) fn clear_initial_routing_sync(&mut self) {
290 if self.flags.len() > 0 {
291 self.flags[0] &= !(1 << 3);
296 impl<T: sealed::PaymentSecret> Features<T> {
298 // Note that we never need to test this since what really matters is the invoice - iff the
299 // invoice provides a payment_secret, we assume that we can use it (ie that the recipient
300 // supports payment_secret).
301 pub(crate) fn supports_payment_secret(&self) -> bool {
302 self.flags.len() > 1 && (self.flags[1] & (3 << (14-8))) != 0
306 impl<T: sealed::BasicMPP> Features<T> {
307 // We currently never test for this since we don't actually *generate* multipath routes.
309 pub(crate) fn supports_basic_mpp(&self) -> bool {
310 self.flags.len() > 2 && (self.flags[2] & (3 << (16-8*2))) != 0
314 impl<T: sealed::Context> Writeable for Features<T> {
315 fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
316 w.size_hint(self.flags.len() + 2);
317 (self.flags.len() as u16).write(w)?;
318 for f in self.flags.iter().rev() { // Swap back to big-endian
325 impl<T: sealed::Context> Readable for Features<T> {
326 fn read<R: ::std::io::Read>(r: &mut R) -> Result<Self, DecodeError> {
327 let mut flags: Vec<u8> = Readable::read(r)?;
328 flags.reverse(); // Swap to little-endian
338 use super::{ChannelFeatures, InitFeatures, NodeFeatures, Features};
341 fn sanity_test_our_features() {
342 assert!(!ChannelFeatures::supported().requires_unknown_bits());
343 assert!(!ChannelFeatures::supported().supports_unknown_bits());
344 assert!(!InitFeatures::supported().requires_unknown_bits());
345 assert!(!InitFeatures::supported().supports_unknown_bits());
346 assert!(!NodeFeatures::supported().requires_unknown_bits());
347 assert!(!NodeFeatures::supported().supports_unknown_bits());
349 assert!(InitFeatures::supported().supports_upfront_shutdown_script());
350 assert!(NodeFeatures::supported().supports_upfront_shutdown_script());
352 assert!(InitFeatures::supported().supports_data_loss_protect());
353 assert!(NodeFeatures::supported().supports_data_loss_protect());
355 assert!(InitFeatures::supported().supports_variable_length_onion());
356 assert!(NodeFeatures::supported().supports_variable_length_onion());
358 assert!(InitFeatures::supported().supports_payment_secret());
359 assert!(NodeFeatures::supported().supports_payment_secret());
361 assert!(InitFeatures::supported().supports_basic_mpp());
362 assert!(NodeFeatures::supported().supports_basic_mpp());
364 let mut init_features = InitFeatures::supported();
365 assert!(init_features.initial_routing_sync());
366 init_features.clear_initial_routing_sync();
367 assert!(!init_features.initial_routing_sync());
371 fn sanity_test_unkown_bits_testing() {
372 let mut features = ChannelFeatures::supported();
373 features.set_require_unknown_bits();
374 assert!(features.requires_unknown_bits());
375 features.clear_require_unknown_bits();
376 assert!(!features.requires_unknown_bits());
380 fn test_node_with_known_relevant_init_flags() {
381 // Create an InitFeatures with initial_routing_sync supported.
382 let init_features = InitFeatures::supported();
383 assert!(init_features.initial_routing_sync());
385 // Attempt to pull out non-node-context feature flags from these InitFeatures.
386 let res = NodeFeatures::with_known_relevant_init_flags(&init_features);
389 // Check that the flags are as expected: optional_data_loss_protect,
390 // option_upfront_shutdown_script, var_onion_optin, payment_secret, and
392 assert_eq!(res.flags.len(), 3);
393 assert_eq!(res.flags[0], 0b00100010);
394 assert_eq!(res.flags[1], 0b10000010);
395 assert_eq!(res.flags[2], 0b00000010);
398 // Check that the initial_routing_sync feature was correctly blanked out.
399 let new_features: InitFeatures = Features::from_le_bytes(res.flags);
400 assert!(!new_features.initial_routing_sync());