]> git.bitcoin.ninja Git - rust-lightning/commitdiff
Merge pull request #30 from TheBlueMatt/master
authorMatt Corallo <649246+TheBlueMatt@users.noreply.github.com>
Sun, 17 Jun 2018 04:09:21 +0000 (00:09 -0400)
committerGitHub <noreply@github.com>
Sun, 17 Jun 2018 04:09:21 +0000 (00:09 -0400)
Working initial routing sync from lnd node

22 files changed:
fuzz/Cargo.toml
fuzz/fuzz_targets/msg_ping_target.rs [new file with mode: 0644]
fuzz/fuzz_targets/msg_pong_target.rs [new file with mode: 0644]
fuzz/fuzz_targets/msg_targets/msg_accept_channel_target.rs
fuzz/fuzz_targets/msg_targets/msg_closing_signed_target.rs
fuzz/fuzz_targets/msg_targets/msg_commitment_signed_target.rs
fuzz/fuzz_targets/msg_targets/msg_funding_created_target.rs
fuzz/fuzz_targets/msg_targets/msg_funding_locked_target.rs
fuzz/fuzz_targets/msg_targets/msg_funding_signed_target.rs
fuzz/fuzz_targets/msg_targets/msg_open_channel_target.rs
fuzz/fuzz_targets/msg_targets/msg_revoke_and_ack_target.rs
fuzz/fuzz_targets/msg_targets/msg_shutdown_target.rs
fuzz/fuzz_targets/msg_targets/msg_target_template.txt
fuzz/fuzz_targets/msg_targets/msg_update_add_htlc_target.rs
fuzz/fuzz_targets/msg_targets/msg_update_fail_htlc_target.rs
fuzz/fuzz_targets/msg_targets/msg_update_fail_malformed_htlc_target.rs
fuzz/fuzz_targets/msg_targets/msg_update_fee_target.rs
fuzz/fuzz_targets/msg_targets/msg_update_fulfill_htlc_target.rs
fuzz/fuzz_targets/msg_targets/utils.rs
src/ln/msgs.rs
src/ln/peer_handler.rs
src/ln/router.rs

index bcaa2932a704510060e2512f2aac690c932efc48..c302292e67ec3a035195adcde97d088a551385f7 100644 (file)
@@ -43,6 +43,14 @@ name = "full_stack_target"
 path = "fuzz_targets/full_stack_target.rs"
 
 # message fuzz targets
+[[bin]]
+name = "msg_ping_target"
+path = "fuzz_targets/msg_ping_target.rs"
+
+[[bin]]
+name = "msg_pong_target"
+path = "fuzz_targets/msg_pong_target.rs"
+
 [[bin]]
 name = "msg_accept_channel_target"
 path = "fuzz_targets/msg_targets/msg_accept_channel_target.rs"
