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 << 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 set_initial_routing_sync(&mut self) {
290 if self.flags.len() == 0 {
291 self.flags.resize(1, 1 << 3);
293 self.flags[0] |= 1 << 3;
298 impl<T: sealed::PaymentSecret> Features<T> {
300 // Note that we never need to test this since what really matters is the invoice - iff the
301 // invoice provides a payment_secret, we assume that we can use it (ie that the recipient
302 // supports payment_secret).
303 pub(crate) fn supports_payment_secret(&self) -> bool {
304 self.flags.len() > 1 && (self.flags[1] & (3 << (14-8))) != 0
308 impl<T: sealed::BasicMPP> Features<T> {
309 // We currently never test for this since we don't actually *generate* multipath routes.
311 pub(crate) fn supports_basic_mpp(&self) -> bool {
312 self.flags.len() > 2 && (self.flags[2] & (3 << (16-8*2))) != 0
316 impl<T: sealed::Context> Writeable for Features<T> {
317 fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
318 w.size_hint(self.flags.len() + 2);
319 (self.flags.len() as u16).write(w)?;
320 for f in self.flags.iter().rev() { // Swap back to big-endian
327 impl<T: sealed::Context> Readable for Features<T> {
328 fn read<R: ::std::io::Read>(r: &mut R) -> Result<Self, DecodeError> {
329 let mut flags: Vec<u8> = Readable::read(r)?;
330 flags.reverse(); // Swap to little-endian
340 use super::{ChannelFeatures, InitFeatures, NodeFeatures, Features};
343 fn sanity_test_our_features() {
344 assert!(!ChannelFeatures::supported().requires_unknown_bits());
345 assert!(!ChannelFeatures::supported().supports_unknown_bits());
346 assert!(!InitFeatures::supported().requires_unknown_bits());
347 assert!(!InitFeatures::supported().supports_unknown_bits());
348 assert!(!NodeFeatures::supported().requires_unknown_bits());
349 assert!(!NodeFeatures::supported().supports_unknown_bits());
351 assert!(InitFeatures::supported().supports_upfront_shutdown_script());
352 assert!(NodeFeatures::supported().supports_upfront_shutdown_script());
354 assert!(InitFeatures::supported().supports_data_loss_protect());
355 assert!(NodeFeatures::supported().supports_data_loss_protect());
357 assert!(InitFeatures::supported().supports_variable_length_onion());
358 assert!(NodeFeatures::supported().supports_variable_length_onion());
360 assert!(InitFeatures::supported().supports_payment_secret());
361 assert!(NodeFeatures::supported().supports_payment_secret());
363 assert!(InitFeatures::supported().supports_basic_mpp());
364 assert!(NodeFeatures::supported().supports_basic_mpp());
366 let mut init_features = InitFeatures::supported();
367 init_features.set_initial_routing_sync();
368 assert!(!init_features.requires_unknown_bits());
369 assert!(!init_features.supports_unknown_bits());
373 fn sanity_test_unkown_bits_testing() {
374 let mut features = ChannelFeatures::supported();
375 features.set_require_unknown_bits();
376 assert!(features.requires_unknown_bits());
377 features.clear_require_unknown_bits();
378 assert!(!features.requires_unknown_bits());
382 fn test_node_with_known_relevant_init_flags() {
383 // Create an InitFeatures with initial_routing_sync supported.
384 let mut init_features = InitFeatures::supported();
385 init_features.set_initial_routing_sync();
387 // Attempt to pull out non-node-context feature flags from these InitFeatures.
388 let res = NodeFeatures::with_known_relevant_init_flags(&init_features);
391 // Check that the flags are as expected: optional_data_loss_protect,
392 // option_upfront_shutdown_script, var_onion_optin, payment_secret, and
394 assert_eq!(res.flags.len(), 3);
395 assert_eq!(res.flags[0], 0b00100010);
396 assert_eq!(res.flags[1], 0b10000010);
397 assert_eq!(res.flags[2], 0b00000010);
400 // Check that the initial_routing_sync feature was correctly blanked out.
401 let new_features: InitFeatures = Features::from_le_bytes(res.flags);
402 assert!(!new_features.initial_routing_sync());