|
22 | 22 | //! [BOLT #9]: https://github.com/lightningnetwork/lightning-rfc/blob/master/09-features.md
|
23 | 23 | //! [messages]: crate::ln::msgs
|
24 | 24 |
|
25 |
| -use io; |
| 25 | +use {io, io_extras}; |
26 | 26 | use prelude::*;
|
27 | 27 | use core::{cmp, fmt};
|
28 | 28 | use core::hash::{Hash, Hasher};
|
@@ -194,6 +194,30 @@ mod sealed {
|
194 | 194 | BasicMPP,
|
195 | 195 | ],
|
196 | 196 | });
|
| 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 | + }); |
197 | 221 |
|
198 | 222 | /// Defines a feature with the given bits for the specified [`Context`]s. The generated trait is
|
199 | 223 | /// useful for manipulating feature flags.
|
@@ -325,7 +349,7 @@ mod sealed {
|
325 | 349 | define_feature!(9, VariableLengthOnion, [InitContext, NodeContext, InvoiceContext],
|
326 | 350 | "Feature flags for `var_onion_optin`.", set_variable_length_onion_optional,
|
327 | 351 | set_variable_length_onion_required);
|
328 |
| - define_feature!(13, StaticRemoteKey, [InitContext, NodeContext], |
| 352 | + define_feature!(13, StaticRemoteKey, [InitContext, NodeContext, ChannelTypeContext], |
329 | 353 | "Feature flags for `option_static_remotekey`.", set_static_remote_key_optional,
|
330 | 354 | set_static_remote_key_required);
|
331 | 355 | define_feature!(15, PaymentSecret, [InitContext, NodeContext, InvoiceContext],
|
@@ -388,6 +412,18 @@ pub type ChannelFeatures = Features<sealed::ChannelContext>;
|
388 | 412 | /// Features used within an invoice.
|
389 | 413 | pub type InvoiceFeatures = Features<sealed::InvoiceContext>;
|
390 | 414 |
|
| 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 | + |
391 | 427 | impl InitFeatures {
|
392 | 428 | /// Writes all features present up to, and including, 13.
|
393 | 429 | pub(crate) fn write_up_to_13<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
|
@@ -442,6 +478,21 @@ impl InvoiceFeatures {
|
442 | 478 | }
|
443 | 479 | }
|
444 | 480 |
|
| 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 | + counterparty_init.to_context_internal() |
| 486 | + } |
| 487 | + |
| 488 | + /// Constructs a ChannelTypeFeatures with only static_remotekey set |
| 489 | + pub(crate) fn only_static_remote_key() -> Self { |
| 490 | + let mut ret = Self::empty(); |
| 491 | + <sealed::ChannelTypeContext as sealed::StaticRemoteKey>::set_required_bit(&mut ret.flags); |
| 492 | + ret |
| 493 | + } |
| 494 | +} |
| 495 | + |
445 | 496 | impl ToBase32 for InvoiceFeatures {
|
446 | 497 | fn write_base32<W: WriteBase32>(&self, writer: &mut W) -> Result<(), <W as WriteBase32>::Err> {
|
447 | 498 | // Explanation for the "4": the normal way to round up when dividing is to add the divisor
|
@@ -553,6 +604,20 @@ impl<T: sealed::Context> Features<T> {
|
553 | 604 | &self.flags
|
554 | 605 | }
|
555 | 606 |
|
| 607 | + fn write_be<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> { |
| 608 | + for f in self.flags.iter().rev() { // Swap back to big-endian |
| 609 | + f.write(w)?; |
| 610 | + } |
| 611 | + Ok(()) |
| 612 | + } |
| 613 | + fn from_be_bytes(mut flags: Vec<u8>) -> Features<T> { |
| 614 | + flags.reverse(); // Swap to little-endian |
| 615 | + Self { |
| 616 | + flags, |
| 617 | + mark: PhantomData, |
| 618 | + } |
| 619 | + } |
| 620 | + |
556 | 621 | /// Returns true if this `Features` object contains unknown feature flags which are set as
|
557 | 622 | /// "required".
|
558 | 623 | pub fn requires_unknown_bits(&self) -> bool {
|
@@ -692,25 +757,35 @@ impl<T: sealed::ShutdownAnySegwit> Features<T> {
|
692 | 757 | self
|
693 | 758 | }
|
694 | 759 | }
|
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)?; |
| 760 | +macro_rules! impl_feature_len_prefixed_write { |
| 761 | + ($features: ident) => { |
| 762 | + impl Writeable for $features { |
| 763 | + fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> { |
| 764 | + (self.flags.len() as u16).write(w)?; |
| 765 | + self.write_be(w) |
| 766 | + } |
| 767 | + } |
| 768 | + impl Readable for $features { |
| 769 | + fn read<R: io::Read>(r: &mut R) -> Result<Self, DecodeError> { |
| 770 | + Ok(Self::from_be_bytes(Vec::<u8>::read(r)?)) |
| 771 | + } |
701 | 772 | }
|
702 |
| - Ok(()) |
703 | 773 | }
|
704 | 774 | }
|
| 775 | +impl_feature_len_prefixed_write!(InitFeatures); |
| 776 | +impl_feature_len_prefixed_write!(ChannelFeatures); |
| 777 | +impl_feature_len_prefixed_write!(NodeFeatures); |
| 778 | +impl_feature_len_prefixed_write!(InvoiceFeatures); |
705 | 779 |
|
706 |
| -impl<T: sealed::Context> Readable for Features<T> { |
| 780 | +impl Writeable for ChannelTypeFeatures { |
| 781 | + fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> { |
| 782 | + self.write_be(w) |
| 783 | + } |
| 784 | +} |
| 785 | +impl Readable for ChannelTypeFeatures { |
707 | 786 | 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 |
| - }) |
| 787 | + let v = io_extras::read_to_end(r)?; |
| 788 | + Ok(Self::from_be_bytes(v)) |
714 | 789 | }
|
715 | 790 | }
|
716 | 791 |
|
|
0 commit comments