diff --git a/fuzz/fuzz_targets/msg_ping_target.rs b/fuzz/fuzz_targets/msg_ping_target.rs
new file mode 100644 (file)
index 0000000..f2eaf0d
--- /dev/null
@@ -0,0 +1,63 @@
+// This file is auto-generated by gen_target.sh based on msg_target_template.txt
+// To modify it, modify msg_target_template.txt and run gen_target.sh instead.
+
+extern crate lightning;
+
+use lightning::util::reset_rng_state;
+
+use lightning::ln::msgs::{MsgEncodable, MsgDecodable, Ping};
+
+#[inline]
+pub fn do_test(data: &[u8]) {
+       reset_rng_state();
+       if let Ok(msg) = Ping::decode(data) {
+               let _ = msg.encode();
+       }
+}
+
+#[cfg(feature = "afl")]
+extern crate afl;
+#[cfg(feature = "afl")]
+fn main() {
+       afl::read_stdio_bytes(|data| {
+               do_test(&data);
+       });
+}
+
+#[cfg(feature = "honggfuzz")]
+#[macro_use] extern crate honggfuzz;
+#[cfg(feature = "honggfuzz")]
+fn main() {
+       loop {
+               fuzz!(|data| {
+                       do_test(data);
+               });
+       }
+}
+
+#[cfg(test)]
+mod tests {
+       fn extend_vec_from_hex(hex: &str, out: &mut Vec<u8>) {
+               let mut b = 0;
+               for (idx, c) in hex.as_bytes().iter().enumerate() {
+                       b <<= 4;
+                       match *c {
+                               b'A'...b'F' => b |= c - b'A' + 10,
+                               b'a'...b'f' => b |= c - b'a' + 10,
+                               b'0'...b'9' => b |= c - b'0',
+                               _ => panic!("Bad hex"),
+                       }
+                       if (idx & 1) == 1 {
+                               out.push(b);
+                               b = 0;
+                       }
+               }
+       }
+
+       #[test]
+       fn duplicate_crash() {
+               let mut a = Vec::new();
+               extend_vec_from_hex("00", &mut a);
+               super::do_test(&a);
+       }
+}
diff --git a/fuzz/fuzz_targets/msg_pong_target.rs b/fuzz/fuzz_targets/msg_pong_target.rs
new file mode 100644 (file)
index 0000000..9843b79
--- /dev/null
@@ -0,0 +1,63 @@
+// This file is auto-generated by gen_target.sh based on msg_target_template.txt
+// To modify it, modify msg_target_template.txt and run gen_target.sh instead.
+
+extern crate lightning;
+
+use lightning::util::reset_rng_state;
+
+use lightning::ln::msgs::{MsgEncodable, MsgDecodable, Pong};
+
+#[inline]
+pub fn do_test(data: &[u8]) {
+       reset_rng_state();
+       if let Ok(msg) = Pong::decode(data) {
+               let _ = msg.encode();
+       }
+}
+
+#[cfg(feature = "afl")]
+extern crate afl;
+#[cfg(feature = "afl")]
+fn main() {
+       afl::read_stdio_bytes(|data| {
+               do_test(&data);
+       });
+}
+
+#[cfg(feature = "honggfuzz")]
+#[macro_use] extern crate honggfuzz;
+#[cfg(feature = "honggfuzz")]
+fn main() {
+       loop {
+               fuzz!(|data| {
+                       do_test(data);
+               });
+       }
+}
+
+#[cfg(test)]
+mod tests {
+       fn extend_vec_from_hex(hex: &str, out: &mut Vec<u8>) {
+               let mut b = 0;
+               for (idx, c) in hex.as_bytes().iter().enumerate() {
+                       b <<= 4;
+                       match *c {
+                               b'A'...b'F' => b |= c - b'A' + 10,
+                               b'a'...b'f' => b |= c - b'a' + 10,
+                               b'0'...b'9' => b |= c - b'0',
+                               _ => panic!("Bad hex"),
+                       }
+                       if (idx & 1) == 1 {
+                               out.push(b);
+                               b = 0;
+                       }
+               }
+       }
+
+       #[test]
+       fn duplicate_crash() {
+               let mut a = Vec::new();
+               extend_vec_from_hex("00", &mut a);
+               super::do_test(&a);
+       }
+}
index 146358cb8cd349f44fc55d54d1feb499f9050679..a0e9cc4efb511240f632b2e1c260ebc288d4c792 100644 (file)
@@ -9,15 +9,11 @@ use lightning::util::reset_rng_state;
 use lightning::ln::msgs::{MsgEncodable, MsgDecodable};
 
 mod utils;
-use utils::slice_to_be16;
 
 #[inline]
 pub fn do_test(data: &[u8]) {
        reset_rng_state();
-       let mut read_pos = 0;
-       loop {
-               test_msg!(msgs::AcceptChannel, data, read_pos);
-       }
+       test_msg!(msgs::AcceptChannel, data);
 }
 
 #[cfg(feature = "afl")]
index 1c32ab6ed116070e6aa85a3b52d6695b8db1e84c..621ffe2b18d70bfa6157a35f0ffc33c6c25d45df 100644 (file)
@@ -9,15 +9,11 @@ use lightning::util::reset_rng_state;
 use lightning::ln::msgs::{MsgEncodable, MsgDecodable};
 
 mod utils;
-use utils::slice_to_be16;
 
 #[inline]
 pub fn do_test(data: &[u8]) {
        reset_rng_state();
-       let mut read_pos = 0;
-       loop {
-               test_msg!(msgs::ClosingSigned, data, read_pos);
-       }
+       test_msg!(msgs::ClosingSigned, data);
 }
 
 #[cfg(feature = "afl")]
index 494ce54c2c9394567c93089d5cbf3366eae2ff13..e73696c8d3801e9805d32ee28ca8fd3499cb29a5 100644 (file)
@@ -9,15 +9,11 @@ use lightning::util::reset_rng_state;
 use lightning::ln::msgs::{MsgEncodable, MsgDecodable};
 
 mod utils;
