X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Ffeatures.rs;h=9d34433161a55e064afcddca798fa6fe7aaacdeb;hb=ea1a68c6e6098e8d330792204b05c20d705a372c;hp=e8a3e6d26facd524c3ae3036ed87ec54a08b8937;hpb=f4f1093edc506314484c8d52a40dd155e692394b;p=rust-lightning diff --git a/lightning/src/ln/features.rs b/lightning/src/ln/features.rs index e8a3e6d2..9d344331 100644 --- a/lightning/src/ln/features.rs +++ b/lightning/src/ln/features.rs @@ -65,7 +65,7 @@ use core::marker::PhantomData; use bitcoin::bech32; use bitcoin::bech32::{Base32Len, FromBase32, ToBase32, u5, WriteBase32}; use crate::ln::msgs::DecodeError; -use crate::util::ser::{Readable, Writeable, Writer}; +use crate::util::ser::{Readable, WithoutLength, Writeable, Writer}; mod sealed { use crate::prelude::*; @@ -157,6 +157,8 @@ mod sealed { // Byte 2 BasicMPP, ]); + define_context!(OfferContext, []); + define_context!(InvoiceRequestContext, []); // This isn't a "real" feature context, and is only used in the channel_type field in an // `OpenChannel` message. define_context!(ChannelTypeContext, [ @@ -366,7 +368,8 @@ mod sealed { supports_keysend, requires_keysend); #[cfg(test)] - define_feature!(123456789, UnknownFeature, [NodeContext, ChannelContext, InvoiceContext], + define_feature!(123456789, UnknownFeature, + [NodeContext, ChannelContext, InvoiceContext, OfferContext, InvoiceRequestContext], "Feature flags for an unknown feature used in testing.", set_unknown_feature_optional, set_unknown_feature_required, supports_unknown_test_feature, requires_unknown_test_feature); } @@ -425,6 +428,10 @@ pub type NodeFeatures = Features; pub type ChannelFeatures = Features; /// Features used within an invoice. pub type InvoiceFeatures = Features; +/// Features used within an `offer`. +pub type OfferFeatures = Features; +/// Features used within an `invoice_request`. +pub type InvoiceRequestFeatures = Features; /// Features used within the channel_type field in an OpenChannel message. /// @@ -684,6 +691,15 @@ impl Features { } } +#[cfg(test)] +impl Features { + pub(crate) fn unknown() -> Self { + let mut features = Self::empty(); + features.set_unknown_feature_required(); + features + } +} + macro_rules! impl_feature_len_prefixed_write { ($features: ident) => { impl Writeable for $features { @@ -704,25 +720,45 @@ impl_feature_len_prefixed_write!(ChannelFeatures); impl_feature_len_prefixed_write!(NodeFeatures); impl_feature_len_prefixed_write!(InvoiceFeatures); -// Because ChannelTypeFeatures only appears inside of TLVs, it doesn't have a length prefix when -// serialized. Thus, we can't use `impl_feature_len_prefixed_write`, above, and have to write our -// own serialization. -impl Writeable for ChannelTypeFeatures { +// Some features only appear inside of TLVs, so they don't have a length prefix when serialized. +macro_rules! impl_feature_tlv_write { + ($features: ident) => { + impl Writeable for $features { + fn write(&self, w: &mut W) -> Result<(), io::Error> { + WithoutLength(self).write(w) + } + } + impl Readable for $features { + fn read(r: &mut R) -> Result { + Ok(WithoutLength::::read(r)?.0) + } + } + } +} + +impl_feature_tlv_write!(ChannelTypeFeatures); + +// Some features may appear both in a TLV record and as part of a TLV subtype sequence. The latter +// requires a length but the former does not. + +impl Writeable for WithoutLength<&Features> { fn write(&self, w: &mut W) -> Result<(), io::Error> { - self.write_be(w) + self.0.write_be(w) } } -impl Readable for ChannelTypeFeatures { + +impl Readable for WithoutLength> { fn read(r: &mut R) -> Result { let v = io_extras::read_to_end(r)?; - Ok(Self::from_be_bytes(v)) + Ok(WithoutLength(Features::::from_be_bytes(v))) } } #[cfg(test)] mod tests { - use super::{ChannelFeatures, ChannelTypeFeatures, InitFeatures, InvoiceFeatures, NodeFeatures, sealed}; + use super::{ChannelFeatures, ChannelTypeFeatures, InitFeatures, InvoiceFeatures, NodeFeatures, OfferFeatures, sealed}; use bitcoin::bech32::{Base32Len, FromBase32, ToBase32, u5}; + use crate::util::ser::{Readable, WithoutLength, Writeable}; #[test] fn sanity_test_unknown_bits() { @@ -816,6 +852,20 @@ mod tests { assert!(features.supports_payment_secret()); } + #[test] + fn encodes_features_without_length() { + let features = OfferFeatures::from_le_bytes(vec![1, 2, 3, 4, 5, 42, 100, 101]); + assert_eq!(features.flags.len(), 8); + + let mut serialized_features = Vec::new(); + WithoutLength(&features).write(&mut serialized_features).unwrap(); + assert_eq!(serialized_features.len(), 8); + + let deserialized_features = + WithoutLength::::read(&mut &serialized_features[..]).unwrap().0; + assert_eq!(features, deserialized_features); + } + #[test] fn invoice_features_encoding() { let features_as_u5s = vec![