Skip to content

Commit e847c87

Browse files
committed
Add a ChannelTypeFeatures features object for the new channel_type
Its semantics are somewhat different from existing features, however not enough to merit a different struct entirely. Specifically, it only supports required features (if you send a channel_type, the counterparty has to accept it wholesale or try again, it cannot select only a subset of the flags) and it is serialized differently (only appearing in TLVs).
1 parent d0c3fb7 commit e847c87

File tree

1 file changed

+119
-18
lines changed

1 file changed

+119
-18
lines changed

lightning/src/ln/features.rs

Lines changed: 119 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
//! [BOLT #9]: https://github.com/lightningnetwork/lightning-rfc/blob/master/09-features.md
2323
//! [messages]: crate::ln::msgs
2424
25-
use io;
25+
use {io, io_extras};
2626
use prelude::*;
2727
use core::{cmp, fmt};
2828
use core::hash::{Hash, Hasher};
@@ -194,6 +194,30 @@ mod sealed {
194194
BasicMPP,
195195
],
196196
});
197+
// This isn't a "real" feature context, and is only used in the channel_type field in an
198+
// `OpenChannel` message.
199+
define_context!(ChannelTypeContext {
200+
required_features: [
201+
// Byte 0
202+
,
203+
// Byte 1
204+
StaticRemoteKey,
205+
// Byte 2
206+
,
207+
// Byte 3
208+
,
209+
],
210+
optional_features: [
211+
// Byte 0
212+
,
213+
// Byte 1
214+
,
215+
// Byte 2
216+
,
217+
// Byte 3
218+
,
219+
],
220+
});
197221