-use utils::slice_to_be16;
 
 #[inline]
 pub fn do_test(data: &[u8]) {
        reset_rng_state();
-       let mut read_pos = 0;
-       loop {
-               test_msg!(msgs::CommitmentSigned, data, read_pos);
-       }
+       test_msg!(msgs::CommitmentSigned, data);
 }
 
 #[cfg(feature = "afl")]
index 2420e921ecff8775ac9a93f0bcd298bfd0d306eb..f7d1a58a5e930ef3c3cfb4593754a46b877f837c 100644 (file)
@@ -9,15 +9,11 @@ use lightning::util::reset_rng_state;
 use lightning::ln::msgs::{MsgEncodable, MsgDecodable};
 
 mod utils;
-use utils::slice_to_be16;
 
 #[inline]
 pub fn do_test(data: &[u8]) {
        reset_rng_state();
-       let mut read_pos = 0;
-       loop {
-               test_msg!(msgs::FundingCreated, data, read_pos);
-       }
+       test_msg!(msgs::FundingCreated, data);
 }
 
 #[cfg(feature = "afl")]
index edf7ba9eb96239d0bc387a6fe85427bebb0045ff..00fdef3f82d572fd139ccad7f4025643d5a55368 100644 (file)
@@ -9,15 +9,11 @@ use lightning::util::reset_rng_state;
 use lightning::ln::msgs::{MsgEncodable, MsgDecodable};
 
 mod utils;
-use utils::slice_to_be16;
 
 #[inline]
 pub fn do_test(data: &[u8]) {
        reset_rng_state();
-       let mut read_pos = 0;
-       loop {
-               test_msg!(msgs::FundingLocked, data, read_pos);
-       }
+       test_msg!(msgs::FundingLocked, data);
 }
 
 #[cfg(feature = "afl")]
index a17b9ba8077ede56bc574e32aaad13af53076d7d..9b66c88fefeae67aa35710114923176e0da7d7f6 100644 (file)
@@ -9,15 +9,11 @@ use lightning::util::reset_rng_state;
 use lightning::ln::msgs::{MsgEncodable, MsgDecodable};
 
 mod utils;
-use utils::slice_to_be16;
 
 #[inline]
 pub fn do_test(data: &[u8]) {
        reset_rng_state();
-       let mut read_pos = 0;
-       loop {
-               test_msg!(msgs::FundingSigned, data, read_pos);
-       }
+       test_msg!(msgs::FundingSigned, data);
 }
 
 #[cfg(feature = "afl")]
index f4c8803cb3894742a4c1aae23b1d478efb2841dc..8d7664f8ac5bfc7cfb07b1f0441d6469766f92e1 100644 (file)
@@ -9,15 +9,11 @@ use lightning::util::reset_rng_state;
 use lightning::ln::msgs::{MsgEncodable, MsgDecodable};
 
 mod utils;
-use utils::slice_to_be16;
 
 #[inline]
 pub fn do_test(data: &[u8]) {
        reset_rng_state();
-       let mut read_pos = 0;
-       loop {
-               test_msg!(msgs::OpenChannel, data, read_pos);
-       }
+       test_msg!(msgs::OpenChannel, data);
 }
 
 #[cfg(feature = "afl")]
index 725903af730045369768b238174a782076def76d..de7e9314118b265612590051bf7358c29818e0ef 100644 (file)
@@ -9,15 +9,11 @@ use lightning::util::reset_rng_state;
 use lightning::ln::msgs::{MsgEncodable, MsgDecodable};
 
 mod utils;
-use utils::slice_to_be16;
 
 #[inline]
 pub fn do_test(data: &[u8]) {
        reset_rng_state();
-       let mut read_pos = 0;
-       loop {
-               test_msg!(msgs::RevokeAndACK, data, read_pos);
-       }
+       test_msg!(msgs::RevokeAndACK, data);
 }
 
 #[cfg(feature = "afl")]
index 855b4aa7f41c52b33eac96e05132befcaebae2dc..57e245676d935763742607fee194a338c5d616b4 100644 (file)
@@ -9,15 +9,11 @@ use lightning::util::reset_rng_state;
 use lightning::ln::msgs::{MsgEncodable, MsgDecodable};
 
 mod utils;
