Do not require upfront_shutdown as the security gain is marginal
[rust-lightning] / src / ln / msgs.rs
index ccc4aef39e462571b02c7d295f7dabaef4c1a1e0..f6968c5d3a32dfd4b0b20915ee5db02839943efb 100644 (file)
@@ -18,7 +18,7 @@
 use secp256k1::key::PublicKey;
 use secp256k1::Signature;
 use secp256k1;
-use bitcoin::util::hash::Sha256dHash;
+use bitcoin_hashes::sha256d::Hash as Sha256dHash;
 use bitcoin::blockdata::script::Script;
 
 use std::error::Error;
@@ -59,9 +59,17 @@ pub struct LocalFeatures {
 }
 
 impl LocalFeatures {
+       /// Create a blank LocalFeatures flags (visibility extended for fuzz tests)
+       #[cfg(not(feature = "fuzztarget"))]
        pub(crate) fn new() -> LocalFeatures {
                LocalFeatures {
-                       flags: Vec::new(),
+                       flags: vec![1 << 5],
+               }
+       }
+       #[cfg(feature = "fuzztarget")]
+       pub fn new() -> LocalFeatures {
+               LocalFeatures {
+                       flags: vec![1 << 5],
                }
        }
 
@@ -86,30 +94,21 @@ impl LocalFeatures {
        pub(crate) fn supports_upfront_shutdown_script(&self) -> bool {
                self.flags.len() > 0 && (self.flags[0] & (3 << 4)) != 0
        }
-       pub(crate) fn requires_upfront_shutdown_script(&self) -> bool {
-               self.flags.len() > 0 && (self.flags[0] & (1 << 4)) != 0
+       #[cfg(test)]
+       pub(crate) fn unset_upfront_shutdown_script(&mut self) {
+               self.flags[0] ^= 1 << 5;
        }
 
        pub(crate) fn requires_unknown_bits(&self) -> bool {
-               for (idx, &byte) in self.flags.iter().enumerate() {
-                       if idx != 0 && (byte & 0x55) != 0 {
-                               return true;
-                       } else if idx == 0 && (byte & 0x14) != 0 {
-                               return true;
-                       }
-               }
-               return false;
+               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 {
-               for (idx, &byte) in self.flags.iter().enumerate() {
-                       if idx != 0 && byte != 0 {
-                               return true;
-                       } else if idx == 0 && (byte & 0xc4) != 0 {
-                               return true;
-                       }
-               }
-               return false;
+               self.flags.iter().enumerate().any(|(idx, &byte)| {
+                       ( idx != 0 && byte != 0 ) || ( idx == 0 && (byte & 0xc4) != 0 )
+               })
        }
 }
 
@@ -621,9 +620,9 @@ pub enum OptionalField<T> {
 pub trait ChannelMessageHandler : events::MessageSendEventsProvider + Send + Sync {
        //Channel init:
        /// Handle an incoming open_channel message from the given peer.
-       fn handle_open_channel(&self, their_node_id: &PublicKey, msg: &OpenChannel) -> Result<(), HandleError>;
+       fn handle_open_channel(&self, their_node_id: &PublicKey, their_local_features: LocalFeatures, msg: &OpenChannel) -> Result<(), HandleError>;
        /// Handle an incoming accept_channel message from the given peer.
-       fn handle_accept_channel(&self, their_node_id: &PublicKey, msg: &AcceptChannel) -> Result<(), HandleError>;
+       fn handle_accept_channel(&self, their_node_id: &PublicKey, their_local_features: LocalFeatures, msg: &AcceptChannel) -> Result<(), HandleError>;
        /// Handle an incoming funding_created message from the given peer.
        fn handle_funding_created(&self, their_node_id: &PublicKey, msg: &FundingCreated) -> Result<(), HandleError>;
        /// Handle an incoming funding_signed message from the given peer.
@@ -715,7 +714,6 @@ mod fuzzy_internal_msgs {
                pub(crate) data: OnionRealm0HopData,
                pub(crate) hmac: [u8; 32],
        }
-       unsafe impl ::util::internal_traits::NoDealloc for OnionHopData{}
 
        pub struct DecodedOnionErrorPacket {
                pub(crate) hmac: [u8; 32],
@@ -1392,11 +1390,12 @@ impl_writeable_len_match!(NodeAnnouncement, {
 mod tests {
        use hex;
        use ln::msgs;
-       use ln::msgs::{GlobalFeatures, OptionalField, OnionErrorPacket};
+       use ln::msgs::{GlobalFeatures, LocalFeatures, OptionalField, OnionErrorPacket};
        use ln::channelmanager::{PaymentPreimage, PaymentHash};
        use util::ser::Writeable;
 
-       use bitcoin::util::hash::Sha256dHash;
+       use bitcoin_hashes::sha256d::Hash as Sha256dHash;
+       use bitcoin_hashes::hex::FromHex;
        use bitcoin::util::address::Address;
        use bitcoin::network::constants::Network;
        use bitcoin::blockdata::script::Builder;
@@ -1722,7 +1721,7 @@ mod tests {
                        htlc_basepoint: pubkey_5,
                        first_per_commitment_point: pubkey_6,
                        channel_flags: if random_bit { 1 << 5 } else { 0 },
-                       shutdown_scriptpubkey: if shutdown { OptionalField::Present(Address::p2pkh(&pubkey_1, Network::Testnet).script_pubkey()) } else { OptionalField::Absent }
+                       shutdown_scriptpubkey: if shutdown { OptionalField::Present(Address::p2pkh(&::bitcoin::PublicKey{compressed: true, key: pubkey_1}, Network::Testnet).script_pubkey()) } else { OptionalField::Absent }
                };
                let encoded_value = open_channel.encode();
                let mut target_value = Vec::new();
@@ -1775,7 +1774,7 @@ mod tests {
                        delayed_payment_basepoint: pubkey_4,
                        htlc_basepoint: pubkey_5,
                        first_per_commitment_point: pubkey_6,
-                       shutdown_scriptpubkey: if shutdown { OptionalField::Present(Address::p2pkh(&pubkey_1, Network::Testnet).script_pubkey()) } else { OptionalField::Absent }
+                       shutdown_scriptpubkey: if shutdown { OptionalField::Present(Address::p2pkh(&::bitcoin::PublicKey{compressed: true, key: pubkey_1}, Network::Testnet).script_pubkey()) } else { OptionalField::Absent }
                };
                let encoded_value = accept_channel.encode();
                let mut target_value = hex::decode("020202020202020202020202020202020202020202020202020202020202020212345678901234562334032891223698321446687011447600083a840000034d000c89d4c0bcc0bc031b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f024d4b6cd1361032ca9bd2aeb9d900aa4d45d9ead80ac9423374c451a7254d076602531fe6068134503d2723133227c867ac8fa6c83c537e9a44c3c5bdbdcb1fe33703462779ad4aad39514614751a71085f2f10e1c7a593e4e030efb5b8721ce55b0b0362c0a046dacce86ddd0343c6d3c7c79c2208ba0d9c9cf24a6d046d21d21f90f703f006a18d5653c4edf5391ff23a61f03ff83d237e880ee61187fa9f379a028e0a").unwrap();
@@ -1840,7 +1839,7 @@ mod tests {
                let script = Builder::new().push_opcode(opcodes::OP_TRUE).into_script();
                let shutdown = msgs::Shutdown {
                        channel_id: [2; 32],
-                       scriptpubkey: if script_type == 1 { Address::p2pkh(&pubkey_1, Network::Testnet).script_pubkey() } else if script_type == 2 { Address::p2sh(&script, Network::Testnet).script_pubkey() } else if script_type == 3 { Address::p2wpkh(&pubkey_1, Network::Testnet).script_pubkey() } else { Address::p2wsh(&script, Network::Testnet).script_pubkey() },
+                       scriptpubkey: if script_type == 1 { Address::p2pkh(&::bitcoin::PublicKey{compressed: true, key: pubkey_1}, Network::Testnet).script_pubkey() } else if script_type == 2 { Address::p2sh(&script, Network::Testnet).script_pubkey() } else if script_type == 3 { Address::p2wpkh(&::bitcoin::PublicKey{compressed: true, key: pubkey_1}, Network::Testnet).script_pubkey() } else { Address::p2wsh(&script, Network::Testnet).script_pubkey() },
                };
                let encoded_value = shutdown.encode();
                let mut target_value = hex::decode("0202020202020202020202020202020202020202020202020202020202020202").unwrap();
@@ -1997,4 +1996,72 @@ mod tests {
                let target_value = hex::decode("0202020202020202020202020202020202020202020202020202020202020202013413a7").unwrap();
                assert_eq!(encoded_value, target_value);
        }
+
+       fn do_encoding_init(unknown_global_bits: bool, initial_routing_sync: bool) {
+               let mut global = GlobalFeatures::new();
+               if unknown_global_bits {
+                       global.flags = vec![0xFF, 0xFF];
+               }
+               let mut local = LocalFeatures::new();
+               if initial_routing_sync {
+                       local.set_initial_routing_sync();
+               }
+               let init = msgs::Init {
+                       global_features: global,
+                       local_features: local,
+               };
+               let encoded_value = init.encode();
+               let mut target_value = Vec::new();
+               if unknown_global_bits {
+                       target_value.append(&mut hex::decode("0002ffff").unwrap());
+               } else {
+                       target_value.append(&mut hex::decode("0000").unwrap());
+               }
+               if initial_routing_sync {
+                       target_value.append(&mut hex::decode("000128").unwrap());
+               } else {
+                       target_value.append(&mut hex::decode("000120").unwrap());
+               }
+               assert_eq!(encoded_value, target_value);
+       }
+
+       #[test]
+       fn encoding_init() {
+               do_encoding_init(false, false);
+               do_encoding_init(true, false);
+               do_encoding_init(false, true);
+               do_encoding_init(true, true);
+       }
+
+       #[test]
+       fn encoding_error() {
+               let error = msgs::ErrorMessage {
+                       channel_id: [2; 32],
+                       data: String::from("rust-lightning"),
+               };
+               let encoded_value = error.encode();
+               let target_value = hex::decode("0202020202020202020202020202020202020202020202020202020202020202000e727573742d6c696768746e696e67").unwrap();
+               assert_eq!(encoded_value, target_value);
+       }
+
+       #[test]
+       fn encoding_ping() {
+               let ping = msgs::Ping {
+                       ponglen: 64,
+                       byteslen: 64
+               };
+               let encoded_value = ping.encode();
+               let target_value = hex::decode("0040004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").unwrap();
+               assert_eq!(encoded_value, target_value);
+       }
+
+       #[test]
+       fn encoding_pong() {
+               let pong = msgs::Pong {
+                       byteslen: 64
+               };
+               let encoded_value = pong.encode();
+               let target_value = hex::decode("004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").unwrap();
+               assert_eq!(encoded_value, target_value);
+       }
 }