198222
/// Defines a feature with the given bits for the specified [`Context`]s. The generated trait is
199223
/// useful for manipulating feature flags.
@@ -325,7 +349,7 @@ mod sealed {
325349
define_feature!(9, VariableLengthOnion, [InitContext, NodeContext, InvoiceContext],
326350
"Feature flags for `var_onion_optin`.", set_variable_length_onion_optional,
327351
set_variable_length_onion_required);
328-
define_feature!(13, StaticRemoteKey, [InitContext, NodeContext],
352+
define_feature!(13, StaticRemoteKey, [InitContext, NodeContext, ChannelTypeContext],
329353
"Feature flags for `option_static_remotekey`.", set_static_remote_key_optional,
330354
set_static_remote_key_required);
331355
define_feature!(15, PaymentSecret, [InitContext, NodeContext, InvoiceContext],
@@ -388,6 +412,18 @@ pub type ChannelFeatures = Features<sealed::ChannelContext>;
388412
/// Features used within an invoice.
389413
pub type InvoiceFeatures = Features<sealed::InvoiceContext>;
390414

415+
/// Features used within the channel_type field in an OpenChannel message.
416+
///
417+
/// A channel is always of some known "type", describing the transaction formats used and the exact
418+
/// semantics of our interaction with our peer.
419+
///
420+
/// Note that because a channel is a specific type which is proposed by the opener and accepted by
421+
/// the counterparty, only required features are allowed here.
422+
///
423+
/// This is serialized differently from other feature types - it is not prefixed by a length, and
424+
/// thus must only appear inside a TLV where its length is known in advance.
425+
pub type ChannelTypeFeatures = Features<sealed::ChannelTypeContext>;
426+
391427
impl InitFeatures {
392428
/// Writes all features present up to, and including, 13.
393429
pub(crate) fn write_up_to_13<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
@@ -442,6 +478,28 @@ impl InvoiceFeatures {
442478
}
443479
}
444480

481+
impl ChannelTypeFeatures {
482+
/// Constructs the implicit channel type based on the common supported types between us and our
483+
/// counterparty
484+
pub(crate) fn from_counterparty_init(counterparty_init: &InitFeatures) -> Self {
485+
let mut ret = counterparty_init.to_context_internal();
486+
// ChannelTypeFeatures must only contain required bits, so we OR the required forms of all
487+
// optional bits and then AND out the optional ones.
488+
for byte in ret.flags.iter_mut() {
489+
*byte |= (*byte & 0b10_10_10_10) >> 1;
490+
*byte &= 0b01_01_01_01;
491+
}
492+
ret
493+
}
494+
495+
/// Constructs a ChannelTypeFeatures with only static_remotekey set
496+
pub(crate) fn only_static_remote_key() -> Self {
497+
let mut ret = Self::empty();
498+
<sealed::ChannelTypeContext as sealed::StaticRemoteKey>::set_required_bit(&mut ret.flags);
499+
ret
500+
}
501+
}
502+
445503
impl ToBase32 for InvoiceFeatures {
446504
fn write_base32<W: WriteBase32>(&self, writer: &mut W) -> Result<(), <W as WriteBase32>::Err> {
447505
// Explanation for the "4": the normal way to round up when dividing is to add the divisor
@@ -553,6 +611,25 @@ impl<T: sealed::Context> Features<T> {
553611
&self.flags
554612
}
555613

614+
fn write_be<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
615+
for f in self.flags.iter().rev() { // Swap back to big-endian
616+
f.write(w)?;
617+
}
618+
Ok(())
619+
}
620+
621+
fn from_be_bytes(mut flags: Vec<u8>) -> Features<T> {
622+
flags.reverse(); // Swap to little-endian
623+
Self {
624+
flags,
625+
mark: PhantomData,
626+
}
627+
}
628+
629+
pub(crate) fn supports_any_optional_bits(&self) -> bool {
630+
self.flags.iter().any(|&byte| (byte & 0b10_10_10_10) != 0)
631+
}
632+
556633
/// Returns true if this `Features` object contains unknown feature flags which are set as
557634
/// "required".
558635
pub fn requires_unknown_bits(&self) -> bool {
@@ -692,31 +769,44 @@ impl<T: sealed::ShutdownAnySegwit> Features<T> {
692769
self
693770
}
694771
}
695-
696-
impl<T: sealed::Context> Writeable for Features<T> {
697-
fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
698-
(self.flags.len() as u16).write(w)?;
699-
for f in self.flags.iter().rev() { // Swap back to big-endian
700-
f.write(w)?;
772+
macro_rules! impl_feature_len_prefixed_write {
773+
($features: ident) => {
774+
impl Writeable for $features {
775+
fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
776+
(self.flags.len() as u16).write(w)?;
777+
self.write_be(w)
778+
}
779+
}
780+
impl Readable for $features {
781+
fn read<R: io::Read>(r: &mut R) -> Result<Self, DecodeError> {
782+
Ok(Self::from_be_bytes(Vec::<u8>::read(r)?))
783+
}
701784
}
702-
Ok(())
703785
}
704786
}
705-
706-
impl<T: sealed::Context> Readable for Features<T> {
787+
impl_feature_len_prefixed_write!(InitFeatures);
788+
impl_feature_len_prefixed_write!(ChannelFeatures);
789+
impl_feature_len_prefixed_write!(NodeFeatures);
790+
impl_feature_len_prefixed_write!(InvoiceFeatures);
791+
792+
// Because ChannelTypeFeatures only appears inside of TLVs, it doesn't have a length prefix when
793+
// serialized. Thus, we can't use `impl_feature_len_prefixed_write`, above, and have to write our
794+
// own serialization.
795+
impl Writeable for ChannelTypeFeatures {
796+
fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
797+
self.write_be(w)
798+
}
799+
}
800+
impl Readable for ChannelTypeFeatures {
707801
fn read<R: io::Read>(r: &mut R) -> Result<Self, DecodeError> {
708-
let mut flags: Vec<u8> = Readable::read(r)?;
709-
flags.reverse(); // Swap to little-endian
710-
Ok(Self {
711-
flags,
712-
mark: PhantomData,
713-
})
802+
let v = io_extras::read_to_end(r)?;
803+
Ok(Self::from_be_bytes(v))
714804
}
715805
}
716806

717807
#[cfg(test)]
718808
mod tests {
719-
use super::{ChannelFeatures, InitFeatures, InvoiceFeatures, NodeFeatures};
809+
use super::{ChannelFeatures, ChannelTypeFeatures, InitFeatures, InvoiceFeatures, NodeFeatures};
720810
use bitcoin::bech32::{Base32Len, FromBase32, ToBase32, u5};
721811

722812
#[test]
@@ -875,4 +965,15 @@ mod tests {
875965
let features_deserialized = InvoiceFeatures::from_base32(&features_as_u5s).unwrap();
876966
assert_eq!(features, features_deserialized);
877967
}
968+
969+
#[test]
970+
fn test_channel_type_mapping() {
971+
// If we map an InvoiceFeatures with StaticRemoteKey optional, it should map into a
972+
// required-StaticRemoteKey ChannelTypeFeatures.
973+
let init_features = InitFeatures::empty().set_static_remote_key_optional();
974+
let converted_features = ChannelTypeFeatures::from_counterparty_init(&init_features);
975+
assert_eq!(converted_features, ChannelTypeFeatures::only_static_remote_key());
976+
assert!(!converted_features.supports_any_optional_bits());
977+
assert!(converted_features.requires_static_remote_key());
978+
}
878979
}

0 commit comments

Comments
 (0)