Move features into a separate module out of msgs.
[rust-lightning] / lightning / src / ln / features.rs
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.
3
4 use std::{cmp, fmt};
5 use std::result::Result;
6 use std::marker::PhantomData;
7
8 use ln::msgs::DecodeError;
9 use util::ser::{Readable, Writeable, Writer};
10
11 /// The context in which a Feature object appears determines which bits of features the node
12 /// supports will be set. We use this when creating our own Feature objects to select which bits to
13 /// set and when passing around Feature objects to ensure the bits we're checking for are
14 /// available.
15 ///
16 /// This Context represents when the Feature appears in the init message, sent between peers and not
17 /// rumored around the P2P network.
18 pub struct FeatureContextInit {}
19 /// The context in which a Feature object appears determines which bits of features the node
20 /// supports will be set. We use this when creating our own Feature objects to select which bits to
21 /// set and when passing around Feature objects to ensure the bits we're checking for are
22 /// available.
23 ///
24 /// This Context represents when the Feature appears in the node_announcement message, as it is
25 /// rumored around the P2P network.
26 pub struct FeatureContextNode {}
27 /// The context in which a Feature object appears determines which bits of features the node
28 /// supports will be set. We use this when creating our own Feature objects to select which bits to
29 /// set and when passing around Feature objects to ensure the bits we're checking for are
30 /// available.
31 ///
32 /// This Context represents when the Feature appears in the ChannelAnnouncement message, as it is
33 /// rumored around the P2P network.
34 pub struct FeatureContextChannel {}
35 /// The context in which a Feature object appears determines which bits of features the node
36 /// supports will be set. We use this when creating our own Feature objects to select which bits to
37 /// set and when passing around Feature objects to ensure the bits we're checking for are
38 /// available.
39 ///
40 /// This Context represents when the Feature appears in an invoice, used to determine the different
41 /// options available for routing a payment.
42 ///
43 /// Note that this is currently unused as invoices come to us via a different crate and are not
44 /// native to rust-lightning directly.
45 pub struct FeatureContextInvoice {}
46
47 /// An internal trait capturing the various future context types
48 pub trait FeatureContext {}
49 impl FeatureContext for FeatureContextInit {}
50 impl FeatureContext for FeatureContextNode {}
51 impl FeatureContext for FeatureContextChannel {}
52 impl FeatureContext for FeatureContextInvoice {}
53
54 /// An internal trait capturing FeatureContextInit and FeatureContextNode
55 pub trait FeatureContextInitNode : FeatureContext {}
56 impl FeatureContextInitNode for FeatureContextInit {}
57 impl FeatureContextInitNode for FeatureContextNode {}
58
59 /// Tracks the set of features which a node implements, templated by the context in which it
60 /// appears.
61 pub struct Features<T: FeatureContext> {
62         /// Note that, for convinience, flags is LITTLE endian (despite being big-endian on the wire)
63         flags: Vec<u8>,
64         mark: PhantomData<T>,
65 }
66
67 impl<T: FeatureContext> Clone for Features<T> {
68         fn clone(&self) -> Self {
69                 Self {
70                         flags: self.flags.clone(),
71                         mark: PhantomData,
72                 }
73         }
74 }
75 impl<T: FeatureContext> PartialEq for Features<T> {
76         fn eq(&self, o: &Self) -> bool {
77                 self.flags.eq(&o.flags)
78         }
79 }
80 impl<T: FeatureContext> fmt::Debug for Features<T> {
81         fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
82                 self.flags.fmt(fmt)
83         }
84 }
85
86 /// A feature message as it appears in an init message
87 pub type InitFeatures = Features<FeatureContextInit>;
88 /// A feature message as it appears in a node_announcement message
89 pub type NodeFeatures = Features<FeatureContextNode>;
90 /// A feature message as it appears in a channel_announcement message
91 pub type ChannelFeatures = Features<FeatureContextChannel>;
92
93 impl<T: FeatureContextInitNode> Features<T> {
94         /// Create a Features with the features we support
95         #[cfg(not(feature = "fuzztarget"))]
96         pub(crate) fn supported() -> Features<T> {
97                 Features {
98                         flags: vec![2 | 1 << 5],
99                         mark: PhantomData,
100                 }
101         }
102         #[cfg(feature = "fuzztarget")]
103         pub fn supported() -> Features<T> {
104                 Features {
105                         flags: vec![2 | 1 << 5],
106                         mark: PhantomData,
107                 }
108         }
109 }
110
111 impl Features<FeatureContextChannel> {
112         /// Create a Features with the features we support
113         #[cfg(not(feature = "fuzztarget"))]
114         pub(crate) fn supported() -> Features<FeatureContextChannel> {
115                 Features {
116                         flags: Vec::new(),
117                         mark: PhantomData,
118                 }
119         }
120         #[cfg(feature = "fuzztarget")]
121         pub fn supported() -> Features<FeatureContextChannel> {
122                 Features {
123                         flags: Vec::new(),
124                         mark: PhantomData,
125                 }
126         }
127 }
128
129 impl<T: FeatureContext> Features<T> {
130         /// Create a blank Features with no features set
131         pub fn empty() -> Features<T> {
132                 Features {
133                         flags: Vec::new(),
134                         mark: PhantomData,
135                 }
136         }
137
138         #[cfg(test)]
139         /// Create a Features given a set of flags, in LE.
140         pub fn from_le_bytes(flags: Vec<u8>) -> Features<T> {
141                 Features {
142                         flags,
143                         mark: PhantomData,
144                 }
145         }
146
147         #[cfg(test)]
148         /// Gets the underlying flags set, in LE.
149         pub fn le_flags(&self) -> &Vec<u8> {
150                 &self.flags
151         }
152
153         pub(crate) fn requires_unknown_bits(&self) -> bool {
154                 self.flags.iter().enumerate().any(|(idx, &byte)| {
155                         ( idx != 0 && (byte & 0x55) != 0 ) || ( idx == 0 && (byte & 0x14) != 0 )
156                 })
157         }
158
159         pub(crate) fn supports_unknown_bits(&self) -> bool {
160                 self.flags.iter().enumerate().any(|(idx, &byte)| {
161                         ( idx != 0 && byte != 0 ) || ( idx == 0 && (byte & 0xc4) != 0 )
162                 })
163         }
164
165         /// The number of bytes required to represent the feature flags present. This does not include
166         /// the length bytes which are included in the serialized form.
167         pub(crate) fn byte_count(&self) -> usize {
168                 self.flags.len()
169         }
170
171         #[cfg(test)]
172         pub(crate) fn set_require_unknown_bits(&mut self) {
173                 let newlen = cmp::max(2, self.flags.len());
174                 self.flags.resize(newlen, 0u8);
175                 self.flags[1] |= 0x40;
176         }
177
178         #[cfg(test)]
179         pub(crate) fn clear_require_unknown_bits(&mut self) {
180                 let newlen = cmp::max(2, self.flags.len());
181                 self.flags.resize(newlen, 0u8);
182                 self.flags[1] &= !0x40;
183                 if self.flags.len() == 2 && self.flags[1] == 0 {
184                         self.flags.resize(1, 0u8);
185                 }
186         }
187 }
188
189 impl<T: FeatureContextInitNode> Features<T> {
190         pub(crate) fn supports_data_loss_protect(&self) -> bool {
191                 self.flags.len() > 0 && (self.flags[0] & 3) != 0
192         }
193
194         pub(crate) fn supports_upfront_shutdown_script(&self) -> bool {
195                 self.flags.len() > 0 && (self.flags[0] & (3 << 4)) != 0
196         }
197         #[cfg(test)]
198         pub(crate) fn unset_upfront_shutdown_script(&mut self) {
199                 self.flags[0] ^= 1 << 5;
200         }
201 }
202
203 impl Features<FeatureContextInit> {
204         pub(crate) fn initial_routing_sync(&self) -> bool {
205                 self.flags.len() > 0 && (self.flags[0] & (1 << 3)) != 0
206         }
207         pub(crate) fn set_initial_routing_sync(&mut self) {
208                 if self.flags.len() == 0 {
209                         self.flags.resize(1, 1 << 3);
210                 } else {
211                         self.flags[0] |= 1 << 3;
212                 }
213         }
214
215         /// Writes all features present up to, and including, 13.
216         pub(crate) fn write_up_to_13<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
217                 let len = cmp::min(2, self.flags.len());
218                 w.size_hint(len + 2);
219                 (len as u16).write(w)?;
220                 for i in (0..len).rev() {
221                         if i == 0 {
222                                 self.flags[i].write(w)?;
223                         } else {
224                                 (self.flags[i] & ((1 << (14 - 8)) - 1)).write(w)?;
225                         }
226                 }
227                 Ok(())
228         }
229
230         /// or's another InitFeatures into this one.
231         pub(crate) fn or(mut self, o: InitFeatures) -> InitFeatures {
232                 let total_feature_len = cmp::max(self.flags.len(), o.flags.len());
233                 self.flags.resize(total_feature_len, 0u8);
234                 for (feature, o_feature) in self.flags.iter_mut().zip(o.flags.iter()) {
235                         *feature |= *o_feature;
236                 }
237                 self
238         }
239 }
240
241 impl<T: FeatureContext> Writeable for Features<T> {
242         fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
243                 w.size_hint(self.flags.len() + 2);
244                 (self.flags.len() as u16).write(w)?;
245                 for f in self.flags.iter().rev() { // Swap back to big-endian
246                         f.write(w)?;
247                 }
248                 Ok(())
249         }
250 }
251
252 impl<R: ::std::io::Read, T: FeatureContext> Readable<R> for Features<T> {
253         fn read(r: &mut R) -> Result<Self, DecodeError> {
254                 let mut flags: Vec<u8> = Readable::read(r)?;
255                 flags.reverse(); // Swap to little-endian
256                 Ok(Self {
257                         flags,
258                         mark: PhantomData,
259                 })
260         }
261 }