Move initial_routing_sync decision to the Router
[rust-lightning] / lightning / src / ln / msgs.rs
index cccbf83acd2a740271f8d962e67d6038c4b61f75..519c56542ba491856329319c9df6bd231ba88ed2 100644 (file)
@@ -21,11 +21,12 @@ use secp256k1;
 use bitcoin_hashes::sha256d::Hash as Sha256dHash;
 use bitcoin::blockdata::script::Script;
 
+use ln::features::{ChannelFeatures, InitFeatures, NodeFeatures};
+
 use std::error::Error;
 use std::{cmp, fmt};
 use std::io::Read;
 use std::result::Result;
-use std::marker::PhantomData;
 
 use util::events;
 use util::ser::{Readable, Writeable, Writer};
@@ -53,233 +54,12 @@ pub enum DecodeError {
        Io(::std::io::Error),
 }
 
-/// The context in which a Feature object appears determines which bits of features the node
-/// supports will be set. We use this when creating our own Feature objects to select which bits to
-/// set and when passing around Feature objects to ensure the bits we're checking for are
-/// available.
-///
-/// This Context represents when the Feature appears in the init message, sent between peers and not
-/// rumored around the P2P network.
-pub struct FeatureContextInit {}
-/// The context in which a Feature object appears determines which bits of features the node
-/// supports will be set. We use this when creating our own Feature objects to select which bits to
-/// set and when passing around Feature objects to ensure the bits we're checking for are
-/// available.
-///
-/// This Context represents when the Feature appears in the node_announcement message, as it is
-/// rumored around the P2P network.
-pub struct FeatureContextNode {}
-/// The context in which a Feature object appears determines which bits of features the node
-/// supports will be set. We use this when creating our own Feature objects to select which bits to
-/// set and when passing around Feature objects to ensure the bits we're checking for are
-/// available.
-///
-/// This Context represents when the Feature appears in the ChannelAnnouncement message, as it is
-/// rumored around the P2P network.
-pub struct FeatureContextChannel {}
-/// The context in which a Feature object appears determines which bits of features the node
-/// supports will be set. We use this when creating our own Feature objects to select which bits to
-/// set and when passing around Feature objects to ensure the bits we're checking for are
-/// available.
-///
-/// This Context represents when the Feature appears in an invoice, used to determine the different
-/// options available for routing a payment.
-///
-/// Note that this is currently unused as invoices come to us via a different crate and are not
-/// native to rust-lightning directly.
-pub struct FeatureContextInvoice {}
-
-/// An internal trait capturing the various future context types
-pub trait FeatureContext {}
-impl FeatureContext for FeatureContextInit {}
-impl FeatureContext for FeatureContextNode {}
-impl FeatureContext for FeatureContextChannel {}
-impl FeatureContext for FeatureContextInvoice {}
-
-/// An internal trait capturing FeatureContextInit and FeatureContextNode
-pub trait FeatureContextInitNode : FeatureContext {}
-impl FeatureContextInitNode for FeatureContextInit {}
-impl FeatureContextInitNode for FeatureContextNode {}
-
-/// Tracks the set of features which a node implements, templated by the context in which it
-/// appears.
-pub struct Features<T: FeatureContext> {
-       #[cfg(not(test))]
-       flags: Vec<u8>,
-       // Used to test encoding of diverse msgs
-       #[cfg(test)]
-       pub flags: Vec<u8>,
-       mark: PhantomData<T>,
-}
-
-impl<T: FeatureContext> Clone for Features<T> {
-       fn clone(&self) -> Self {
-               Self {
-                       flags: self.flags.clone(),
-                       mark: PhantomData,
-               }
-       }
-}
-impl<T: FeatureContext> PartialEq for Features<T> {
-       fn eq(&self, o: &Self) -> bool {
-               self.flags.eq(&o.flags)
-       }
-}
-impl<T: FeatureContext> fmt::Debug for Features<T> {
-       fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
-               self.flags.fmt(fmt)
-       }
-}
-
-/// A feature message as it appears in an init message
-pub type InitFeatures = Features<FeatureContextInit>;
-/// A feature message as it appears in a node_announcement message
-pub type NodeFeatures = Features<FeatureContextNode>;
-/// A feature message as it appears in a channel_announcement message
-pub type ChannelFeatures = Features<FeatureContextChannel>;
-
-impl<T: FeatureContextInitNode> Features<T> {
-       /// Create a blank Features flags (visibility extended for fuzz tests)
-       #[cfg(not(feature = "fuzztarget"))]
-       pub(crate) fn new() -> Features<T> {
-               Features {
-                       flags: vec![2 | 1 << 5],
-                       mark: PhantomData,
-               }
-       }
-       #[cfg(feature = "fuzztarget")]
-       pub fn new() -> Features<T> {
-               Features {
-                       flags: vec![2 | 1 << 5],
-                       mark: PhantomData,
-               }
-       }
-}
-
-impl Features<FeatureContextChannel> {
-       /// Create a blank Features flags (visibility extended for fuzz tests)
-       #[cfg(not(feature = "fuzztarget"))]
-       pub(crate) fn new() -> Features<FeatureContextChannel> {
-               Features {
-                       flags: Vec::new(),
-                       mark: PhantomData,
-               }
-       }
-       #[cfg(feature = "fuzztarget")]
-       pub fn new() -> Features<FeatureContextChannel> {
-               Features {
-                       flags: Vec::new(),
-                       mark: PhantomData,
-               }
-       }
-}
-
-impl<T: FeatureContext> Features<T> {
-       pub(crate) fn requires_unknown_bits(&self) -> bool {
-               self.flags.iter().enumerate().any(|(idx, &byte)| {
-                       ( idx != 0 && (byte & 0x55) != 0 ) || ( idx == 0 && (byte & 0x14) != 0 )
-               })
-       }
-
-       pub(crate) fn supports_unknown_bits(&self) -> bool {
-               self.flags.iter().enumerate().any(|(idx, &byte)| {
-                       ( idx != 0 && byte != 0 ) || ( idx == 0 && (byte & 0xc4) != 0 )
-               })
-       }
-
-       /// The number of bytes required to represent the feaature flags present. This does not include
-       /// the length bytes which are included in the serialized form.
-       pub(crate) fn byte_count(&self) -> usize {
-               self.flags.len()
-       }
-
-       #[cfg(test)]
-       pub(crate) fn set_require_unknown_bits(&mut self) {
-               let newlen = cmp::max(2, self.flags.len());
-               self.flags.resize(newlen, 0u8);
-               self.flags[1] |= 0x40;
-       }
-
-       #[cfg(test)]
-       pub(crate) fn clear_require_unknown_bits(&mut self) {
-               let newlen = cmp::max(2, self.flags.len());
-               self.flags.resize(newlen, 0u8);
-               self.flags[1] &= !0x40;
-               if self.flags.len() == 2 && self.flags[1] == 0 {
-                       self.flags.resize(1, 0u8);
-               }
-       }
-}
-
-impl<T: FeatureContextInitNode> Features<T> {
-       pub(crate) fn supports_data_loss_protect(&self) -> bool {
-               self.flags.len() > 0 && (self.flags[0] & 3) != 0
-       }
-
-       pub(crate) fn supports_upfront_shutdown_script(&self) -> bool {
-               self.flags.len() > 0 && (self.flags[0] & (3 << 4)) != 0
-       }
-       #[cfg(test)]
-       pub(crate) fn unset_upfront_shutdown_script(&mut self) {
-               self.flags[0] ^= 1 << 5;
-       }
-}
-
-impl Features<FeatureContextInit> {
-       pub(crate) fn initial_routing_sync(&self) -> bool {
-               self.flags.len() > 0 && (self.flags[0] & (1 << 3)) != 0
-       }
-       pub(crate) fn set_initial_routing_sync(&mut self) {
-               if self.flags.len() == 0 {
-                       self.flags.resize(1, 1 << 3);
-               } else {
-                       self.flags[0] |= 1 << 3;
-               }
-       }
-
-       /// Writes all features present up to, and including, 13.
-       pub(crate) fn write_up_to_13<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
-               let len = cmp::min(2, self.flags.len());
-               w.size_hint(len + 2);
-               (len as u16).write(w)?;
-               for i in (0..len).rev() {
-                       if i == 0 {
-                               self.flags[i].write(w)?;
-                       } else {
-                               (self.flags[i] & ((1 << (14 - 8)) - 1)).write(w)?;
-                       }
-               }
-               Ok(())
-       }
-
-       /// or's another InitFeatures into this one.
-       pub(crate) fn or(&mut self, o: &InitFeatures) {
-               let total_feature_len = cmp::max(self.flags.len(), o.flags.len());
-               self.flags.resize(total_feature_len, 0u8);
-               for (feature, o_feature) in self.flags.iter_mut().zip(o.flags.iter()) {
-                       *feature |= *o_feature;
-               }
-       }
-}
-
-impl<T: FeatureContext> Writeable for Features<T> {
-       fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
-               w.size_hint(self.flags.len() + 2);
-               self.flags.write(w)
-       }
-}
-
-impl<R: ::std::io::Read, T: FeatureContext> Readable<R> for Features<T> {
-       fn read(r: &mut R) -> Result<Self, DecodeError> {
-               Ok(Self {
-                       flags: Readable::read(r)?,
-                       mark: PhantomData,
-               })
-       }
-}
 /// An init message to be sent or received from a peer
 pub struct Init {
+       #[cfg(not(feature = "fuzztarget"))]
        pub(crate) features: InitFeatures,
+       #[cfg(feature = "fuzztarget")]
+       pub features: InitFeatures,
 }
 
 /// An error message to be sent or received from a peer
