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 {}
38 /// Tracks the set of features which a node implements, templated by the context in which it
40 pub struct Features<T: sealed::Context> {
41 /// Note that, for convinience, flags is LITTLE endian (despite being big-endian on the wire)
46 impl<T: sealed::Context> Clone for Features<T> {
47 fn clone(&self) -> Self {
49 flags: self.flags.clone(),
54 impl<T: sealed::Context> PartialEq for Features<T> {
55 fn eq(&self, o: &Self) -> bool {
56 self.flags.eq(&o.flags)
59 impl<T: sealed::Context> fmt::Debug for Features<T> {
60 fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
65 /// A feature message as it appears in an init message
66 pub type InitFeatures = Features<sealed::InitContext>;
67 /// A feature message as it appears in a node_announcement message
68 pub type NodeFeatures = Features<sealed::NodeContext>;
69 /// A feature message as it appears in a channel_announcement message
70 pub type ChannelFeatures = Features<sealed::ChannelContext>;
73 /// Create a Features with the features we support
74 pub fn supported() -> InitFeatures {
76 flags: vec![2 | 1 << 5, 1 << (9-8)],
81 /// Writes all features present up to, and including, 13.
82 pub(crate) fn write_up_to_13<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
83 let len = cmp::min(2, self.flags.len());
85 (len as u16).write(w)?;
86 for i in (0..len).rev() {
88 self.flags[i].write(w)?;
90 // On byte 1, we want up-to-and-including-bit-13, 0-indexed, which is
91 // up-to-and-including-bit-5, 0-indexed, on this byte:
92 (self.flags[i] & 0b00_11_11_11).write(w)?;
98 /// or's another InitFeatures into this one.
99 pub(crate) fn or(mut self, o: InitFeatures) -> InitFeatures {
100 let total_feature_len = cmp::max(self.flags.len(), o.flags.len());
101 self.flags.resize(total_feature_len, 0u8);
102 for (byte, o_byte) in self.flags.iter_mut().zip(o.flags.iter()) {
109 impl ChannelFeatures {
110 /// Create a Features with the features we support
111 #[cfg(not(feature = "fuzztarget"))]
112 pub(crate) fn supported() -> ChannelFeatures {
118 #[cfg(feature = "fuzztarget")]
119 pub fn supported() -> ChannelFeatures {
126 /// Takes the flags that we know how to interpret in an init-context features that are also
127 /// relevant in a channel-context features and creates a channel-context features from them.
128 pub(crate) fn with_known_relevant_init_flags(_init_ctx: &InitFeatures) -> Self {
129 // There are currently no channel flags defined that we understand.
130 Self { flags: Vec::new(), mark: PhantomData, }
135 /// Create a Features with the features we support
136 #[cfg(not(feature = "fuzztarget"))]
137 pub(crate) fn supported() -> NodeFeatures {
139 flags: vec![2 | 1 << 5, 1 << (9-8)],
143 #[cfg(feature = "fuzztarget")]
144 pub fn supported() -> NodeFeatures {
146 flags: vec![2 | 1 << 5, 1 << (9-8)],
151 /// Takes the flags that we know how to interpret in an init-context features that are also
152 /// relevant in a node-context features and creates a node-context features from them.
153 pub(crate) fn with_known_relevant_init_flags(init_ctx: &InitFeatures) -> Self {
154 let mut flags = Vec::new();
155 for (i, feature_byte)in init_ctx.flags.iter().enumerate() {
157 // Blank out initial_routing_sync (feature bits 2/3), gossip_queries (6/7),
158 // gossip_queries_ex (10/11), option_static_remotekey (12/13), and
159 // payment_secret (14/15)
160 0 => flags.push(feature_byte & 0b00110011),
161 1 => flags.push(feature_byte & 0b00000011),
165 Self { flags, mark: PhantomData, }
169 impl<T: sealed::Context> Features<T> {
170 /// Create a blank Features with no features set
171 pub fn empty() -> Features<T> {
179 /// Create a Features given a set of flags, in LE.
180 pub fn from_le_bytes(flags: Vec<u8>) -> Features<T> {
188 /// Gets the underlying flags set, in LE.
189 pub fn le_flags(&self) -> &Vec<u8> {
193 pub(crate) fn requires_unknown_bits(&self) -> bool {
194 self.flags.iter().enumerate().any(|(idx, &byte)| {
196 // Unknown bits are even bits which we don't understand, we list ones which we do
198 // unknown, upfront_shutdown_script, unknown (actually initial_routing_sync, but it
199 // is only valid as an optional feature), and data_loss_protect:
200 0 => (byte & 0b01000100),
201 // unknown, unknown, unknown, var_onion_optin:
202 1 => (byte & 0b01010100),
203 // fallback, all even bits set:
204 _ => (byte & 0b01010101),
209 pub(crate) fn supports_unknown_bits(&self) -> bool {
210 self.flags.iter().enumerate().any(|(idx, &byte)| {
212 // unknown, upfront_shutdown_script, initial_routing_sync (is only valid as an
213 // optional feature), and data_loss_protect:
214 0 => (byte & 0b11000100),
215 // unknown, unknown, unknown, var_onion_optin:
216 1 => (byte & 0b11111100),
222 /// The number of bytes required to represent the feature flags present. This does not include
223 /// the length bytes which are included in the serialized form.
224 pub(crate) fn byte_count(&self) -> usize {
229 pub(crate) fn set_require_unknown_bits(&mut self) {
230 let newlen = cmp::max(2, self.flags.len());
231 self.flags.resize(newlen, 0u8);
232 self.flags[1] |= 0x40;
236 pub(crate) fn clear_require_unknown_bits(&mut self) {
237 let newlen = cmp::max(2, self.flags.len());
238 self.flags.resize(newlen, 0u8);
239 self.flags[1] &= !0x40;
240 if self.flags.len() == 2 && self.flags[1] == 0 {
241 self.flags.resize(1, 0u8);
246 impl<T: sealed::DataLossProtect> Features<T> {
247 pub(crate) fn supports_data_loss_protect(&self) -> bool {
248 self.flags.len() > 0 && (self.flags[0] & 3) != 0
252 impl<T: sealed::UpfrontShutdownScript> Features<T> {
253 pub(crate) fn supports_upfront_shutdown_script(&self) -> bool {
254 self.flags.len() > 0 && (self.flags[0] & (3 << 4)) != 0
257 pub(crate) fn unset_upfront_shutdown_script(&mut self) {
258 self.flags[0] ^= 1 << 5;
262 impl<T: sealed::VariableLengthOnion> Features<T> {
263 pub(crate) fn supports_variable_length_onion(&self) -> bool {
264 self.flags.len() > 1 && (self.flags[1] & 3) != 0
268 impl<T: sealed::InitialRoutingSync> Features<T> {
269 pub(crate) fn initial_routing_sync(&self) -> bool {
270 self.flags.len() > 0 && (self.flags[0] & (1 << 3)) != 0
272 pub(crate) fn set_initial_routing_sync(&mut self) {
273 if self.flags.len() == 0 {
274 self.flags.resize(1, 1 << 3);
276 self.flags[0] |= 1 << 3;
281 impl<T: sealed::Context> Writeable for Features<T> {
282 fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
283 w.size_hint(self.flags.len() + 2);
284 (self.flags.len() as u16).write(w)?;
285 for f in self.flags.iter().rev() { // Swap back to big-endian
292 impl<T: sealed::Context> Readable for Features<T> {
293 fn read<R: ::std::io::Read>(r: &mut R) -> Result<Self, DecodeError> {
294 let mut flags: Vec<u8> = Readable::read(r)?;
295 flags.reverse(); // Swap to little-endian
305 use super::{ChannelFeatures, InitFeatures, NodeFeatures, Features};
308 fn sanity_test_our_features() {
309 assert!(!ChannelFeatures::supported().requires_unknown_bits());
310 assert!(!ChannelFeatures::supported().supports_unknown_bits());
311 assert!(!InitFeatures::supported().requires_unknown_bits());
312 assert!(!InitFeatures::supported().supports_unknown_bits());
313 assert!(!NodeFeatures::supported().requires_unknown_bits());
314 assert!(!NodeFeatures::supported().supports_unknown_bits());
316 assert!(InitFeatures::supported().supports_upfront_shutdown_script());
317 assert!(NodeFeatures::supported().supports_upfront_shutdown_script());
319 assert!(InitFeatures::supported().supports_data_loss_protect());
320 assert!(NodeFeatures::supported().supports_data_loss_protect());
322 assert!(InitFeatures::supported().supports_variable_length_onion());
323 assert!(NodeFeatures::supported().supports_variable_length_onion());
325 let mut init_features = InitFeatures::supported();
326 init_features.set_initial_routing_sync();
327 assert!(!init_features.requires_unknown_bits());
328 assert!(!init_features.supports_unknown_bits());
332 fn sanity_test_unkown_bits_testing() {
333 let mut features = ChannelFeatures::supported();
334 features.set_require_unknown_bits();
335 assert!(features.requires_unknown_bits());
336 features.clear_require_unknown_bits();
337 assert!(!features.requires_unknown_bits());
341 fn test_node_with_known_relevant_init_flags() {
342 // Create an InitFeatures with initial_routing_sync supported.
343 let mut init_features = InitFeatures::supported();
344 init_features.set_initial_routing_sync();
346 // Attempt to pull out non-node-context feature flags from these InitFeatures.
347 let res = NodeFeatures::with_known_relevant_init_flags(&init_features);
350 // Check that the flags are as expected.
351 assert_eq!(res.flags[0], 0b00100010);
352 assert_eq!(res.flags[1], 0b00000010);
353 assert_eq!(res.flags.len(), 2);
356 // Check that the initial_routing_sync feature was correctly blanked out.
357 let new_features: InitFeatures = Features::from_le_bytes(res.flags);
358 assert!(!new_features.initial_routing_sync());