Skip to content

Commit bc7d64c

Browse files
committed
Seal the features contexts
1 parent 6cdf40e commit bc7d64c

File tree

1 file changed

+91
-93
lines changed

1 file changed

+91
-93
lines changed

lightning/src/ln/features.rs

+91-93
Original file line numberDiff line numberDiff line change
@@ -8,57 +8,35 @@ 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 {}
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 {}
11+
mod sealed { // You should just use the type aliases instead.
12+
pub struct FeatureContextInit {}
13+
pub struct FeatureContextNode {}
14+
pub struct FeatureContextChannel {}
15+
//TODO: Figure out what to do with invoice feature sets with the rust-lightning-invoice crate.
16+
//pub struct FeatureContextInvoice {}
17+
18+
/// An internal trait capturing the various future context types
19+
pub trait FeatureContext {}
20+
impl FeatureContext for FeatureContextInit {}
21+
impl FeatureContext for FeatureContextNode {}
22+
impl FeatureContext for FeatureContextChannel {}
23+
//impl FeatureContext for FeatureContextInvoice {}
24+
25+
pub trait DataLossProtect: FeatureContext {}
26+
impl DataLossProtect for FeatureContextInit {}
27+
impl DataLossProtect for FeatureContextNode {}
28+
29+
pub trait InitialRoutingSync: FeatureContext {}
30+
impl InitialRoutingSync for FeatureContextInit {}
31+
32+
pub trait UpfrontShutdownScript: FeatureContext {}
33+
impl UpfrontShutdownScript for FeatureContextInit {}
34+
impl UpfrontShutdownScript for FeatureContextNode {}
35+
}
5836