@@ -362,9 +142,10 @@ pub struct FundingSigned {
 
 /// A funding_locked message to be sent or received from a peer
 #[derive(Clone, PartialEq)]
+#[allow(missing_docs)]
 pub struct FundingLocked {
-       pub(crate) channel_id: [u8; 32],
-       pub(crate) next_per_commitment_point: PublicKey,
+       pub channel_id: [u8; 32],
+       pub next_per_commitment_point: PublicKey,
 }
 
 /// A shutdown message to be sent or received from a peer
@@ -793,7 +574,7 @@ pub trait ChannelMessageHandler : events::MessageSendEventsProvider + Send + Syn
        fn peer_disconnected(&self, their_node_id: &PublicKey, no_connection_possible: bool);
 
        /// Handle a peer reconnecting, possibly generating channel_reestablish message(s).
-       fn peer_connected(&self, their_node_id: &PublicKey);
+       fn peer_connected(&self, their_node_id: &PublicKey, msg: &Init);
        /// Handle an incoming channel_reestablish message from the given peer.
        fn handle_channel_reestablish(&self, their_node_id: &PublicKey, msg: &ChannelReestablish);
 
@@ -823,6 +604,8 @@ pub trait RoutingMessageHandler : Send + Sync {
        /// starting at the node *after* the provided publickey and including batch_amount entries.
        /// If None is provided for starting_point, we start at the first node.
        fn get_next_node_announcements(&self, starting_point: Option<&PublicKey>, batch_amount: u8) -> Vec<NodeAnnouncement>;
+       /// Returns whether a full sync should be requested from a peer.
+       fn should_request_full_sync(&self, node_id: &PublicKey) -> bool;
 }
 
 pub(crate) struct OnionRealm0HopData {
@@ -1062,10 +845,9 @@ impl Writeable for Init {
 impl<R: Read> Readable<R> for Init {
        fn read(r: &mut R) -> Result<Self, DecodeError> {
                let global_features: InitFeatures = Readable::read(r)?;
-               let mut features: InitFeatures = Readable::read(r)?;
-               features.or(&global_features);
+               let features: InitFeatures = Readable::read(r)?;
                Ok(Init {
-                       features
+                       features: features.or(global_features),
                })
        }
 }
@@ -1524,8 +1306,6 @@ mod tests {
        use secp256k1::key::{PublicKey,SecretKey};
        use secp256k1::{Secp256k1, Message};
 
-       use std::marker::PhantomData;
-
        #[test]
        fn encoding_channel_reestablish_no_secret() {
                let cr = msgs::ChannelReestablish {
@@ -1609,9 +1389,9 @@ mod tests {
                let sig_2 = get_sig_on!(privkey_2, secp_ctx, String::from("01010101010101010101010101010101"));
                let sig_3 = get_sig_on!(privkey_3, secp_ctx, String::from("01010101010101010101010101010101"));
                let sig_4 = get_sig_on!(privkey_4, secp_ctx, String::from("01010101010101010101010101010101"));
-               let mut features = ChannelFeatures::new();
+               let mut features = ChannelFeatures::supported();
                if unknown_features_bits {
-                       features.flags = vec![0xFF, 0xFF];
+                       features = ChannelFeatures::from_le_bytes(vec![0xFF, 0xFF]);
                }
                let unsigned_channel_announcement = msgs::UnsignedChannelAnnouncement {
                        features,
@@ -1665,10 +1445,12 @@ mod tests {
                let secp_ctx = Secp256k1::new();
                let (privkey_1, pubkey_1) = get_keys_from!("0101010101010101010101010101010101010101010101010101010101010101", secp_ctx);
                let sig_1 = get_sig_on!(privkey_1, secp_ctx, String::from("01010101010101010101010101010101"));
-               let mut features = NodeFeatures::new();
-               if unknown_features_bits {
-                       features.flags = vec![0xFF, 0xFF];
-               }
+               let features = if unknown_features_bits {
+                       NodeFeatures::from_le_bytes(vec![0xFF, 0xFF])
+               } else {
+                       // Set to some features we may support
+                       NodeFeatures::from_le_bytes(vec![2 | 1 << 5])
+               };
                let mut addresses = Vec::new();
                if ipv4 {
                        addresses.push(msgs::NetAddress::IPv4 {
@@ -2122,22 +1904,13 @@ mod tests {
        #[test]
        fn encoding_init() {
                assert_eq!(msgs::Init {
-                       features: InitFeatures {
-                               flags: vec![0xFF, 0xFF, 0xFF],
-                               mark: PhantomData,
-                       },
+                       features: InitFeatures::from_le_bytes(vec![0xFF, 0xFF, 0xFF]),
                }.encode(), hex::decode("00023fff0003ffffff").unwrap());
                assert_eq!(msgs::Init {
-                       features: InitFeatures {
-                               flags: vec![0xFF],
-                               mark: PhantomData,
-                       },
+                       features: InitFeatures::from_le_bytes(vec![0xFF]),
                }.encode(), hex::decode("0001ff0001ff").unwrap());
                assert_eq!(msgs::Init {
-                       features: InitFeatures {
-                               flags: vec![],
-                               mark: PhantomData,
-                       },
+                       features: InitFeatures::from_le_bytes(vec![]),
                }.encode(), hex::decode("00000000").unwrap());
        }