-use utils::slice_to_be16;
 
 #[inline]
 pub fn do_test(data: &[u8]) {
        reset_rng_state();
-       let mut read_pos = 0;
-       loop {
-               test_msg!(msgs::Shutdown, data, read_pos);
-       }
+       test_msg!(msgs::Shutdown, data);
 }
 
 #[cfg(feature = "afl")]
index 05abd72367e0a7b57e4196698f55ff1a5a3fa5d3..55a9761c9d611127c261b68bba4cd72ec0243a25 100644 (file)
@@ -9,15 +9,11 @@ use lightning::util::reset_rng_state;
 use lightning::ln::msgs::{MsgEncodable, MsgDecodable};
 
 mod utils;
-use utils::slice_to_be16;
 
 #[inline]
 pub fn do_test(data: &[u8]) {
        reset_rng_state();
-       let mut read_pos = 0;
-       loop {
-               test_msg!(msgs::MSG_TARGET, data, read_pos);
-       }
+       test_msg!(msgs::MSG_TARGET, data);
 }
 
 #[cfg(feature = "afl")]
index a6489cb41ad99d17fb109e1e9e6ebf789a684e27..2a2c80701cb98232ba054a1452454178746dd41f 100644 (file)
@@ -9,15 +9,11 @@ use lightning::util::reset_rng_state;
 use lightning::ln::msgs::{MsgEncodable, MsgDecodable};
 
 mod utils;
-use utils::slice_to_be16;
 
 #[inline]
 pub fn do_test(data: &[u8]) {
        reset_rng_state();
-       let mut read_pos = 0;
-       loop {
-               test_msg!(msgs::UpdateAddHTLC, data, read_pos);
-       }
+       test_msg!(msgs::UpdateAddHTLC, data);
 }
 
 #[cfg(feature = "afl")]
index d389b36ca6a6f9bbadd6c86b7d03518dbd05a663..aca62f7bb4bf9dd343f80b38f3f5596e939a97ad 100644 (file)
@@ -9,15 +9,11 @@ use lightning::util::reset_rng_state;
 use lightning::ln::msgs::{MsgEncodable, MsgDecodable};
 
 mod utils;
-use utils::slice_to_be16;
 
 #[inline]
 pub fn do_test(data: &[u8]) {
        reset_rng_state();
-       let mut read_pos = 0;
-       loop {
-               test_msg!(msgs::UpdateFailHTLC, data, read_pos);
-       }
+       test_msg!(msgs::UpdateFailHTLC, data);
 }
 
 #[cfg(feature = "afl")]
index 4ea37a5b1d9302689a9c56c6b12fa03fe445171d..e91bb3bdfd1a832d3a581df22a26622f2e57c06c 100644 (file)
@@ -9,15 +9,11 @@ use lightning::util::reset_rng_state;
 use lightning::ln::msgs::{MsgEncodable, MsgDecodable};
 
 mod utils;
-use utils::slice_to_be16;
 
 #[inline]
 pub fn do_test(data: &[u8]) {
        reset_rng_state();
-       let mut read_pos = 0;
-       loop {
-               test_msg!(msgs::UpdateFailMalformedHTLC, data, read_pos);
-       }
+       test_msg!(msgs::UpdateFailMalformedHTLC, data);
 }
 
 #[cfg(feature = "afl")]
index 4025d94908ba1846a71123c33d1e1a9772acf473..e7488306b16e98a9961371901b295237ea01bae8 100644 (file)
@@ -9,15 +9,11 @@ use lightning::util::reset_rng_state;
 use lightning::ln::msgs::{MsgEncodable, MsgDecodable};
 
 mod utils;
-use utils::slice_to_be16;
 
 #[inline]
 pub fn do_test(data: &[u8]) {
        reset_rng_state();
-       let mut read_pos = 0;
-       loop {
-               test_msg!(msgs::UpdateFee, data, read_pos);
-       }
+       test_msg!(msgs::UpdateFee, data);
 }
 
 #[cfg(feature = "afl")]
index edddfb54cbab41d96673cdce097adb5d999241d4..cd449908a1736faad13884d41c8cd516fd74ecd4 100644 (file)
@@ -9,15 +9,11 @@ use lightning::util::reset_rng_state;
 use lightning::ln::msgs::{MsgEncodable, MsgDecodable};
 
 mod utils;