5937
/// Tracks the set of features which a node implements, templated by the context in which it
6038
/// appears.
61-
pub struct Features<T: FeatureContext> {
39+
pub struct Features<T: sealed::FeatureContext> {
6240
#[cfg(not(test))]
6341
/// Note that, for convinience, flags is LITTLE endian (despite being big-endian on the wire)
6442
flags: Vec<u8>,
@@ -72,69 +50,111 @@ pub struct Features<T: FeatureContext> {
7250
pub mark: PhantomData<T>,
7351
}
7452

75-
impl<T: FeatureContext> Clone for Features<T> {
53+
impl<T: sealed::FeatureContext> Clone for Features<T> {
7654
fn clone(&self) -> Self {
7755
Self {
7856
flags: self.flags.clone(),
7957
mark: PhantomData,
8058
}
8159
}
8260
}
83-
impl<T: FeatureContext> PartialEq for Features<T> {
61+
impl<T: sealed::FeatureContext> PartialEq for Features<T> {
8462
fn eq(&self, o: &Self) -> bool {
8563
self.flags.eq(&o.flags)
8664
}
8765
}
88-
impl<T: FeatureContext> fmt::Debug for Features<T> {
66+
impl<T: sealed::FeatureContext> fmt::Debug for Features<T> {
8967
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
9068
self.flags.fmt(fmt)
9169
}
9270
}
9371

9472
/// A feature message as it appears in an init message
95-
pub type InitFeatures = Features<FeatureContextInit>;
73+
pub type InitFeatures = Features<sealed::FeatureContextInit>;
9674
/// A feature message as it appears in a node_announcement message
97-
pub type NodeFeatures = Features<FeatureContextNode>;
75+
pub type NodeFeatures = Features<sealed::FeatureContextNode>;
9876
/// A feature message as it appears in a channel_announcement message
99-
pub type ChannelFeatures = Features<FeatureContextChannel>;
77+
pub type ChannelFeatures = Features<sealed::FeatureContextChannel>;
10078

101-
impl<T: FeatureContextInitNode> Features<T> {
79+
impl InitFeatures {
10280
/// Create a Features with the features we support
10381
#[cfg(not(feature = "fuzztarget"))]
104-
pub(crate) fn our_features() -> Features<T> {
105-
Features {
82+
pub(crate) fn our_features() -> InitFeatures {
83+
InitFeatures {
10684
flags: vec![2 | 1 << 5],
10785
mark: PhantomData,
10886
}
10987
}
11088
#[cfg(feature = "fuzztarget")]
111-
pub fn our_features() -> Features<T> {
112-
Features {
89+
pub fn our_features() -> InitFeatures {
90+
InitFeatures {
11391
flags: vec![2 | 1 << 5],
11492
mark: PhantomData,
11593
}
11694
}
95+
96+
/// Writes all features present up to, and including, 13.
97+
pub(crate) fn write_up_to_13<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
98+
let len = cmp::min(2, self.flags.len());
99+
w.size_hint(len + 2);
100+
(len as u16).write(w)?;
101+
for i in (0..len).rev() {
102+
if i == 0 {
103+
self.flags[i].write(w)?;
104+
} else {
105+
(self.flags[i] & ((1 << (14 - 8)) - 1)).write(w)?;
106+
}
107+
}
108+
Ok(())
109+
}
110+
111+
/// or's another InitFeatures into this one.
112+
pub(crate) fn or(&mut self, o: &InitFeatures) {
113+
let total_feature_len = cmp::max(self.flags.len(), o.flags.len());
114+
self.flags.resize(total_feature_len, 0u8);
115+
for (feature, o_feature) in self.flags.iter_mut().zip(o.flags.iter()) {
116+
*feature |= *o_feature;
117+
}
118+
}
117119
}
118120

119-
impl Features<FeatureContextChannel> {
121+
impl ChannelFeatures {
120122
/// Create a Features with the features we support
121123
#[cfg(not(feature = "fuzztarget"))]
122-
pub(crate) fn our_features() -> Features<FeatureContextChannel> {
123-
Features {
124+
pub(crate) fn our_features() -> ChannelFeatures {
125+
ChannelFeatures {
124126
flags: Vec::new(),
125127
mark: PhantomData,
126128
}
127129
}
128130
#[cfg(feature = "fuzztarget")]
129-
pub fn our_features() -> Features<FeatureContextChannel> {
130-
Features {
131+
pub fn our_features() -> ChannelFeatures {
132+
ChannelFeatures {
131133
flags: Vec::new(),
132134
mark: PhantomData,
133135
}
134136
}
135137
}
136138

137-
impl<T: FeatureContext> Features<T> {
139+
impl NodeFeatures {
140+
/// Create a Features with the features we support
141+
#[cfg(not(feature = "fuzztarget"))]
142+
pub(crate) fn our_features() -> NodeFeatures {
143+
NodeFeatures {
144+
flags: vec![2 | 1 << 5],
145+
mark: PhantomData,
146+
}
147+
}
148+
#[cfg(feature = "fuzztarget")]
149+
pub fn our_features() -> NodeFeatures {
150+
NodeFeatures {
151+
flags: vec![2 | 1 << 5],
152+
mark: PhantomData,
153+
}
154+
}
155+
}
156+
157+
impl<T: sealed::FeatureContext> Features<T> {
138158
/// Create a blank Features with no fetures set
139159
pub fn empty() -> Features<T> {
140160
Features {
@@ -179,11 +199,13 @@ impl<T: FeatureContext> Features<T> {
179199
}
180200
}
181201

182-
impl<T: FeatureContextInitNode> Features<T> {
202+
impl<T: sealed::DataLossProtect> Features<T> {
183203
pub(crate) fn supports_data_loss_protect(&self) -> bool {
184204
self.flags.len() > 0 && (self.flags[0] & 3) != 0
185205
}
206+
}
186207

208+
impl<T: sealed::UpfrontShutdownScript> Features<T> {
187209
pub(crate) fn supports_upfront_shutdown_script(&self) -> bool {
188210
self.flags.len() > 0 && (self.flags[0] & (3 << 4)) != 0
189211
}
@@ -193,7 +215,7 @@ impl<T: FeatureContextInitNode> Features<T> {
193215
}
194216
}
195217

196-
impl Features<FeatureContextInit> {
218+
impl<T: sealed::InitialRoutingSync> Features<T> {
197219
pub(crate) fn initial_routing_sync(&self) -> bool {
198220
self.flags.len() > 0 && (self.flags[0] & (1 << 3)) != 0
199221
}
@@ -204,33 +226,9 @@ impl Features<FeatureContextInit> {
204226
self.flags[0] |= 1 << 3;
205227
}
206228
}
207-
208-
/// Writes all features present up to, and including, 13.
209-
pub(crate) fn write_up_to_13<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
210-
let len = cmp::min(2, self.flags.len());
211-
w.size_hint(len + 2);
212-
(len as u16).write(w)?;
213-
for i in (0..len).rev() {
214-
if i == 0 {
215-
self.flags[i].write(w)?;
216-
} else {
217-
(self.flags[i] & ((1 << (14 - 8)) - 1)).write(w)?;
218-
}
219-
}
220-
Ok(())
221-
}
222-
223-
/// or's another InitFeatures into this one.
224-
pub(crate) fn or(&mut self, o: &InitFeatures) {
225-
let total_feature_len = cmp::max(self.flags.len(), o.flags.len());
226-
self.flags.resize(total_feature_len, 0u8);
227-
for (feature, o_feature) in self.flags.iter_mut().zip(o.flags.iter()) {
228-
*feature |= *o_feature;
229-
}
230-
}
231229
}
232230

233-
impl<T: FeatureContext> Writeable for Features<T> {
231+
impl<T: sealed::FeatureContext> Writeable for Features<T> {
234232
fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
235233
w.size_hint(self.flags.len() + 2);
236234
(self.flags.len() as u16).write(w)?;
@@ -241,7 +239,7 @@ impl<T: FeatureContext> Writeable for Features<T> {
241239
}
242240
}
243241

244-
impl<R: ::std::io::Read, T: FeatureContext> Readable<R> for Features<T> {
242+
impl<R: ::std::io::Read, T: sealed::FeatureContext> Readable<R> for Features<T> {
245243
fn read(r: &mut R) -> Result<Self, DecodeError> {
246244
let mut flags: Vec<u8> = Readable::read(r)?;
247245
flags.reverse(); // Swap to big-endian

0 commit comments

Comments
 (0)