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 {}
34 /// Tracks the set of features which a node implements, templated by the context in which it
36 pub struct Features<T: sealed::Context> {
37 /// Note that, for convinience, flags is LITTLE endian (despite being big-endian on the wire)
42 impl<T: sealed::Context> Clone for Features<T> {
43 fn clone(&self) -> Self {
45 flags: self.flags.clone(),
50 impl<T: sealed::Context> PartialEq for Features<T> {
51 fn eq(&self, o: &Self) -> bool {
52 self.flags.eq(&o.flags)
55 impl<T: sealed::Context> fmt::Debug for Features<T> {
56 fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
61 /// A feature message as it appears in an init message
62 pub type InitFeatures = Features<sealed::InitContext>;
63 /// A feature message as it appears in a node_announcement message
64 pub type NodeFeatures = Features<sealed::NodeContext>;
65 /// A feature message as it appears in a channel_announcement message
66 pub type ChannelFeatures = Features<sealed::ChannelContext>;
69 /// Create a Features with the features we support
70 pub fn supported() -> InitFeatures {
72 flags: vec![2 | 1 << 5],
77 /// Writes all features present up to, and including, 13.
78 pub(crate) fn write_up_to_13<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
79 let len = cmp::min(2, self.flags.len());
81 (len as u16).write(w)?;
82 for i in (0..len).rev() {
84 self.flags[i].write(w)?;
86 // On byte 1, we want up-to-and-including-bit-13, 0-indexed, which is
87 // up-to-and-including-bit-5, 0-indexed, on this byte:
88 (self.flags[i] & 0b00_11_11_11).write(w)?;
94 /// or's another InitFeatures into this one.
95 pub(crate) fn or(mut self, o: InitFeatures) -> InitFeatures {
96 let total_feature_len = cmp::max(self.flags.len(), o.flags.len());
97 self.flags.resize(total_feature_len, 0u8);
98 for (byte, o_byte) in self.flags.iter_mut().zip(o.flags.iter()) {
105 impl ChannelFeatures {
106 /// Create a Features with the features we support
107 #[cfg(not(feature = "fuzztarget"))]
108 pub(crate) fn supported() -> ChannelFeatures {
114 #[cfg(feature = "fuzztarget")]
115 pub fn supported() -> ChannelFeatures {
122 /// Takes the flags that we know how to interpret in an init-context features that are also
123 /// relevant in a channel-context features and creates a channel-context features from them.
124 pub(crate) fn with_known_relevant_init_flags(_init_ctx: &InitFeatures) -> Self {
125 // There are currently no channel flags defined that we understand.
126 Self { flags: Vec::new(), mark: PhantomData, }
131 /// Create a Features with the features we support
132 #[cfg(not(feature = "fuzztarget"))]
133 pub(crate) fn supported() -> NodeFeatures {
135 flags: vec![2 | 1 << 5],
139 #[cfg(feature = "fuzztarget")]
140 pub fn supported() -> NodeFeatures {
142 flags: vec![2 | 1 << 5],
147 /// Takes the flags that we know how to interpret in an init-context features that are also
148 /// relevant in a node-context features and creates a node-context features from them.
149 pub(crate) fn with_known_relevant_init_flags(init_ctx: &InitFeatures) -> Self {
150 let mut flags = Vec::new();
151 if init_ctx.flags.len() > 0 {
152 // Pull out data_loss_protect and upfront_shutdown_script (bits 0, 1, 4, and 5)
153 flags.push(init_ctx.flags.last().unwrap() & 0b00110011);
155 Self { flags, mark: PhantomData, }
159 impl<T: sealed::Context> Features<T> {
160 /// Create a blank Features with no features set
161 pub fn empty() -> Features<T> {
169 /// Create a Features given a set of flags, in LE.
170 pub fn from_le_bytes(flags: Vec<u8>) -> Features<T> {
178 /// Gets the underlying flags set, in LE.
179 pub fn le_flags(&self) -> &Vec<u8> {
183 pub(crate) fn requires_unknown_bits(&self) -> bool {
184 self.flags.iter().enumerate().any(|(idx, &byte)| {
185 ( idx != 0 && (byte & 0x55) != 0 ) || ( idx == 0 && (byte & 0x14) != 0 )
189 pub(crate) fn supports_unknown_bits(&self) -> bool {
190 self.flags.iter().enumerate().any(|(idx, &byte)| {
191 ( idx != 0 && byte != 0 ) || ( idx == 0 && (byte & 0xc4) != 0 )
195 /// The number of bytes required to represent the feature flags present. This does not include
196 /// the length bytes which are included in the serialized form.
197 pub(crate) fn byte_count(&self) -> usize {
202 pub(crate) fn set_require_unknown_bits(&mut self) {
203 let newlen = cmp::max(2, self.flags.len());
204 self.flags.resize(newlen, 0u8);
205 self.flags[1] |= 0x40;
209 pub(crate) fn clear_require_unknown_bits(&mut self) {
210 let newlen = cmp::max(2, self.flags.len());
211 self.flags.resize(newlen, 0u8);
212 self.flags[1] &= !0x40;
213 if self.flags.len() == 2 && self.flags[1] == 0 {
214 self.flags.resize(1, 0u8);
219 impl<T: sealed::DataLossProtect> Features<T> {
220 pub(crate) fn supports_data_loss_protect(&self) -> bool {
221 self.flags.len() > 0 && (self.flags[0] & 3) != 0
225 impl<T: sealed::UpfrontShutdownScript> Features<T> {
226 pub(crate) fn supports_upfront_shutdown_script(&self) -> bool {
227 self.flags.len() > 0 && (self.flags[0] & (3 << 4)) != 0
230 pub(crate) fn unset_upfront_shutdown_script(&mut self) {
231 self.flags[0] ^= 1 << 5;
235 impl<T: sealed::InitialRoutingSync> Features<T> {
236 pub(crate) fn initial_routing_sync(&self) -> bool {
237 self.flags.len() > 0 && (self.flags[0] & (1 << 3)) != 0
239 pub(crate) fn set_initial_routing_sync(&mut self) {
240 if self.flags.len() == 0 {
241 self.flags.resize(1, 1 << 3);
243 self.flags[0] |= 1 << 3;
248 impl<T: sealed::Context> Writeable for Features<T> {
249 fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
250 w.size_hint(self.flags.len() + 2);
251 (self.flags.len() as u16).write(w)?;
252 for f in self.flags.iter().rev() { // Swap back to big-endian
259 impl<R: ::std::io::Read, T: sealed::Context> Readable<R> for Features<T> {
260 fn read(r: &mut R) -> Result<Self, DecodeError> {
261 let mut flags: Vec<u8> = Readable::read(r)?;
262 flags.reverse(); // Swap to little-endian