Skip to content

Commit a682fb4

Browse files
committed
Seal the features contexts
1 parent aab84ee commit a682fb4

File tree

1 file changed

+89
-92
lines changed

1 file changed

+89
-92
lines changed

lightning/src/ln/features.rs

+89-92
Original file line numberDiff line numberDiff line change
@@ -8,125 +8,145 @@ use std::marker::PhantomData;
88
use ln::msgs::DecodeError;
99
use util::ser::{Readable, Writeable, Writer};
1010

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 {}
11+
mod sealed { // You should just use the type aliases instead.
12+
pub struct InitContext {}
13+
pub struct NodeContext {}
14+
pub struct ChannelContext {}
4615

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 {}
16+
/// An internal trait capturing the various feature context types
17+
pub trait Context {}
18+
impl Context for InitContext {}
19+
impl Context for NodeContext {}
20+
impl Context for ChannelContext {}
5321

54-
/// An internal trait capturing FeatureContextInit and FeatureContextNode
55-
pub trait FeatureContextInitNode : FeatureContext {}
56-
impl FeatureContextInitNode for FeatureContextInit {}
57-
impl FeatureContextInitNode for FeatureContextNode {}
22+
pub trait DataLossProtect: Context {}
23+
impl DataLossProtect for InitContext {}
24+
impl DataLossProtect for NodeContext {}
25+
26+
pub trait InitialRoutingSync: Context {}
27+
impl InitialRoutingSync for InitContext {}
28+
29+
pub trait UpfrontShutdownScript: Context {}
30+
impl UpfrontShutdownScript for InitContext {}
31+
impl UpfrontShutdownScript for NodeContext {}
32+
}
5833