-use utils::slice_to_be16;
 
 #[inline]
 pub fn do_test(data: &[u8]) {
        reset_rng_state();
-       let mut read_pos = 0;
-       loop {
-               test_msg!(msgs::UpdateFulfillHTLC, data, read_pos);
-       }
+       test_msg!(msgs::UpdateFulfillHTLC, data);
 }
 
 #[cfg(feature = "afl")]
index cfe5a10e9b0896e91a861052e13f458c6abe79a8..4d355585da5d18d42dceaabdd8188953e038c3f8 100644 (file)
@@ -1,50 +1,13 @@
 #![macro_use]
 
-#[allow(dead_code)]
-#[inline]
-pub fn slice_to_be16(v: &[u8]) -> u16 {
-       ((v[0] as u16) << 8*1) |
-       ((v[1] as u16) << 8*0)
-}
-
 #[macro_export]
 macro_rules! test_msg {
-       ($MsgType: path, $data: ident, $read_pos: ident) => {
-               {
-                       let len = slice_to_be16(get_slice!($data, $read_pos, 2));
-                       let raw = get_slice!($data, $read_pos, len);
-                       let cb = decode_msg!($MsgType, raw).encode();
-                       assert_eq!(&raw[..cb.len()], &cb[..]);
-               }
-       }
-}
-
-#[macro_export]
-macro_rules! decode_msg {
-       ($MsgType: path, $data: expr) => {
-               match <($MsgType)>::decode($data) {
-                       Ok(msg) => msg,
-                       Err(e) => match e {
-                               msgs::DecodeError::UnknownRealmByte => return,
-                               msgs::DecodeError::BadPublicKey => return,
-                               msgs::DecodeError::BadSignature => return,
-                               msgs::DecodeError::ExtraAddressesPerType => return,
-                               msgs::DecodeError::WrongLength => return,
-                       }
-               }
-       }
-}
-
-#[macro_export]
-macro_rules! get_slice {
-       ($data: ident, $read_pos: ident, $len: expr) => {
+       ($MsgType: path, $data: ident) => {
                {
-                       let slice_len = $len as usize;
-                       if $data.len() < $read_pos + slice_len {
-                               return;
+                       if let Ok(msg) = <$MsgType as MsgDecodable>::decode($data){
+                               let enc = msg.encode();
+                               assert_eq!(&$data[..enc.len()], &enc[..]);
                        }
-                       $read_pos += slice_len;
-                       &$data[$read_pos - slice_len..$read_pos]
                }
        }
 }
index 0a86b031eb1755401337fcf21ee051075536414e..bc7c0ed98b3c38052df2fa06f8eccb9078a2bd1f 100644 (file)
@@ -61,9 +61,16 @@ impl LocalFeatures {
                self.flags.len() > 0 && (self.flags[0] & 1) != 0
        }
 
-       pub fn supports_initial_routing_sync(&self) -> bool {
+       pub fn initial_routing_sync(&self) -> bool {
                self.flags.len() > 0 && (self.flags[0] & (1 << 3)) != 0
        }
+       pub fn set_initial_routing_sync(&mut self) {
+               if self.flags.len() == 0 {
+                       self.flags.resize(1, 1 << 3);
+               } else {
+                       self.flags[0] |= 1 << 3;
+               }
+       }
 
        pub fn supports_upfront_shutdown_script(&self) -> bool {
                self.flags.len() > 0 && (self.flags[0] & (3 << 4)) != 0
@@ -132,6 +139,15 @@ pub struct Init {
        pub local_features: LocalFeatures,
 }
 
+pub struct Ping {
+       pub ponglen: u16,
+       pub byteslen: u16,
+}
+
+pub struct Pong {
+       pub byteslen: u16,
+}
+
 pub struct OpenChannel {
        pub chain_hash: Sha256dHash,
        pub temporary_channel_id: Uint256,
@@ -357,7 +373,9 @@ pub enum ErrorAction {
                msg: UpdateFailHTLC
        },
        /// The peer took some action which made us think they were useless. Disconnect them.
-       DisconnectPeer {},
+       DisconnectPeer,
+       /// The peer did something harmless that we weren't able to process, just log and ignore
+       IgnoreError,
 }
 
 pub struct HandleError { //TODO: rename me
@@ -506,7 +524,7 @@ macro_rules! secp_signature {
 
 impl MsgDecodable for LocalFeatures {
        fn decode(v: &[u8]) -> Result<Self, DecodeError> {
-               if v.len() < 3 { return Err(DecodeError::WrongLength); }
+               if v.len() < 2 { return Err(DecodeError::WrongLength); }
                let len = byte_utils::slice_to_be16(&v[0..2]) as usize;
                if v.len() < len + 2 { return Err(DecodeError::WrongLength); }
                let mut flags = Vec::with_capacity(len);
@@ -528,7 +546,7 @@ impl MsgEncodable for LocalFeatures {
 
 impl MsgDecodable for GlobalFeatures {
        fn decode(v: &[u8]) -> Result<Self, DecodeError> {
-               if v.len() < 3 { return Err(DecodeError::WrongLength); }
+               if v.len() < 2 { return Err(DecodeError::WrongLength); }
                let len = byte_utils::slice_to_be16(&v[0..2]) as usize;
                if v.len() < len + 2 { return Err(DecodeError::WrongLength); }
                let mut flags = Vec::with_capacity(len);
@@ -570,6 +588,54 @@ impl MsgEncodable for Init {
        }
 }
 
+impl MsgDecodable for Ping {
+       fn decode(v: &[u8]) -> Result<Self, DecodeError> {
+               if v.len() < 4 {
+                       return Err(DecodeError::WrongLength);
+               }
+               let ponglen = byte_utils::slice_to_be16(&v[0..2]);
+               let byteslen = byte_utils::slice_to_be16(&v[2..4]);
+               if v.len() < 4 + byteslen as usize {
+                       return Err(DecodeError::WrongLength);
+               }
+               Ok(Self {
+                       ponglen,
+                       byteslen,
+               })
+       }
+}
+impl MsgEncodable for Ping {
+       fn encode(&self) -> Vec<u8> {
+               let mut res = Vec::with_capacity(self.byteslen as usize + 2);
+               res.extend_from_slice(&byte_utils::be16_to_array(self.byteslen));
+               res.resize(2 + self.byteslen as usize, 0);
+               res
+       }
+}
+
+impl MsgDecodable for Pong {
+       fn decode(v: &[u8]) -> Result<Self, DecodeError> {
+               if v.len() < 2 {
+                       return Err(DecodeError::WrongLength);
+               }
+               let byteslen = byte_utils::slice_to_be16(&v[0..2]);
+               if v.len() < 2 + byteslen as usize {
+                       return Err(DecodeError::WrongLength);
+               }
+               Ok(Self {
+                       byteslen
+               })
+       }
+}
+impl MsgEncodable for Pong {
+       fn encode(&self) -> Vec<u8> {
+               let mut res = Vec::with_capacity(self.byteslen as usize + 2);
+               res.extend_from_slice(&byte_utils::be16_to_array(self.byteslen));
+               res.resize(2 + self.byteslen as usize, 0);
+               res
+       }
+}
+
 impl MsgDecodable for OpenChannel {
        fn decode(v: &[u8]) -> Result<Self, DecodeError> {
                if v.len() < 2*32+6*8+4+2*2+6*33+1 {
index 7b140b0797284f04ca55d993b75a45f53be5069a..aec3a32e945b3f773c0519e46aec957696d1f50c 100644 (file)
@@ -8,6 +8,7 @@ use util::events::{EventsProvider,Event};
 
 use std::collections::{HashMap,LinkedList};
 use std::sync::{Arc, Mutex};
+use std::sync::atomic::{AtomicUsize, Ordering};
 use std::{cmp,error,mem,hash,fmt};
 
 pub struct MessageHandler {
@@ -86,6 +87,7 @@ pub struct PeerManager<Descriptor: SocketDescriptor> {
        peers: Mutex<PeerHolder<Descriptor>>,
        pending_events: Mutex<Vec<Event>>,
        our_node_secret: SecretKey,
+       initial_syncs_sent: AtomicUsize,
 }
 
 
@@ -101,6 +103,9 @@ macro_rules! encode_msg {
        }
 }
 
+//TODO: Really should do something smarter for this
+const INITIAL_SYNCS_TO_SEND: usize = 5;
+
 /// Manages and reacts to connection events. You probably want to use file descriptors as PeerIds.
 /// PeerIds may repeat, but only after disconnect_event() has been called.
 impl<Descriptor: SocketDescriptor> PeerManager<Descriptor> {
@@ -110,6 +115,7 @@ impl<Descriptor: SocketDescriptor> PeerManager<Descriptor> {
                        peers: Mutex::new(PeerHolder { peers: HashMap::new(), node_id_to_descriptor: HashMap::new() }),
                        pending_events: Mutex::new(Vec::new()),
                        our_node_secret: our_node_secret,
+                       initial_syncs_sent: AtomicUsize::new(0),
                }
        }
 
@@ -272,16 +278,19 @@ impl<Descriptor: SocketDescriptor> PeerManager<Descriptor> {
                                                                        match $thing {
                                                                                Ok(x) => x,
                                                                                Err(e) => {
-                                                                                       // TODO: Log e.err
+                                                                                       println!("Got error handling message: {}!", e.err);
                                                                                        if let Some(action) = e.msg {
                                                                                                match action {
                                                                                                        msgs::ErrorAction::UpdateFailHTLC { msg } => {
                                                                                                                encode_and_send_msg!(msg, 131);
                                                                                                                continue;
                                                                                                        },
-                                                                                                       msgs::ErrorAction::DisconnectPeer {} => {
+                                                                                                       msgs::ErrorAction::DisconnectPeer => {
                                                                                                                return Err(PeerHandleError{ no_connection_possible: false });
                                                                                                        },
+                                                                                                       msgs::ErrorAction::IgnoreError => {
+                                                                                                               continue;
+                                                                                                       },
                                                                                                }
                                                                                        } else {
                                                                                                return Err(PeerHandleError{ no_connection_possible: false });
@@ -296,6 +305,7 @@ impl<Descriptor: SocketDescriptor> PeerManager<Descriptor> {
                                                                        match $thing {
                                                                                Ok(x) => x,
                                                                                Err(_e) => {
+                                                                                       println!("Error decoding message");
                                                                                        //TODO: Handle e?
                                                                                        return Err(PeerHandleError{ no_connection_possible: false });
                                                                                }
@@ -303,6 +313,18 @@ impl<Descriptor: SocketDescriptor> PeerManager<Descriptor> {
                                                                }
                                                        }
 
+                                                       macro_rules! try_ignore_potential_decodeerror {
+                                                               ($thing: expr) => {
+                                                                       match $thing {
+                                                                               Ok(x) => x,
+                                                                               Err(_e) => {
+                                                                                       println!("Error decoding message, ignoring due to lnd spec incompatibility. See https://github.com/lightningnetwork/lnd/issues/1407");
+                                                                                       continue;
+                                                                               }
+                                                                       };
+                                                               }
+                                                       }
+
                                                        let next_step = peer.channel_encryptor.get_noise_step();
                                                        match next_step {
                                                                NextNoiseStep::ActOne => {
@@ -317,9 +339,14 @@ impl<Descriptor: SocketDescriptor> PeerManager<Descriptor> {
                                                                        peer.pending_read_is_header = true;
 
                                                                        insert_node_id = Some(peer.their_node_id.unwrap());
+                                                                       let mut local_features = msgs::LocalFeatures::new();
+                                                                       if self.initial_syncs_sent.load(Ordering::Acquire) < INITIAL_SYNCS_TO_SEND {
+                                                                               self.initial_syncs_sent.fetch_add(1, Ordering::AcqRel);
+                                                                               local_features.set_initial_routing_sync();
+                                                                       }
                                                                        encode_and_send_msg!(msgs::Init {
                                                                                global_features: msgs::GlobalFeatures::new(),
-                                                                               local_features: msgs::LocalFeatures::new(),
+                                                                               local_features,
                                                                        }, 16);
                                                                },
                                                                NextNoiseStep::ActThree => {
@@ -365,17 +392,29 @@ impl<Descriptor: SocketDescriptor> PeerManager<Descriptor> {
                                                                                                peer.their_local_features = Some(msg.local_features);
 
                                                                                                if !peer.outbound {
+                                                                                                       let mut local_features = msgs::LocalFeatures::new();
+                                                                                                       if self.initial_syncs_sent.load(Ordering::Acquire) < INITIAL_SYNCS_TO_SEND {
+                                                                                                               self.initial_syncs_sent.fetch_add(1, Ordering::AcqRel);
+                                                                                                               local_features.set_initial_routing_sync();
+                                                                                                       }
                                                                                                        encode_and_send_msg!(msgs::Init {
                                                                                                                global_features: msgs::GlobalFeatures::new(),
-                                                                                                               local_features: msgs::LocalFeatures::new(),
+                                                                                                               local_features,
                                                                                                        }, 16);
                                                                                                }
                                                                                        },
                                                                                        17 => {
                                                                                                // Error msg
                                                                                        },
-                                                                                       18 => { }, // ping
-                                                                                       19 => { }, // pong
+
+                                                                                       18 => {
+                                                                                               let msg = try_potential_decodeerror!(msgs::Ping::decode(&msg_data[2..]));
+                                                                                               let resp = msgs::Pong { byteslen: msg.ponglen };
+                                                                                               encode_and_send_msg!(resp, 19);
+                                                                                       },
+                                                                                       19 => {
+                                                                                               try_potential_decodeerror!(msgs::Pong::decode(&msg_data[2..]));
+                                                                                       },
 
                                                                                        // Channel control:
                                                                                        32 => {
@@ -491,7 +530,7 @@ impl<Descriptor: SocketDescriptor> PeerManager<Descriptor> {
                                                                                                }
                                                                                        },
                                                                                        257 => {
-                                                                                               let msg = try_potential_decodeerror!(msgs::NodeAnnouncement::decode(&msg_data[2..]));
+                                                                                               let msg = try_ignore_potential_decodeerror!(msgs::NodeAnnouncement::decode(&msg_data[2..]));
                                                                                                try_potential_handleerror!(self.message_handler.route_handler.handle_node_announcement(&msg));
                                                                                        },
                                                                                        258 => {
index 19a677580a5c101fe08e78d52ac17dbee4dc0ffe..e4473fa41838d87072d87cb13747c24f984cc442 100644 (file)
@@ -3,7 +3,7 @@ use secp256k1::{Secp256k1,Message};
 
 use bitcoin::util::hash::Sha256dHash;
 
-use ln::msgs::{HandleError,RoutingMessageHandler,MsgEncodable,NetAddress,GlobalFeatures};
+use ln::msgs::{ErrorAction,HandleError,RoutingMessageHandler,MsgEncodable,NetAddress,GlobalFeatures};
 use ln::msgs;
 
 use std::cmp;
@@ -122,10 +122,10 @@ impl RoutingMessageHandler for Router {
 
                let mut network = self.network_map.write().unwrap();
                match network.nodes.get_mut(&msg.contents.node_id) {
-                       None => Err(HandleError{err: "No existing channels for node_announcement", msg: None}),
+                       None => Err(HandleError{err: "No existing channels for node_announcement", msg: Some(ErrorAction::IgnoreError)}),
                        Some(node) => {
                                if node.last_update >= msg.contents.timestamp {
-                                       return Err(HandleError{err: "Update older than last processed update", msg: None});
+                                       return Err(HandleError{err: "Update older than last processed update", msg: Some(ErrorAction::IgnoreError)});
                                }
 
                                node.features = msg.contents.features.clone();
@@ -159,7 +159,7 @@ impl RoutingMessageHandler for Router {
                                //TODO: because asking the blockchain if short_channel_id is valid is only optional
                                //in the blockchain API, we need to handle it smartly here, though its unclear
                                //exactly how...
-                               return Err(HandleError{err: "Already have knowledge of channel", msg: None})
+                               return Err(HandleError{err: "Already have knowledge of channel", msg: Some(ErrorAction::IgnoreError)})
                        },
                        Entry::Vacant(entry) => {
                                entry.insert(ChannelInfo {
@@ -233,12 +233,12 @@ impl RoutingMessageHandler for Router {
                let chan_was_enabled;
 
                match network.channels.get_mut(&NetworkMap::get_key(msg.contents.short_channel_id, msg.contents.chain_hash)) {
-                       None => return Err(HandleError{err: "Couldn't find channel for update", msg: None}),
+                       None => return Err(HandleError{err: "Couldn't find channel for update", msg: Some(ErrorAction::IgnoreError)}),
                        Some(channel) => {
                                macro_rules! maybe_update_channel_info {
                                        ( $target: expr) => {
                                                if $target.last_update >= msg.contents.timestamp {
-                                                       return Err(HandleError{err: "Update older than last processed update", msg: None});
+                                                       return Err(HandleError{err: "Update older than last processed update", msg: Some(ErrorAction::IgnoreError)});
                                                }
                                                chan_was_enabled = $target.enabled;
                                                $target.last_update = msg.contents.timestamp;