5934
/// Tracks the set of features which a node implements, templated by the context in which it
6035
/// appears.
61-
pub struct Features<T: FeatureContext> {
36+
pub struct Features<T: sealed::Context> {
6237
/// Note that, for convinience, flags is LITTLE endian (despite being big-endian on the wire)
6338
flags: Vec<u8>,
6439
mark: PhantomData<T>,
6540
}
6641

67-
impl<T: FeatureContext> Clone for Features<T> {
42+
impl<T: sealed::Context> Clone for Features<T> {
6843
fn clone(&self) -> Self {
6944
Self {
7045
flags: self.flags.clone(),
7146
mark: PhantomData,
7247
}
7348
}
7449
}
75-
impl<T: FeatureContext> PartialEq for Features<T> {
50+
impl<T: sealed::Context> PartialEq for Features<T> {
7651
fn eq(&self, o: &Self) -> bool {
7752
self.flags.eq(&o.flags)
7853
}
7954
}
80-
impl<T: FeatureContext> fmt::Debug for Features<T> {
55+
impl<T: sealed::Context> fmt::Debug for Features<T> {
8156
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
8257
self.flags.fmt(fmt)
8358
}
8459
}
8560

8661
/// A feature message as it appears in an init message
87-
pub type InitFeatures = Features<FeatureContextInit>;
62+
pub type InitFeatures = Features<sealed::InitContext>;
8863
/// A feature message as it appears in a node_announcement message
89-
pub type NodeFeatures = Features<FeatureContextNode>;
64+
pub type NodeFeatures = Features<sealed::NodeContext>;
9065
/// A feature message as it appears in a channel_announcement message
91-
pub type ChannelFeatures = Features<FeatureContextChannel>;
66+
pub type ChannelFeatures = Features<sealed::ChannelContext>;
9267

93-
impl<T: FeatureContextInitNode> Features<T> {
68+
impl InitFeatures {
9469
/// Create a Features with the features we support
9570
#[cfg(not(feature = "fuzztarget"))]
96-
pub(crate) fn supported() -> Features<T> {
97-
Features {
71+
pub(crate) fn supported() -> InitFeatures {
72+
InitFeatures {
9873
flags: vec![2 | 1 << 5],
9974
mark: PhantomData,
10075
}
10176
}
10277
#[cfg(feature = "fuzztarget")]
103-
pub fn supported() -> Features<T> {
104-
Features {
78+
pub fn supported() -> InitFeatures {
79+
InitFeatures {
10580
flags: vec![2 | 1 << 5],
10681
mark: PhantomData,
10782
}
10883
}
84+
85+
/// Writes all features present up to, and including, 13.
86+
pub(crate) fn write_up_to_13<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
87+
let len = cmp::min(2, self.flags.len());
88+
w.size_hint(len + 2);
89+
(len as u16).write(w)?;
90+
for i in (0..len).rev() {
91+
if i == 0 {
92+
self.flags[i].write(w)?;
93+
} else {
94+
// On byte 1, we want up-to-and-including-bit-13, 0-indexed, which is
95+
// up-to-and-including-bit-5, 0-indexed, on this byte:
96+
(self.flags[i] & 0b00_11_11_11).write(w)?;
97+
}
98+
}
99+
Ok(())
100+
}
101+
102+
/// or's another InitFeatures into this one.
103+
pub(crate) fn or(mut self, o: InitFeatures) -> InitFeatures {
104+
let total_feature_len = cmp::max(self.flags.len(), o.flags.len());
105+
self.flags.resize(total_feature_len, 0u8);
106+
for (byte, o_byte) in self.flags.iter_mut().zip(o.flags.iter()) {
107+
*byte |= *o_byte;
108+
}
109+
self
110+
}
109111
}
110112

111-
impl Features<FeatureContextChannel> {
113+
impl ChannelFeatures {
112114
/// Create a Features with the features we support
113115
#[cfg(not(feature = "fuzztarget"))]
114-
pub(crate) fn supported() -> Features<FeatureContextChannel> {
115-
Features {
116+
pub(crate) fn supported() -> ChannelFeatures {
117+
ChannelFeatures {
116118
flags: Vec::new(),
117119
mark: PhantomData,
118120
}
119121
}
120122
#[cfg(feature = "fuzztarget")]
121-
pub fn supported() -> Features<FeatureContextChannel> {
122-
Features {
123+
pub fn supported() -> ChannelFeatures {
124+
ChannelFeatures {
123125
flags: Vec::new(),
124126
mark: PhantomData,
125127
}
126128
}
127129
}
128130

129-
impl<T: FeatureContext> Features<T> {
131+
impl NodeFeatures {
132+
/// Create a Features with the features we support
133+
#[cfg(not(feature = "fuzztarget"))]
134+
pub(crate) fn supported() -> NodeFeatures {
135+
NodeFeatures {
136+
flags: vec![2 | 1 << 5],
137+
mark: PhantomData,
138+
}
139+
}
140+
#[cfg(feature = "fuzztarget")]
141+
pub fn supported() -> NodeFeatures {
142+
NodeFeatures {
143+
flags: vec![2 | 1 << 5],
144+
mark: PhantomData,
145+
}
146+
}
147+
}
148+
149+
impl<T: sealed::Context> Features<T> {
130150
/// Create a blank Features with no features set
131151
pub fn empty() -> Features<T> {
132152
Features {
@@ -186,11 +206,13 @@ impl<T: FeatureContext> Features<T> {
186206
}
187207
}
188208

189-
impl<T: FeatureContextInitNode> Features<T> {
209+
impl<T: sealed::DataLossProtect> Features<T> {
190210
pub(crate) fn supports_data_loss_protect(&self) -> bool {
191211
self.flags.len() > 0 && (self.flags[0] & 3) != 0
192212
}
213+
}
193214

215+
impl<T: sealed::UpfrontShutdownScript> Features<T> {
194216
pub(crate) fn supports_upfront_shutdown_script(&self) -> bool {
195217
self.flags.len() > 0 && (self.flags[0] & (3 << 4)) != 0
196218
}
@@ -200,7 +222,7 @@ impl<T: FeatureContextInitNode> Features<T> {
200222
}
201223
}
202224

203-
impl Features<FeatureContextInit> {
225+
impl<T: sealed::InitialRoutingSync> Features<T> {
204226
pub(crate) fn initial_routing_sync(&self) -> bool {
205227
self.flags.len() > 0 && (self.flags[0] & (1 << 3)) != 0
206228
}
@@ -211,34 +233,9 @@ impl Features<FeatureContextInit> {
211233
self.flags[0] |= 1 << 3;
212234
}
213235
}
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-
}
239236
}
240237

241-
impl<T: FeatureContext> Writeable for Features<T> {
238+
impl<T: sealed::Context> Writeable for Features<T> {
242239
fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
243240
w.size_hint(self.flags.len() + 2);
244241
(self.flags.len() as u16).write(w)?;
@@ -249,7 +246,7 @@ impl<T: FeatureContext> Writeable for Features<T> {
249246
}
250247
}
251248

252-
impl<R: ::std::io::Read, T: FeatureContext> Readable<R> for Features<T> {
249+
impl<R: ::std::io::Read, T: sealed::Context> Readable<R> for Features<T> {
253250
fn read(r: &mut R) -> Result<Self, DecodeError> {
254251
let mut flags: Vec<u8> = Readable::read(r)?;
255252
flags.reverse(); // Swap to little-endian

0 commit comments

Comments
 (0)