diff --git a/fuzz/src/full_stack.rs b/fuzz/src/full_stack.rs index 42da4d90312..fc45b7b91c3 100644 --- a/fuzz/src/full_stack.rs +++ b/fuzz/src/full_stack.rs @@ -30,7 +30,7 @@ use lightning::chain::transaction::OutPoint; use lightning::chain::keysinterface::{InMemoryChannelKeys, KeysInterface}; use lightning::ln::channelmonitor; use lightning::ln::channelmanager::{ChannelManager, PaymentHash, PaymentPreimage, PaymentSecret}; -use lightning::ln::peer_handler::{MessageHandler,PeerManager,SocketDescriptor}; +use lightning::ln::peers::handler::{MessageHandler,PeerManager,SocketDescriptor}; use lightning::routing::router::get_route; use lightning::routing::network_graph::NetGraphMsgHandler; use lightning::util::events::{EventsProvider,Event}; @@ -894,15 +894,15 @@ mod tests { super::do_test(&::hex::decode("00000000000000000000000000000000000000000000000000000000000000000000000001000300000000000000000000000000000000000000000000000000000000000000000300320003000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000030012000a0300000000000000000000000000000003001a00100002200000022000030000000000000000000000000000000300120141030000000000000000000000000000000300fe00207500000000000000000000000000000000000000000000000000000000000000ff4f00f805273c1b203bb5ebf8436bfde57b3be8c2f5e95d9491dbb181909679000000000000c35000000000000000000000000000000222ffffffffffffffff00000000000002220000000000000000000000fd000601e3030000000000000000000000000000000000000000000000000000000000000001030000000000000000000000000000000000000000000000000000000000000002030000000000000000000000000000000000000000000000000000000000000003030000000000000000000000000000000000000000000000000000000000000004030053030000000000000000000000000000000000000000000000000000000000000005030000000000000000000000000000000000000000000000000000000000000000010300000000000000000000000000000000fd00fd00fd0300120084030000000000000000000000000000000300940022ff4f00f805273c1b203bb5ebf8436bfde57b3be8c2f5e95d9491dbb1819096793d00000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001030000000000000000000000000000000c005e020000000100000000000000000000000000000000000000000000000000000000000000000000000000ffffffff0150c3000000000000220020ae00000000000000000000000000000000000000000000000000000000000000000000000c00000c00000c00000c00000c00000c00000c00000c00000c00000c00000c00000c000003001200430300000000000000000000000000000003005300243d0000000000000000000000000000000000000000000000000000000000000003010000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000010301320003000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000030142000302000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000003000000000000000000000000000000030112000a0100000000000000000000000000000003011a0010000220000002200001000000000000000000000000000000050103020000000000000000000000000000000000000000000000000000000000000000c3500003e800fd00fd0301120110010000000000000000000000000000000301ff00210000000000000000000000000000000000000000000000000000000000000e02000000000000001a00000000004c4b4000000000000003e800000000000003e80000000203f00005030000000000000000000000000000000000000000000000000000000000000100030000000000000000000000000000000000000000000000000000000000000200030000000000000000000000000000000000000000000000000000000000000300030000000000000000000000000000000000000000000000000000000000000400030000000000000000000000000000000000000000000000000000000000000500030000000000000000000000000000000301210000000000000000000000000000000000010000000000000000000000000000000a03011200620100000000000000000000000000000003017200233900000000000000000000000000000000000000000000000000000000000000f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100010000000000000000000000000000000b030112004301000000000000000000000000000000030153002439000000000000000000000000000000000000000000000000000000000000000301000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000003001205ac030000000000000000000000000000000300ff00803d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003e80ff0000000000000000000000000000000000000000000000000000000000000000000121000300000000000000000000000000000000000000000000000000000000000005550000000e000001000000000000000003e80000007b0000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300c1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff95000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000fd03001200640300000000000000000000000000000003007400843d000000000000000000000000000000000000000000000000000000000000003100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000300000000000000000000000000000003001200630300000000000000000000000000000003007300853d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000703011200640100000000000000000000000000000003017400843900000000000000000000000000000000000000000000000000000000000000f100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000100000000000000000000000000000003011200630100000000000000000000000000000003017300853900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003020000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000030112004a0100000000000000000000000000000003015a008239000000000000000000000000000000000000000000000000000000000000000000000000000000ff008888888888888888888888888888888888888888888888888888888888880100000000000000000000000000000003011200640100000000000000000000000000000003017400843900000000000000000000000000000000000000000000000000000000000000fd0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000010000000000000000000000000000000301120063010000000000000000000000000000000301730085390000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000303000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000003001205ac030000000000000000000000000000000300ff00803d0000000000000000000000000000000000000000000000000000000000000000000000000000010000000000003e80ff0000000000000000000000000000000000000000000000000000000000000000000121000300000000000000000000000000000000000000000000000000000000000005550000000e000001000000000000000003e80000007b0000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300c1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff95000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000fd03001200630300000000000000000000000000000003007300853d0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000303000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000003001200640300000000000000000000000000000003007400843d00000000000000000000000000000000000000000000000000000000000000c200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000300000000000000000000000000000003001200630300000000000000000000000000000003007300853d000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030400000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000703011200640100000000000000000000000000000003017400843900000000000000000000000000000000000000000000000000000000000000fc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000100000000000000000000000000000003011200630100000000000000000000000000000003017300853900000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003040000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000030112002c0100000000000000000000000000000003013c00833900000000000000000000000000000000000000000000000000000000000000000000000000000100000100000000000000000000000000000003011200640100000000000000000000000000000003017400843900000000000000000000000000000000000000000000000000000000000000fb000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000001000000000000000000000000000000030112006301000000000000000000000000000000030173008539000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000030500000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000703001200630300000000000000000000000000000003007300853d0000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000305000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000003001200640300000000000000000000000000000003007400843d000000000000000000000000000000000000000000000000000000000000003300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000300000000000000000000000000000003001205ac030000000000000000000000000000000300ff00803d00000000000000000000000000000000000000000000000000000000000000000000000000000200000000000b0838ff0000000000000000000000000000000000000000000000000000000000000000000121000300000000000000000000000000000000000000000000000000000000000005550000000e0000010000000000000003e8000000007b0000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300c1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff95000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000fd03001200a4030000000000000000000000000000000300b400843d000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001c8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007f000000000000000300000000000000000000000000000003001200630300000000000000000000000000000003007300853d00000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000003060000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000070c007d02000000013900000000000000000000000000000000000000000000000000000000000000000000000000000080020001000000000000220020bb000000000000000000000000000000000000000000000000000000000000006cc10000000000001600142b000000000000000000000000000000000000000500002000fd00fd0c005e0200000001a100000000000000000000000000000000000000000000000000000000000000000000000000000000014f00000000000000220020f600000000000000000000000000000000000000000000000000000000000000000000000c00000c000000fd0c00000c00000c000007").unwrap(), &(Arc::clone(&logger) as Arc)); let log_entries = logger.lines.lock().unwrap(); - assert_eq!(log_entries.get(&("lightning::ln::peer_handler".to_string(), "Handling SendAcceptChannel event in peer_handler for node 030000000000000000000000000000000000000000000000000000000000000000 for channel ff4f00f805273c1b203bb5ebf8436bfde57b3be8c2f5e95d9491dbb181909679".to_string())), Some(&1)); // 1 - assert_eq!(log_entries.get(&("lightning::ln::peer_handler".to_string(), "Handling SendFundingSigned event in peer_handler for node 030000000000000000000000000000000000000000000000000000000000000000 for channel 3d00000000000000000000000000000000000000000000000000000000000000".to_string())), Some(&1)); // 2 - assert_eq!(log_entries.get(&("lightning::ln::peer_handler".to_string(), "Handling SendFundingLocked event in peer_handler for node 030000000000000000000000000000000000000000000000000000000000000000 for channel 3d00000000000000000000000000000000000000000000000000000000000000".to_string())), Some(&1)); // 3 - assert_eq!(log_entries.get(&("lightning::ln::peer_handler".to_string(), "Handling SendFundingLocked event in peer_handler for node 030200000000000000000000000000000000000000000000000000000000000000 for channel 3900000000000000000000000000000000000000000000000000000000000000".to_string())), Some(&1)); // 4 - assert_eq!(log_entries.get(&("lightning::ln::peer_handler".to_string(), "Handling SendRevokeAndACK event in peer_handler for node 030000000000000000000000000000000000000000000000000000000000000000 for channel 3d00000000000000000000000000000000000000000000000000000000000000".to_string())), Some(&4)); // 5 - assert_eq!(log_entries.get(&("lightning::ln::peer_handler".to_string(), "Handling UpdateHTLCs event in peer_handler for node 030000000000000000000000000000000000000000000000000000000000000000 with 0 adds, 0 fulfills, 0 fails for channel 3d00000000000000000000000000000000000000000000000000000000000000".to_string())), Some(&3)); // 6 - assert_eq!(log_entries.get(&("lightning::ln::peer_handler".to_string(), "Handling UpdateHTLCs event in peer_handler for node 030200000000000000000000000000000000000000000000000000000000000000 with 1 adds, 0 fulfills, 0 fails for channel 3900000000000000000000000000000000000000000000000000000000000000".to_string())), Some(&3)); // 7 - assert_eq!(log_entries.get(&("lightning::ln::peer_handler".to_string(), "Handling UpdateHTLCs event in peer_handler for node 030000000000000000000000000000000000000000000000000000000000000000 with 0 adds, 1 fulfills, 0 fails for channel 3d00000000000000000000000000000000000000000000000000000000000000".to_string())), Some(&1)); // 8 - assert_eq!(log_entries.get(&("lightning::ln::peer_handler".to_string(), "Handling UpdateHTLCs event in peer_handler for node 030000000000000000000000000000000000000000000000000000000000000000 with 0 adds, 0 fulfills, 1 fails for channel 3d00000000000000000000000000000000000000000000000000000000000000".to_string())), Some(&2)); // 9 + assert_eq!(log_entries.get(&("lightning::ln::peers::handler".to_string(), "Handling SendAcceptChannel event in peer_handler for node 030000000000000000000000000000000000000000000000000000000000000000 for channel ff4f00f805273c1b203bb5ebf8436bfde57b3be8c2f5e95d9491dbb181909679".to_string())), Some(&1)); // 1 + assert_eq!(log_entries.get(&("lightning::ln::peers::handler".to_string(), "Handling SendFundingSigned event in peer_handler for node 030000000000000000000000000000000000000000000000000000000000000000 for channel 3d00000000000000000000000000000000000000000000000000000000000000".to_string())), Some(&1)); // 2 + assert_eq!(log_entries.get(&("lightning::ln::peers::handler".to_string(), "Handling SendFundingLocked event in peer_handler for node 030000000000000000000000000000000000000000000000000000000000000000 for channel 3d00000000000000000000000000000000000000000000000000000000000000".to_string())), Some(&1)); // 3 + assert_eq!(log_entries.get(&("lightning::ln::peers::handler".to_string(), "Handling SendFundingLocked event in peer_handler for node 030200000000000000000000000000000000000000000000000000000000000000 for channel 3900000000000000000000000000000000000000000000000000000000000000".to_string())), Some(&1)); // 4 + assert_eq!(log_entries.get(&("lightning::ln::peers::handler".to_string(), "Handling SendRevokeAndACK event in peer_handler for node 030000000000000000000000000000000000000000000000000000000000000000 for channel 3d00000000000000000000000000000000000000000000000000000000000000".to_string())), Some(&4)); // 5 + assert_eq!(log_entries.get(&("lightning::ln::peers::handler".to_string(), "Handling UpdateHTLCs event in peer_handler for node 030000000000000000000000000000000000000000000000000000000000000000 with 0 adds, 0 fulfills, 0 fails for channel 3d00000000000000000000000000000000000000000000000000000000000000".to_string())), Some(&3)); // 6 + assert_eq!(log_entries.get(&("lightning::ln::peers::handler".to_string(), "Handling UpdateHTLCs event in peer_handler for node 030200000000000000000000000000000000000000000000000000000000000000 with 1 adds, 0 fulfills, 0 fails for channel 3900000000000000000000000000000000000000000000000000000000000000".to_string())), Some(&3)); // 7 + assert_eq!(log_entries.get(&("lightning::ln::peers::handler".to_string(), "Handling UpdateHTLCs event in peer_handler for node 030000000000000000000000000000000000000000000000000000000000000000 with 0 adds, 1 fulfills, 0 fails for channel 3d00000000000000000000000000000000000000000000000000000000000000".to_string())), Some(&1)); // 8 + assert_eq!(log_entries.get(&("lightning::ln::peers::handler".to_string(), "Handling UpdateHTLCs event in peer_handler for node 030000000000000000000000000000000000000000000000000000000000000000 with 0 adds, 0 fulfills, 1 fails for channel 3d00000000000000000000000000000000000000000000000000000000000000".to_string())), Some(&2)); // 9 assert_eq!(log_entries.get(&("lightning::ln::channelmonitor".to_string(), "Input spending counterparty commitment tx (00000000000000000000000000000000000000000000000000000000000000a1:0) in 0000000000000000000000000000000000000000000000000000000000000018 resolves outbound HTLC with payment hash ff00000000000000000000000000000000000000000000000000000000000000 with timeout".to_string())), Some(&1)); // 10 } } diff --git a/fuzz/src/peer_crypt.rs b/fuzz/src/peer_crypt.rs index f41137fc828..522e8a40361 100644 --- a/fuzz/src/peer_crypt.rs +++ b/fuzz/src/peer_crypt.rs @@ -7,81 +7,363 @@ // You may not use this file except in accordance with one or both of these // licenses. -use lightning::ln::peer_channel_encryptor::PeerChannelEncryptor; +use std::cmp; +use std::{error, fmt}; -use bitcoin::secp256k1::key::{PublicKey,SecretKey}; +use bitcoin::secp256k1; +use bitcoin::secp256k1::key::{PublicKey,SecretKey}; +use lightning::ln::peers::handshake::{CompletedHandshakeInfo, PeerHandshake}; +use lightning::ln::peers::transport::IPeerHandshake; use utils::test_logger; -#[inline] -fn slice_to_be16(v: &[u8]) -> u16 { - ((v[0] as u16) << 8*1) | - ((v[1] as u16) << 8*0) +// Test structure used to generate "random" values based on input data. It is used throughout +// the various test cases to send random messages between nodes and to ensure the code does not fail +// unexpectedly. +pub struct FuzzGen<'a> { + read_pos: usize, + data: &'a [u8], +} + +impl<'a> FuzzGen<'a> { + fn new(data: &'a [u8]) -> Self { + Self { + read_pos: 0, + data + } + } + + fn generate_bytes(&mut self, num: usize) -> Result<&'a [u8], GeneratorFinishedError> { + if self.data.len() < self.read_pos + num { + return Err(GeneratorFinishedError { }); + } + + self.read_pos += num; + Ok(&self.data[self.read_pos - num..self.read_pos]) + } + + fn generate_secret_key(&mut self) -> Result { + // Loop through the input 32 bytes at a time until a valid + // secret key can be created or we run out of bytes + loop { + match SecretKey::from_slice(self.generate_bytes(32)?) { + Ok(key) => { return Ok(key) }, + _ => { } + } + } + } + + fn generate_bool(&mut self) -> Result { + let next_byte = self.generate_bytes(1)?; + Ok(next_byte[0] & 1 == 1) + } } +#[derive(PartialEq)] +struct GeneratorFinishedError { } + +impl fmt::Debug for GeneratorFinishedError { + fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { + formatter.write_str("Generator out of bytes") + } +} +impl fmt::Display for GeneratorFinishedError { + fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { + formatter.write_str("Generator out of bytes") + } +} +impl error::Error for GeneratorFinishedError { + fn description(&self) -> &str { "Generator out of bytes" } +} + +struct TestCtx { + initiator_static_public_key: PublicKey, + initiator_handshake: PeerHandshake, + responder_static_public_key: PublicKey, + responder_handshake: PeerHandshake, + act1: Vec +} + +impl TestCtx { + fn make(generator: &mut FuzzGen) -> Result { + let curve = secp256k1::Secp256k1::new(); + + // Generate needed keys for successful handshake + let initiator_static_private_key = generator.generate_secret_key()?; + let initiator_static_public_key = PublicKey::from_secret_key(&curve, &initiator_static_private_key); + let initiator_ephemeral_private_key = generator.generate_secret_key()?; + let responder_static_private_key = generator.generate_secret_key()?; + let responder_static_public_key = PublicKey::from_secret_key(&curve, &responder_static_private_key); + let responder_ephemeral_private_key = generator.generate_secret_key()?; + + let mut initiator_handshake = PeerHandshake::new_outbound(&initiator_static_private_key, &responder_static_public_key, &initiator_ephemeral_private_key); + let act1 = initiator_handshake.set_up_outbound(); + let responder_handshake = PeerHandshake::new_inbound(&responder_static_private_key, &responder_ephemeral_private_key); + + Ok(TestCtx { + initiator_static_public_key, + initiator_handshake, + responder_static_public_key, + responder_handshake, + act1 + }) + } +} + +// Common test function that sends encrypted messages between an encryptor/decryptor until the +// source data runs out. #[inline] -pub fn do_test(data: &[u8]) { - let mut read_pos = 0; - macro_rules! get_slice { - ($len: expr) => { - { - let slice_len = $len as usize; - if data.len() < read_pos + slice_len { - return; +fn do_encrypted_communication_tests(generator: &mut FuzzGen, + initiator_completed_handshake_info: &mut CompletedHandshakeInfo, + responder_completed_handshake_info: &mut CompletedHandshakeInfo, + failures_expected: bool) -> Result<(), GeneratorFinishedError> { + // Keep sending messages back and forth until the input data is consumed + loop { + // Randomly generate message length + let msg_len_raw = generator.generate_bytes(1)?; + let msg_len = msg_len_raw[0] as usize; + + // Randomly generate message + let sender_unencrypted_msg = generator.generate_bytes(msg_len)?; + + // randomly choose sender of message + let receiver_unencrypted_msg = if generator.generate_bool()? { + let encrypted_msg = initiator_completed_handshake_info.encryptor.encrypt(sender_unencrypted_msg); + if let Ok(_) = responder_completed_handshake_info.decryptor.read(&encrypted_msg) { + if let Some(msg) = responder_completed_handshake_info.decryptor.next() { + msg + } else { + assert!(failures_expected); + return Ok(()); } - read_pos += slice_len; - &data[read_pos - slice_len..read_pos] + } else { + assert!(failures_expected); + return Ok(()); } - } + } else { + let encrypted_msg = responder_completed_handshake_info.encryptor.encrypt(sender_unencrypted_msg); + if let Ok(_) = initiator_completed_handshake_info.decryptor.read(&encrypted_msg) { + if let Some(msg) = initiator_completed_handshake_info.decryptor.next() { + msg + } else { + assert!(failures_expected); + return Ok(()); + } + } else { + assert!(failures_expected); + return Ok(()); + } + }; + + assert_eq!(sender_unencrypted_msg, receiver_unencrypted_msg.as_slice()); } +} + +// This test completes a valid handshake based on "random" private keys and then sends variable +// length encrypted messages between the local and remote encryptor/decryptor to verify they can +// communicate. +#[inline] +fn do_completed_handshake_test(generator: &mut FuzzGen) -> Result<(), GeneratorFinishedError> { + let mut test_ctx = TestCtx::make(generator)?; - let our_network_key = match SecretKey::from_slice(get_slice!(32)) { - Ok(key) => key, - Err(_) => return, + // The handshake should complete with any valid private keys + let act2 = test_ctx.responder_handshake.process_act(&test_ctx.act1).unwrap().0.unwrap(); + let (act3, mut initiator_completed_handshake_info) = match test_ctx.initiator_handshake.process_act(&act2) { + Ok((Some(act3), Some(completed_handshake_info))) => { + (act3, completed_handshake_info) + } + _ => panic!("handshake failed") }; - let ephemeral_key = match SecretKey::from_slice(get_slice!(32)) { - Ok(key) => key, - Err(_) => return, + + let mut responder_completed_handshake_info = match test_ctx.responder_handshake.process_act(&act3) { + Ok((None, Some(completed_handshake_info))) => { + completed_handshake_info + } + _ => panic!("handshake failed") }; - let mut crypter = if get_slice!(1)[0] != 0 { - let their_pubkey = match PublicKey::from_slice(get_slice!(33)) { - Ok(key) => key, - Err(_) => return, + // The handshake should complete with each peer knowing the static_public_key of the remote peer + assert_eq!(responder_completed_handshake_info.their_node_id, test_ctx.initiator_static_public_key); + assert_eq!(initiator_completed_handshake_info.their_node_id, test_ctx.responder_static_public_key); + + // The nodes should be able to communicate with the Encryptor/Decryptors + do_encrypted_communication_tests(generator, &mut initiator_completed_handshake_info, &mut responder_completed_handshake_info, false) +} + +// Either returns (act, false) or (random_bytes, true) where random_bytes is the same len as act +fn maybe_generate_bad_act(generator: &mut FuzzGen, act: Vec) -> Result<(Vec, bool), GeneratorFinishedError> { + if generator.generate_bool()? { + Ok(((generator.generate_bytes(act.len())?).to_vec(), true)) + } else { + Ok((act, false)) + } +} + +// Add between 0..15 bytes of garbage to a vec and returns whether or not it added bytes +fn maybe_add_garbage(generator: &mut FuzzGen, input: &mut Vec) -> Result { + let garbage_amount = (generator.generate_bytes(1)?)[0] >> 4; + + if garbage_amount != 0 { + input.extend(generator.generate_bytes(garbage_amount as usize)?); + Ok(true) + } else { + Ok(false) + } +} + +// Splits a Vec into between 1..7 chunks returning a Vec of slices into the original data +fn split_vec<'a>(generator: &mut FuzzGen, input: &'a Vec) -> Result, GeneratorFinishedError> { + let num_chunks = cmp::max(1, ((generator.generate_bytes(1)?)[0] as u8) >> 5) as usize; + let chunk_size = input.len() / num_chunks; + + Ok(input.chunks(chunk_size).collect()) +} + +// This test variant goes through the peer handshake between the initiator and responder with +// "random" failures to verify that nothing panics. +// In the event of an error from process_act() we validate that the input data was generated +// randomly to ensure real act generation still produces valid transitions. +#[inline] +fn do_handshake_test(generator: &mut FuzzGen) -> Result<(), GeneratorFinishedError> { + let mut test_ctx = TestCtx::make(generator)?; + + // Possibly generate bad data for act1 + let (mut act1, mut used_generated_data) = maybe_generate_bad_act(generator, test_ctx.act1)?; + + // Optionally, add garbage data to the end + used_generated_data |= maybe_add_garbage(generator, &mut act1)?; + + // Split act1 into between 1..7 chunks + let act1_chunks = split_vec(generator, &act1)?; + + let mut act2_option = None; + for partial_act1 in act1_chunks { + match test_ctx.responder_handshake.process_act(&partial_act1) { + // Save valid act2 for initiator + Ok((Some(act2_option_inner), None)) => { + act2_option = Some(act2_option_inner); + }, + // Partial act + Ok((None, None)) => { } + // errors are fine as long as they happened due to using bad data + Err(_) => { + assert!(used_generated_data); + return Ok(()); + } + _ => panic!("responder required to output act bytes and no completed_handshake_info") + }; + } + let act2 = act2_option.unwrap(); + + // Possibly generate bad data for act2 + let (mut act2, is_bad_data) = maybe_generate_bad_act(generator, act2)?; + + // Optionally, add garbage data to the end + let did_add_garbage = maybe_add_garbage(generator, &mut act2)?; + + // Keep track of whether or not we have generated bad data up to this point + used_generated_data |= (is_bad_data | did_add_garbage); + + // Split act2 into between 1..7 chunks + let act2_chunks = split_vec(generator, &act2)?; + + let mut act3_option = None; + let mut initiator_completed_handshake_info_option = None; + for partial_act2 in act2_chunks { + match test_ctx.initiator_handshake.process_act(&partial_act2) { + Ok((Some(act3), Some(completed_handshake_info_option_inner))) => { + act3_option = Some(act3); + initiator_completed_handshake_info_option = Some(completed_handshake_info_option_inner); + + // Valid completed_handshake_info indicates handshake is over + break; + } + // Partial act + Ok((None, None)) => { }, + // errors are fine as long as they happened due to using bad data + Err(_) => { + assert!(used_generated_data); + return Ok(()); + } + _ => panic!("initiator required to output act bytes and completed_handshake_info") + }; + } + + // Ensure we actually received act3 bytes, completed_handshake_info from process_act() + let act3 = act3_option.unwrap(); + let mut initiator_completed_handshake_info = initiator_completed_handshake_info_option.unwrap(); + + // Possibly generate bad data for act3 + let (mut act3, is_bad_data) = maybe_generate_bad_act(generator, act3)?; + + // Optionally, add garbage data to the end + let did_add_garbage = maybe_add_garbage(generator, &mut act3)?; + + // Keep track of whether or not we have generated bad data up to this point + used_generated_data |= (is_bad_data | did_add_garbage); + + // Split act3 into between 1..7 chunks + let act3_chunks = split_vec(generator, &act3)?; + + let mut responder_completed_handshake_info = None; + for partial_act3 in act3_chunks { + match test_ctx.responder_handshake.process_act(&partial_act3) { + Ok((None, Some(completed_handshake_info_inner))) => { + responder_completed_handshake_info = Some(completed_handshake_info_inner); + + // Valid completed_handshake_info indicates handshake is over + break; + }, + // partial act + Ok((None, None)) => { }, + // errors are fine as long as they happened due to using bad data + Err(_) => { + assert!(used_generated_data); + return Ok(()); + }, + _ => panic!("responder required to output completed_handshake_info") }; - let mut crypter = PeerChannelEncryptor::new_outbound(their_pubkey, ephemeral_key); - crypter.get_act_one(); - match crypter.process_act_two(get_slice!(50), &our_network_key) { - Ok(_) => {}, - Err(_) => return, + } + // Ensure we actually received completed_handshake_info from process_act() + let mut responder_completed_handshake_info = responder_completed_handshake_info.unwrap(); + + // The handshake should complete with each peer knowing the static_public_key of the remote peer + if responder_completed_handshake_info.their_node_id != test_ctx.initiator_static_public_key { + assert!(used_generated_data); + return Ok(()); + } + if initiator_completed_handshake_info.their_node_id != test_ctx.responder_static_public_key { + assert!(used_generated_data); + return Ok(()); + } + + // The nodes should be able to communicate over the encryptor/decryptor + do_encrypted_communication_tests(generator, &mut initiator_completed_handshake_info, &mut responder_completed_handshake_info, used_generated_data) +} + +#[inline] +fn do_test(data: &[u8]) { + let mut generator = FuzzGen::new(data); + + // Based on a "random" bool, decide which test variant to run + let do_valid_handshake = match generator.generate_bool() { + Ok(value) => { value }, + _ => { return } + }; + + // The only valid error that can leak here is the FuzzGen error to indicate + // the input bytes have been exhausted and the test can't proceed. Everything + // else should be caught and handled by the individual tests to validate any + // errors. + if do_valid_handshake { + match do_completed_handshake_test(&mut generator) { + Err(_) => { } + _ => { } } - assert!(crypter.is_ready_for_encryption()); - crypter } else { - let mut crypter = PeerChannelEncryptor::new_inbound(&our_network_key); - match crypter.process_act_one_with_keys(get_slice!(50), &our_network_key, ephemeral_key) { - Ok(_) => {}, - Err(_) => return, - } - match crypter.process_act_three(get_slice!(66)) { - Ok(_) => {}, - Err(_) => return, - } - assert!(crypter.is_ready_for_encryption()); - crypter - }; - loop { - if get_slice!(1)[0] == 0 { - crypter.encrypt_message(get_slice!(slice_to_be16(get_slice!(2)))); - } else { - let len = match crypter.decrypt_length_header(get_slice!(16+2)) { - Ok(len) => len, - Err(_) => return, - }; - match crypter.decrypt_message(get_slice!(len as usize + 16)) { - Ok(_) => {}, - Err(_) => return, - } + match do_handshake_test(&mut generator) { + Err(_) => { } + _ => { } } } } @@ -94,3 +376,145 @@ pub fn peer_crypt_test(data: &[u8], _out: Out) { pub extern "C" fn peer_crypt_run(data: *const u8, datalen: usize) { do_test(unsafe { std::slice::from_raw_parts(data, datalen) }); } + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn data_generator_empty() { + let mut generator = FuzzGen::new(&[]); + assert_eq!(generator.generate_bool(), Err(GeneratorFinishedError { })); + } + + #[test] + fn data_generator_bool_true() { + let mut generator = FuzzGen::new(&[1]); + assert!(generator.generate_bool().unwrap()); + } + + #[test] + fn data_generator_bool_false() { + let mut generator = FuzzGen::new(&[0]); + assert!(!generator.generate_bool().unwrap()); + } + + #[test] + fn data_generator_bool_then_error() { + let mut generator = FuzzGen::new(&[1]); + assert!(generator.generate_bool().unwrap()); + assert_eq!(generator.generate_bool(), Err(GeneratorFinishedError { })); + } + + #[test] + fn data_generator_bytes_too_many() { + let mut generator = FuzzGen::new(&[1, 2, 3, 4]); + assert_eq!(generator.generate_bytes(5), Err(GeneratorFinishedError { })); + } + + #[test] + fn data_generator_bytes() { + let input = [1, 2, 3, 4]; + let mut generator = FuzzGen::new(&input); + let result = generator.generate_bytes(4).unwrap(); + assert_eq!(result, input); + } + + #[test] + fn data_generator_bytes_sequential() { + let input = [1, 2, 3, 4]; + let mut generator = FuzzGen::new(&input); + let result = generator.generate_bytes(2).unwrap(); + assert_eq!(result, &input[..2]); + let result = generator.generate_bytes(2).unwrap(); + assert_eq!(result, &input[2..]); + assert_eq!(generator.generate_bytes(1), Err(GeneratorFinishedError { })); + } + + #[test] + fn maybe_generate_bad_act_gen_bad() { + // 1 is used to take bad branch and 2 is used to generate bad act + let input = [1, 2]; + let mut generator = FuzzGen::new(&input); + + let original_act = &[5]; + + let (act, is_bad) = maybe_generate_bad_act(&mut generator, original_act.to_vec()).unwrap(); + assert!(is_bad); + assert_eq!(act, &[2]); + } + + #[test] + fn maybe_generate_bad_act_gen_good() { + // 0 is used to take good branch + let input = [0]; + let mut generator = FuzzGen::new(&input); + let original_act = &[5]; + + let (act, is_bad) = maybe_generate_bad_act(&mut generator, original_act.to_vec()).unwrap(); + assert!(!is_bad); + assert_eq!(act, &[5]); + } + + #[test] + fn maybe_add_garbage_did_add() { + // 0x10 consumed to specify amount of garbage (1 byte) and 2 is consumed to add garbage + let input = [0x10, 2]; + let mut generator = FuzzGen::new(&input); + let mut act = vec![5]; + + let did_add_garbage = maybe_add_garbage(&mut generator, &mut act).unwrap(); + assert!(did_add_garbage); + assert_eq!(act, &[5, 2]); + } + + #[test] + fn maybe_add_garbage_no_add() { + // 0x10 consumed to specify amount of garbage (1 byte) and 2 is consumed to add garbage + let input = [0]; + let mut generator = FuzzGen::new(&input); + let mut act = vec![5]; + + let did_add_garbage = maybe_add_garbage(&mut generator, &mut act).unwrap(); + assert!(!did_add_garbage); + assert_eq!(act, &[5]); + } + + #[test] + fn split_vec_1_chunk() { + // 0 consumed for number of chunks (1 is min) + let input = [0]; + let mut generator = FuzzGen::new(&input); + let act = vec![5, 6]; + + let act_parts = split_vec(&mut generator, &act).unwrap(); + assert_eq!(act_parts.len(), 1); + assert_eq!(act_parts[0], &[5, 6]); + } + + #[test] + fn split_vec_2_chunks() { + // 40 consumed for number of chunks. Chunk size is equal to the high three bits (2) + let input = [0x40]; + let mut generator = FuzzGen::new(&input); + let act = vec![5, 6]; + + let act_parts = split_vec(&mut generator, &act).unwrap(); + assert_eq!(act_parts.len(), 2); + assert_eq!(act_parts[0], &[5]); + assert_eq!(act_parts[1], &[6]); + } + #[test] + fn split_vec_2_chunks_odd() { + // 40 consumed for number of chunks. Chunk size is equal to the high three bits (2) + let input = [0x40]; + let mut generator = FuzzGen::new(&input); + let act = vec![5, 6, 7, 8, 9]; + + let act_parts = split_vec(&mut generator, &act).unwrap(); + assert_eq!(act_parts.len(), 3); + assert_eq!(act_parts[0], &[5, 6]); + assert_eq!(act_parts[1], &[7, 8]); + assert_eq!(act_parts[2], &[9]); + } +} \ No newline at end of file diff --git a/lightning-net-tokio/src/lib.rs b/lightning-net-tokio/src/lib.rs index a7818d7b85c..6e2ff91ab0f 100644 --- a/lightning-net-tokio/src/lib.rs +++ b/lightning-net-tokio/src/lib.rs @@ -37,7 +37,7 @@ //! type ChainWatchInterface = dyn lightning::chain::chaininterface::ChainWatchInterface; //! type ChannelMonitor = lightning::ln::channelmonitor::SimpleManyChannelMonitor, Arc, Arc, Arc>; //! type ChannelManager = lightning::ln::channelmanager::SimpleArcChannelManager; -//! type PeerManager = lightning::ln::peer_handler::SimpleArcPeerManager; +//! type PeerManager = lightning::ln::peers::handler::SimpleArcPeerManager; //! //! // Connect to node with pubkey their_node_id at addr: //! async fn connect_to_node(peer_manager: PeerManager, channel_monitor: Arc, channel_manager: ChannelManager, their_node_id: PublicKey, addr: SocketAddr) { @@ -77,8 +77,8 @@ use tokio::{io, time}; use tokio::sync::mpsc; use tokio::io::{AsyncReadExt, AsyncWrite, AsyncWriteExt}; -use lightning::ln::peer_handler; -use lightning::ln::peer_handler::SocketDescriptor as LnSocketTrait; +use lightning::ln::peers::handler; +use lightning::ln::peers::handler::SocketDescriptor as LnSocketTrait; use lightning::ln::msgs::{ChannelMessageHandler, RoutingMessageHandler}; use lightning::util::logger::Logger; @@ -133,7 +133,7 @@ impl Connection { _ => panic!() } } - async fn schedule_read(peer_manager: Arc, Arc, Arc>>, us: Arc>, mut reader: io::ReadHalf, mut read_wake_receiver: mpsc::Receiver<()>, mut write_avail_receiver: mpsc::Receiver<()>) where + async fn schedule_read(peer_manager: Arc, Arc, Arc>>, us: Arc>, mut reader: io::ReadHalf, mut read_wake_receiver: mpsc::Receiver<()>, mut write_avail_receiver: mpsc::Receiver<()>) where CMH: ChannelMessageHandler + 'static, RMH: RoutingMessageHandler + 'static, L: Logger + 'static + ?Sized { @@ -189,17 +189,20 @@ impl Connection { Ok(len) => { prepare_read_write_call!(); let read_res = peer_manager.read_event(&mut our_descriptor, &buf[0..len]); - let mut us_lock = us.lock().unwrap(); - match read_res { - Ok(pause_read) => { - if pause_read { - us_lock.read_paused = true; - } - Self::event_trigger(&mut us_lock); - }, - Err(e) => shutdown_socket!(e, Disconnect::CloseConnection), + { + let mut us_lock = us.lock().unwrap(); + match read_res { + Ok(pause_read) => { + if pause_read { + us_lock.read_paused = true; + } + Self::event_trigger(&mut us_lock); + }, + Err(e) => shutdown_socket!(e, Disconnect::CloseConnection), + } + us_lock.block_disconnect_socket = false; } - us_lock.block_disconnect_socket = false; + peer_manager.process_events(); }, Err(e) => shutdown_socket!(e, Disconnect::PeerDisconnected), }, @@ -246,7 +249,7 @@ impl Connection { /// not need to poll the provided future in order to make progress. /// /// See the module-level documentation for how to handle the event_notify mpsc::Sender. -pub fn setup_inbound(peer_manager: Arc, Arc, Arc>>, event_notify: mpsc::Sender<()>, stream: TcpStream) -> impl std::future::Future where +pub fn setup_inbound(peer_manager: Arc, Arc, Arc>>, event_notify: mpsc::Sender<()>, stream: TcpStream) -> impl std::future::Future where CMH: ChannelMessageHandler + 'static, RMH: RoutingMessageHandler + 'static, L: Logger + 'static + ?Sized { @@ -288,7 +291,7 @@ pub fn setup_inbound(peer_manager: Arc(peer_manager: Arc, Arc, Arc>>, event_notify: mpsc::Sender<()>, their_node_id: PublicKey, stream: TcpStream) -> impl std::future::Future where +pub fn setup_outbound(peer_manager: Arc, Arc, Arc>>, event_notify: mpsc::Sender<()>, their_node_id: PublicKey, stream: TcpStream) -> impl std::future::Future where CMH: ChannelMessageHandler + 'static, RMH: RoutingMessageHandler + 'static, L: Logger + 'static + ?Sized { @@ -360,7 +363,7 @@ pub fn setup_outbound(peer_manager: Arc(peer_manager: Arc, Arc, Arc>>, event_notify: mpsc::Sender<()>, their_node_id: PublicKey, addr: SocketAddr) -> Option> where +pub async fn connect_outbound(peer_manager: Arc, Arc, Arc>>, event_notify: mpsc::Sender<()>, their_node_id: PublicKey, addr: SocketAddr) -> Option> where CMH: ChannelMessageHandler + 'static, RMH: RoutingMessageHandler + 'static, L: Logger + 'static + ?Sized { @@ -411,7 +414,7 @@ impl SocketDescriptor { Self { conn, id } } } -impl peer_handler::SocketDescriptor for SocketDescriptor { +impl handler::SocketDescriptor for SocketDescriptor { fn send_data(&mut self, data: &[u8], resume_read: bool) -> usize { // To send data, we take a lock on our Connection to access the WriteHalf of the TcpStream, // writing to it if there's room in the kernel buffer, or otherwise create a new Waker with @@ -503,7 +506,7 @@ impl Hash for SocketDescriptor { mod tests { use lightning::ln::features::*; use lightning::ln::msgs::*; - use lightning::ln::peer_handler::{MessageHandler, PeerManager}; + use lightning::ln::peers::handler::{MessageHandler, PeerManager}; use lightning::util::events::*; use bitcoin::secp256k1::{Secp256k1, SecretKey, PublicKey}; diff --git a/lightning/src/ln/features.rs b/lightning/src/ln/features.rs index f573ac4c43a..1e9f8341de4 100644 --- a/lightning/src/ln/features.rs +++ b/lightning/src/ln/features.rs @@ -491,6 +491,10 @@ impl Features { pub(crate) fn requires_static_remote_key(&self) -> bool { ::requires_feature(&self.flags) } + #[cfg(test)] + pub(crate) fn clear_requires_static_remote_key(&mut self) { + ::clear_bits(&mut self.flags) + } } impl Features { diff --git a/lightning/src/ln/mod.rs b/lightning/src/ln/mod.rs index b0c0283cb01..ee9c12d3787 100644 --- a/lightning/src/ln/mod.rs +++ b/lightning/src/ln/mod.rs @@ -21,16 +21,11 @@ pub mod channelmanager; pub mod channelmonitor; pub mod msgs; -pub mod peer_handler; +pub mod peers; pub mod chan_utils; pub mod features; pub(crate) mod onchaintx; -#[cfg(feature = "fuzztarget")] -pub mod peer_channel_encryptor; -#[cfg(not(feature = "fuzztarget"))] -pub(crate) mod peer_channel_encryptor; - mod channel; mod onion_utils; mod wire; @@ -50,5 +45,3 @@ mod functional_tests; mod chanmon_update_fail_tests; #[cfg(test)] mod reorg_tests; - -pub use self::peer_channel_encryptor::LN_MAX_MSG_LEN; diff --git a/lightning/src/ln/msgs.rs b/lightning/src/ln/msgs.rs index 16ba08629fe..8ffff144b86 100644 --- a/lightning/src/ln/msgs.rs +++ b/lightning/src/ln/msgs.rs @@ -672,6 +672,7 @@ pub enum ErrorAction { } /// An Err type for failure to process messages. +#[derive(Clone)] pub struct LightningError { /// A human-readable message describing the error pub err: String, diff --git a/lightning/src/ln/peer_channel_encryptor.rs b/lightning/src/ln/peer_channel_encryptor.rs deleted file mode 100644 index 8310edb64e2..00000000000 --- a/lightning/src/ln/peer_channel_encryptor.rs +++ /dev/null @@ -1,738 +0,0 @@ -// This file is Copyright its original authors, visible in version control -// history. -// -// This file is licensed under the Apache License, Version 2.0 or the MIT license -// , at your option. -// You may not use this file except in accordance with one or both of these -// licenses. - -use ln::msgs::LightningError; -use ln::msgs; - -use bitcoin::hashes::{Hash, HashEngine, Hmac, HmacEngine}; -use bitcoin::hashes::sha256::Hash as Sha256; - -use bitcoin::secp256k1::Secp256k1; -use bitcoin::secp256k1::key::{PublicKey,SecretKey}; -use bitcoin::secp256k1::ecdh::SharedSecret; -use bitcoin::secp256k1; - -use util::chacha20poly1305rfc::ChaCha20Poly1305RFC; -use util::byte_utils; -use bitcoin::hashes::hex::ToHex; - -/// Maximum Lightning message data length according to -/// [BOLT-8](https://github.com/lightningnetwork/lightning-rfc/blob/v1.0/08-transport.md#lightning-message-specification) -/// and [BOLT-1](https://github.com/lightningnetwork/lightning-rfc/blob/master/01-messaging.md#lightning-message-format): -pub const LN_MAX_MSG_LEN: usize = ::std::u16::MAX as usize; // Must be equal to 65535 - -// Sha256("Noise_XK_secp256k1_ChaChaPoly_SHA256") -const NOISE_CK: [u8; 32] = [0x26, 0x40, 0xf5, 0x2e, 0xeb, 0xcd, 0x9e, 0x88, 0x29, 0x58, 0x95, 0x1c, 0x79, 0x42, 0x50, 0xee, 0xdb, 0x28, 0x00, 0x2c, 0x05, 0xd7, 0xdc, 0x2e, 0xa0, 0xf1, 0x95, 0x40, 0x60, 0x42, 0xca, 0xf1]; -// Sha256(NOISE_CK || "lightning") -const NOISE_H: [u8; 32] = [0xd1, 0xfb, 0xf6, 0xde, 0xe4, 0xf6, 0x86, 0xf1, 0x32, 0xfd, 0x70, 0x2c, 0x4a, 0xbf, 0x8f, 0xba, 0x4b, 0xb4, 0x20, 0xd8, 0x9d, 0x2a, 0x04, 0x8a, 0x3c, 0x4f, 0x4c, 0x09, 0x2e, 0x37, 0xb6, 0x76]; - -pub enum NextNoiseStep { - ActOne, - ActTwo, - ActThree, - NoiseComplete, -} - -#[derive(PartialEq)] -enum NoiseStep { - PreActOne, - PostActOne, - PostActTwo, - // When done swap noise_state for NoiseState::Finished -} - -struct BidirectionalNoiseState { - h: [u8; 32], - ck: [u8; 32], -} -enum DirectionalNoiseState { - Outbound { - ie: SecretKey, - }, - Inbound { - ie: Option, // filled in if state >= PostActOne - re: Option, // filled in if state >= PostActTwo - temp_k2: Option<[u8; 32]>, // filled in if state >= PostActTwo - } -} -enum NoiseState { - InProgress { - state: NoiseStep, - directional_state: DirectionalNoiseState, - bidirectional_state: BidirectionalNoiseState, - }, - Finished { - sk: [u8; 32], - sn: u64, - sck: [u8; 32], - rk: [u8; 32], - rn: u64, - rck: [u8; 32], - } -} - -pub struct PeerChannelEncryptor { - secp_ctx: Secp256k1, - their_node_id: Option, // filled in for outbound, or inbound after noise_state is Finished - - noise_state: NoiseState, -} - -impl PeerChannelEncryptor { - pub fn new_outbound(their_node_id: PublicKey, ephemeral_key: SecretKey) -> PeerChannelEncryptor { - let secp_ctx = Secp256k1::signing_only(); - - let mut sha = Sha256::engine(); - sha.input(&NOISE_H); - sha.input(&their_node_id.serialize()[..]); - let h = Sha256::from_engine(sha).into_inner(); - - PeerChannelEncryptor { - their_node_id: Some(their_node_id), - secp_ctx: secp_ctx, - noise_state: NoiseState::InProgress { - state: NoiseStep::PreActOne, - directional_state: DirectionalNoiseState::Outbound { - ie: ephemeral_key, - }, - bidirectional_state: BidirectionalNoiseState { - h: h, - ck: NOISE_CK, - }, - } - } - } - - pub fn new_inbound(our_node_secret: &SecretKey) -> PeerChannelEncryptor { - let secp_ctx = Secp256k1::signing_only(); - - let mut sha = Sha256::engine(); - sha.input(&NOISE_H); - let our_node_id = PublicKey::from_secret_key(&secp_ctx, our_node_secret); - sha.input(&our_node_id.serialize()[..]); - let h = Sha256::from_engine(sha).into_inner(); - - PeerChannelEncryptor { - their_node_id: None, - secp_ctx: secp_ctx, - noise_state: NoiseState::InProgress { - state: NoiseStep::PreActOne, - directional_state: DirectionalNoiseState::Inbound { - ie: None, - re: None, - temp_k2: None, - }, - bidirectional_state: BidirectionalNoiseState { - h: h, - ck: NOISE_CK, - }, - } - } - } - - #[inline] - fn encrypt_with_ad(res: &mut[u8], n: u64, key: &[u8; 32], h: &[u8], plaintext: &[u8]) { - let mut nonce = [0; 12]; - nonce[4..].copy_from_slice(&byte_utils::le64_to_array(n)); - - let mut chacha = ChaCha20Poly1305RFC::new(key, &nonce, h); - let mut tag = [0; 16]; - chacha.encrypt(plaintext, &mut res[0..plaintext.len()], &mut tag); - res[plaintext.len()..].copy_from_slice(&tag); - } - - #[inline] - fn decrypt_with_ad(res: &mut[u8], n: u64, key: &[u8; 32], h: &[u8], cyphertext: &[u8]) -> Result<(), LightningError> { - let mut nonce = [0; 12]; - nonce[4..].copy_from_slice(&byte_utils::le64_to_array(n)); - - let mut chacha = ChaCha20Poly1305RFC::new(key, &nonce, h); - if !chacha.decrypt(&cyphertext[0..cyphertext.len() - 16], res, &cyphertext[cyphertext.len() - 16..]) { - return Err(LightningError{err: "Bad MAC".to_owned(), action: msgs::ErrorAction::DisconnectPeer{ msg: None }}); - } - Ok(()) - } - - fn hkdf_extract_expand(salt: &[u8], ikm: &[u8]) -> ([u8; 32], [u8; 32]) { - let mut hmac = HmacEngine::::new(salt); - hmac.input(ikm); - let prk = Hmac::from_engine(hmac).into_inner(); - let mut hmac = HmacEngine::::new(&prk[..]); - hmac.input(&[1; 1]); - let t1 = Hmac::from_engine(hmac).into_inner(); - let mut hmac = HmacEngine::::new(&prk[..]); - hmac.input(&t1); - hmac.input(&[2; 1]); - (t1, Hmac::from_engine(hmac).into_inner()) - } - - #[inline] - fn hkdf(state: &mut BidirectionalNoiseState, ss: SharedSecret) -> [u8; 32] { - let (t1, t2) = Self::hkdf_extract_expand(&state.ck, &ss[..]); - state.ck = t1; - t2 - } - - #[inline] - fn outbound_noise_act(secp_ctx: &Secp256k1, state: &mut BidirectionalNoiseState, our_key: &SecretKey, their_key: &PublicKey) -> ([u8; 50], [u8; 32]) { - let our_pub = PublicKey::from_secret_key(secp_ctx, &our_key); - - let mut sha = Sha256::engine(); - sha.input(&state.h); - sha.input(&our_pub.serialize()[..]); - state.h = Sha256::from_engine(sha).into_inner(); - - let ss = SharedSecret::new(&their_key, &our_key); - let temp_k = PeerChannelEncryptor::hkdf(state, ss); - - let mut res = [0; 50]; - res[1..34].copy_from_slice(&our_pub.serialize()[..]); - PeerChannelEncryptor::encrypt_with_ad(&mut res[34..], 0, &temp_k, &state.h, &[0; 0]); - - let mut sha = Sha256::engine(); - sha.input(&state.h); - sha.input(&res[34..]); - state.h = Sha256::from_engine(sha).into_inner(); - - (res, temp_k) - } - - #[inline] - fn inbound_noise_act(state: &mut BidirectionalNoiseState, act: &[u8], our_key: &SecretKey) -> Result<(PublicKey, [u8; 32]), LightningError> { - assert_eq!(act.len(), 50); - - if act[0] != 0 { - return Err(LightningError{err: format!("Unknown handshake version number {}", act[0]), action: msgs::ErrorAction::DisconnectPeer{ msg: None }}); - } - - let their_pub = match PublicKey::from_slice(&act[1..34]) { - Err(_) => return Err(LightningError{err: format!("Invalid public key {}", &act[1..34].to_hex()), action: msgs::ErrorAction::DisconnectPeer{ msg: None }}), - Ok(key) => key, - }; - - let mut sha = Sha256::engine(); - sha.input(&state.h); - sha.input(&their_pub.serialize()[..]); - state.h = Sha256::from_engine(sha).into_inner(); - - let ss = SharedSecret::new(&their_pub, &our_key); - let temp_k = PeerChannelEncryptor::hkdf(state, ss); - - let mut dec = [0; 0]; - PeerChannelEncryptor::decrypt_with_ad(&mut dec, 0, &temp_k, &state.h, &act[34..])?; - - let mut sha = Sha256::engine(); - sha.input(&state.h); - sha.input(&act[34..]); - state.h = Sha256::from_engine(sha).into_inner(); - - Ok((their_pub, temp_k)) - } - - pub fn get_act_one(&mut self) -> [u8; 50] { - match self.noise_state { - NoiseState::InProgress { ref mut state, ref directional_state, ref mut bidirectional_state } => - match directional_state { - &DirectionalNoiseState::Outbound { ref ie } => { - if *state != NoiseStep::PreActOne { - panic!("Requested act at wrong step"); - } - - let (res, _) = PeerChannelEncryptor::outbound_noise_act(&self.secp_ctx, bidirectional_state, &ie, &self.their_node_id.unwrap()); - *state = NoiseStep::PostActOne; - res - }, - _ => panic!("Wrong direction for act"), - }, - _ => panic!("Cannot get act one after noise handshake completes"), - } - } - - pub fn process_act_one_with_keys(&mut self, act_one: &[u8], our_node_secret: &SecretKey, our_ephemeral: SecretKey) -> Result<[u8; 50], LightningError> { - assert_eq!(act_one.len(), 50); - - match self.noise_state { - NoiseState::InProgress { ref mut state, ref mut directional_state, ref mut bidirectional_state } => - match directional_state { - &mut DirectionalNoiseState::Inbound { ref mut ie, ref mut re, ref mut temp_k2 } => { - if *state != NoiseStep::PreActOne { - panic!("Requested act at wrong step"); - } - - let (their_pub, _) = PeerChannelEncryptor::inbound_noise_act(bidirectional_state, act_one, &our_node_secret)?; - ie.get_or_insert(their_pub); - - re.get_or_insert(our_ephemeral); - - let (res, temp_k) = PeerChannelEncryptor::outbound_noise_act(&self.secp_ctx, bidirectional_state, &re.unwrap(), &ie.unwrap()); - *temp_k2 = Some(temp_k); - *state = NoiseStep::PostActTwo; - Ok(res) - }, - _ => panic!("Wrong direction for act"), - }, - _ => panic!("Cannot get act one after noise handshake completes"), - } - } - - pub fn process_act_two(&mut self, act_two: &[u8], our_node_secret: &SecretKey) -> Result<([u8; 66], PublicKey), LightningError> { - assert_eq!(act_two.len(), 50); - - let final_hkdf; - let ck; - let res: [u8; 66] = match self.noise_state { - NoiseState::InProgress { ref state, ref directional_state, ref mut bidirectional_state } => - match directional_state { - &DirectionalNoiseState::Outbound { ref ie } => { - if *state != NoiseStep::PostActOne { - panic!("Requested act at wrong step"); - } - - let (re, temp_k2) = PeerChannelEncryptor::inbound_noise_act(bidirectional_state, act_two, &ie)?; - - let mut res = [0; 66]; - let our_node_id = PublicKey::from_secret_key(&self.secp_ctx, &our_node_secret); - - PeerChannelEncryptor::encrypt_with_ad(&mut res[1..50], 1, &temp_k2, &bidirectional_state.h, &our_node_id.serialize()[..]); - - let mut sha = Sha256::engine(); - sha.input(&bidirectional_state.h); - sha.input(&res[1..50]); - bidirectional_state.h = Sha256::from_engine(sha).into_inner(); - - let ss = SharedSecret::new(&re, our_node_secret); - let temp_k = PeerChannelEncryptor::hkdf(bidirectional_state, ss); - - PeerChannelEncryptor::encrypt_with_ad(&mut res[50..], 0, &temp_k, &bidirectional_state.h, &[0; 0]); - final_hkdf = Self::hkdf_extract_expand(&bidirectional_state.ck, &[0; 0]); - ck = bidirectional_state.ck.clone(); - res - }, - _ => panic!("Wrong direction for act"), - }, - _ => panic!("Cannot get act one after noise handshake completes"), - }; - - let (sk, rk) = final_hkdf; - self.noise_state = NoiseState::Finished { - sk: sk, - sn: 0, - sck: ck.clone(), - rk: rk, - rn: 0, - rck: ck, - }; - - Ok((res, self.their_node_id.unwrap().clone())) - } - - pub fn process_act_three(&mut self, act_three: &[u8]) -> Result { - assert_eq!(act_three.len(), 66); - - let final_hkdf; - let ck; - match self.noise_state { - NoiseState::InProgress { ref state, ref directional_state, ref mut bidirectional_state } => - match directional_state { - &DirectionalNoiseState::Inbound { ie: _, ref re, ref temp_k2 } => { - if *state != NoiseStep::PostActTwo { - panic!("Requested act at wrong step"); - } - if act_three[0] != 0 { - return Err(LightningError{err: format!("Unknown handshake version number {}", act_three[0]), action: msgs::ErrorAction::DisconnectPeer{ msg: None }}); - } - - let mut their_node_id = [0; 33]; - PeerChannelEncryptor::decrypt_with_ad(&mut their_node_id, 1, &temp_k2.unwrap(), &bidirectional_state.h, &act_three[1..50])?; - self.their_node_id = Some(match PublicKey::from_slice(&their_node_id) { - Ok(key) => key, - Err(_) => return Err(LightningError{err: format!("Bad node_id from peer, {}", &their_node_id.to_hex()), action: msgs::ErrorAction::DisconnectPeer{ msg: None }}), - }); - - let mut sha = Sha256::engine(); - sha.input(&bidirectional_state.h); - sha.input(&act_three[1..50]); - bidirectional_state.h = Sha256::from_engine(sha).into_inner(); - - let ss = SharedSecret::new(&self.their_node_id.unwrap(), &re.unwrap()); - let temp_k = PeerChannelEncryptor::hkdf(bidirectional_state, ss); - - PeerChannelEncryptor::decrypt_with_ad(&mut [0; 0], 0, &temp_k, &bidirectional_state.h, &act_three[50..])?; - final_hkdf = Self::hkdf_extract_expand(&bidirectional_state.ck, &[0; 0]); - ck = bidirectional_state.ck.clone(); - }, - _ => panic!("Wrong direction for act"), - }, - _ => panic!("Cannot get act one after noise handshake completes"), - } - - let (rk, sk) = final_hkdf; - self.noise_state = NoiseState::Finished { - sk: sk, - sn: 0, - sck: ck.clone(), - rk: rk, - rn: 0, - rck: ck, - }; - - Ok(self.their_node_id.unwrap().clone()) - } - - /// Encrypts the given message, returning the encrypted version - /// panics if msg.len() > 65535 or Noise handshake has not finished. - pub fn encrypt_message(&mut self, msg: &[u8]) -> Vec { - if msg.len() > LN_MAX_MSG_LEN { - panic!("Attempted to encrypt message longer than 65535 bytes!"); - } - - let mut res = Vec::with_capacity(msg.len() + 16*2 + 2); - res.resize(msg.len() + 16*2 + 2, 0); - - match self.noise_state { - NoiseState::Finished { ref mut sk, ref mut sn, ref mut sck, rk: _, rn: _, rck: _ } => { - if *sn >= 1000 { - let (new_sck, new_sk) = Self::hkdf_extract_expand(sck, sk); - *sck = new_sck; - *sk = new_sk; - *sn = 0; - } - - Self::encrypt_with_ad(&mut res[0..16+2], *sn, sk, &[0; 0], &byte_utils::be16_to_array(msg.len() as u16)); - *sn += 1; - - Self::encrypt_with_ad(&mut res[16+2..], *sn, sk, &[0; 0], msg); - *sn += 1; - }, - _ => panic!("Tried to encrypt a message prior to noise handshake completion"), - } - - res - } - - /// Decrypts a message length header from the remote peer. - /// panics if noise handshake has not yet finished or msg.len() != 18 - pub fn decrypt_length_header(&mut self, msg: &[u8]) -> Result { - assert_eq!(msg.len(), 16+2); - - match self.noise_state { - NoiseState::Finished { sk: _, sn: _, sck: _, ref mut rk, ref mut rn, ref mut rck } => { - if *rn >= 1000 { - let (new_rck, new_rk) = Self::hkdf_extract_expand(rck, rk); - *rck = new_rck; - *rk = new_rk; - *rn = 0; - } - - let mut res = [0; 2]; - Self::decrypt_with_ad(&mut res, *rn, rk, &[0; 0], msg)?; - *rn += 1; - Ok(byte_utils::slice_to_be16(&res)) - }, - _ => panic!("Tried to decrypt a message prior to noise handshake completion"), - } - } - - /// Decrypts the given message. - /// panics if msg.len() > 65535 + 16 - pub fn decrypt_message(&mut self, msg: &[u8]) -> Result, LightningError> { - if msg.len() > LN_MAX_MSG_LEN + 16 { - panic!("Attempted to decrypt message longer than 65535 + 16 bytes!"); - } - - match self.noise_state { - NoiseState::Finished { sk: _, sn: _, sck: _, ref rk, ref mut rn, rck: _ } => { - let mut res = Vec::with_capacity(msg.len() - 16); - res.resize(msg.len() - 16, 0); - Self::decrypt_with_ad(&mut res[..], *rn, rk, &[0; 0], msg)?; - *rn += 1; - - Ok(res) - }, - _ => panic!("Tried to decrypt a message prior to noise handshake completion"), - } - } - - pub fn get_noise_step(&self) -> NextNoiseStep { - match self.noise_state { - NoiseState::InProgress {ref state, ..} => { - match state { - &NoiseStep::PreActOne => NextNoiseStep::ActOne, - &NoiseStep::PostActOne => NextNoiseStep::ActTwo, - &NoiseStep::PostActTwo => NextNoiseStep::ActThree, - } - }, - NoiseState::Finished {..} => NextNoiseStep::NoiseComplete, - } - } - - pub fn is_ready_for_encryption(&self) -> bool { - match self.noise_state { - NoiseState::InProgress {..} => { false }, - NoiseState::Finished {..} => { true } - } - } -} - -#[cfg(test)] -mod tests { - use super::LN_MAX_MSG_LEN; - - use bitcoin::secp256k1::key::{PublicKey,SecretKey}; - - use hex; - - use ln::peer_channel_encryptor::{PeerChannelEncryptor,NoiseState}; - - fn get_outbound_peer_for_initiator_test_vectors() -> PeerChannelEncryptor { - let their_node_id = PublicKey::from_slice(&hex::decode("028d7500dd4c12685d1f568b4c2b5048e8534b873319f3a8daa612b469132ec7f7").unwrap()[..]).unwrap(); - - let mut outbound_peer = PeerChannelEncryptor::new_outbound(their_node_id, SecretKey::from_slice(&hex::decode("1212121212121212121212121212121212121212121212121212121212121212").unwrap()[..]).unwrap()); - assert_eq!(outbound_peer.get_act_one()[..], hex::decode("00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").unwrap()[..]); - outbound_peer - } - - fn get_inbound_peer_for_test_vectors() -> PeerChannelEncryptor { - // transport-responder successful handshake - let our_node_id = SecretKey::from_slice(&hex::decode("2121212121212121212121212121212121212121212121212121212121212121").unwrap()[..]).unwrap(); - let our_ephemeral = SecretKey::from_slice(&hex::decode("2222222222222222222222222222222222222222222222222222222222222222").unwrap()[..]).unwrap(); - - let mut inbound_peer = PeerChannelEncryptor::new_inbound(&our_node_id); - - let act_one = hex::decode("00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").unwrap().to_vec(); - assert_eq!(inbound_peer.process_act_one_with_keys(&act_one[..], &our_node_id, our_ephemeral.clone()).unwrap()[..], hex::decode("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap()[..]); - - let act_three = hex::decode("00b9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139ba").unwrap().to_vec(); - // test vector doesn't specify the initiator static key, but it's the same as the one - // from transport-initiator successful handshake - assert_eq!(inbound_peer.process_act_three(&act_three[..]).unwrap().serialize()[..], hex::decode("034f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b704075871aa").unwrap()[..]); - - match inbound_peer.noise_state { - NoiseState::Finished { sk, sn, sck, rk, rn, rck } => { - assert_eq!(sk, hex::decode("bb9020b8965f4df047e07f955f3c4b88418984aadc5cdb35096b9ea8fa5c3442").unwrap()[..]); - assert_eq!(sn, 0); - assert_eq!(sck, hex::decode("919219dbb2920afa8db80f9a51787a840bcf111ed8d588caf9ab4be716e42b01").unwrap()[..]); - assert_eq!(rk, hex::decode("969ab31b4d288cedf6218839b27a3e2140827047f2c0f01bf5c04435d43511a9").unwrap()[..]); - assert_eq!(rn, 0); - assert_eq!(rck, hex::decode("919219dbb2920afa8db80f9a51787a840bcf111ed8d588caf9ab4be716e42b01").unwrap()[..]); - }, - _ => panic!() - } - - inbound_peer - } - - #[test] - fn noise_initiator_test_vectors() { - let our_node_id = SecretKey::from_slice(&hex::decode("1111111111111111111111111111111111111111111111111111111111111111").unwrap()[..]).unwrap(); - - { - // transport-initiator successful handshake - let mut outbound_peer = get_outbound_peer_for_initiator_test_vectors(); - - let act_two = hex::decode("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap().to_vec(); - assert_eq!(outbound_peer.process_act_two(&act_two[..], &our_node_id).unwrap().0[..], hex::decode("00b9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139ba").unwrap()[..]); - - match outbound_peer.noise_state { - NoiseState::Finished { sk, sn, sck, rk, rn, rck } => { - assert_eq!(sk, hex::decode("969ab31b4d288cedf6218839b27a3e2140827047f2c0f01bf5c04435d43511a9").unwrap()[..]); - assert_eq!(sn, 0); - assert_eq!(sck, hex::decode("919219dbb2920afa8db80f9a51787a840bcf111ed8d588caf9ab4be716e42b01").unwrap()[..]); - assert_eq!(rk, hex::decode("bb9020b8965f4df047e07f955f3c4b88418984aadc5cdb35096b9ea8fa5c3442").unwrap()[..]); - assert_eq!(rn, 0); - assert_eq!(rck, hex::decode("919219dbb2920afa8db80f9a51787a840bcf111ed8d588caf9ab4be716e42b01").unwrap()[..]); - }, - _ => panic!() - } - } - { - // transport-initiator act2 short read test - // Can't actually test this cause process_act_two requires you pass the right length! - } - { - // transport-initiator act2 bad version test - let mut outbound_peer = get_outbound_peer_for_initiator_test_vectors(); - - let act_two = hex::decode("0102466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap().to_vec(); - assert!(outbound_peer.process_act_two(&act_two[..], &our_node_id).is_err()); - } - - { - // transport-initiator act2 bad key serialization test - let mut outbound_peer = get_outbound_peer_for_initiator_test_vectors(); - - let act_two = hex::decode("0004466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap().to_vec(); - assert!(outbound_peer.process_act_two(&act_two[..], &our_node_id).is_err()); - } - - { - // transport-initiator act2 bad MAC test - let mut outbound_peer = get_outbound_peer_for_initiator_test_vectors(); - - let act_two = hex::decode("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730af").unwrap().to_vec(); - assert!(outbound_peer.process_act_two(&act_two[..], &our_node_id).is_err()); - } - } - - #[test] - fn noise_responder_test_vectors() { - let our_node_id = SecretKey::from_slice(&hex::decode("2121212121212121212121212121212121212121212121212121212121212121").unwrap()[..]).unwrap(); - let our_ephemeral = SecretKey::from_slice(&hex::decode("2222222222222222222222222222222222222222222222222222222222222222").unwrap()[..]).unwrap(); - - { - let _ = get_inbound_peer_for_test_vectors(); - } - { - // transport-responder act1 short read test - // Can't actually test this cause process_act_one requires you pass the right length! - } - { - // transport-responder act1 bad version test - let mut inbound_peer = PeerChannelEncryptor::new_inbound(&our_node_id); - - let act_one = hex::decode("01036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").unwrap().to_vec(); - assert!(inbound_peer.process_act_one_with_keys(&act_one[..], &our_node_id, our_ephemeral.clone()).is_err()); - } - { - // transport-responder act1 bad key serialization test - let mut inbound_peer = PeerChannelEncryptor::new_inbound(&our_node_id); - - let act_one =hex::decode("00046360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").unwrap().to_vec(); - assert!(inbound_peer.process_act_one_with_keys(&act_one[..], &our_node_id, our_ephemeral.clone()).is_err()); - } - { - // transport-responder act1 bad MAC test - let mut inbound_peer = PeerChannelEncryptor::new_inbound(&our_node_id); - - let act_one = hex::decode("00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6b").unwrap().to_vec(); - assert!(inbound_peer.process_act_one_with_keys(&act_one[..], &our_node_id, our_ephemeral.clone()).is_err()); - } - { - // transport-responder act3 bad version test - let mut inbound_peer = PeerChannelEncryptor::new_inbound(&our_node_id); - - let act_one = hex::decode("00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").unwrap().to_vec(); - assert_eq!(inbound_peer.process_act_one_with_keys(&act_one[..], &our_node_id, our_ephemeral.clone()).unwrap()[..], hex::decode("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap()[..]); - - let act_three = hex::decode("01b9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139ba").unwrap().to_vec(); - assert!(inbound_peer.process_act_three(&act_three[..]).is_err()); - } - { - // transport-responder act3 short read test - // Can't actually test this cause process_act_three requires you pass the right length! - } - { - // transport-responder act3 bad MAC for ciphertext test - let mut inbound_peer = PeerChannelEncryptor::new_inbound(&our_node_id); - - let act_one = hex::decode("00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").unwrap().to_vec(); - assert_eq!(inbound_peer.process_act_one_with_keys(&act_one[..], &our_node_id, our_ephemeral.clone()).unwrap()[..], hex::decode("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap()[..]); - - let act_three = hex::decode("00c9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139ba").unwrap().to_vec(); - assert!(inbound_peer.process_act_three(&act_three[..]).is_err()); - } - { - // transport-responder act3 bad rs test - let mut inbound_peer = PeerChannelEncryptor::new_inbound(&our_node_id); - - let act_one = hex::decode("00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").unwrap().to_vec(); - assert_eq!(inbound_peer.process_act_one_with_keys(&act_one[..], &our_node_id, our_ephemeral.clone()).unwrap()[..], hex::decode("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap()[..]); - - let act_three = hex::decode("00bfe3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa2235536ad09a8ee351870c2bb7f78b754a26c6cef79a98d25139c856d7efd252c2ae73c").unwrap().to_vec(); - assert!(inbound_peer.process_act_three(&act_three[..]).is_err()); - } - { - // transport-responder act3 bad MAC test - let mut inbound_peer = PeerChannelEncryptor::new_inbound(&our_node_id); - - let act_one = hex::decode("00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").unwrap().to_vec(); - assert_eq!(inbound_peer.process_act_one_with_keys(&act_one[..], &our_node_id, our_ephemeral.clone()).unwrap()[..], hex::decode("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap()[..]); - - let act_three = hex::decode("00b9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139bb").unwrap().to_vec(); - assert!(inbound_peer.process_act_three(&act_three[..]).is_err()); - } - } - - - #[test] - fn message_encryption_decryption_test_vectors() { - // We use the same keys as the initiator and responder test vectors, so we copy those tests - // here and use them to encrypt. - let mut outbound_peer = get_outbound_peer_for_initiator_test_vectors(); - - { - let our_node_id = SecretKey::from_slice(&hex::decode("1111111111111111111111111111111111111111111111111111111111111111").unwrap()[..]).unwrap(); - - let act_two = hex::decode("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap().to_vec(); - assert_eq!(outbound_peer.process_act_two(&act_two[..], &our_node_id).unwrap().0[..], hex::decode("00b9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139ba").unwrap()[..]); - - match outbound_peer.noise_state { - NoiseState::Finished { sk, sn, sck, rk, rn, rck } => { - assert_eq!(sk, hex::decode("969ab31b4d288cedf6218839b27a3e2140827047f2c0f01bf5c04435d43511a9").unwrap()[..]); - assert_eq!(sn, 0); - assert_eq!(sck, hex::decode("919219dbb2920afa8db80f9a51787a840bcf111ed8d588caf9ab4be716e42b01").unwrap()[..]); - assert_eq!(rk, hex::decode("bb9020b8965f4df047e07f955f3c4b88418984aadc5cdb35096b9ea8fa5c3442").unwrap()[..]); - assert_eq!(rn, 0); - assert_eq!(rck, hex::decode("919219dbb2920afa8db80f9a51787a840bcf111ed8d588caf9ab4be716e42b01").unwrap()[..]); - }, - _ => panic!() - } - } - - let mut inbound_peer = get_inbound_peer_for_test_vectors(); - - for i in 0..1005 { - let msg = [0x68, 0x65, 0x6c, 0x6c, 0x6f]; - let res = outbound_peer.encrypt_message(&msg); - assert_eq!(res.len(), 5 + 2*16 + 2); - - let len_header = res[0..2+16].to_vec(); - assert_eq!(inbound_peer.decrypt_length_header(&len_header[..]).unwrap() as usize, msg.len()); - assert_eq!(inbound_peer.decrypt_message(&res[2+16..]).unwrap()[..], msg[..]); - - if i == 0 { - assert_eq!(res, hex::decode("cf2b30ddf0cf3f80e7c35a6e6730b59fe802473180f396d88a8fb0db8cbcf25d2f214cf9ea1d95").unwrap()); - } else if i == 1 { - assert_eq!(res, hex::decode("72887022101f0b6753e0c7de21657d35a4cb2a1f5cde2650528bbc8f837d0f0d7ad833b1a256a1").unwrap()); - } else if i == 500 { - assert_eq!(res, hex::decode("178cb9d7387190fa34db9c2d50027d21793c9bc2d40b1e14dcf30ebeeeb220f48364f7a4c68bf8").unwrap()); - } else if i == 501 { - assert_eq!(res, hex::decode("1b186c57d44eb6de4c057c49940d79bb838a145cb528d6e8fd26dbe50a60ca2c104b56b60e45bd").unwrap()); - } else if i == 1000 { - assert_eq!(res, hex::decode("4a2f3cc3b5e78ddb83dcb426d9863d9d9a723b0337c89dd0b005d89f8d3c05c52b76b29b740f09").unwrap()); - } else if i == 1001 { - assert_eq!(res, hex::decode("2ecd8c8a5629d0d02ab457a0fdd0f7b90a192cd46be5ecb6ca570bfc5e268338b1a16cf4ef2d36").unwrap()); - } - } - } - - #[test] - fn max_msg_len_limit_value() { - assert_eq!(LN_MAX_MSG_LEN, 65535); - assert_eq!(LN_MAX_MSG_LEN, ::std::u16::MAX as usize); - } - - #[test] - #[should_panic(expected = "Attempted to encrypt message longer than 65535 bytes!")] - fn max_message_len_encryption() { - let mut outbound_peer = get_outbound_peer_for_initiator_test_vectors(); - let msg = [4u8; LN_MAX_MSG_LEN + 1]; - outbound_peer.encrypt_message(&msg); - } - - #[test] - #[should_panic(expected = "Attempted to decrypt message longer than 65535 + 16 bytes!")] - fn max_message_len_decryption() { - let mut inbound_peer = get_inbound_peer_for_test_vectors(); - - // MSG should not exceed LN_MAX_MSG_LEN + 16 - let msg = [4u8; LN_MAX_MSG_LEN + 17]; - inbound_peer.decrypt_message(&msg).unwrap(); - } -} diff --git a/lightning/src/ln/peer_handler.rs b/lightning/src/ln/peer_handler.rs deleted file mode 100644 index edb2084c716..00000000000 --- a/lightning/src/ln/peer_handler.rs +++ /dev/null @@ -1,1417 +0,0 @@ -// This file is Copyright its original authors, visible in version control -// history. -// -// This file is licensed under the Apache License, Version 2.0 or the MIT license -// , at your option. -// You may not use this file except in accordance with one or both of these -// licenses. - -//! Top level peer message handling and socket handling logic lives here. -//! -//! Instead of actually servicing sockets ourselves we require that you implement the -//! SocketDescriptor interface and use that to receive actions which you should perform on the -//! socket, and call into PeerManager with bytes read from the socket. The PeerManager will then -//! call into the provided message handlers (probably a ChannelManager and NetGraphmsgHandler) with messages -//! they should handle, and encoding/sending response messages. - -use bitcoin::secp256k1::key::{SecretKey,PublicKey}; - -use ln::features::InitFeatures; -use ln::msgs; -use ln::msgs::{ChannelMessageHandler, LightningError, RoutingMessageHandler}; -use ln::channelmanager::{SimpleArcChannelManager, SimpleRefChannelManager}; -use util::ser::{VecWriter, Writeable}; -use ln::peer_channel_encryptor::{PeerChannelEncryptor,NextNoiseStep}; -use ln::wire; -use ln::wire::Encode; -use util::byte_utils; -use util::events::{MessageSendEvent, MessageSendEventsProvider}; -use util::logger::Logger; -use routing::network_graph::NetGraphMsgHandler; - -use std::collections::{HashMap,hash_map,HashSet,LinkedList}; -use std::sync::{Arc, Mutex}; -use std::sync::atomic::{AtomicUsize, Ordering}; -use std::{cmp,error,hash,fmt}; -use std::ops::Deref; - -use bitcoin::hashes::sha256::Hash as Sha256; -use bitcoin::hashes::sha256::HashEngine as Sha256Engine; -use bitcoin::hashes::{HashEngine, Hash}; - -/// Provides references to trait impls which handle different types of messages. -pub struct MessageHandler where - CM::Target: ChannelMessageHandler, - RM::Target: RoutingMessageHandler { - /// A message handler which handles messages specific to channels. Usually this is just a - /// ChannelManager object. - pub chan_handler: CM, - /// A message handler which handles messages updating our knowledge of the network channel - /// graph. Usually this is just a NetGraphMsgHandlerMonitor object. - pub route_handler: RM, -} - -/// Provides an object which can be used to send data to and which uniquely identifies a connection -/// to a remote host. You will need to be able to generate multiple of these which meet Eq and -/// implement Hash to meet the PeerManager API. -/// -/// For efficiency, Clone should be relatively cheap for this type. -/// -/// You probably want to just extend an int and put a file descriptor in a struct and implement -/// send_data. Note that if you are using a higher-level net library that may call close() itself, -/// be careful to ensure you don't have races whereby you might register a new connection with an -/// fd which is the same as a previous one which has yet to be removed via -/// PeerManager::socket_disconnected(). -pub trait SocketDescriptor : cmp::Eq + hash::Hash + Clone { - /// Attempts to send some data from the given slice to the peer. - /// - /// Returns the amount of data which was sent, possibly 0 if the socket has since disconnected. - /// Note that in the disconnected case, socket_disconnected must still fire and further write - /// attempts may occur until that time. - /// - /// If the returned size is smaller than data.len(), a write_available event must - /// trigger the next time more data can be written. Additionally, until the a send_data event - /// completes fully, no further read_events should trigger on the same peer! - /// - /// If a read_event on this descriptor had previously returned true (indicating that read - /// events should be paused to prevent DoS in the send buffer), resume_read may be set - /// indicating that read events on this descriptor should resume. A resume_read of false does - /// *not* imply that further read events should be paused. - fn send_data(&mut self, data: &[u8], resume_read: bool) -> usize; - /// Disconnect the socket pointed to by this SocketDescriptor. Once this function returns, no - /// more calls to write_buffer_space_avail, read_event or socket_disconnected may be made with - /// this descriptor. No socket_disconnected call should be generated as a result of this call, - /// though races may occur whereby disconnect_socket is called after a call to - /// socket_disconnected but prior to socket_disconnected returning. - fn disconnect_socket(&mut self); -} - -/// Error for PeerManager errors. If you get one of these, you must disconnect the socket and -/// generate no further read_event/write_buffer_space_avail calls for the descriptor, only -/// triggering a single socket_disconnected call (unless it was provided in response to a -/// new_*_connection event, in which case no such socket_disconnected() must be called and the -/// socket silently disconencted). -pub struct PeerHandleError { - /// Used to indicate that we probably can't make any future connections to this peer, implying - /// we should go ahead and force-close any channels we have with it. - pub no_connection_possible: bool, -} -impl fmt::Debug for PeerHandleError { - fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { - formatter.write_str("Peer Sent Invalid Data") - } -} -impl fmt::Display for PeerHandleError { - fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { - formatter.write_str("Peer Sent Invalid Data") - } -} -impl error::Error for PeerHandleError { - fn description(&self) -> &str { - "Peer Sent Invalid Data" - } -} - -enum InitSyncTracker{ - NoSyncRequested, - ChannelsSyncing(u64), - NodesSyncing(PublicKey), -} - -struct Peer { - channel_encryptor: PeerChannelEncryptor, - outbound: bool, - their_node_id: Option, - their_features: Option, - - pending_outbound_buffer: LinkedList>, - pending_outbound_buffer_first_msg_offset: usize, - awaiting_write_event: bool, - - pending_read_buffer: Vec, - pending_read_buffer_pos: usize, - pending_read_is_header: bool, - - sync_status: InitSyncTracker, - - awaiting_pong: bool, -} - -impl Peer { - /// Returns true if the channel announcements/updates for the given channel should be - /// forwarded to this peer. - /// If we are sending our routing table to this peer and we have not yet sent channel - /// announcements/updates for the given channel_id then we will send it when we get to that - /// point and we shouldn't send it yet to avoid sending duplicate updates. If we've already - /// sent the old versions, we should send the update, and so return true here. - fn should_forward_channel_announcement(&self, channel_id: u64)->bool{ - match self.sync_status { - InitSyncTracker::NoSyncRequested => true, - InitSyncTracker::ChannelsSyncing(i) => i < channel_id, - InitSyncTracker::NodesSyncing(_) => true, - } - } - - /// Similar to the above, but for node announcements indexed by node_id. - fn should_forward_node_announcement(&self, node_id: PublicKey) -> bool { - match self.sync_status { - InitSyncTracker::NoSyncRequested => true, - InitSyncTracker::ChannelsSyncing(_) => false, - InitSyncTracker::NodesSyncing(pk) => pk < node_id, - } - } -} - -struct PeerHolder { - peers: HashMap, - /// Added to by do_read_event for cases where we pushed a message onto the send buffer but - /// didn't call do_attempt_write_data to avoid reentrancy. Cleared in process_events() - peers_needing_send: HashSet, - /// Only add to this set when noise completes: - node_id_to_descriptor: HashMap, -} - -#[cfg(not(any(target_pointer_width = "32", target_pointer_width = "64")))] -fn _check_usize_is_32_or_64() { - // See below, less than 32 bit pointers may be unsafe here! - unsafe { mem::transmute::<*const usize, [u8; 4]>(panic!()); } -} - -/// SimpleArcPeerManager is useful when you need a PeerManager with a static lifetime, e.g. -/// when you're using lightning-net-tokio (since tokio::spawn requires parameters with static -/// lifetimes). Other times you can afford a reference, which is more efficient, in which case -/// SimpleRefPeerManager is the more appropriate type. Defining these type aliases prevents -/// issues such as overly long function definitions. -pub type SimpleArcPeerManager = Arc, Arc, Arc>>, Arc>>; - -/// SimpleRefPeerManager is a type alias for a PeerManager reference, and is the reference -/// counterpart to the SimpleArcPeerManager type alias. Use this type by default when you don't -/// need a PeerManager with a static lifetime. You'll need a static lifetime in cases such as -/// usage of lightning-net-tokio (since tokio::spawn requires parameters with static lifetimes). -/// But if this is not necessary, using a reference is more efficient. Defining these type aliases -/// helps with issues such as long function definitions. -pub type SimpleRefPeerManager<'a, 'b, 'c, 'd, 'e, 'f, 'g, SD, M, T, F, C, L> = PeerManager, &'e NetGraphMsgHandler<&'g C, &'f L>, &'f L>; - -/// A PeerManager manages a set of peers, described by their SocketDescriptor and marshalls socket -/// events into messages which it passes on to its MessageHandlers. -/// -/// Rather than using a plain PeerManager, it is preferable to use either a SimpleArcPeerManager -/// a SimpleRefPeerManager, for conciseness. See their documentation for more details, but -/// essentially you should default to using a SimpleRefPeerManager, and use a -/// SimpleArcPeerManager when you require a PeerManager with a static lifetime, such as when -/// you're using lightning-net-tokio. -pub struct PeerManager where - CM::Target: ChannelMessageHandler, - RM::Target: RoutingMessageHandler, - L::Target: Logger { - message_handler: MessageHandler, - peers: Mutex>, - our_node_secret: SecretKey, - ephemeral_key_midstate: Sha256Engine, - - // Usize needs to be at least 32 bits to avoid overflowing both low and high. If usize is 64 - // bits we will never realistically count into high: - peer_counter_low: AtomicUsize, - peer_counter_high: AtomicUsize, - - logger: L, -} - -enum MessageHandlingError { - PeerHandleError(PeerHandleError), - LightningError(LightningError), -} - -impl From for MessageHandlingError { - fn from(error: PeerHandleError) -> Self { - MessageHandlingError::PeerHandleError(error) - } -} - -impl From for MessageHandlingError { - fn from(error: LightningError) -> Self { - MessageHandlingError::LightningError(error) - } -} - -macro_rules! encode_msg { - ($msg: expr) => {{ - let mut buffer = VecWriter(Vec::new()); - wire::write($msg, &mut buffer).unwrap(); - buffer.0 - }} -} - -/// Manages and reacts to connection events. You probably want to use file descriptors as PeerIds. -/// PeerIds may repeat, but only after socket_disconnected() has been called. -impl PeerManager where - CM::Target: ChannelMessageHandler, - RM::Target: RoutingMessageHandler, - L::Target: Logger { - /// Constructs a new PeerManager with the given message handlers and node_id secret key - /// ephemeral_random_data is used to derive per-connection ephemeral keys and must be - /// cryptographically secure random bytes. - pub fn new(message_handler: MessageHandler, our_node_secret: SecretKey, ephemeral_random_data: &[u8; 32], logger: L) -> Self { - let mut ephemeral_key_midstate = Sha256::engine(); - ephemeral_key_midstate.input(ephemeral_random_data); - - PeerManager { - message_handler, - peers: Mutex::new(PeerHolder { - peers: HashMap::new(), - peers_needing_send: HashSet::new(), - node_id_to_descriptor: HashMap::new() - }), - our_node_secret, - ephemeral_key_midstate, - peer_counter_low: AtomicUsize::new(0), - peer_counter_high: AtomicUsize::new(0), - logger, - } - } - - /// Get the list of node ids for peers which have completed the initial handshake. - /// - /// For outbound connections, this will be the same as the their_node_id parameter passed in to - /// new_outbound_connection, however entries will only appear once the initial handshake has - /// completed and we are sure the remote peer has the private key for the given node_id. - pub fn get_peer_node_ids(&self) -> Vec { - let peers = self.peers.lock().unwrap(); - peers.peers.values().filter_map(|p| { - if !p.channel_encryptor.is_ready_for_encryption() || p.their_features.is_none() { - return None; - } - p.their_node_id - }).collect() - } - - fn get_ephemeral_key(&self) -> SecretKey { - let mut ephemeral_hash = self.ephemeral_key_midstate.clone(); - let low = self.peer_counter_low.fetch_add(1, Ordering::AcqRel); - let high = if low == 0 { - self.peer_counter_high.fetch_add(1, Ordering::AcqRel) - } else { - self.peer_counter_high.load(Ordering::Acquire) - }; - ephemeral_hash.input(&byte_utils::le64_to_array(low as u64)); - ephemeral_hash.input(&byte_utils::le64_to_array(high as u64)); - SecretKey::from_slice(&Sha256::from_engine(ephemeral_hash).into_inner()).expect("You broke SHA-256!") - } - - /// Indicates a new outbound connection has been established to a node with the given node_id. - /// Note that if an Err is returned here you MUST NOT call socket_disconnected for the new - /// descriptor but must disconnect the connection immediately. - /// - /// Returns a small number of bytes to send to the remote node (currently always 50). - /// - /// Panics if descriptor is duplicative with some other descriptor which has not yet had a - /// socket_disconnected(). - pub fn new_outbound_connection(&self, their_node_id: PublicKey, descriptor: Descriptor) -> Result, PeerHandleError> { - let mut peer_encryptor = PeerChannelEncryptor::new_outbound(their_node_id.clone(), self.get_ephemeral_key()); - let res = peer_encryptor.get_act_one().to_vec(); - let pending_read_buffer = [0; 50].to_vec(); // Noise act two is 50 bytes - - let mut peers = self.peers.lock().unwrap(); - if peers.peers.insert(descriptor, Peer { - channel_encryptor: peer_encryptor, - outbound: true, - their_node_id: None, - their_features: None, - - pending_outbound_buffer: LinkedList::new(), - pending_outbound_buffer_first_msg_offset: 0, - awaiting_write_event: false, - - pending_read_buffer: pending_read_buffer, - pending_read_buffer_pos: 0, - pending_read_is_header: false, - - sync_status: InitSyncTracker::NoSyncRequested, - - awaiting_pong: false, - }).is_some() { - panic!("PeerManager driver duplicated descriptors!"); - }; - Ok(res) - } - - /// Indicates a new inbound connection has been established. - /// - /// May refuse the connection by returning an Err, but will never write bytes to the remote end - /// (outbound connector always speaks first). Note that if an Err is returned here you MUST NOT - /// call socket_disconnected for the new descriptor but must disconnect the connection - /// immediately. - /// - /// Panics if descriptor is duplicative with some other descriptor which has not yet had - /// socket_disconnected called. - pub fn new_inbound_connection(&self, descriptor: Descriptor) -> Result<(), PeerHandleError> { - let peer_encryptor = PeerChannelEncryptor::new_inbound(&self.our_node_secret); - let pending_read_buffer = [0; 50].to_vec(); // Noise act one is 50 bytes - - let mut peers = self.peers.lock().unwrap(); - if peers.peers.insert(descriptor, Peer { - channel_encryptor: peer_encryptor, - outbound: false, - their_node_id: None, - their_features: None, - - pending_outbound_buffer: LinkedList::new(), - pending_outbound_buffer_first_msg_offset: 0, - awaiting_write_event: false, - - pending_read_buffer: pending_read_buffer, - pending_read_buffer_pos: 0, - pending_read_is_header: false, - - sync_status: InitSyncTracker::NoSyncRequested, - - awaiting_pong: false, - }).is_some() { - panic!("PeerManager driver duplicated descriptors!"); - }; - Ok(()) - } - - fn do_attempt_write_data(&self, descriptor: &mut Descriptor, peer: &mut Peer) { - macro_rules! encode_and_send_msg { - ($msg: expr) => { - { - log_trace!(self.logger, "Encoding and sending sync update message of type {} to {}", $msg.type_id(), log_pubkey!(peer.their_node_id.unwrap())); - peer.pending_outbound_buffer.push_back(peer.channel_encryptor.encrypt_message(&encode_msg!($msg)[..])); - } - } - } - const MSG_BUFF_SIZE: usize = 10; - while !peer.awaiting_write_event { - if peer.pending_outbound_buffer.len() < MSG_BUFF_SIZE { - match peer.sync_status { - InitSyncTracker::NoSyncRequested => {}, - InitSyncTracker::ChannelsSyncing(c) if c < 0xffff_ffff_ffff_ffff => { - let steps = ((MSG_BUFF_SIZE - peer.pending_outbound_buffer.len() + 2) / 3) as u8; - let all_messages = self.message_handler.route_handler.get_next_channel_announcements(c, steps); - for &(ref announce, ref update_a_option, ref update_b_option) in all_messages.iter() { - encode_and_send_msg!(announce); - if let &Some(ref update_a) = update_a_option { - encode_and_send_msg!(update_a); - } - if let &Some(ref update_b) = update_b_option { - encode_and_send_msg!(update_b); - } - peer.sync_status = InitSyncTracker::ChannelsSyncing(announce.contents.short_channel_id + 1); - } - if all_messages.is_empty() || all_messages.len() != steps as usize { - peer.sync_status = InitSyncTracker::ChannelsSyncing(0xffff_ffff_ffff_ffff); - } - }, - InitSyncTracker::ChannelsSyncing(c) if c == 0xffff_ffff_ffff_ffff => { - let steps = (MSG_BUFF_SIZE - peer.pending_outbound_buffer.len()) as u8; - let all_messages = self.message_handler.route_handler.get_next_node_announcements(None, steps); - for msg in all_messages.iter() { - encode_and_send_msg!(msg); - peer.sync_status = InitSyncTracker::NodesSyncing(msg.contents.node_id); - } - if all_messages.is_empty() || all_messages.len() != steps as usize { - peer.sync_status = InitSyncTracker::NoSyncRequested; - } - }, - InitSyncTracker::ChannelsSyncing(_) => unreachable!(), - InitSyncTracker::NodesSyncing(key) => { - let steps = (MSG_BUFF_SIZE - peer.pending_outbound_buffer.len()) as u8; - let all_messages = self.message_handler.route_handler.get_next_node_announcements(Some(&key), steps); - for msg in all_messages.iter() { - encode_and_send_msg!(msg); - peer.sync_status = InitSyncTracker::NodesSyncing(msg.contents.node_id); - } - if all_messages.is_empty() || all_messages.len() != steps as usize { - peer.sync_status = InitSyncTracker::NoSyncRequested; - } - }, - } - } - - if { - let next_buff = match peer.pending_outbound_buffer.front() { - None => return, - Some(buff) => buff, - }; - - let should_be_reading = peer.pending_outbound_buffer.len() < MSG_BUFF_SIZE; - let pending = &next_buff[peer.pending_outbound_buffer_first_msg_offset..]; - let data_sent = descriptor.send_data(pending, should_be_reading); - peer.pending_outbound_buffer_first_msg_offset += data_sent; - if peer.pending_outbound_buffer_first_msg_offset == next_buff.len() { true } else { false } - } { - peer.pending_outbound_buffer_first_msg_offset = 0; - peer.pending_outbound_buffer.pop_front(); - } else { - peer.awaiting_write_event = true; - } - } - } - - /// Indicates that there is room to write data to the given socket descriptor. - /// - /// May return an Err to indicate that the connection should be closed. - /// - /// Will most likely call send_data on the descriptor passed in (or the descriptor handed into - /// new_*\_connection) before returning. Thus, be very careful with reentrancy issues! The - /// invariants around calling write_buffer_space_avail in case a write did not fully complete - /// must still hold - be ready to call write_buffer_space_avail again if a write call generated - /// here isn't sufficient! Panics if the descriptor was not previously registered in a - /// new_\*_connection event. - pub fn write_buffer_space_avail(&self, descriptor: &mut Descriptor) -> Result<(), PeerHandleError> { - let mut peers = self.peers.lock().unwrap(); - match peers.peers.get_mut(descriptor) { - None => panic!("Descriptor for write_event is not already known to PeerManager"), - Some(peer) => { - peer.awaiting_write_event = false; - self.do_attempt_write_data(descriptor, peer); - } - }; - Ok(()) - } - - /// Indicates that data was read from the given socket descriptor. - /// - /// May return an Err to indicate that the connection should be closed. - /// - /// Will *not* call back into send_data on any descriptors to avoid reentrancy complexity. - /// Thus, however, you almost certainly want to call process_events() after any read_event to - /// generate send_data calls to handle responses. - /// - /// If Ok(true) is returned, further read_events should not be triggered until a send_data call - /// on this file descriptor has resume_read set (preventing DoS issues in the send buffer). - /// - /// Panics if the descriptor was not previously registered in a new_*_connection event. - pub fn read_event(&self, peer_descriptor: &mut Descriptor, data: &[u8]) -> Result { - match self.do_read_event(peer_descriptor, data) { - Ok(res) => Ok(res), - Err(e) => { - self.disconnect_event_internal(peer_descriptor, e.no_connection_possible); - Err(e) - } - } - } - - /// Append a message to a peer's pending outbound/write buffer, and update the map of peers needing sends accordingly. - fn enqueue_message(&self, peers_needing_send: &mut HashSet, peer: &mut Peer, descriptor: Descriptor, message: &M) { - let mut buffer = VecWriter(Vec::new()); - wire::write(message, &mut buffer).unwrap(); // crash if the write failed - let encoded_message = buffer.0; - - log_trace!(self.logger, "Enqueueing message of type {} to {}", message.type_id(), log_pubkey!(peer.their_node_id.unwrap())); - peer.pending_outbound_buffer.push_back(peer.channel_encryptor.encrypt_message(&encoded_message[..])); - peers_needing_send.insert(descriptor); - } - - fn do_read_event(&self, peer_descriptor: &mut Descriptor, data: &[u8]) -> Result { - let pause_read = { - let mut peers_lock = self.peers.lock().unwrap(); - let peers = &mut *peers_lock; - let pause_read = match peers.peers.get_mut(peer_descriptor) { - None => panic!("Descriptor for read_event is not already known to PeerManager"), - Some(peer) => { - assert!(peer.pending_read_buffer.len() > 0); - assert!(peer.pending_read_buffer.len() > peer.pending_read_buffer_pos); - - let mut read_pos = 0; - while read_pos < data.len() { - { - let data_to_copy = cmp::min(peer.pending_read_buffer.len() - peer.pending_read_buffer_pos, data.len() - read_pos); - peer.pending_read_buffer[peer.pending_read_buffer_pos..peer.pending_read_buffer_pos + data_to_copy].copy_from_slice(&data[read_pos..read_pos + data_to_copy]); - read_pos += data_to_copy; - peer.pending_read_buffer_pos += data_to_copy; - } - - if peer.pending_read_buffer_pos == peer.pending_read_buffer.len() { - peer.pending_read_buffer_pos = 0; - - macro_rules! try_potential_handleerror { - ($thing: expr) => { - match $thing { - Ok(x) => x, - Err(e) => { - match e.action { - msgs::ErrorAction::DisconnectPeer { msg: _ } => { - //TODO: Try to push msg - log_trace!(self.logger, "Got Err handling message, disconnecting peer because {}", e.err); - return Err(PeerHandleError{ no_connection_possible: false }); - }, - msgs::ErrorAction::IgnoreError => { - log_trace!(self.logger, "Got Err handling message, ignoring because {}", e.err); - continue; - }, - msgs::ErrorAction::SendErrorMessage { msg } => { - log_trace!(self.logger, "Got Err handling message, sending Error message because {}", e.err); - self.enqueue_message(&mut peers.peers_needing_send, peer, peer_descriptor.clone(), &msg); - continue; - }, - } - } - }; - } - } - - macro_rules! insert_node_id { - () => { - match peers.node_id_to_descriptor.entry(peer.their_node_id.unwrap()) { - hash_map::Entry::Occupied(_) => { - log_trace!(self.logger, "Got second connection with {}, closing", log_pubkey!(peer.their_node_id.unwrap())); - peer.their_node_id = None; // Unset so that we don't generate a peer_disconnected event - return Err(PeerHandleError{ no_connection_possible: false }) - }, - hash_map::Entry::Vacant(entry) => { - log_trace!(self.logger, "Finished noise handshake for connection with {}", log_pubkey!(peer.their_node_id.unwrap())); - entry.insert(peer_descriptor.clone()) - }, - }; - } - } - - let next_step = peer.channel_encryptor.get_noise_step(); - match next_step { - NextNoiseStep::ActOne => { - let act_two = try_potential_handleerror!(peer.channel_encryptor.process_act_one_with_keys(&peer.pending_read_buffer[..], &self.our_node_secret, self.get_ephemeral_key())).to_vec(); - peer.pending_outbound_buffer.push_back(act_two); - peer.pending_read_buffer = [0; 66].to_vec(); // act three is 66 bytes long - }, - NextNoiseStep::ActTwo => { - let (act_three, their_node_id) = try_potential_handleerror!(peer.channel_encryptor.process_act_two(&peer.pending_read_buffer[..], &self.our_node_secret)); - peer.pending_outbound_buffer.push_back(act_three.to_vec()); - peer.pending_read_buffer = [0; 18].to_vec(); // Message length header is 18 bytes - peer.pending_read_is_header = true; - - peer.their_node_id = Some(their_node_id); - insert_node_id!(); - let mut features = InitFeatures::known(); - if !self.message_handler.route_handler.should_request_full_sync(&peer.their_node_id.unwrap()) { - features.clear_initial_routing_sync(); - } - - let resp = msgs::Init { features }; - self.enqueue_message(&mut peers.peers_needing_send, peer, peer_descriptor.clone(), &resp); - }, - NextNoiseStep::ActThree => { - let their_node_id = try_potential_handleerror!(peer.channel_encryptor.process_act_three(&peer.pending_read_buffer[..])); - peer.pending_read_buffer = [0; 18].to_vec(); // Message length header is 18 bytes - peer.pending_read_is_header = true; - peer.their_node_id = Some(their_node_id); - insert_node_id!(); - }, - NextNoiseStep::NoiseComplete => { - if peer.pending_read_is_header { - let msg_len = try_potential_handleerror!(peer.channel_encryptor.decrypt_length_header(&peer.pending_read_buffer[..])); - peer.pending_read_buffer = Vec::with_capacity(msg_len as usize + 16); - peer.pending_read_buffer.resize(msg_len as usize + 16, 0); - if msg_len < 2 { // Need at least the message type tag - return Err(PeerHandleError{ no_connection_possible: false }); - } - peer.pending_read_is_header = false; - } else { - let msg_data = try_potential_handleerror!(peer.channel_encryptor.decrypt_message(&peer.pending_read_buffer[..])); - assert!(msg_data.len() >= 2); - - // Reset read buffer - peer.pending_read_buffer = [0; 18].to_vec(); - peer.pending_read_is_header = true; - - let mut reader = ::std::io::Cursor::new(&msg_data[..]); - let message_result = wire::read(&mut reader); - let message = match message_result { - Ok(x) => x, - Err(e) => { - match e { - msgs::DecodeError::UnknownVersion => return Err(PeerHandleError { no_connection_possible: false }), - msgs::DecodeError::UnknownRequiredFeature => { - log_debug!(self.logger, "Got a channel/node announcement with an known required feature flag, you may want to update!"); - continue; - } - msgs::DecodeError::InvalidValue => { - log_debug!(self.logger, "Got an invalid value while deserializing message"); - return Err(PeerHandleError { no_connection_possible: false }); - } - msgs::DecodeError::ShortRead => { - log_debug!(self.logger, "Deserialization failed due to shortness of message"); - return Err(PeerHandleError { no_connection_possible: false }); - } - msgs::DecodeError::BadLengthDescriptor => return Err(PeerHandleError { no_connection_possible: false }), - msgs::DecodeError::Io(_) => return Err(PeerHandleError { no_connection_possible: false }), - } - } - }; - - if let Err(handling_error) = self.handle_message(&mut peers.peers_needing_send, peer, peer_descriptor.clone(), message){ - match handling_error { - MessageHandlingError::PeerHandleError(e) => { return Err(e) }, - MessageHandlingError::LightningError(e) => { - try_potential_handleerror!(Err(e)); - }, - } - } - } - } - } - } - } - - self.do_attempt_write_data(peer_descriptor, peer); - - peer.pending_outbound_buffer.len() > 10 // pause_read - } - }; - - pause_read - }; - - Ok(pause_read) - } - - /// Process an incoming message and return a decision (ok, lightning error, peer handling error) regarding the next action with the peer - fn handle_message(&self, peers_needing_send: &mut HashSet, peer: &mut Peer, peer_descriptor: Descriptor, message: wire::Message) -> Result<(), MessageHandlingError> { - log_trace!(self.logger, "Received message of type {} from {}", message.type_id(), log_pubkey!(peer.their_node_id.unwrap())); - - // Need an Init as first message - if let wire::Message::Init(_) = message { - } else if peer.their_features.is_none() { - log_trace!(self.logger, "Peer {} sent non-Init first message", log_pubkey!(peer.their_node_id.unwrap())); - return Err(PeerHandleError{ no_connection_possible: false }.into()); - } - - match message { - // Setup and Control messages: - wire::Message::Init(msg) => { - if msg.features.requires_unknown_bits() { - log_info!(self.logger, "Peer global features required unknown version bits"); - return Err(PeerHandleError{ no_connection_possible: true }.into()); - } - if msg.features.requires_unknown_bits() { - log_info!(self.logger, "Peer local features required unknown version bits"); - return Err(PeerHandleError{ no_connection_possible: true }.into()); - } - if peer.their_features.is_some() { - return Err(PeerHandleError{ no_connection_possible: false }.into()); - } - - log_info!( - self.logger, "Received peer Init message: data_loss_protect: {}, initial_routing_sync: {}, upfront_shutdown_script: {}, static_remote_key: {}, unknown flags (local and global): {}", - if msg.features.supports_data_loss_protect() { "supported" } else { "not supported"}, - if msg.features.initial_routing_sync() { "requested" } else { "not requested" }, - if msg.features.supports_upfront_shutdown_script() { "supported" } else { "not supported"}, - if msg.features.supports_static_remote_key() { "supported" } else { "not supported"}, - if msg.features.supports_unknown_bits() { "present" } else { "none" } - ); - - if msg.features.initial_routing_sync() { - peer.sync_status = InitSyncTracker::ChannelsSyncing(0); - peers_needing_send.insert(peer_descriptor.clone()); - } - if !msg.features.supports_static_remote_key() { - log_debug!(self.logger, "Peer {} does not support static remote key, disconnecting with no_connection_possible", log_pubkey!(peer.their_node_id.unwrap())); - return Err(PeerHandleError{ no_connection_possible: true }.into()); - } - - if !peer.outbound { - let mut features = InitFeatures::known(); - if !self.message_handler.route_handler.should_request_full_sync(&peer.their_node_id.unwrap()) { - features.clear_initial_routing_sync(); - } - - let resp = msgs::Init { features }; - self.enqueue_message(peers_needing_send, peer, peer_descriptor.clone(), &resp); - } - - self.message_handler.chan_handler.peer_connected(&peer.their_node_id.unwrap(), &msg); - peer.their_features = Some(msg.features); - }, - wire::Message::Error(msg) => { - let mut data_is_printable = true; - for b in msg.data.bytes() { - if b < 32 || b > 126 { - data_is_printable = false; - break; - } - } - - if data_is_printable { - log_debug!(self.logger, "Got Err message from {}: {}", log_pubkey!(peer.their_node_id.unwrap()), msg.data); - } else { - log_debug!(self.logger, "Got Err message from {} with non-ASCII error message", log_pubkey!(peer.their_node_id.unwrap())); - } - self.message_handler.chan_handler.handle_error(&peer.their_node_id.unwrap(), &msg); - if msg.channel_id == [0; 32] { - return Err(PeerHandleError{ no_connection_possible: true }.into()); - } - }, - - wire::Message::Ping(msg) => { - if msg.ponglen < 65532 { - let resp = msgs::Pong { byteslen: msg.ponglen }; - self.enqueue_message(peers_needing_send, peer, peer_descriptor.clone(), &resp); - } - }, - wire::Message::Pong(_msg) => { - peer.awaiting_pong = false; - }, - - // Channel messages: - wire::Message::OpenChannel(msg) => { - self.message_handler.chan_handler.handle_open_channel(&peer.their_node_id.unwrap(), peer.their_features.clone().unwrap(), &msg); - }, - wire::Message::AcceptChannel(msg) => { - self.message_handler.chan_handler.handle_accept_channel(&peer.their_node_id.unwrap(), peer.their_features.clone().unwrap(), &msg); - }, - - wire::Message::FundingCreated(msg) => { - self.message_handler.chan_handler.handle_funding_created(&peer.their_node_id.unwrap(), &msg); - }, - wire::Message::FundingSigned(msg) => { - self.message_handler.chan_handler.handle_funding_signed(&peer.their_node_id.unwrap(), &msg); - }, - wire::Message::FundingLocked(msg) => { - self.message_handler.chan_handler.handle_funding_locked(&peer.their_node_id.unwrap(), &msg); - }, - - wire::Message::Shutdown(msg) => { - self.message_handler.chan_handler.handle_shutdown(&peer.their_node_id.unwrap(), &msg); - }, - wire::Message::ClosingSigned(msg) => { - self.message_handler.chan_handler.handle_closing_signed(&peer.their_node_id.unwrap(), &msg); - }, - - // Commitment messages: - wire::Message::UpdateAddHTLC(msg) => { - self.message_handler.chan_handler.handle_update_add_htlc(&peer.their_node_id.unwrap(), &msg); - }, - wire::Message::UpdateFulfillHTLC(msg) => { - self.message_handler.chan_handler.handle_update_fulfill_htlc(&peer.their_node_id.unwrap(), &msg); - }, - wire::Message::UpdateFailHTLC(msg) => { - self.message_handler.chan_handler.handle_update_fail_htlc(&peer.their_node_id.unwrap(), &msg); - }, - wire::Message::UpdateFailMalformedHTLC(msg) => { - self.message_handler.chan_handler.handle_update_fail_malformed_htlc(&peer.their_node_id.unwrap(), &msg); - }, - - wire::Message::CommitmentSigned(msg) => { - self.message_handler.chan_handler.handle_commitment_signed(&peer.their_node_id.unwrap(), &msg); - }, - wire::Message::RevokeAndACK(msg) => { - self.message_handler.chan_handler.handle_revoke_and_ack(&peer.their_node_id.unwrap(), &msg); - }, - wire::Message::UpdateFee(msg) => { - self.message_handler.chan_handler.handle_update_fee(&peer.their_node_id.unwrap(), &msg); - }, - wire::Message::ChannelReestablish(msg) => { - self.message_handler.chan_handler.handle_channel_reestablish(&peer.their_node_id.unwrap(), &msg); - }, - - // Routing messages: - wire::Message::AnnouncementSignatures(msg) => { - self.message_handler.chan_handler.handle_announcement_signatures(&peer.their_node_id.unwrap(), &msg); - }, - wire::Message::ChannelAnnouncement(msg) => { - let should_forward = match self.message_handler.route_handler.handle_channel_announcement(&msg) { - Ok(v) => v, - Err(e) => { return Err(e.into()); }, - }; - - if should_forward { - // TODO: forward msg along to all our other peers! - } - }, - wire::Message::NodeAnnouncement(msg) => { - let should_forward = match self.message_handler.route_handler.handle_node_announcement(&msg) { - Ok(v) => v, - Err(e) => { return Err(e.into()); }, - }; - - if should_forward { - // TODO: forward msg along to all our other peers! - } - }, - wire::Message::ChannelUpdate(msg) => { - let should_forward = match self.message_handler.route_handler.handle_channel_update(&msg) { - Ok(v) => v, - Err(e) => { return Err(e.into()); }, - }; - - if should_forward { - // TODO: forward msg along to all our other peers! - } - }, - - // Unknown messages: - wire::Message::Unknown(msg_type) if msg_type.is_even() => { - log_debug!(self.logger, "Received unknown even message of type {}, disconnecting peer!", msg_type); - // Fail the channel if message is an even, unknown type as per BOLT #1. - return Err(PeerHandleError{ no_connection_possible: true }.into()); - }, - wire::Message::Unknown(msg_type) => { - log_trace!(self.logger, "Received unknown odd message of type {}, ignoring", msg_type); - } - }; - Ok(()) - } - - /// Checks for any events generated by our handlers and processes them. Includes sending most - /// response messages as well as messages generated by calls to handler functions directly (eg - /// functions like ChannelManager::process_pending_htlc_forward or send_payment). - pub fn process_events(&self) { - { - // TODO: There are some DoS attacks here where you can flood someone's outbound send - // buffer by doing things like announcing channels on another node. We should be willing to - // drop optional-ish messages when send buffers get full! - - let mut events_generated = self.message_handler.chan_handler.get_and_clear_pending_msg_events(); - let mut peers_lock = self.peers.lock().unwrap(); - let peers = &mut *peers_lock; - for event in events_generated.drain(..) { - macro_rules! get_peer_for_forwarding { - ($node_id: expr, $handle_no_such_peer: block) => { - { - let descriptor = match peers.node_id_to_descriptor.get($node_id) { - Some(descriptor) => descriptor.clone(), - None => { - $handle_no_such_peer; - continue; - }, - }; - match peers.peers.get_mut(&descriptor) { - Some(peer) => { - if peer.their_features.is_none() { - $handle_no_such_peer; - continue; - } - (descriptor, peer) - }, - None => panic!("Inconsistent peers set state!"), - } - } - } - } - match event { - MessageSendEvent::SendAcceptChannel { ref node_id, ref msg } => { - log_trace!(self.logger, "Handling SendAcceptChannel event in peer_handler for node {} for channel {}", - log_pubkey!(node_id), - log_bytes!(msg.temporary_channel_id)); - let (mut descriptor, peer) = get_peer_for_forwarding!(node_id, { - //TODO: Drop the pending channel? (or just let it timeout, but that sucks) - }); - peer.pending_outbound_buffer.push_back(peer.channel_encryptor.encrypt_message(&encode_msg!(msg))); - self.do_attempt_write_data(&mut descriptor, peer); - }, - MessageSendEvent::SendOpenChannel { ref node_id, ref msg } => { - log_trace!(self.logger, "Handling SendOpenChannel event in peer_handler for node {} for channel {}", - log_pubkey!(node_id), - log_bytes!(msg.temporary_channel_id)); - let (mut descriptor, peer) = get_peer_for_forwarding!(node_id, { - //TODO: Drop the pending channel? (or just let it timeout, but that sucks) - }); - peer.pending_outbound_buffer.push_back(peer.channel_encryptor.encrypt_message(&encode_msg!(msg))); - self.do_attempt_write_data(&mut descriptor, peer); - }, - MessageSendEvent::SendFundingCreated { ref node_id, ref msg } => { - log_trace!(self.logger, "Handling SendFundingCreated event in peer_handler for node {} for channel {} (which becomes {})", - log_pubkey!(node_id), - log_bytes!(msg.temporary_channel_id), - log_funding_channel_id!(msg.funding_txid, msg.funding_output_index)); - let (mut descriptor, peer) = get_peer_for_forwarding!(node_id, { - //TODO: generate a DiscardFunding event indicating to the wallet that - //they should just throw away this funding transaction - }); - peer.pending_outbound_buffer.push_back(peer.channel_encryptor.encrypt_message(&encode_msg!(msg))); - self.do_attempt_write_data(&mut descriptor, peer); - }, - MessageSendEvent::SendFundingSigned { ref node_id, ref msg } => { - log_trace!(self.logger, "Handling SendFundingSigned event in peer_handler for node {} for channel {}", - log_pubkey!(node_id), - log_bytes!(msg.channel_id)); - let (mut descriptor, peer) = get_peer_for_forwarding!(node_id, { - //TODO: generate a DiscardFunding event indicating to the wallet that - //they should just throw away this funding transaction - }); - peer.pending_outbound_buffer.push_back(peer.channel_encryptor.encrypt_message(&encode_msg!(msg))); - self.do_attempt_write_data(&mut descriptor, peer); - }, - MessageSendEvent::SendFundingLocked { ref node_id, ref msg } => { - log_trace!(self.logger, "Handling SendFundingLocked event in peer_handler for node {} for channel {}", - log_pubkey!(node_id), - log_bytes!(msg.channel_id)); - let (mut descriptor, peer) = get_peer_for_forwarding!(node_id, { - //TODO: Do whatever we're gonna do for handling dropped messages - }); - peer.pending_outbound_buffer.push_back(peer.channel_encryptor.encrypt_message(&encode_msg!(msg))); - self.do_attempt_write_data(&mut descriptor, peer); - }, - MessageSendEvent::SendAnnouncementSignatures { ref node_id, ref msg } => { - log_trace!(self.logger, "Handling SendAnnouncementSignatures event in peer_handler for node {} for channel {})", - log_pubkey!(node_id), - log_bytes!(msg.channel_id)); - let (mut descriptor, peer) = get_peer_for_forwarding!(node_id, { - //TODO: generate a DiscardFunding event indicating to the wallet that - //they should just throw away this funding transaction - }); - peer.pending_outbound_buffer.push_back(peer.channel_encryptor.encrypt_message(&encode_msg!(msg))); - self.do_attempt_write_data(&mut descriptor, peer); - }, - MessageSendEvent::UpdateHTLCs { ref node_id, updates: msgs::CommitmentUpdate { ref update_add_htlcs, ref update_fulfill_htlcs, ref update_fail_htlcs, ref update_fail_malformed_htlcs, ref update_fee, ref commitment_signed } } => { - log_trace!(self.logger, "Handling UpdateHTLCs event in peer_handler for node {} with {} adds, {} fulfills, {} fails for channel {}", - log_pubkey!(node_id), - update_add_htlcs.len(), - update_fulfill_htlcs.len(), - update_fail_htlcs.len(), - log_bytes!(commitment_signed.channel_id)); - let (mut descriptor, peer) = get_peer_for_forwarding!(node_id, { - //TODO: Do whatever we're gonna do for handling dropped messages - }); - for msg in update_add_htlcs { - peer.pending_outbound_buffer.push_back(peer.channel_encryptor.encrypt_message(&encode_msg!(msg))); - } - for msg in update_fulfill_htlcs { - peer.pending_outbound_buffer.push_back(peer.channel_encryptor.encrypt_message(&encode_msg!(msg))); - } - for msg in update_fail_htlcs { - peer.pending_outbound_buffer.push_back(peer.channel_encryptor.encrypt_message(&encode_msg!(msg))); - } - for msg in update_fail_malformed_htlcs { - peer.pending_outbound_buffer.push_back(peer.channel_encryptor.encrypt_message(&encode_msg!(msg))); - } - if let &Some(ref msg) = update_fee { - peer.pending_outbound_buffer.push_back(peer.channel_encryptor.encrypt_message(&encode_msg!(msg))); - } - peer.pending_outbound_buffer.push_back(peer.channel_encryptor.encrypt_message(&encode_msg!(commitment_signed))); - self.do_attempt_write_data(&mut descriptor, peer); - }, - MessageSendEvent::SendRevokeAndACK { ref node_id, ref msg } => { - log_trace!(self.logger, "Handling SendRevokeAndACK event in peer_handler for node {} for channel {}", - log_pubkey!(node_id), - log_bytes!(msg.channel_id)); - let (mut descriptor, peer) = get_peer_for_forwarding!(node_id, { - //TODO: Do whatever we're gonna do for handling dropped messages - }); - peer.pending_outbound_buffer.push_back(peer.channel_encryptor.encrypt_message(&encode_msg!(msg))); - self.do_attempt_write_data(&mut descriptor, peer); - }, - MessageSendEvent::SendClosingSigned { ref node_id, ref msg } => { - log_trace!(self.logger, "Handling SendClosingSigned event in peer_handler for node {} for channel {}", - log_pubkey!(node_id), - log_bytes!(msg.channel_id)); - let (mut descriptor, peer) = get_peer_for_forwarding!(node_id, { - //TODO: Do whatever we're gonna do for handling dropped messages - }); - peer.pending_outbound_buffer.push_back(peer.channel_encryptor.encrypt_message(&encode_msg!(msg))); - self.do_attempt_write_data(&mut descriptor, peer); - }, - MessageSendEvent::SendShutdown { ref node_id, ref msg } => { - log_trace!(self.logger, "Handling Shutdown event in peer_handler for node {} for channel {}", - log_pubkey!(node_id), - log_bytes!(msg.channel_id)); - let (mut descriptor, peer) = get_peer_for_forwarding!(node_id, { - //TODO: Do whatever we're gonna do for handling dropped messages - }); - peer.pending_outbound_buffer.push_back(peer.channel_encryptor.encrypt_message(&encode_msg!(msg))); - self.do_attempt_write_data(&mut descriptor, peer); - }, - MessageSendEvent::SendChannelReestablish { ref node_id, ref msg } => { - log_trace!(self.logger, "Handling SendChannelReestablish event in peer_handler for node {} for channel {}", - log_pubkey!(node_id), - log_bytes!(msg.channel_id)); - let (mut descriptor, peer) = get_peer_for_forwarding!(node_id, { - //TODO: Do whatever we're gonna do for handling dropped messages - }); - peer.pending_outbound_buffer.push_back(peer.channel_encryptor.encrypt_message(&encode_msg!(msg))); - self.do_attempt_write_data(&mut descriptor, peer); - }, - MessageSendEvent::BroadcastChannelAnnouncement { ref msg, ref update_msg } => { - log_trace!(self.logger, "Handling BroadcastChannelAnnouncement event in peer_handler for short channel id {}", msg.contents.short_channel_id); - if self.message_handler.route_handler.handle_channel_announcement(msg).is_ok() && self.message_handler.route_handler.handle_channel_update(update_msg).is_ok() { - let encoded_msg = encode_msg!(msg); - let encoded_update_msg = encode_msg!(update_msg); - - for (ref descriptor, ref mut peer) in peers.peers.iter_mut() { - if !peer.channel_encryptor.is_ready_for_encryption() || peer.their_features.is_none() || - !peer.should_forward_channel_announcement(msg.contents.short_channel_id) { - continue - } - match peer.their_node_id { - None => continue, - Some(their_node_id) => { - if their_node_id == msg.contents.node_id_1 || their_node_id == msg.contents.node_id_2 { - continue - } - } - } - peer.pending_outbound_buffer.push_back(peer.channel_encryptor.encrypt_message(&encoded_msg[..])); - peer.pending_outbound_buffer.push_back(peer.channel_encryptor.encrypt_message(&encoded_update_msg[..])); - self.do_attempt_write_data(&mut (*descriptor).clone(), peer); - } - } - }, - MessageSendEvent::BroadcastNodeAnnouncement { ref msg } => { - log_trace!(self.logger, "Handling BroadcastNodeAnnouncement event in peer_handler"); - if self.message_handler.route_handler.handle_node_announcement(msg).is_ok() { - let encoded_msg = encode_msg!(msg); - - for (ref descriptor, ref mut peer) in peers.peers.iter_mut() { - if !peer.channel_encryptor.is_ready_for_encryption() || peer.their_features.is_none() || - !peer.should_forward_node_announcement(msg.contents.node_id) { - continue - } - peer.pending_outbound_buffer.push_back(peer.channel_encryptor.encrypt_message(&encoded_msg[..])); - self.do_attempt_write_data(&mut (*descriptor).clone(), peer); - } - } - }, - MessageSendEvent::BroadcastChannelUpdate { ref msg } => { - log_trace!(self.logger, "Handling BroadcastChannelUpdate event in peer_handler for short channel id {}", msg.contents.short_channel_id); - if self.message_handler.route_handler.handle_channel_update(msg).is_ok() { - let encoded_msg = encode_msg!(msg); - - for (ref descriptor, ref mut peer) in peers.peers.iter_mut() { - if !peer.channel_encryptor.is_ready_for_encryption() || peer.their_features.is_none() || - !peer.should_forward_channel_announcement(msg.contents.short_channel_id) { - continue - } - peer.pending_outbound_buffer.push_back(peer.channel_encryptor.encrypt_message(&encoded_msg[..])); - self.do_attempt_write_data(&mut (*descriptor).clone(), peer); - } - } - }, - MessageSendEvent::PaymentFailureNetworkUpdate { ref update } => { - self.message_handler.route_handler.handle_htlc_fail_channel_update(update); - }, - MessageSendEvent::HandleError { ref node_id, ref action } => { - match *action { - msgs::ErrorAction::DisconnectPeer { ref msg } => { - if let Some(mut descriptor) = peers.node_id_to_descriptor.remove(node_id) { - peers.peers_needing_send.remove(&descriptor); - if let Some(mut peer) = peers.peers.remove(&descriptor) { - if let Some(ref msg) = *msg { - log_trace!(self.logger, "Handling DisconnectPeer HandleError event in peer_handler for node {} with message {}", - log_pubkey!(node_id), - msg.data); - peer.pending_outbound_buffer.push_back(peer.channel_encryptor.encrypt_message(&encode_msg!(msg))); - // This isn't guaranteed to work, but if there is enough free - // room in the send buffer, put the error message there... - self.do_attempt_write_data(&mut descriptor, &mut peer); - } else { - log_trace!(self.logger, "Handling DisconnectPeer HandleError event in peer_handler for node {} with no message", log_pubkey!(node_id)); - } - } - descriptor.disconnect_socket(); - self.message_handler.chan_handler.peer_disconnected(&node_id, false); - } - }, - msgs::ErrorAction::IgnoreError => {}, - msgs::ErrorAction::SendErrorMessage { ref msg } => { - log_trace!(self.logger, "Handling SendErrorMessage HandleError event in peer_handler for node {} with message {}", - log_pubkey!(node_id), - msg.data); - let (mut descriptor, peer) = get_peer_for_forwarding!(node_id, { - //TODO: Do whatever we're gonna do for handling dropped messages - }); - peer.pending_outbound_buffer.push_back(peer.channel_encryptor.encrypt_message(&encode_msg!(msg))); - self.do_attempt_write_data(&mut descriptor, peer); - }, - } - } - } - } - - for mut descriptor in peers.peers_needing_send.drain() { - match peers.peers.get_mut(&descriptor) { - Some(peer) => self.do_attempt_write_data(&mut descriptor, peer), - None => panic!("Inconsistent peers set state!"), - } - } - } - } - - /// Indicates that the given socket descriptor's connection is now closed. - /// - /// This must only be called if the socket has been disconnected by the peer or your own - /// decision to disconnect it and must NOT be called in any case where other parts of this - /// library (eg PeerHandleError, explicit disconnect_socket calls) instruct you to disconnect - /// the peer. - /// - /// Panics if the descriptor was not previously registered in a successful new_*_connection event. - pub fn socket_disconnected(&self, descriptor: &Descriptor) { - self.disconnect_event_internal(descriptor, false); - } - - fn disconnect_event_internal(&self, descriptor: &Descriptor, no_connection_possible: bool) { - let mut peers = self.peers.lock().unwrap(); - peers.peers_needing_send.remove(descriptor); - let peer_option = peers.peers.remove(descriptor); - match peer_option { - None => panic!("Descriptor for disconnect_event is not already known to PeerManager"), - Some(peer) => { - match peer.their_node_id { - Some(node_id) => { - peers.node_id_to_descriptor.remove(&node_id); - self.message_handler.chan_handler.peer_disconnected(&node_id, no_connection_possible); - }, - None => {} - } - } - }; - } - - /// This function should be called roughly once every 30 seconds. - /// It will send pings to each peer and disconnect those which did not respond to the last round of pings. - - /// Will most likely call send_data on all of the registered descriptors, thus, be very careful with reentrancy issues! - pub fn timer_tick_occured(&self) { - let mut peers_lock = self.peers.lock().unwrap(); - { - let peers = &mut *peers_lock; - let peers_needing_send = &mut peers.peers_needing_send; - let node_id_to_descriptor = &mut peers.node_id_to_descriptor; - let peers = &mut peers.peers; - let mut descriptors_needing_disconnect = Vec::new(); - - peers.retain(|descriptor, peer| { - if peer.awaiting_pong { - peers_needing_send.remove(descriptor); - descriptors_needing_disconnect.push(descriptor.clone()); - match peer.their_node_id { - Some(node_id) => { - log_trace!(self.logger, "Disconnecting peer with id {} due to ping timeout", node_id); - node_id_to_descriptor.remove(&node_id); - self.message_handler.chan_handler.peer_disconnected(&node_id, false); - } - None => { - // This can't actually happen as we should have hit - // is_ready_for_encryption() previously on this same peer. - unreachable!(); - }, - } - return false; - } - - if !peer.channel_encryptor.is_ready_for_encryption() { - // The peer needs to complete its handshake before we can exchange messages - return true; - } - - let ping = msgs::Ping { - ponglen: 0, - byteslen: 64, - }; - peer.pending_outbound_buffer.push_back(peer.channel_encryptor.encrypt_message(&encode_msg!(&ping))); - - let mut descriptor_clone = descriptor.clone(); - self.do_attempt_write_data(&mut descriptor_clone, peer); - - peer.awaiting_pong = true; - true - }); - - for mut descriptor in descriptors_needing_disconnect.drain(..) { - descriptor.disconnect_socket(); - } - } - } -} - -#[cfg(test)] -mod tests { - use ln::peer_handler::{PeerManager, MessageHandler, SocketDescriptor}; - use ln::msgs; - use util::events; - use util::test_utils; - - use bitcoin::secp256k1::Secp256k1; - use bitcoin::secp256k1::key::{SecretKey, PublicKey}; - - use std; - use std::sync::{Arc, Mutex}; - use std::sync::atomic::Ordering; - - #[derive(Clone)] - struct FileDescriptor { - fd: u16, - outbound_data: Arc>>, - } - impl PartialEq for FileDescriptor { - fn eq(&self, other: &Self) -> bool { - self.fd == other.fd - } - } - impl Eq for FileDescriptor { } - impl std::hash::Hash for FileDescriptor { - fn hash(&self, hasher: &mut H) { - self.fd.hash(hasher) - } - } - - impl SocketDescriptor for FileDescriptor { - fn send_data(&mut self, data: &[u8], _resume_read: bool) -> usize { - self.outbound_data.lock().unwrap().extend_from_slice(data); - data.len() - } - - fn disconnect_socket(&mut self) {} - } - - struct PeerManagerCfg { - chan_handler: test_utils::TestChannelMessageHandler, - routing_handler: test_utils::TestRoutingMessageHandler, - logger: test_utils::TestLogger, - } - - fn create_peermgr_cfgs(peer_count: usize) -> Vec { - let mut cfgs = Vec::new(); - for _ in 0..peer_count { - cfgs.push( - PeerManagerCfg{ - chan_handler: test_utils::TestChannelMessageHandler::new(), - logger: test_utils::TestLogger::new(), - routing_handler: test_utils::TestRoutingMessageHandler::new(), - } - ); - } - - cfgs - } - - fn create_network<'a>(peer_count: usize, cfgs: &'a Vec) -> Vec> { - let mut peers = Vec::new(); - for i in 0..peer_count { - let node_secret = SecretKey::from_slice(&[42 + i as u8; 32]).unwrap(); - let ephemeral_bytes = [i as u8; 32]; - let msg_handler = MessageHandler { chan_handler: &cfgs[i].chan_handler, route_handler: &cfgs[i].routing_handler }; - let peer = PeerManager::new(msg_handler, node_secret, &ephemeral_bytes, &cfgs[i].logger); - peers.push(peer); - } - - peers - } - - fn establish_connection<'a>(peer_a: &PeerManager, peer_b: &PeerManager) -> (FileDescriptor, FileDescriptor) { - let secp_ctx = Secp256k1::new(); - let a_id = PublicKey::from_secret_key(&secp_ctx, &peer_a.our_node_secret); - let mut fd_a = FileDescriptor { fd: 1, outbound_data: Arc::new(Mutex::new(Vec::new())) }; - let mut fd_b = FileDescriptor { fd: 1, outbound_data: Arc::new(Mutex::new(Vec::new())) }; - let initial_data = peer_b.new_outbound_connection(a_id, fd_b.clone()).unwrap(); - peer_a.new_inbound_connection(fd_a.clone()).unwrap(); - assert_eq!(peer_a.read_event(&mut fd_a, &initial_data).unwrap(), false); - assert_eq!(peer_b.read_event(&mut fd_b, &fd_a.outbound_data.lock().unwrap().split_off(0)).unwrap(), false); - assert_eq!(peer_a.read_event(&mut fd_a, &fd_b.outbound_data.lock().unwrap().split_off(0)).unwrap(), false); - (fd_a.clone(), fd_b.clone()) - } - - fn establish_connection_and_read_events<'a>(peer_a: &PeerManager, peer_b: &PeerManager) -> (FileDescriptor, FileDescriptor) { - let (mut fd_a, mut fd_b) = establish_connection(peer_a, peer_b); - assert_eq!(peer_b.read_event(&mut fd_b, &fd_a.outbound_data.lock().unwrap().split_off(0)).unwrap(), false); - assert_eq!(peer_a.read_event(&mut fd_a, &fd_b.outbound_data.lock().unwrap().split_off(0)).unwrap(), false); - (fd_a.clone(), fd_b.clone()) - } - - #[test] - fn test_disconnect_peer() { - // Simple test which builds a network of PeerManager, connects and brings them to NoiseState::Finished and - // push a DisconnectPeer event to remove the node flagged by id - let cfgs = create_peermgr_cfgs(2); - let chan_handler = test_utils::TestChannelMessageHandler::new(); - let mut peers = create_network(2, &cfgs); - establish_connection(&peers[0], &peers[1]); - assert_eq!(peers[0].peers.lock().unwrap().peers.len(), 1); - - let secp_ctx = Secp256k1::new(); - let their_id = PublicKey::from_secret_key(&secp_ctx, &peers[1].our_node_secret); - - chan_handler.pending_events.lock().unwrap().push(events::MessageSendEvent::HandleError { - node_id: their_id, - action: msgs::ErrorAction::DisconnectPeer { msg: None }, - }); - assert_eq!(chan_handler.pending_events.lock().unwrap().len(), 1); - peers[0].message_handler.chan_handler = &chan_handler; - - peers[0].process_events(); - assert_eq!(peers[0].peers.lock().unwrap().peers.len(), 0); - } - - #[test] - fn test_timer_tick_occurred() { - // Create peers, a vector of two peer managers, perform initial set up and check that peers[0] has one Peer. - let cfgs = create_peermgr_cfgs(2); - let peers = create_network(2, &cfgs); - establish_connection(&peers[0], &peers[1]); - assert_eq!(peers[0].peers.lock().unwrap().peers.len(), 1); - - // peers[0] awaiting_pong is set to true, but the Peer is still connected - peers[0].timer_tick_occured(); - assert_eq!(peers[0].peers.lock().unwrap().peers.len(), 1); - - // Since timer_tick_occured() is called again when awaiting_pong is true, all Peers are disconnected - peers[0].timer_tick_occured(); - assert_eq!(peers[0].peers.lock().unwrap().peers.len(), 0); - } - - #[test] - fn test_do_attempt_write_data() { - // Create 2 peers with custom TestRoutingMessageHandlers and connect them. - let cfgs = create_peermgr_cfgs(2); - cfgs[0].routing_handler.request_full_sync.store(true, Ordering::Release); - cfgs[1].routing_handler.request_full_sync.store(true, Ordering::Release); - let peers = create_network(2, &cfgs); - - // By calling establish_connect, we trigger do_attempt_write_data between - // the peers. Previously this function would mistakenly enter an infinite loop - // when there were more channel messages available than could fit into a peer's - // buffer. This issue would now be detected by this test (because we use custom - // RoutingMessageHandlers that intentionally return more channel messages - // than can fit into a peer's buffer). - let (mut fd_a, mut fd_b) = establish_connection(&peers[0], &peers[1]); - - // Make each peer to read the messages that the other peer just wrote to them. - peers[1].read_event(&mut fd_b, &fd_a.outbound_data.lock().unwrap().split_off(0)).unwrap(); - peers[0].read_event(&mut fd_a, &fd_b.outbound_data.lock().unwrap().split_off(0)).unwrap(); - - // Check that each peer has received the expected number of channel updates and channel - // announcements. - assert_eq!(cfgs[0].routing_handler.chan_upds_recvd.load(Ordering::Acquire), 100); - assert_eq!(cfgs[0].routing_handler.chan_anns_recvd.load(Ordering::Acquire), 50); - assert_eq!(cfgs[1].routing_handler.chan_upds_recvd.load(Ordering::Acquire), 100); - assert_eq!(cfgs[1].routing_handler.chan_anns_recvd.load(Ordering::Acquire), 50); - } - - #[test] - fn limit_initial_routing_sync_requests() { - // Inbound peer 0 requests initial_routing_sync, but outbound peer 1 does not. - { - let cfgs = create_peermgr_cfgs(2); - cfgs[0].routing_handler.request_full_sync.store(true, Ordering::Release); - let peers = create_network(2, &cfgs); - let (fd_0_to_1, fd_1_to_0) = establish_connection_and_read_events(&peers[0], &peers[1]); - - let peer_0 = peers[0].peers.lock().unwrap(); - let peer_1 = peers[1].peers.lock().unwrap(); - - let peer_0_features = peer_1.peers.get(&fd_1_to_0).unwrap().their_features.as_ref(); - let peer_1_features = peer_0.peers.get(&fd_0_to_1).unwrap().their_features.as_ref(); - - assert!(peer_0_features.unwrap().initial_routing_sync()); - assert!(!peer_1_features.unwrap().initial_routing_sync()); - } - - // Outbound peer 1 requests initial_routing_sync, but inbound peer 0 does not. - { - let cfgs = create_peermgr_cfgs(2); - cfgs[1].routing_handler.request_full_sync.store(true, Ordering::Release); - let peers = create_network(2, &cfgs); - let (fd_0_to_1, fd_1_to_0) = establish_connection_and_read_events(&peers[0], &peers[1]); - - let peer_0 = peers[0].peers.lock().unwrap(); - let peer_1 = peers[1].peers.lock().unwrap(); - - let peer_0_features = peer_1.peers.get(&fd_1_to_0).unwrap().their_features.as_ref(); - let peer_1_features = peer_0.peers.get(&fd_0_to_1).unwrap().their_features.as_ref(); - - assert!(!peer_0_features.unwrap().initial_routing_sync()); - assert!(peer_1_features.unwrap().initial_routing_sync()); - } - } -} diff --git a/lightning/src/ln/peers/chacha.rs b/lightning/src/ln/peers/chacha.rs new file mode 100644 index 00000000000..7d5ab45c50c --- /dev/null +++ b/lightning/src/ln/peers/chacha.rs @@ -0,0 +1,46 @@ +// This file is Copyright its original authors, visible in version control +// history. +// +// This file is licensed under the Apache License, Version 2.0 or the MIT license +// , at your option. +// You may not use this file except in accordance with one or both of these +// licenses. + +use util::byte_utils; +use util::chacha20poly1305rfc::ChaCha20Poly1305RFC; + +pub const TAG_SIZE: usize = 16; + +pub fn encrypt(key: &[u8], nonce: u64, associated_data: &[u8], plaintext: &[u8], ciphertext_out: &mut [u8]) { + let mut nonce_bytes = [0; 12]; + nonce_bytes[4..].copy_from_slice(&byte_utils::le64_to_array(nonce)); + + let mut chacha = ChaCha20Poly1305RFC::new(key, &nonce_bytes, associated_data); + let mut authentication_tag = [0u8; 16]; + chacha.encrypt(plaintext, &mut ciphertext_out[..plaintext.len()], &mut authentication_tag); + + ciphertext_out[plaintext.len()..].copy_from_slice(&authentication_tag); +} + +pub fn decrypt(key: &[u8], nonce: u64, associated_data: &[u8], tagged_ciphertext: &[u8], plaintext_out: &mut [u8]) -> Result<(), String> { + let mut nonce_bytes = [0; 12]; + nonce_bytes[4..].copy_from_slice(&byte_utils::le64_to_array(nonce)); + + let length = tagged_ciphertext.len(); + if length < 16 { + return Err("ciphertext cannot be shorter than tag length of 16 bytes".to_string()); + } + let end_index = length - 16; + let ciphertext = &tagged_ciphertext[0..end_index]; + let authentication_tag = &tagged_ciphertext[end_index..]; + + let mut chacha = ChaCha20Poly1305RFC::new(key, &nonce_bytes, associated_data); + let success = chacha.decrypt(ciphertext, plaintext_out, authentication_tag); + + if !success { + Err("invalid hmac".to_string()) + } else { + Ok(()) + } +} diff --git a/lightning/src/ln/peers/encryption.rs b/lightning/src/ln/peers/encryption.rs new file mode 100644 index 00000000000..b79e3afa788 --- /dev/null +++ b/lightning/src/ln/peers/encryption.rs @@ -0,0 +1,394 @@ +// This file is Copyright its original authors, visible in version control +// history. +// +// This file is licensed under the Apache License, Version 2.0 or the MIT license +// , at your option. +// You may not use this file except in accordance with one or both of these +// licenses. + +//! Handles all over the wire message encryption and decryption upon handshake completion. + +use ln::peers::{chacha, hkdf5869rfc}; +use util::byte_utils; +use std::collections::VecDeque; + +/// Maximum Lightning message data length according to +/// [BOLT-8](https://github.com/lightningnetwork/lightning-rfc/blob/v1.0/08-transport.md#lightning-message-specification) +/// and [BOLT-1](https://github.com/lightningnetwork/lightning-rfc/blob/master/01-messaging.md#lightning-message-format): +pub const LN_MAX_MSG_LEN: usize = ::std::u16::MAX as usize; // Must be equal to 65535 + +pub(super) type SymmetricKey = [u8; 32]; + +const MESSAGE_LENGTH_HEADER_SIZE: usize = 2; +const TAGGED_MESSAGE_LENGTH_HEADER_SIZE: usize = MESSAGE_LENGTH_HEADER_SIZE + chacha::TAG_SIZE; + +const KEY_ROTATION_INDEX: u32 = 1000; + +/// Instantiate a new (Encryptor, Decryptor) with specified sending and receiving keys +pub fn create_encryptor_decryptor(sending_key: SymmetricKey, receiving_key: SymmetricKey, chaining_key: SymmetricKey) -> (Encryptor, Decryptor) { + (Encryptor { + sending_key, + sending_chaining_key: chaining_key, + sending_nonce: 0 + }, + Decryptor { + receiving_key, + receiving_chaining_key: chaining_key, + receiving_nonce: 0, + read_buffer: Some(vec![]), + pending_message_length: None, + decrypted_payloads: VecDeque::new(), + }) +} + +// Shared helper for the Encryptor and Decryptor +fn increment_nonce_helper(nonce: &mut u32, chaining_key: &mut SymmetricKey, key: &mut SymmetricKey) { + *nonce += 1; + if *nonce == KEY_ROTATION_INDEX { + rotate_key(chaining_key, key); + *nonce = 0; + } +} + +// Shared helper for the Encryptor and Decryptor +fn rotate_key(chaining_key: &mut SymmetricKey, key: &mut SymmetricKey) { + let (new_chaining_key, new_key) = hkdf5869rfc::derive(chaining_key, key); + chaining_key.copy_from_slice(&new_chaining_key); + key.copy_from_slice(&new_key); +} + +pub struct Encryptor { + sending_key: SymmetricKey, + sending_chaining_key: SymmetricKey, + sending_nonce: u32, +} + +pub struct Decryptor { + receiving_key: SymmetricKey, + receiving_chaining_key: SymmetricKey, + receiving_nonce: u32, + + pending_message_length: Option, + read_buffer: Option>, + decrypted_payloads: VecDeque>, +} + +impl Iterator for Decryptor { + type Item = Vec; + + fn next(&mut self) -> Option { + self.decrypted_payloads.pop_front() + } +} + +impl Encryptor { + pub fn encrypt(&mut self, buffer: &[u8]) -> Vec { + if buffer.len() > LN_MAX_MSG_LEN { + panic!("Attempted to encrypt message longer than 65535 bytes!"); + } + + let length = buffer.len() as u16; + let length_bytes = byte_utils::be16_to_array(length); + + let mut ciphertext = vec![0u8; TAGGED_MESSAGE_LENGTH_HEADER_SIZE + length as usize + chacha::TAG_SIZE]; + + chacha::encrypt(&self.sending_key, self.sending_nonce as u64, &[0; 0], &length_bytes, &mut ciphertext[..TAGGED_MESSAGE_LENGTH_HEADER_SIZE]); + self.increment_nonce(); + + &chacha::encrypt(&self.sending_key, self.sending_nonce as u64, &[0; 0], buffer, &mut ciphertext[TAGGED_MESSAGE_LENGTH_HEADER_SIZE..]); + self.increment_nonce(); + + ciphertext + } + + fn increment_nonce(&mut self) { + increment_nonce_helper(&mut self.sending_nonce, &mut self.sending_chaining_key, &mut self.sending_key); + } +} + +impl Decryptor { + + // Read in new encrypted data and process it. This attempts to decrypt the input data and any + // existing data in the internal read buffer and can return an error if there is an error raised + // from the decryption code. + pub fn read(&mut self, data: &[u8]) -> Result<(), String> { + let mut read_buffer = self.read_buffer.take().unwrap(); + + let buffer = if read_buffer.is_empty() { + data + } else { + read_buffer.extend_from_slice(data); + read_buffer.as_slice() + }; + + let mut read_offset = 0; + loop { + match self.decrypt_next(&buffer[read_offset..]) { + Ok((Some(result), bytes_read)) => { + read_offset += bytes_read; + self.decrypted_payloads.push_back(result); + }, + Ok((None, 0)) => { + self.read_buffer = Some(buffer[read_offset..].to_vec()); + break; + } + Err(e) => { + return Err(e); + } + Ok((None, _)) => { panic!("Invalid return from decrypt_next()") } + } + } + + Ok(()) + } + + // Decrypt the next payload from the slice returning the number of bytes consumed during the + // operation. This will always be (None, 0) if no payload could be decrypted. + fn decrypt_next(&mut self, buffer: &[u8]) -> Result<(Option>, usize), String> { + if buffer.len() > LN_MAX_MSG_LEN + 16 { + panic!("Attempted to decrypt message longer than 65535 + 16 bytes!"); + } + + let message_length = if let Some(length) = self.pending_message_length { + // we have already decrypted the header + length + } else { + if buffer.len() < TAGGED_MESSAGE_LENGTH_HEADER_SIZE { + // A message must be at least 18 bytes (2 for encrypted length, 16 for the tag) + return Ok((None, 0)); + } + + let encrypted_length = &buffer[0..TAGGED_MESSAGE_LENGTH_HEADER_SIZE]; + let mut length_bytes = [0u8; MESSAGE_LENGTH_HEADER_SIZE]; + chacha::decrypt(&self.receiving_key, self.receiving_nonce as u64, &[0; 0], encrypted_length, &mut length_bytes)?; + + self.increment_nonce(); + + // the message length + byte_utils::slice_to_be16(&length_bytes) as usize + }; + + let message_end_index = TAGGED_MESSAGE_LENGTH_HEADER_SIZE + message_length + chacha::TAG_SIZE; + + if buffer.len() < message_end_index { + self.pending_message_length = Some(message_length); + return Ok((None, 0)); + } + + self.pending_message_length = None; + + let encrypted_message = &buffer[TAGGED_MESSAGE_LENGTH_HEADER_SIZE..message_end_index]; + let mut message = vec![0u8; message_length]; + + chacha::decrypt(&self.receiving_key, self.receiving_nonce as u64, &[0; 0], encrypted_message, &mut message)?; + + self.increment_nonce(); + + Ok((Some(message), message_end_index)) + } + + fn increment_nonce(&mut self) { + increment_nonce_helper(&mut self.receiving_nonce, &mut self.receiving_chaining_key, &mut self.receiving_key); + } + + // Used in tests to determine whether or not excess bytes entered the Decryptor without needing + // to bring up infrastructure to properly encode it + #[cfg(test)] + pub fn read_buffer_length(&self) -> usize { + match &self.read_buffer { + &Some(ref vec) => { vec.len() } + &None => 0 + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use hex; + + fn setup_peers() -> ((Encryptor, Decryptor), (Encryptor, Decryptor)) { + let chaining_key_vec = hex::decode("919219dbb2920afa8db80f9a51787a840bcf111ed8d588caf9ab4be716e42b01").unwrap(); + let mut chaining_key = [0u8; 32]; + chaining_key.copy_from_slice(&chaining_key_vec); + + let sending_key_vec = hex::decode("969ab31b4d288cedf6218839b27a3e2140827047f2c0f01bf5c04435d43511a9").unwrap(); + let mut sending_key = [0u8; 32]; + sending_key.copy_from_slice(&sending_key_vec); + + let receiving_key_vec = hex::decode("bb9020b8965f4df047e07f955f3c4b88418984aadc5cdb35096b9ea8fa5c3442").unwrap(); + let mut receiving_key = [0u8; 32]; + receiving_key.copy_from_slice(&receiving_key_vec); + + let connected_peer = create_encryptor_decryptor(sending_key, receiving_key, chaining_key); + let remote_peer = create_encryptor_decryptor(receiving_key, sending_key, chaining_key); + + (connected_peer, remote_peer) + } + + #[test] + fn test_empty_message() { + let ((mut connected_encryptor, _), (_, mut remote_decryptor)) = setup_peers(); + + let message: Vec = vec![]; + let encrypted_message = connected_encryptor.encrypt(&message); + assert_eq!(encrypted_message.len(), 2 + 16 + 16); + + remote_decryptor.read(&encrypted_message[..]).unwrap(); + let decrypted_message = remote_decryptor.next().unwrap(); + assert_eq!(decrypted_message, Vec::::new()); + } + + // Test that descrypting from a slice that is the partial data followed by another decrypt call + // with the remaining data works. This exercises the slow-path for decryption and ensures the + // data is written to the read_buffer properly. + #[test] + fn test_decrypt_from_slice_two_calls_no_header_then_rest() { + let ((mut connected_encryptor, _), (_, mut remote_decryptor)) = setup_peers(); + + let message: Vec = vec![1]; + let encrypted_message = connected_encryptor.encrypt(&message); + + remote_decryptor.read(&encrypted_message[..1]).unwrap(); + assert!(remote_decryptor.next().is_none()); + + remote_decryptor.read(&encrypted_message[1..]).unwrap(); + let decrypted_message = remote_decryptor.next().unwrap(); + + assert_eq!(decrypted_message, vec![1]); + } + + // Include the header in the first slice + #[test] + fn test_decrypt_from_slice_two_calls_header_then_rest() { + let ((mut connected_encryptor, _), (_, mut remote_decryptor)) = setup_peers(); + + let message: Vec = vec![1]; + let encrypted_message = connected_encryptor.encrypt(&message); + + remote_decryptor.read(&encrypted_message[..20]).unwrap(); + assert!(remote_decryptor.next().is_none()); + + remote_decryptor.read(&encrypted_message[20..]).unwrap(); + let decrypted_message = remote_decryptor.next().unwrap(); + + assert_eq!(decrypted_message, vec![1]); + } + + #[test] + fn test_nonce_chaining() { + let ((mut connected_encryptor, _), _) = setup_peers(); + let message = hex::decode("68656c6c6f").unwrap(); + + let encrypted_message = connected_encryptor.encrypt(&message); + assert_eq!(encrypted_message, hex::decode("cf2b30ddf0cf3f80e7c35a6e6730b59fe802473180f396d88a8fb0db8cbcf25d2f214cf9ea1d95").unwrap()); + + // the second time the same message is encrypted, the ciphertext should be different + let encrypted_message = connected_encryptor.encrypt(&message); + assert_eq!(encrypted_message, hex::decode("72887022101f0b6753e0c7de21657d35a4cb2a1f5cde2650528bbc8f837d0f0d7ad833b1a256a1").unwrap()); + } + + #[test] + /// Based on RFC test vectors: https://github.com/lightningnetwork/lightning-rfc/blob/master/08-transport.md#message-encryption-tests + fn test_key_rotation() { + let ((mut connected_encryptor, _), _) = setup_peers(); + + let message = hex::decode("68656c6c6f").unwrap(); + let mut encrypted_messages: Vec> = Vec::new(); + + for _ in 0..1002 { + let encrypted_message = connected_encryptor.encrypt(&message); + encrypted_messages.push(encrypted_message); + } + + assert_eq!(encrypted_messages[500], hex::decode("178cb9d7387190fa34db9c2d50027d21793c9bc2d40b1e14dcf30ebeeeb220f48364f7a4c68bf8").unwrap()); + assert_eq!(encrypted_messages[501], hex::decode("1b186c57d44eb6de4c057c49940d79bb838a145cb528d6e8fd26dbe50a60ca2c104b56b60e45bd").unwrap()); + assert_eq!(encrypted_messages[1000], hex::decode("4a2f3cc3b5e78ddb83dcb426d9863d9d9a723b0337c89dd0b005d89f8d3c05c52b76b29b740f09").unwrap()); + assert_eq!(encrypted_messages[1001], hex::decode("2ecd8c8a5629d0d02ab457a0fdd0f7b90a192cd46be5ecb6ca570bfc5e268338b1a16cf4ef2d36").unwrap()); + } + + #[test] + fn test_decryption_buffering() { + let ((mut connected_encryptor, _), (_, mut remote_decryptor)) = setup_peers(); + + let message = hex::decode("68656c6c6f").unwrap(); + let mut encrypted_messages: Vec> = Vec::new(); + + for _ in 0..1002 { + let encrypted_message = connected_encryptor.encrypt(&message); + encrypted_messages.push(encrypted_message); + } + + for _ in 0..501 { + // read two messages at once, filling buffer + let mut current_encrypted_message = encrypted_messages.remove(0); + let next_encrypted_message = encrypted_messages.remove(0); + current_encrypted_message.extend_from_slice(&next_encrypted_message); + remote_decryptor.read(¤t_encrypted_message[..]).unwrap(); + + let decrypted_message = remote_decryptor.next().unwrap(); + assert_eq!(decrypted_message, message); + } + + for _ in 0..501 { + // decrypt messages directly from buffer without adding to it + remote_decryptor.read(&[]).unwrap(); + let decrypted_message = remote_decryptor.next().unwrap(); + assert_eq!(decrypted_message, message); + } + } + + // Decryption errors should result in Err + #[test] + fn decryption_failure_errors() { + let ((mut connected_encryptor, _), (_, mut remote_decryptor)) = setup_peers(); + let encrypted = connected_encryptor.encrypt(&[1]); + + remote_decryptor.receiving_key = [0; 32]; + assert_eq!(remote_decryptor.read(&encrypted), Err("invalid hmac".to_string())); + } + + // Test next()::None + #[test] + fn decryptor_iterator_empty() { + let (_, (_, mut remote_decryptor)) = setup_peers(); + + assert_eq!(remote_decryptor.next(), None); + } + + // Test next() -> next()::None + #[test] + fn decryptor_iterator_one_item_valid() { + let ((mut connected_encryptor, _), (_, mut remote_decryptor)) = setup_peers(); + let encrypted = connected_encryptor.encrypt(&[1]); + remote_decryptor.read(&encrypted).unwrap(); + + assert_eq!(remote_decryptor.next(), Some(vec![1])); + assert_eq!(remote_decryptor.next(), None); + } + + #[test] + fn max_msg_len_limit_value() { + assert_eq!(LN_MAX_MSG_LEN, 65535); + assert_eq!(LN_MAX_MSG_LEN, ::std::u16::MAX as usize); + } + + #[test] + #[should_panic(expected = "Attempted to encrypt message longer than 65535 bytes!")] + fn max_message_len_encryption() { + let ((mut connected_encryptor, _), _) = setup_peers(); + let msg = [4u8; LN_MAX_MSG_LEN + 1]; + let _should_panic = connected_encryptor.encrypt(&msg); + } + + #[test] + #[should_panic(expected = "Attempted to decrypt message longer than 65535 + 16 bytes!")] + fn max_message_len_decryption() { + let ((_, mut connected_decryptor), _) = setup_peers(); + + // MSG should not exceed LN_MAX_MSG_LEN + 16 + let msg = [4u8; LN_MAX_MSG_LEN + 17]; + connected_decryptor.read(&msg).unwrap(); + } +} \ No newline at end of file diff --git a/lightning/src/ln/peers/handler.rs b/lightning/src/ln/peers/handler.rs new file mode 100644 index 00000000000..0cd90cc7bef --- /dev/null +++ b/lightning/src/ln/peers/handler.rs @@ -0,0 +1,3275 @@ +// This file is Copyright its original authors, visible in version control +// history. +// +// This file is licensed under the Apache License, Version 2.0 or the MIT license +// , at your option. +// You may not use this file except in accordance with one or both of these +// licenses. + +//! Top level peer message handling and socket handling logic lives here. +//! +//! Instead of actually servicing sockets ourselves we require that you implement the +//! SocketDescriptor interface and use that to receive actions which you should perform on the +//! socket, and call into PeerManager with bytes read from the socket. The PeerManager will then +//! call into the provided message handlers (probably a ChannelManager and NetGraphmsgHandler) with messages +//! they should handle, and encoding/sending response messages. + +use bitcoin::secp256k1::key::{SecretKey,PublicKey}; + +use ln::features::InitFeatures; +use ln::msgs; +use ln::msgs::{ChannelMessageHandler, LightningError, RoutingMessageHandler}; +use ln::channelmanager::{SimpleArcChannelManager, SimpleRefChannelManager}; +use util::ser::{Writeable}; +use ln::wire; +use ln::wire::{Encode, Message}; +use util::byte_utils; +use util::events::{MessageSendEvent, MessageSendEventsProvider}; +use util::logger::Logger; +use routing::network_graph::NetGraphMsgHandler; + +use std::collections::{HashMap,HashSet}; +use std::sync::{Arc, Mutex}; +use std::sync::atomic::{AtomicUsize, Ordering}; +use std::{cmp,error,hash,fmt}; +use std::ops::Deref; + +use bitcoin::hashes::sha256::Hash as Sha256; +use bitcoin::hashes::sha256::HashEngine as Sha256Engine; +use bitcoin::hashes::{HashEngine, Hash}; +use ln::peers::outbound_queue::OutboundQueue; +use ln::peers::transport::{PayloadQueuer, Transport}; +use bitcoin::hashes::core::iter::Filter; +use std::collections::hash_map::IterMut; + +const MSG_BUFF_SIZE: usize = 10; + +/// Interface PeerManager uses to interact with the Transport object +pub(super) trait ITransport: MessageQueuer { + /// Instantiate the new outbound Transport + fn new_outbound(initiator_static_private_key: &SecretKey, responder_static_public_key: &PublicKey, initiator_ephemeral_private_key: &SecretKey) -> Self; + + /// Set up the Transport receiving any bytes that need to be sent to the peer + fn set_up_outbound(&mut self) -> Vec; + + /// Instantiate a new inbound Transport + fn new_inbound(responder_static_private_key: &SecretKey, responder_ephemeral_private_key: &SecretKey) -> Self; + + /// Process input data similar to reading it off a descriptor directly. + fn process_input(&mut self, input: &[u8], output_buffer: &mut impl PayloadQueuer) -> Result; + + /// Returns true if the connection is established and encrypted messages can be sent. + fn is_connected(&self) -> bool; + + /// Returns the node_id of the remote node. Panics if not connected. + fn get_their_node_id(&self) -> PublicKey; + + /// Returns all Messages that have been received and can be parsed by the Transport + fn drain_messages(&mut self, logger: L) -> Result, PeerHandleError> where L::Target: Logger; +} + +/// Interface PeerManager uses to queue message to send. Used primarily to restrict the interface in +/// specific contexts. e.g. Only queueing during read_event(). No flushing allowed. +pub(super) trait MessageQueuer { + /// Encodes, encrypts, and enqueues a message to the outbound queue. Panics if the connection is + /// not established yet. + fn enqueue_message(&mut self, message: &M, output_buffer: &mut Q, logger: L) where L::Target: Logger; +} + +/// Trait representing a container that can try to flush data through a SocketDescriptor +pub(super) trait SocketDescriptorFlusher { + /// Write previously enqueued data to the SocketDescriptor. A return of false indicates the + /// underlying SocketDescriptor could not fulfill the send_data() call and the blocked state + /// has been set. Use unblock() when the SocketDescriptor may have more room. + fn try_flush_one(&mut self, descriptor: &mut impl SocketDescriptor) -> bool; + + /// Clear the blocked state caused when a previous write failed + fn unblock(&mut self); + + /// Check if the container is in a blocked state + fn is_blocked(&self) -> bool; +} + +/// Provides references to trait impls which handle different types of messages. +pub struct MessageHandler where + CM::Target: ChannelMessageHandler, + RM::Target: RoutingMessageHandler { + /// A message handler which handles messages specific to channels. Usually this is just a + /// ChannelManager object. + pub chan_handler: CM, + /// A message handler which handles messages updating our knowledge of the network channel + /// graph. Usually this is just a NetGraphMsgHandlerMonitor object. + pub route_handler: RM, +} + +/// Provides an object which can be used to send data to and which uniquely identifies a connection +/// to a remote host. You will need to be able to generate multiple of these which meet Eq and +/// implement Hash to meet the PeerManager API. +/// +/// For efficiency, Clone should be relatively cheap for this type. +/// +/// You probably want to just extend an int and put a file descriptor in a struct and implement +/// send_data. Note that if you are using a higher-level net library that may call close() itself, +/// be careful to ensure you don't have races whereby you might register a new connection with an +/// fd which is the same as a previous one which has yet to be removed via +/// PeerManager::socket_disconnected(). +pub trait SocketDescriptor : cmp::Eq + hash::Hash + Clone { + /// Attempts to send some data from the given slice to the peer. + /// + /// Returns the amount of data which was sent, possibly 0 if the socket has since disconnected. + /// Note that in the disconnected case, socket_disconnected must still fire and further write + /// attempts may occur until that time. + /// + /// If the returned size is smaller than data.len(), a write_available event must + /// trigger the next time more data can be written. Additionally, until the a send_data event + /// completes fully, no further read_events should trigger on the same peer! + /// + /// If a read_event on this descriptor had previously returned true (indicating that read + /// events should be paused to prevent DoS in the send buffer), resume_read may be set + /// indicating that read events on this descriptor should resume. A resume_read of false does + /// *not* imply that further read events should be paused. + fn send_data(&mut self, data: &[u8], resume_read: bool) -> usize; + /// Disconnect the socket pointed to by this SocketDescriptor. Once this function returns, no + /// more calls to write_buffer_space_avail, read_event or socket_disconnected may be made with + /// this descriptor. No socket_disconnected call should be generated as a result of this call, + /// though races may occur whereby disconnect_socket is called after a call to + /// socket_disconnected but prior to socket_disconnected returning. + fn disconnect_socket(&mut self); +} + +/// Error for PeerManager errors. If you get one of these, you must disconnect the socket and +/// generate no further read_event/write_buffer_space_avail calls for the descriptor, only +/// triggering a single socket_disconnected call (unless it was provided in response to a +/// new_*_connection event, in which case no such socket_disconnected() must be called and the +/// socket silently disconencted). +pub struct PeerHandleError { + /// Used to indicate that we probably can't make any future connections to this peer, implying + /// we should go ahead and force-close any channels we have with it. + pub no_connection_possible: bool, +} +impl fmt::Debug for PeerHandleError { + fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { + formatter.write_str("Peer Sent Invalid Data") + } +} +impl fmt::Display for PeerHandleError { + fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { + formatter.write_str("Peer Sent Invalid Data") + } +} +impl error::Error for PeerHandleError { + fn description(&self) -> &str { + "Peer Sent Invalid Data" + } +} + +enum InitSyncTracker{ + NoSyncRequested, + ChannelsSyncing(u64), + NodesSyncing(PublicKey), +} + +// Container for all state only valid after an Init message is seen +struct PostInitState { + awaiting_pong: bool, + sync_status: InitSyncTracker, + their_features: InitFeatures, +} + +impl PostInitState { + fn new(sync_status: InitSyncTracker, their_features: InitFeatures) -> Self { + Self { + awaiting_pong: false, + sync_status, + their_features + } + } +} + +struct Peer { + outbound: bool, + outbound_queue: OutboundQueue, + post_init_state: Option, + transport: TransportImpl, +} + +impl Peer { + fn new(outbound: bool, transport: TransportImpl) -> Self { + Self { + outbound, + outbound_queue: OutboundQueue::new(MSG_BUFF_SIZE), + post_init_state: None, + transport + } + } + + /// Returns true if an INIT message has been received from this peer. Implies that this node + /// can send and receive encrypted messages. + fn is_initialized(&self) -> bool { + self.post_init_state.is_some() + } + + /// Returns true if the channel announcements/updates for the given channel should be + /// forwarded to this peer. + /// If we are sending our routing table to this peer and we have not yet sent channel + /// announcements/updates for the given channel_id then we will send it when we get to that + /// point and we shouldn't send it yet to avoid sending duplicate updates. If we've already + /// sent the old versions, we should send the update, and so return true here. + fn should_forward_channel_announcement(&self, channel_id: u64) -> bool{ + match &self.post_init_state { + None => panic!("should_forward_channel_announcement() only valid on an uninitialized peer"), + Some(state) => { + match state.sync_status { + InitSyncTracker::NoSyncRequested => true, + InitSyncTracker::ChannelsSyncing(i) => i < channel_id, + InitSyncTracker::NodesSyncing(_) => true, + } + } + } + } + + /// Similar to the above, but for node announcements indexed by node_id. + fn should_forward_node_announcement(&self, node_id: PublicKey) -> bool { + match &self.post_init_state { + None => panic!("should_forward_channel_announcement() only valid on an uninitialized peer"), + Some(state) => { + match state.sync_status { + InitSyncTracker::NoSyncRequested => true, + InitSyncTracker::ChannelsSyncing(_) => false, + InitSyncTracker::NodesSyncing(pk) => pk < node_id, + } + } + } + } +} + +struct PeerHolder { + peers: HashMap>, + /// Added to by do_read_event for cases where we pushed a message onto the send buffer but + /// didn't call do_attempt_write_data to avoid reentrancy. Cleared in process_events() + peers_needing_send: HashSet, + /// Only add to this set when noise completes: + node_id_to_descriptor: HashMap, +} + +impl PeerHolder { + fn initialized_peer_by_node_id_mut(&mut self, node_id: &PublicKey) -> Option<(Descriptor, &mut Peer)> { + match self.node_id_to_descriptor.get_mut(node_id) { + None => None, + Some(descriptor) => { + assert!(self.peers.contains_key(descriptor), "Invalid PeerHolder state"); + + match self.peers.get_mut(&descriptor) { + None => panic!("Invalid PeerHolder state!"), + Some(peer) => { + + // their_features is set after receiving an Init message + if peer.post_init_state.is_none() { + None + } else { + Some((descriptor.clone(), peer)) + } + } + } + } + } + } + + // Returns the subset of peers that are initialized w/ their SocketDescriptor (mutable) + fn initialized_peers_mut<'a>(&'a mut self) -> Filter>, fn(&(&'a Descriptor, &'a mut Peer)) -> bool> { + self.peers.iter_mut().filter(| entry | { + entry.1.post_init_state.is_some() + }) + } + + // Returns the node id's of the subset of peers that are initialized + fn initialized_peer_node_ids(&self) -> Vec { + self.node_id_to_descriptor.keys().cloned().collect() + } + + // Removes all associated metadata for descriptor and returns the Peer object associated with it + fn remove_peer_by_descriptor(&mut self, descriptor: &Descriptor) -> Peer { + // may or may not be in this set depending on in-flight messages + self.peers_needing_send.remove(descriptor); + + let peer_option = self.peers.remove(descriptor); + match peer_option { + None => panic!("Descriptor for disconnect_event is not already known to PeerManager"), + Some(peer) => { + if peer.post_init_state.is_some() { + let their_node_id = peer.transport.get_their_node_id(); + + match self.node_id_to_descriptor.remove(&their_node_id) { + None => { panic!("Initialized peer must be in node_id_to_descriptor")} + Some(removed_descriptor) => { assert!(&removed_descriptor == descriptor, "Invalid PeerHolder state. Descriptors do not match!") } + } + } + peer + } + } + } +} + +#[cfg(not(any(target_pointer_width = "32", target_pointer_width = "64")))] +fn _check_usize_is_32_or_64() { + // See below, less than 32 bit pointers may be unsafe here! + unsafe { mem::transmute::<*const usize, [u8; 4]>(panic!()); } +} + +/// SimpleArcPeerManager is useful when you need a PeerManager with a static lifetime, e.g. +/// when you're using lightning-net-tokio (since tokio::spawn requires parameters with static +/// lifetimes). Other times you can afford a reference, which is more efficient, in which case +/// SimpleRefPeerManager is the more appropriate type. Defining these type aliases prevents +/// issues such as overly long function definitions. +pub type SimpleArcPeerManager = Arc, Arc, Arc>>, Arc>>; + +/// SimpleRefPeerManager is a type alias for a PeerManager reference, and is the reference +/// counterpart to the SimpleArcPeerManager type alias. Use this type by default when you don't +/// need a PeerManager with a static lifetime. You'll need a static lifetime in cases such as +/// usage of lightning-net-tokio (since tokio::spawn requires parameters with static lifetimes). +/// But if this is not necessary, using a reference is more efficient. Defining these type aliases +/// helps with issues such as long function definitions. +pub type SimpleRefPeerManager<'a, 'b, 'c, 'd, 'e, 'f, 'g, SD, M, T, F, C, L> = PeerManager, &'e NetGraphMsgHandler<&'g C, &'f L>, &'f L>; + +/// A PeerManager manages a set of peers, described by their SocketDescriptor and marshalls socket +/// events into messages which it passes on to its MessageHandlers. +/// +/// Rather than using a plain PeerManager, it is preferable to use either a SimpleArcPeerManager +/// a SimpleRefPeerManager, for conciseness. See their documentation for more details, but +/// essentially you should default to using a SimpleRefPeerManager, and use a +/// SimpleArcPeerManager when you require a PeerManager with a static lifetime, such as when +/// you're using lightning-net-tokio. +pub struct PeerManager where + CM::Target: ChannelMessageHandler, + RM::Target: RoutingMessageHandler, + L::Target: Logger { + inner: PeerManagerImpl, +} + +// Internal struct that mirrors the PeerManager interface, but can take in a Transport type parameter +// that is useful for testing. This enables the public docs for PeerManager to stay clean. +// +// All PeerManager calls just delegate to this struct directly and it is important to keep it that +// way to ensure full test coverage of the public APIs. +struct PeerManagerImpl where + CM::Target: ChannelMessageHandler, + RM::Target: RoutingMessageHandler, + L::Target: Logger { + message_handler: MessageHandler, + peers: Mutex>, + our_node_secret: SecretKey, + ephemeral_key_midstate: Mutex, + + // Usize needs to be at least 32 bits to avoid overflowing both low and high. If usize is 64 + // bits we will never realistically count into high: + peer_counter_low: AtomicUsize, + peer_counter_high: AtomicUsize, + + logger: L, +} + +enum MessageHandlingError { + PeerHandleError(PeerHandleError), + LightningError(LightningError), +} + +impl From for MessageHandlingError { + fn from(error: PeerHandleError) -> Self { + MessageHandlingError::PeerHandleError(error) + } +} + +impl From for MessageHandlingError { + fn from(error: LightningError) -> Self { + MessageHandlingError::LightningError(error) + } +} + +/// Manages and reacts to connection events. You probably want to use file descriptors as PeerIds. +/// PeerIds may repeat, but only after socket_disconnected() has been called. +impl PeerManager where + CM::Target: ChannelMessageHandler, + RM::Target: RoutingMessageHandler, + L::Target: Logger { + + /// Constructs a new PeerManager with the given message handlers and node_id secret key + /// ephemeral_random_data is used to derive per-connection ephemeral keys and must be + /// cryptographically secure random bytes. + pub fn new(message_handler: MessageHandler, our_node_secret: SecretKey, ephemeral_random_data: &[u8; 32], logger: L) -> Self { + Self { + inner: PeerManagerImpl::new(message_handler, our_node_secret, ephemeral_random_data, logger) + } + } + + /// Get the list of node ids for peers which have completed the initial handshake. + /// + /// For outbound connections, this will be the same as the their_node_id parameter passed in to + /// new_outbound_connection, however entries will only appear once the initial handshake has + /// completed and we are sure the remote peer has the private key for the given node_id. + pub fn get_peer_node_ids(&self) -> Vec { + self.inner.get_peer_node_ids() + } + + /// Indicates a new outbound connection has been established to a node with the given node_id. + /// Note that if an Err is returned here you MUST NOT call socket_disconnected for the new + /// descriptor but must disconnect the connection immediately. + /// + /// Returns a small number of bytes to send to the remote node (currently always 50). + /// + /// Panics if descriptor is duplicative with some other descriptor which has not yet had a + /// socket_disconnected(). + pub fn new_outbound_connection(&self, their_node_id: PublicKey, descriptor: Descriptor) -> Result, PeerHandleError> { + self.inner.new_outbound_connection(their_node_id, descriptor) + } + + /// Indicates a new inbound connection has been established. + /// + /// May refuse the connection by returning an Err, but will never write bytes to the remote end + /// (outbound connector always speaks first). Note that if an Err is returned here you MUST NOT + /// call socket_disconnected for the new descriptor but must disconnect the connection + /// immediately. + /// + /// Panics if descriptor is duplicative with some other descriptor which has not yet had + /// socket_disconnected called. + pub fn new_inbound_connection(&self, descriptor: Descriptor) -> Result<(), PeerHandleError> { + self.inner.new_inbound_connection(descriptor) + } + + /// Indicates that there is room to write data to the given socket descriptor. + /// + /// May return an Err to indicate that the connection should be closed. + /// + /// Will most likely call send_data on the descriptor passed in (or the descriptor handed into + /// new_*\_connection) before returning. Thus, be very careful with reentrancy issues! The + /// invariants around calling write_buffer_space_avail in case a write did not fully complete + /// must still hold - be ready to call write_buffer_space_avail again if a write call generated + /// here isn't sufficient! Panics if the descriptor was not previously registered in a + /// new_\*_connection event. + pub fn write_buffer_space_avail(&self, descriptor: &mut Descriptor) -> Result<(), PeerHandleError> { + self.inner.write_buffer_space_avail(descriptor) + } + + /// Indicates that data was read from the given socket descriptor. + /// + /// May return an Err to indicate that the connection should be closed. + /// + /// Will *not* call back into send_data on any descriptors to avoid reentrancy complexity. + /// Thus, however, you almost certainly want to call process_events() after any read_event to + /// generate send_data calls to handle responses. + /// + /// If Ok(true) is returned, further read_events should not be triggered until a send_data call + /// on this file descriptor has resume_read set (preventing DoS issues in the send buffer). + /// + /// Panics if the descriptor was not previously registered in a new_*_connection event. + pub fn read_event(&self, peer_descriptor: &mut Descriptor, data: &[u8]) -> Result { + self.inner.read_event(peer_descriptor, data) + } + + /// Checks for any events generated by our handlers and processes them. Includes sending most + /// response messages as well as messages generated by calls to handler functions directly (eg + /// functions like ChannelManager::process_pending_htlc_forward or send_payment). + pub fn process_events(&self) { + self.inner.process_events(); + } + + /// Indicates that the given socket descriptor's connection is now closed. + /// + /// This must only be called if the socket has been disconnected by the peer or your own + /// decision to disconnect it and must NOT be called in any case where other parts of this + /// library (eg PeerHandleError, explicit disconnect_socket calls) instruct you to disconnect + /// the peer. + /// + /// Panics if the descriptor was not previously registered in a successful new_*_connection event. + pub fn socket_disconnected(&self, descriptor: &Descriptor) { + self.inner.socket_disconnected(descriptor) + } + + /// This function should be called roughly once every 30 seconds. + /// It will send pings to each peer and disconnect those which did not respond to the last round of pings. + + /// Will most likely call send_data on all of the registered descriptors, thus, be very careful with reentrancy issues! + pub fn timer_tick_occured(&self) { + self.inner.timer_tick_occured() + } +} + + +impl PeerManagerImpl where + CM::Target: ChannelMessageHandler, + RM::Target: RoutingMessageHandler, + L::Target: Logger { + + fn new(message_handler: MessageHandler, our_node_secret: SecretKey, ephemeral_random_data: &[u8; 32], logger: L) -> Self { + let mut ephemeral_key_midstate = Sha256::engine(); + ephemeral_key_midstate.input(ephemeral_random_data); + + PeerManagerImpl { + message_handler, + peers: Mutex::new(PeerHolder { + peers: HashMap::new(), + peers_needing_send: HashSet::new(), + node_id_to_descriptor: HashMap::new() + }), + our_node_secret, + ephemeral_key_midstate: Mutex::new(ephemeral_key_midstate), + peer_counter_low: AtomicUsize::new(0), + peer_counter_high: AtomicUsize::new(0), + logger, + } + } + + fn get_peer_node_ids(&self) -> Vec { + let peers = self.peers.lock().unwrap(); + peers.initialized_peer_node_ids() + } + + fn get_ephemeral_key(&self) -> SecretKey { + let mut ephemeral_hash = self.ephemeral_key_midstate.lock().unwrap().clone(); + let low = self.peer_counter_low.fetch_add(1, Ordering::AcqRel); + let high = if low == 0 { + self.peer_counter_high.fetch_add(1, Ordering::AcqRel) + } else { + self.peer_counter_high.load(Ordering::Acquire) + }; + ephemeral_hash.input(&byte_utils::le64_to_array(low as u64)); + ephemeral_hash.input(&byte_utils::le64_to_array(high as u64)); + SecretKey::from_slice(&Sha256::from_engine(ephemeral_hash).into_inner()).expect("You broke SHA-256!") + } + + fn new_outbound_connection(&self, their_node_id: PublicKey, descriptor: Descriptor) -> Result, PeerHandleError> { + let transport = TransportImpl::new_outbound(&self.our_node_secret, &their_node_id, &self.get_ephemeral_key()); + self.new_outbound_connection_with_transport(descriptor, transport) + } + + fn new_outbound_connection_with_transport(&self, descriptor: Descriptor, mut transport: TransportImpl) -> Result, PeerHandleError> { + let mut peers = self.peers.lock().unwrap(); + let initial_bytes = transport.set_up_outbound(); + + if peers.peers.insert(descriptor, Peer::::new(true, transport)).is_some() { + panic!("PeerManager driver duplicated descriptors!"); + }; + Ok(initial_bytes) + } + + fn new_inbound_connection(&self, descriptor: Descriptor) -> Result<(), PeerHandleError> { + let transport = TransportImpl::new_inbound(&self.our_node_secret, &self.get_ephemeral_key()); + self.new_inbound_connection_with_transport(descriptor, transport) + } + + fn new_inbound_connection_with_transport(&self, descriptor: Descriptor, transport: TransportImpl) -> Result<(), PeerHandleError> { + let mut peers = self.peers.lock().unwrap(); + if peers.peers.insert(descriptor, Peer::::new(false, transport)).is_some() { + panic!("PeerManager driver duplicated descriptors!"); + }; + Ok(()) + } + + // Fill remaining slots in output queue with sync messages, updating the sync state when + // appropriate + fn fill_message_queue_with_sync( + &self, + sync_status: &mut InitSyncTracker, + message_queuer: &mut impl MessageQueuer, + outbound_queue: &mut Q) { + + let queue_space = outbound_queue.queue_space(); + if queue_space > 0 { + match sync_status { + &mut InitSyncTracker::NoSyncRequested => {}, + &mut InitSyncTracker::ChannelsSyncing(c) if c < 0xffff_ffff_ffff_ffff => { + let steps = ((queue_space + 2) / 3) as u8; + let all_messages = self.message_handler.route_handler.get_next_channel_announcements(c, steps); + for &(ref announce, ref update_a_option, ref update_b_option) in all_messages.iter() { + message_queuer.enqueue_message(announce, outbound_queue, &*self.logger); + if let &Some(ref update_a) = update_a_option { + message_queuer.enqueue_message(update_a, outbound_queue, &*self.logger); + } + if let &Some(ref update_b) = update_b_option { + message_queuer.enqueue_message(update_b, outbound_queue, &*self.logger); + } + *sync_status = InitSyncTracker::ChannelsSyncing(announce.contents.short_channel_id + 1); + } + if all_messages.is_empty() || all_messages.len() != steps as usize { + *sync_status = InitSyncTracker::ChannelsSyncing(0xffff_ffff_ffff_ffff); + } + }, + &mut InitSyncTracker::ChannelsSyncing(c) if c == 0xffff_ffff_ffff_ffff => { + let steps = queue_space as u8; + let all_messages = self.message_handler.route_handler.get_next_node_announcements(None, steps); + for msg in all_messages.iter() { + message_queuer.enqueue_message(msg, outbound_queue, &*self.logger); + *sync_status = InitSyncTracker::NodesSyncing(msg.contents.node_id); + } + if all_messages.is_empty() || all_messages.len() != steps as usize { + *sync_status = InitSyncTracker::NoSyncRequested; + } + }, + &mut InitSyncTracker::ChannelsSyncing(_) => unreachable!(), + &mut InitSyncTracker::NodesSyncing(key) => { + let steps = queue_space as u8; + let all_messages = self.message_handler.route_handler.get_next_node_announcements(Some(&key), steps); + for msg in all_messages.iter() { + message_queuer.enqueue_message(msg, outbound_queue, &*self.logger); + *sync_status = InitSyncTracker::NodesSyncing(msg.contents.node_id); + } + if all_messages.is_empty() || all_messages.len() != steps as usize { + *sync_status = InitSyncTracker::NoSyncRequested; + } + }, + } + } + } + + fn do_attempt_write_data( + &self, + descriptor: &mut Descriptor, + post_init_state: &mut Option, + message_queuer: &mut impl MessageQueuer, + outbound_queue: &mut Q) { + + while !outbound_queue.is_blocked() { + // If connected, fill output queue with sync messages + match post_init_state { + None => {}, + &mut Some(ref mut state) => self.fill_message_queue_with_sync(&mut state.sync_status, message_queuer, outbound_queue) + } + + // No messages to send + if outbound_queue.is_empty() { + break; + } + + outbound_queue.try_flush_one(descriptor); + } + } + + fn write_buffer_space_avail(&self, descriptor: &mut Descriptor) -> Result<(), PeerHandleError> { + let mut peers = self.peers.lock().unwrap(); + match peers.peers.get_mut(descriptor) { + None => panic!("Descriptor for write_event is not already known to PeerManager"), + Some(peer) => { + peer.outbound_queue.unblock(); + self.do_attempt_write_data(descriptor, &mut peer.post_init_state, &mut peer.transport, &mut peer.outbound_queue); + } + }; + Ok(()) + } + + fn read_event(&self, peer_descriptor: &mut Descriptor, data: &[u8]) -> Result { + let peers = &mut *self.peers.lock().unwrap(); + let result = { + let peer = match peers.peers.get_mut(peer_descriptor) { + None => panic!("Descriptor for read_event is not already known to PeerManager"), + Some(peer) => peer + }; + self.do_read_event(peer_descriptor, peer, &mut peers.peers_needing_send, &mut peers.node_id_to_descriptor, data) + }; + + match result { + Ok(res) => Ok(res), + Err(e) => { + self.disconnect_event_internal(peer_descriptor, e.no_connection_possible, peers); + Err(e) + } + } + } + + /// Append a message to a peer's pending outbound/write buffer, and update the map of peers needing sends accordingly. + fn enqueue_message(&self, peers_needing_send: &mut HashSet, message_queuer: &mut impl MessageQueuer, output_buffer: &mut impl PayloadQueuer, descriptor: &Descriptor, message: &M) { + message_queuer.enqueue_message(message, output_buffer, &*self.logger); + peers_needing_send.insert(descriptor.clone()); + } + + // Returns a valid PostInitState given a Init message + fn post_init_state_from_init_message(&self, init_message: &msgs::Init, their_node_id: &PublicKey) -> Result { + if init_message.features.requires_unknown_bits() { + log_info!(self.logger, "Peer global features required unknown version bits"); + return Err(PeerHandleError { no_connection_possible: true }.into()); + } + if init_message.features.requires_unknown_bits() { + log_info!(self.logger, "Peer local features required unknown version bits"); + return Err(PeerHandleError { no_connection_possible: true }.into()); + } + + log_info!( + self.logger, "Received peer Init message: data_loss_protect: {}, initial_routing_sync: {}, upfront_shutdown_script: {}, static_remote_key: {}, unknown flags (local and global): {}", + if init_message.features.supports_data_loss_protect() { "supported" } else { "not supported"}, + if init_message.features.initial_routing_sync() { "requested" } else { "not requested" }, + if init_message.features.supports_upfront_shutdown_script() { "supported" } else { "not supported"}, + if init_message.features.supports_static_remote_key() { "supported" } else { "not supported"}, + if init_message.features.supports_unknown_bits() { "present" } else { "none" } + ); + + let sync_status = if init_message.features.initial_routing_sync() { + InitSyncTracker::ChannelsSyncing(0) + } else { + InitSyncTracker::NoSyncRequested + }; + + if !init_message.features.supports_static_remote_key() { + log_debug!(self.logger, "Peer {} does not support static remote key, disconnecting with no_connection_possible", log_pubkey!(their_node_id)); + return Err(PeerHandleError { no_connection_possible: true }.into()); + } + + Ok(PostInitState::new(sync_status, init_message.features.clone())) + } + + // Add an Init message to the outbound queue + fn queue_init_message(&self, descriptor: &Descriptor, peer: &mut Peer, peers_needing_send: &mut HashSet) { + let mut features = InitFeatures::known(); + if !self.message_handler.route_handler.should_request_full_sync(&peer.transport.get_their_node_id()) { + features.clear_initial_routing_sync(); + } + + let resp = msgs::Init { features }; + self.enqueue_message(peers_needing_send, &mut peer.transport, &mut peer.outbound_queue, descriptor, &resp); + } + + // Process an incoming Init message and set Peer and PeerManager state accordingly + fn process_init_message(&self, message: Message, descriptor: &Descriptor, peer: &mut Peer, peers_needing_send: &mut HashSet, node_id_to_descriptor: &mut HashMap) -> Result<(), PeerHandleError> { + let their_node_id = peer.transport.get_their_node_id(); + + match message { + Message::Init(ref init_message) => { + log_trace!(self.logger, "Received Init message from {}", log_pubkey!(&their_node_id)); + if node_id_to_descriptor.contains_key(&their_node_id) { + log_trace!(self.logger, "Got second connection with {}, closing", log_pubkey!(&their_node_id)); + return Err(PeerHandleError { no_connection_possible: false }); + } + + let new_post_init_state = self.post_init_state_from_init_message(init_message, &their_node_id)?; + + if let InitSyncTracker::ChannelsSyncing(_) = new_post_init_state.sync_status { + peers_needing_send.insert(descriptor.clone()); + } + + if !peer.outbound { + self.queue_init_message(descriptor, peer, peers_needing_send); + } + node_id_to_descriptor.insert(their_node_id.clone(), descriptor.clone()); + self.message_handler.chan_handler.peer_connected(&their_node_id, init_message); + + assert!(peer.post_init_state.is_none()); + peer.post_init_state = Some(new_post_init_state); + } + _ => { + log_trace!(self.logger, "Peer {} sent non-Init first message", log_pubkey!(&their_node_id)); + return Err(PeerHandleError { no_connection_possible: false }) + }, + } + + Ok(()) + } + + fn do_read_event(&self, peer_descriptor: &mut Descriptor, peer: &mut Peer, peers_needing_send: &mut HashSet, node_id_to_descriptor: &mut HashMap, data: &[u8]) -> Result { + + match peer.transport.process_input(data, &mut peer.outbound_queue) { + Err(e) => { + log_trace!(self.logger, "Error while processing input: {}", e); + return Err(PeerHandleError { no_connection_possible: false }) + }, + Ok(newly_connected) => { + if newly_connected { + log_trace!(self.logger, "Finished noise handshake for connection with {}", log_pubkey!(&peer.transport.get_their_node_id())); + } + + if newly_connected && peer.outbound { + self.queue_init_message(peer_descriptor, peer, peers_needing_send); + } + + // If the transport layer placed items in the outbound queue, we need + // to schedule ourselves for flush during the next process_events() + if !peer.outbound_queue.is_empty() { + peers_needing_send.insert(peer_descriptor.clone()); + } + } + } + + let mut received_messages = peer.transport.drain_messages(&*self.logger)?; + + if peer.transport.is_connected() && peer.post_init_state.is_none() && received_messages.len() > 0 { + let init_message = received_messages.remove(0); + self.process_init_message(init_message, peer_descriptor, peer, peers_needing_send, node_id_to_descriptor)?; + } + + for message in received_messages { + macro_rules! try_potential_handleerror { + ($thing: expr) => { + match $thing { + Ok(x) => x, + Err(e) => { + match e.action { + msgs::ErrorAction::DisconnectPeer { msg: _ } => { + //TODO: Try to push msg + log_trace!(self.logger, "Got Err handling message, disconnecting peer because {}", e.err); + return Err(PeerHandleError{ no_connection_possible: false }); + }, + msgs::ErrorAction::IgnoreError => { + log_trace!(self.logger, "Got Err handling message, ignoring because {}", e.err); + continue; + }, + msgs::ErrorAction::SendErrorMessage { msg } => { + log_trace!(self.logger, "Got Err handling message, sending Error message because {}", e.err); + self.enqueue_message(peers_needing_send, &mut peer.transport, &mut peer.outbound_queue, peer_descriptor, &msg); + continue; + }, + } + } + }; + } + } + + if let Err(handling_error) = self.handle_message(message, peer_descriptor, peer, peers_needing_send) { + match handling_error { + MessageHandlingError::PeerHandleError(e) => { return Err(e) }, + MessageHandlingError::LightningError(e) => { + try_potential_handleerror!(Err(e)); + }, + } + } + } + + Ok(peer.outbound_queue.queue_space() == 0) // pause_read + } + + /// Process an incoming message and return a decision (ok, lightning error, peer handling error) regarding the next action with the peer + fn handle_message(&self, + message: wire::Message, + peer_descriptor: &mut Descriptor, + peer: &mut Peer, + peers_needing_send: &mut HashSet) -> Result<(), MessageHandlingError> { + + let their_node_id = peer.transport.get_their_node_id(); + let post_init_state = peer.post_init_state.as_mut().unwrap(); + log_trace!(self.logger, "Received message of type {} from {}", message.type_id(), log_pubkey!(&their_node_id)); + + match message { + // Setup and Control messages: + wire::Message::Init(_) => { + // 1st Init message handled before handle_message() so this must be a non-first + return Err(PeerHandleError{ no_connection_possible: false }.into()); + }, + wire::Message::Error(msg) => { + let mut data_is_printable = true; + for b in msg.data.bytes() { + if b < 32 || b > 126 { + data_is_printable = false; + break; + } + } + + if data_is_printable { + log_debug!(self.logger, "Got Err message from {}: {}", log_pubkey!(&their_node_id), msg.data); + } else { + log_debug!(self.logger, "Got Err message from {} with non-ASCII error message", log_pubkey!(&their_node_id)); + } + self.message_handler.chan_handler.handle_error(&their_node_id, &msg); + if msg.channel_id == [0; 32] { + return Err(PeerHandleError{ no_connection_possible: true }.into()); + } + }, + + wire::Message::Ping(msg) => { + if msg.ponglen < 65532 { + let resp = msgs::Pong { byteslen: msg.ponglen }; + self.enqueue_message(peers_needing_send, &mut peer.transport, &mut peer.outbound_queue, &peer_descriptor, &resp); + } + }, + wire::Message::Pong(_msg) => { + post_init_state.awaiting_pong = false; + }, + + // Channel messages: + wire::Message::OpenChannel(msg) => { + self.message_handler.chan_handler.handle_open_channel(&their_node_id, post_init_state.their_features.clone(), &msg); + }, + wire::Message::AcceptChannel(msg) => { + self.message_handler.chan_handler.handle_accept_channel(&their_node_id, post_init_state.their_features.clone(), &msg); + }, + + wire::Message::FundingCreated(msg) => { + self.message_handler.chan_handler.handle_funding_created(&their_node_id, &msg); + }, + wire::Message::FundingSigned(msg) => { + self.message_handler.chan_handler.handle_funding_signed(&their_node_id, &msg); + }, + wire::Message::FundingLocked(msg) => { + self.message_handler.chan_handler.handle_funding_locked(&their_node_id, &msg); + }, + + wire::Message::Shutdown(msg) => { + self.message_handler.chan_handler.handle_shutdown(&their_node_id, &msg); + }, + wire::Message::ClosingSigned(msg) => { + self.message_handler.chan_handler.handle_closing_signed(&their_node_id, &msg); + }, + + // Commitment messages: + wire::Message::UpdateAddHTLC(msg) => { + self.message_handler.chan_handler.handle_update_add_htlc(&their_node_id, &msg); + }, + wire::Message::UpdateFulfillHTLC(msg) => { + self.message_handler.chan_handler.handle_update_fulfill_htlc(&their_node_id, &msg); + }, + wire::Message::UpdateFailHTLC(msg) => { + self.message_handler.chan_handler.handle_update_fail_htlc(&their_node_id, &msg); + }, + wire::Message::UpdateFailMalformedHTLC(msg) => { + self.message_handler.chan_handler.handle_update_fail_malformed_htlc(&their_node_id, &msg); + }, + + wire::Message::CommitmentSigned(msg) => { + self.message_handler.chan_handler.handle_commitment_signed(&their_node_id, &msg); + }, + wire::Message::RevokeAndACK(msg) => { + self.message_handler.chan_handler.handle_revoke_and_ack(&their_node_id, &msg); + }, + wire::Message::UpdateFee(msg) => { + self.message_handler.chan_handler.handle_update_fee(&their_node_id, &msg); + }, + wire::Message::ChannelReestablish(msg) => { + self.message_handler.chan_handler.handle_channel_reestablish(&their_node_id, &msg); + }, + + // Routing messages: + wire::Message::AnnouncementSignatures(msg) => { + self.message_handler.chan_handler.handle_announcement_signatures(&their_node_id, &msg); + }, + wire::Message::ChannelAnnouncement(msg) => { + let should_forward = match self.message_handler.route_handler.handle_channel_announcement(&msg) { + Ok(v) => v, + Err(e) => { return Err(e.into()); }, + }; + + if should_forward { + // TODO: forward msg along to all our other peers! + } + }, + wire::Message::NodeAnnouncement(msg) => { + let should_forward = match self.message_handler.route_handler.handle_node_announcement(&msg) { + Ok(v) => v, + Err(e) => { return Err(e.into()); }, + }; + + if should_forward { + // TODO: forward msg along to all our other peers! + } + }, + wire::Message::ChannelUpdate(msg) => { + let should_forward = match self.message_handler.route_handler.handle_channel_update(&msg) { + Ok(v) => v, + Err(e) => { return Err(e.into()); }, + }; + + if should_forward { + // TODO: forward msg along to all our other peers! + } + }, + + // Unknown messages: + wire::Message::Unknown(msg_type) if msg_type.is_even() => { + log_debug!(self.logger, "Received unknown even message of type {}, disconnecting peer!", msg_type); + // Fail the channel if message is an even, unknown type as per BOLT #1. + return Err(PeerHandleError{ no_connection_possible: true }.into()); + }, + wire::Message::Unknown(msg_type) => { + log_trace!(self.logger, "Received unknown odd message of type {}, ignoring", msg_type); + } + }; + Ok(()) + } + + fn process_events(&self) { + { + // TODO: There are some DoS attacks here where you can flood someone's outbound send + // buffer by doing things like announcing channels on another node. We should be willing to + // drop optional-ish messages when send buffers get full! + + let mut events_generated = self.message_handler.chan_handler.get_and_clear_pending_msg_events(); + let mut peers_lock = self.peers.lock().unwrap(); + let peers = &mut *peers_lock; + for event in events_generated.drain(..) { + match event { + MessageSendEvent::SendAcceptChannel { ref node_id, ref msg } => { + log_trace!(self.logger, "Handling SendAcceptChannel event in peer_handler for node {} for channel {}", + log_pubkey!(node_id), + log_bytes!(msg.temporary_channel_id)); + if let Some((mut descriptor, peer)) = peers.initialized_peer_by_node_id_mut(node_id) { + peer.transport.enqueue_message(msg, &mut peer.outbound_queue, &*self.logger); + self.do_attempt_write_data(&mut descriptor, &mut peer.post_init_state, &mut peer.transport, &mut peer.outbound_queue); + } else { + //TODO: Drop the pending channel? (or just let it timeout, but that sucks) + } + }, + MessageSendEvent::SendOpenChannel { ref node_id, ref msg } => { + log_trace!(self.logger, "Handling SendOpenChannel event in peer_handler for node {} for channel {}", + log_pubkey!(node_id), + log_bytes!(msg.temporary_channel_id)); + if let Some((mut descriptor, peer)) = peers.initialized_peer_by_node_id_mut(node_id) { + peer.transport.enqueue_message(msg, &mut peer.outbound_queue, &*self.logger); + self.do_attempt_write_data(&mut descriptor, &mut peer.post_init_state, &mut peer.transport, &mut peer.outbound_queue); + } else { + //TODO: Drop the pending channel? (or just let it timeout, but that sucks) + } + }, + MessageSendEvent::SendFundingCreated { ref node_id, ref msg } => { + log_trace!(self.logger, "Handling SendFundingCreated event in peer_handler for node {} for channel {} (which becomes {})", + log_pubkey!(node_id), + log_bytes!(msg.temporary_channel_id), + log_funding_channel_id!(msg.funding_txid, msg.funding_output_index)); + if let Some((mut descriptor, peer)) = peers.initialized_peer_by_node_id_mut(node_id) { + peer.transport.enqueue_message(msg, &mut peer.outbound_queue, &*self.logger); + self.do_attempt_write_data(&mut descriptor, &mut peer.post_init_state, &mut peer.transport, &mut peer.outbound_queue); + } else { + //TODO: generate a DiscardFunding event indicating to the wallet that + //they should just throw away this funding transaction + } + }, + MessageSendEvent::SendFundingSigned { ref node_id, ref msg } => { + log_trace!(self.logger, "Handling SendFundingSigned event in peer_handler for node {} for channel {}", + log_pubkey!(node_id), + log_bytes!(msg.channel_id)); + if let Some((mut descriptor, peer)) = peers.initialized_peer_by_node_id_mut(node_id) { + peer.transport.enqueue_message(msg, &mut peer.outbound_queue, &*self.logger); + self.do_attempt_write_data(&mut descriptor, &mut peer.post_init_state, &mut peer.transport, &mut peer.outbound_queue); + } else { + //TODO: generate a DiscardFunding event indicating to the wallet that + //they should just throw away this funding transaction + } + }, + MessageSendEvent::SendFundingLocked { ref node_id, ref msg } => { + log_trace!(self.logger, "Handling SendFundingLocked event in peer_handler for node {} for channel {}", + log_pubkey!(node_id), + log_bytes!(msg.channel_id)); + if let Some((mut descriptor, peer)) = peers.initialized_peer_by_node_id_mut(node_id) { + peer.transport.enqueue_message(msg, &mut peer.outbound_queue, &*self.logger); + self.do_attempt_write_data(&mut descriptor, &mut peer.post_init_state, &mut peer.transport, &mut peer.outbound_queue); + } else { + //TODO: Do whatever we're gonna do for handling dropped messages + } + }, + MessageSendEvent::SendAnnouncementSignatures { ref node_id, ref msg } => { + log_trace!(self.logger, "Handling SendAnnouncementSignatures event in peer_handler for node {} for channel {})", + log_pubkey!(node_id), + log_bytes!(msg.channel_id)); + if let Some((mut descriptor, peer)) = peers.initialized_peer_by_node_id_mut(node_id) { + peer.transport.enqueue_message(msg, &mut peer.outbound_queue, &*self.logger); + self.do_attempt_write_data(&mut descriptor, &mut peer.post_init_state, &mut peer.transport, &mut peer.outbound_queue); + } else { + //TODO: generate a DiscardFunding event indicating to the wallet that + //they should just throw away this funding transaction + } + }, + MessageSendEvent::UpdateHTLCs { ref node_id, updates: msgs::CommitmentUpdate { ref update_add_htlcs, ref update_fulfill_htlcs, ref update_fail_htlcs, ref update_fail_malformed_htlcs, ref update_fee, ref commitment_signed } } => { + log_trace!(self.logger, "Handling UpdateHTLCs event in peer_handler for node {} with {} adds, {} fulfills, {} fails for channel {}", + log_pubkey!(node_id), + update_add_htlcs.len(), + update_fulfill_htlcs.len(), + update_fail_htlcs.len(), + log_bytes!(commitment_signed.channel_id)); + if let Some((mut descriptor, peer)) = peers.initialized_peer_by_node_id_mut(node_id) { + for msg in update_add_htlcs { + peer.transport.enqueue_message(msg, &mut peer.outbound_queue, &*self.logger); + } + for msg in update_fulfill_htlcs { + peer.transport.enqueue_message(msg, &mut peer.outbound_queue, &*self.logger); + } + for msg in update_fail_htlcs { + peer.transport.enqueue_message(msg, &mut peer.outbound_queue, &*self.logger); + } + for msg in update_fail_malformed_htlcs { + peer.transport.enqueue_message(msg, &mut peer.outbound_queue, &*self.logger); + } + if let &Some(ref msg) = update_fee { + peer.transport.enqueue_message(msg, &mut peer.outbound_queue, &*self.logger); + } + peer.transport.enqueue_message(commitment_signed, &mut peer.outbound_queue, &*self.logger); + self.do_attempt_write_data(&mut descriptor, &mut peer.post_init_state, &mut peer.transport, &mut peer.outbound_queue); + } else { + //TODO: Do whatever we're gonna do for handling dropped messages + } + }, + MessageSendEvent::SendRevokeAndACK { ref node_id, ref msg } => { + log_trace!(self.logger, "Handling SendRevokeAndACK event in peer_handler for node {} for channel {}", + log_pubkey!(node_id), + log_bytes!(msg.channel_id)); + if let Some((mut descriptor, peer)) = peers.initialized_peer_by_node_id_mut(node_id) { + peer.transport.enqueue_message(msg, &mut peer.outbound_queue, &*self.logger); + self.do_attempt_write_data(&mut descriptor, &mut peer.post_init_state, &mut peer.transport, &mut peer.outbound_queue); + } else { + //TODO: Do whatever we're gonna do for handling dropped messages + } + }, + MessageSendEvent::SendClosingSigned { ref node_id, ref msg } => { + log_trace!(self.logger, "Handling SendClosingSigned event in peer_handler for node {} for channel {}", + log_pubkey!(node_id), + log_bytes!(msg.channel_id)); + if let Some((mut descriptor, peer)) = peers.initialized_peer_by_node_id_mut(node_id) { + peer.transport.enqueue_message(msg, &mut peer.outbound_queue, &*self.logger); + self.do_attempt_write_data(&mut descriptor, &mut peer.post_init_state, &mut peer.transport, &mut peer.outbound_queue); + } else { + //TODO: Do whatever we're gonna do for handling dropped messages + } + }, + MessageSendEvent::SendShutdown { ref node_id, ref msg } => { + log_trace!(self.logger, "Handling Shutdown event in peer_handler for node {} for channel {}", + log_pubkey!(node_id), + log_bytes!(msg.channel_id)); + if let Some((mut descriptor, peer)) = peers.initialized_peer_by_node_id_mut(node_id) { + peer.transport.enqueue_message(msg, &mut peer.outbound_queue, &*self.logger); + self.do_attempt_write_data(&mut descriptor, &mut peer.post_init_state, &mut peer.transport, &mut peer.outbound_queue); + } else { + //TODO: Do whatever we're gonna do for handling dropped messages + } + }, + MessageSendEvent::SendChannelReestablish { ref node_id, ref msg } => { + log_trace!(self.logger, "Handling SendChannelReestablish event in peer_handler for node {} for channel {}", + log_pubkey!(node_id), + log_bytes!(msg.channel_id)); + if let Some((mut descriptor, peer)) = peers.initialized_peer_by_node_id_mut(node_id) { + peer.transport.enqueue_message(msg, &mut peer.outbound_queue, &*self.logger); + self.do_attempt_write_data(&mut descriptor, &mut peer.post_init_state, &mut peer.transport, &mut peer.outbound_queue); + } else { + //TODO: Do whatever we're gonna do for handling dropped messages + } + }, + MessageSendEvent::BroadcastChannelAnnouncement { ref msg, ref update_msg } => { + log_trace!(self.logger, "Handling BroadcastChannelAnnouncement event in peer_handler for short channel id {}", msg.contents.short_channel_id); + let route_handler_wants_broadcast = match self.message_handler.route_handler.handle_channel_announcement(msg) { + Err(e) => { + log_trace!(self.logger, "Ignoring because handle_channel_announcement returned error: {:?}", e); + false + } + Ok(false) => false, + Ok(true) => { + match self.message_handler.route_handler.handle_channel_update(update_msg) { + Err(e) => { + log_trace!(self.logger, "Ignoring because handle_channel_update returned error: {:?}", e); + false + }, + Ok(result) => result + } + } + }; + if route_handler_wants_broadcast { + for (descriptor, peer) in peers.initialized_peers_mut() { + if !peer.should_forward_channel_announcement(msg.contents.short_channel_id) { + continue + } + + let their_node_id = peer.transport.get_their_node_id(); + if their_node_id == msg.contents.node_id_1 || their_node_id == msg.contents.node_id_2 { + continue + } + peer.transport.enqueue_message(msg, &mut peer.outbound_queue, &*self.logger); + peer.transport.enqueue_message(update_msg, &mut peer.outbound_queue, &*self.logger); + self.do_attempt_write_data(&mut (*descriptor).clone(), &mut peer.post_init_state, &mut peer.transport, &mut peer.outbound_queue); + } + } + }, + MessageSendEvent::BroadcastNodeAnnouncement { ref msg } => { + log_trace!(self.logger, "Handling BroadcastNodeAnnouncement event in peer_handler"); + match self.message_handler.route_handler.handle_node_announcement(msg) { + Err(e) => { + log_trace!(self.logger, "Ignoring because handle_node_announcement returned error: {:?}", e); + }, + Ok(true) => { + for (descriptor, peer) in peers.initialized_peers_mut() { + if !peer.should_forward_node_announcement(msg.contents.node_id) { + continue + } + peer.transport.enqueue_message(msg, &mut peer.outbound_queue, &*self.logger); + self.do_attempt_write_data(&mut (*descriptor).clone(), &mut peer.post_init_state, &mut peer.transport, &mut peer.outbound_queue); + } + }, + Ok(false) => { } + } + }, + MessageSendEvent::BroadcastChannelUpdate { ref msg } => { + log_trace!(self.logger, "Handling BroadcastChannelUpdate event in peer_handler for short channel id {}", msg.contents.short_channel_id); + match self.message_handler.route_handler.handle_channel_update(msg) { + Err(e) => { + log_trace!(self.logger, "Ignoring because handle_channel_update returned error: {:?}", e); + }, + Ok(true) => { + for (descriptor, peer) in peers.initialized_peers_mut() { + if !peer.should_forward_channel_announcement(msg.contents.short_channel_id) { + continue + } + peer.transport.enqueue_message(msg, &mut peer.outbound_queue, &*self.logger); + self.do_attempt_write_data(&mut (*descriptor).clone(), &mut peer.post_init_state, &mut peer.transport, &mut peer.outbound_queue); + } + }, + Ok(false) => { } + } + }, + MessageSendEvent::PaymentFailureNetworkUpdate { ref update } => { + self.message_handler.route_handler.handle_htlc_fail_channel_update(update); + }, + MessageSendEvent::HandleError { ref node_id, ref action } => { + match *action { + msgs::ErrorAction::DisconnectPeer { ref msg } => { + if let Some(mut descriptor) = peers.node_id_to_descriptor.remove(node_id) { + peers.peers_needing_send.remove(&descriptor); + if let Some(mut peer) = peers.peers.remove(&descriptor) { + if let Some(ref msg) = *msg { + log_trace!(self.logger, "Handling DisconnectPeer HandleError event in peer_handler for node {} with message {}", + log_pubkey!(node_id), + msg.data); + if peer.transport.is_connected() { + peer.transport.enqueue_message(msg, &mut peer.outbound_queue, &*self.logger); + } + // This isn't guaranteed to work, but if there is enough free + // room in the send buffer, put the error message there... + self.do_attempt_write_data(&mut descriptor, &mut peer.post_init_state, &mut peer.transport, &mut peer.outbound_queue); + } else { + log_trace!(self.logger, "Handling DisconnectPeer HandleError event in peer_handler for node {} with no message", log_pubkey!(node_id)); + } + } + descriptor.disconnect_socket(); + self.message_handler.chan_handler.peer_disconnected(&node_id, false); + } + }, + msgs::ErrorAction::IgnoreError => {}, + msgs::ErrorAction::SendErrorMessage { ref msg } => { + log_trace!(self.logger, "Handling SendErrorMessage HandleError event in peer_handler for node {} with message {}", + log_pubkey!(node_id), + msg.data); + if let Some((mut descriptor, peer)) = peers.initialized_peer_by_node_id_mut(node_id) { + peer.transport.enqueue_message(msg, &mut peer.outbound_queue, &*self.logger); + self.do_attempt_write_data(&mut descriptor, &mut peer.post_init_state, &mut peer.transport, &mut peer.outbound_queue); + } else { + //TODO: Do whatever we're gonna do for handling dropped messages + } + }, + } + } + } + } + + for mut descriptor in peers.peers_needing_send.drain() { + match peers.peers.get_mut(&descriptor) { + Some(peer) => self.do_attempt_write_data(&mut descriptor, &mut peer.post_init_state, &mut peer.transport, &mut peer.outbound_queue), + None => panic!("Inconsistent peers set state!"), + } + } + } + } + + fn socket_disconnected(&self, descriptor: &Descriptor) { + let peers = &mut *self.peers.lock().unwrap(); + self.disconnect_event_internal(descriptor, false, peers); + } + + fn disconnect_event_internal(&self, descriptor: &Descriptor, no_connection_possible: bool, peers: &mut PeerHolder) { + let peer = peers.remove_peer_by_descriptor(descriptor); + + if peer.is_initialized() { + self.message_handler.chan_handler.peer_disconnected(&peer.transport.get_their_node_id(), no_connection_possible); + } + } + + fn timer_tick_occured(&self) { + let peers = &mut *self.peers.lock().unwrap(); + let mut descriptors_needing_disconnect = Vec::new(); + + for (descriptor, peer) in peers.initialized_peers_mut() { + // Mark peers that haven't sent a pong for disconnect + if peer.post_init_state.as_ref().unwrap().awaiting_pong { + log_trace!(self.logger, "Disconnecting peer with id {} due to ping timeout", &peer.transport.get_their_node_id()); + descriptors_needing_disconnect.push(descriptor.clone()); + } else { + let ping = msgs::Ping { + ponglen: 0, + byteslen: 64, + }; + peer.transport.enqueue_message(&ping, &mut peer.outbound_queue, &*self.logger); + self.do_attempt_write_data(&mut descriptor.clone(), &mut peer.post_init_state, &mut peer.transport, &mut peer.outbound_queue); + peer.post_init_state.as_mut().unwrap().awaiting_pong = true; + } + } + + for mut descriptor in descriptors_needing_disconnect.drain(..) { + self.disconnect_event_internal(&descriptor, false, peers); + descriptor.disconnect_socket(); + } + } +} + +// Unit tests of the PeerManager object. This leverage dependency inversion by passing in a Transport +// test double and configuring it in various ways to create the conditions needed to exercise the +// interesting code paths. This allows isolated testing of the PeerManager without worrying about +// the transport layer or encryption. The TransportTestStub implements the ITransport interface and +// provides a behavior where enqueue_message() places Messages on the outbound queue unencrypted +// for easy validation through the SocketDescriptor. +// +// In addition, these tests make use of the Spy and Stub test patterns for the MessageHandler and +// RouteHandler traits to ensure that the correct callbacks are called given the correct inputs. +// Basic reference for the types of test doubles that these tests use: +// https://martinfowler.com/articles/mocksArentStubs.html#TheDifferenceBetweenMocksAndStubs +#[cfg(test)] +mod unit_tests { + use super::*; + use ln::peers::test_util::*; + + use bitcoin::secp256k1::{Secp256k1, Signature}; + use ln::channelmanager::{PaymentHash, PaymentPreimage}; + use ln::features::{ChannelFeatures, NodeFeatures}; + use ln::msgs::*; + use util::events::MessageSendEvent::*; + use util::test_utils::{RoutingMessageHandlerTestStub, TestLogger, ChannelMessageHandlerTestSpy, TestChannelMessageHandler, RoutingMessageHandlerTestSpy, TestRoutingMessageHandler}; + use std::cell::RefCell; + + // Split out in a macro so tests can use this value to create test state before the TestCtx is + // created + macro_rules! test_ctx_their_node_id { + () => {{ + let their_node_secret = SecretKey::from_slice(&[0x_12_u8; 32]).unwrap(); + PublicKey::from_secret_key(&Secp256k1::new(), &their_node_secret) + }} + } + + // Container to store the test double objects and test constants that are passed to the + // PeerManager and referenced in the validation code. It supports type parameters so tests can + // use a variety of message handler test doubles with a common set up path. + struct TestCtx { + chan_handler: CM, + logger: TestLogger, + random_data: [u8; 32], + route_handler: RM, + their_node_id: PublicKey, + } + + impl TestCtx { + + // Basic TestCtx with default ChannelMessageHandlerTestSpy and RoutingMessageHandlerTestStub + fn new() -> TestCtx { + TestCtx::::with_channel_and_routing_handlers( + ChannelMessageHandlerTestSpy::new(), RoutingMessageHandlerTestStub::new()) + } + + // TestCtx creation for tests that need to override both default handlers + fn with_channel_and_routing_handlers(chan_handler: CM, route_handler: RM) -> Self { + Self { + chan_handler, + logger: TestLogger::new(), + random_data: [0; 32], + route_handler, + their_node_id: test_ctx_their_node_id!() + } + } + + // TestCtx creation for tests that need to override the routing handler + fn with_routing_handler(route_handler: RM) -> TestCtx { + TestCtx::::with_channel_and_routing_handlers( + ChannelMessageHandlerTestSpy::new(), route_handler) + } + + // TestCtx creation for tests that need to override the message handler + fn with_channel_handler(channel_handler: CM) -> TestCtx { + TestCtx::::with_channel_and_routing_handlers( + channel_handler, RoutingMessageHandlerTestStub::new()) + } + } + + // Convenience macro to hide the RefCell/Builder noise when creating an unconnected transport to + // make the tests more readable. + macro_rules! new_unconnected_transport { + () => {{ + RefCell::new(TransportStubBuilder::new().finish()) + }} + } + + // Convenience macro to hide the RefCell/Builder noise when creating a connected transport to + // make the tests more readable. + macro_rules! new_connected_transport { + ($test_ctx:expr) => {{ + RefCell::new(TransportStubBuilder::new().set_connected(&$test_ctx.their_node_id).finish()) + }} + } + + // Convenience macro to hide the type parameters for the PeerManagerImpl instantiation and test + // context set up. Makes the tests more readable. + macro_rules! new_peer_manager_for_test { + ($test_ctx:expr) => {{ + let our_node_secret = SecretKey::from_slice(&[0x_11_u8; 32]).unwrap(); + let message_handler = MessageHandler { + chan_handler: &$test_ctx.chan_handler, + route_handler: &$test_ctx.route_handler, + }; + PeerManagerImpl::<_, _, _, _, &RefCell>::new(message_handler, our_node_secret, &$test_ctx.random_data, &$test_ctx.logger) + }} + } + + // Generates a PeerManager & TransportStub for test that has already connected and parsed + // the Init message. To reduce test expansion, this only tests with an outbound connection with + // the understanding that after the init process, both connections are identical. + macro_rules! new_peer_manager_post_init { + ($test_ctx: expr, $descriptor: expr, $transport: expr) => {{ + let mut features = InitFeatures::known(); + features.clear_initial_routing_sync(); + + $transport.borrow_mut().add_incoming_message(Message::Init(Init { features })); + + let peer_manager = new_peer_manager_for_test!(&$test_ctx); + new_outbound!(peer_manager, $descriptor, $transport); + assert_matches!(peer_manager.read_event($descriptor, &[]), Ok(_)); + + // Drain pre-init data from descriptor in recording + peer_manager.process_events(); + $descriptor.clear_recording(); + + peer_manager + }} + } + + // Convenience macro to make the tests more readable when creating an outbound connection + macro_rules! new_outbound { + ($peer_manager: expr, $descriptor: expr, $transport: expr) => {{ + $peer_manager.new_outbound_connection_with_transport($descriptor.clone(), $transport).unwrap() + }} + } + + // Convenience macro to make the tests more readable when creating an inbound connection + macro_rules! new_inbound { + ($peer_manager: expr, $descriptor: expr, $transport: expr) => {{ + $peer_manager.new_inbound_connection_with_transport($descriptor.clone(), $transport).unwrap() + }} + } + + // Convenience macro to execute read_event() and assert the return value + macro_rules! assert_read_event_errors { + ($peer_manager: expr, $descriptor: expr, $no_connection_possible: expr) => {{ + assert_matches!($peer_manager.read_event($descriptor, &[]), Err(PeerHandleError { no_connection_possible: $no_connection_possible })) + }} + } + + // Assert that a given slice matches a Message pattern. The TransportTestStub places items on + // the outbound queue unencrypted, so this is used to decode the unencrypted data that makes + // it through the SocketDescriptor. + macro_rules! assert_matches_message { + ($bytes: expr, $message_pattern: pat) => {{ + let mut reader = ::std::io::Cursor::new($bytes); + let message_result = wire::read(&mut reader); + let message = message_result.unwrap(); + assert_matches!(message, $message_pattern) + }} + } + + // Convenience macro for returning the spy value by function name + macro_rules! channel_handler_called { + ($test_ctx:expr, $fn_name: ident) => {{ + $test_ctx.chan_handler.called.lock().unwrap().$fn_name + }} + } + + // Convenience macro for returning the spy value by function name + macro_rules! route_handler_called { + ($test_ctx:expr, $fn_name: ident) => {{ + $test_ctx.route_handler.called.lock().unwrap().$fn_name + }} + } + + // ____ _ _____ _ _____ _ _ + // | _ \ ___ __ _ __| | | ____|_ _____ _ __ | |_ |_ _|__ ___| |_(_)_ __ __ _ + // | |_) / _ \/ _` |/ _` | | _| \ \ / / _ \ '_ \| __| | |/ _ \/ __| __| | '_ \ / _` | + // | _ < __/ (_| | (_| | | |___ \ V / __/ | | | |_ | | __/\__ \ |_| | | | | (_| | + // |_| \_\___|\__,_|\__,_| |_____| \_/ \___|_| |_|\__| |_|\___||___/\__|_|_| |_|\__, | + // |___/ + + // Test that a new inbound connection: + // * get_peer_node_ids() does not contain the node_id + #[test] + fn new_inbound_not_in_get_peer_node_ids() { + let test_ctx = TestCtx::::new(); + let descriptor = SocketDescriptorMock::new(); + let mut transport = new_unconnected_transport!(); + let peer_manager = new_peer_manager_for_test!(&test_ctx); + + new_inbound!(peer_manager, descriptor, &mut transport); + + assert!(peer_manager.get_peer_node_ids().is_empty()); + } + + // Test that a new outbound connection: + // * get_peer_node_ids() does not contain the node_id + #[test] + fn new_outbound_not_in_get_peer_node_ids() { + let test_ctx = TestCtx::::new(); + let descriptor = SocketDescriptorMock::new(); + let mut transport = new_unconnected_transport!(); + let peer_manager = new_peer_manager_for_test!(&test_ctx); + + new_outbound!(peer_manager, descriptor, &mut transport); + + assert!(peer_manager.get_peer_node_ids().is_empty()); + } + + // Test that a new inbound connection: + // * read_event() returns errors from the Transport code + #[test] + fn new_inbound_transport_error_returns_error() { + let test_ctx = TestCtx::::new(); + let mut descriptor = SocketDescriptorMock::new(); + let mut transport = + RefCell::new(TransportStubBuilder::new().process_returns_error().finish()); + let peer_manager = new_peer_manager_for_test!(&test_ctx); + + new_inbound!(peer_manager, descriptor, &mut transport); + + assert_read_event_errors!(peer_manager, &mut descriptor, false); + } + + // Test that a new outbound connection: + // * read_event() returns errors from the Transport code + #[test] + fn new_outbound_transport_error_returns_error() { + let test_ctx = TestCtx::::new(); + let mut descriptor = SocketDescriptorMock::new(); + let mut transport = + RefCell::new(TransportStubBuilder::new().process_returns_error().finish()); + let peer_manager = new_peer_manager_for_test!(&test_ctx); + + new_outbound!(peer_manager, descriptor, &mut transport); + + assert_read_event_errors!(peer_manager, &mut descriptor, false); + } + + // Test that an inbound connection with a connected Transport, but no Init message + // * get_peer_node_ids() does not contain the node_id + // * process_events() does not send an Init message (must receive from Initiator first) + #[test] + fn inbound_connected_transport_not_in_get_peer_node_ids() { + let test_ctx = TestCtx::::new(); + let mut descriptor = SocketDescriptorMock::new(); + let mut transport = new_connected_transport!(&test_ctx); + let peer_manager = new_peer_manager_for_test!(&test_ctx); + + new_inbound!(peer_manager, descriptor, &mut transport); + assert_matches!(peer_manager.read_event(&mut descriptor, &[]), Ok(_)); + + assert!(peer_manager.get_peer_node_ids().is_empty()); + peer_manager.process_events(); + descriptor.assert_called_with(vec![]); + } + + // Test that an outbound connection with a connected Transport, but no Init message + // * read_event() does not call peer_disconnected callback if an error is returned from Transport + #[test] + fn outbound_connected_transport_error_does_not_call_peer_disconnected_on_error() { + let test_ctx = TestCtx::::new(); + let mut descriptor = SocketDescriptorMock::new(); + let transport = new_connected_transport!(&test_ctx); + let peer_manager = new_peer_manager_for_test!(&test_ctx); + new_outbound!(peer_manager, descriptor, &transport); + assert_matches!(peer_manager.read_event(&mut descriptor, &[]), Ok(_)); + + // Signal the error in transport and ensure we don't send a dangling peer_disconnected + transport.borrow_mut().process_returns_error(); + assert_read_event_errors!(peer_manager, &mut descriptor, false); + assert!(!channel_handler_called!(&test_ctx, peer_connected)); + assert!(!channel_handler_called!(&test_ctx, peer_disconnected)); + } + + // Test that an inbound connection with a connected Transport and queued Init message: + // * read_event() does not send anything in read_event() + // * read_event() calls the peer_connected channel manager callback + // * process_events() sends an Init message + #[test] + fn inbound_connected_transport_responds_with_init() { + let test_ctx = TestCtx::::new(); + let mut descriptor = SocketDescriptorMock::new(); + let mut transport = new_connected_transport!(&test_ctx); + let peer_manager = new_peer_manager_for_test!(&test_ctx); + transport.borrow_mut().add_incoming_message( + Message::Init(Init { features: InitFeatures::known() })); + + new_inbound!(peer_manager, descriptor, &mut transport); + + assert_matches!(peer_manager.read_event(&mut descriptor, &[]), Ok(_)); + assert!(channel_handler_called!(&test_ctx, peer_connected)); + descriptor.assert_called_with(vec![]); + + peer_manager.process_events(); + + let recording = descriptor.get_recording(); + assert_matches_message!(&recording[0].0, Message::Init(_)); + } + + // Test that an inbound connection with a connected Transport and queued Init message: + // * read_event() returns true if the outbound queue is full + // * read_event() returns false once room is made and write_buffer_space_avail is called + // Test leverages a 0 capacity SocketDescriptor and the initial routing sync from + // TestRoutingMessagehandler to fill the queue + #[test] + fn inbound_connected_transport_full_outbound_queue() { + let routing_handler = TestRoutingMessageHandler::new(); + let test_ctx = TestCtx::::with_routing_handler(routing_handler); + let mut descriptor = SocketDescriptorMock::with_fixed_size(0); + let mut transport = new_connected_transport!(&test_ctx); + let peer_manager = new_peer_manager_for_test!(&test_ctx); + transport.borrow_mut().add_incoming_message(Message::Init(Init { features: InitFeatures::known() })); + + new_inbound!(peer_manager, descriptor, &mut transport); + + // Process Init through to outbound queue + assert_matches!(peer_manager.read_event(&mut descriptor, &[]), Ok(false)); + peer_manager.process_events(); + + // Call w/o write_buffer_space_avail still returns Ok(true) + assert_matches!(peer_manager.read_event(&mut descriptor, &[]), Ok(true)); + + // Call w/o more room in SocketDescriptor still returns Ok(true) + peer_manager.write_buffer_space_avail(&mut descriptor).unwrap(); + assert_matches!(peer_manager.read_event(&mut descriptor, &[]), Ok(true)); + + // Call after more room in SocketDescriptor returns Ok(false) + descriptor.make_room(100000); + peer_manager.write_buffer_space_avail(&mut descriptor).unwrap(); + assert_matches!(peer_manager.read_event(&mut descriptor, &[]), Ok(_)); + + let recording = descriptor.get_recording(); + assert_matches_message!(&recording[0].0, Message::Init(_)); + assert!(channel_handler_called!(&test_ctx, peer_connected)); + } + + // Test that an outbound connection with a connected Transport: + // * get_peer_node_ids() does not contain the node_id + // * read_event() does not send anything + // * process_events() sends an Init message + #[test] + fn outbound_connected_transport_sends_init_in_process_events() { + let test_ctx = TestCtx::::new(); + let mut descriptor = SocketDescriptorMock::new(); + let mut transport = new_connected_transport!(&test_ctx); + let peer_manager = new_peer_manager_for_test!(&test_ctx); + + new_outbound!(peer_manager, descriptor, &mut transport); + assert_matches!(peer_manager.read_event(&mut descriptor, &[]), Ok(_)); + descriptor.assert_called_with(vec![]); + + assert!(peer_manager.get_peer_node_ids().is_empty()); + + peer_manager.process_events(); + let recording = descriptor.get_recording(); + assert_eq!(1, recording.len()); + + assert_matches_message!(&recording[0].0, Message::Init(_)); + } + + // Test that an outbound connection with a connected Transport: + // * read_event() errors when receiving a Non-Init message first + // * read_event() does not call the peer_connected/peer_disconnected callbacks + #[test] + fn inbound_connected_transport_non_init_first_fails() { + let test_ctx = TestCtx::::new(); + let mut descriptor = SocketDescriptorMock::new(); + let mut transport = new_connected_transport!(&test_ctx); + let peer_manager = new_peer_manager_for_test!(&test_ctx); + transport.borrow_mut().add_incoming_message(Message::Ping(Ping { ponglen: 0, byteslen: 0 })); + + new_inbound!(peer_manager, descriptor, &mut transport); + assert_read_event_errors!(peer_manager, &mut descriptor, false); + assert!(!channel_handler_called!(&test_ctx, peer_connected)); + assert!(!channel_handler_called!(&test_ctx, peer_disconnected)); + } + + // Test that an outbound connection with a connected Transport: + // * read_event() errors when receiving a Non-Init message first + // * read_event() does not call the peer_connected/peer_disconnected callbacks + #[test] + fn outbound_connected_transport_non_init_first_fails() { + let test_ctx = TestCtx::::new(); + let mut descriptor = SocketDescriptorMock::new(); + let mut transport = new_connected_transport!(&test_ctx); + let peer_manager = new_peer_manager_for_test!(&test_ctx); + transport.borrow_mut().add_incoming_message(Message::Ping(Ping { ponglen: 0, byteslen: 0 })); + + new_outbound!(peer_manager, descriptor, &mut transport); + assert_read_event_errors!(peer_manager, &mut descriptor, false); + assert!(!channel_handler_called!(&test_ctx, peer_connected)); + assert!(!channel_handler_called!(&test_ctx, peer_disconnected)); + } + + // Test that an inbound connection with a connected Transport: + // * read_event() errors out with no_connection_possible if an Init message contains requires_unknown_bits + // * read_event() does not call the peer_connected/peer_disconnected callbacks + #[test] + fn inbound_connected_transport_init_with_required_unknown_first_fails() { + let test_ctx = TestCtx::::new(); + let mut descriptor = SocketDescriptorMock::new(); + let mut transport = new_connected_transport!(&test_ctx); + let peer_manager = new_peer_manager_for_test!(&test_ctx); + let mut features = InitFeatures::known(); + features.set_required_unknown_bits(); + transport.borrow_mut().add_incoming_message(Message::Init(Init { features })); + + new_inbound!(peer_manager, descriptor, &mut transport); + assert_read_event_errors!(peer_manager, &mut descriptor, true); + assert!(!channel_handler_called!(&test_ctx, peer_connected)); + assert!(!channel_handler_called!(&test_ctx, peer_disconnected)); + } + + // Test that an outbound connection with a connected Transport: + // * read_event() errors out with no_connection_possible if an Init message contains requires_unknown_bits + // * read_event() does not call the peer_connected/peer_disconnected callbacks + #[test] + fn outbound_connected_transport_init_with_required_unknown_first_fails() { + let test_ctx = TestCtx::::new(); + let mut descriptor = SocketDescriptorMock::new(); + let mut transport = new_connected_transport!(&test_ctx); + let peer_manager = new_peer_manager_for_test!(&test_ctx); + let mut features = InitFeatures::known(); + features.set_required_unknown_bits(); + transport.borrow_mut().add_incoming_message(Message::Init(Init { features })); + + new_outbound!(peer_manager, descriptor, &mut transport); + assert_read_event_errors!(peer_manager, &mut descriptor, true); + assert!(!channel_handler_called!(&test_ctx, peer_connected)); + assert!(!channel_handler_called!(&test_ctx, peer_disconnected)); + } + + // Test that an inbound connection with a connected Transport: + // * read_event() errors out with no_connection_possible if an Init message does not contain requires_static_remote_key + // * read_event() does not call the peer_connected/peer_disconnected callbacks + #[test] + fn inbound_connected_transport_init_with_clear_requires_static_remote_key() { + let test_ctx = TestCtx::::new(); + let mut descriptor = SocketDescriptorMock::new(); + let mut transport = new_connected_transport!(&test_ctx); + let peer_manager = new_peer_manager_for_test!(&test_ctx); + let mut features = InitFeatures::known(); + features.clear_requires_static_remote_key(); + transport.borrow_mut().add_incoming_message(Message::Init(Init { features })); + + new_inbound!(peer_manager, descriptor, &mut transport); + assert_read_event_errors!(peer_manager, &mut descriptor, true); + assert!(!channel_handler_called!(&test_ctx, peer_connected)); + assert!(!channel_handler_called!(&test_ctx, peer_disconnected)); + } + + // Test that an outbound connection with a connected Transport: + // * read_event() errors out with no_connection_possible if an Init message does not contain requires_static_remote_key + // * read_event() does not call the peer_connected/peer_disconnected callbacks + #[test] + fn outbound_connected_transport_init_with_clear_requires_static_remote_key() { + let test_ctx = TestCtx::::new(); + let mut descriptor = SocketDescriptorMock::new(); + let mut transport = new_connected_transport!(&test_ctx); + let peer_manager = new_peer_manager_for_test!(&test_ctx); + let mut features = InitFeatures::known(); + features.clear_requires_static_remote_key(); + transport.borrow_mut().add_incoming_message(Message::Init(Init { features })); + + new_outbound!(peer_manager, descriptor, &mut transport); + assert_read_event_errors!(peer_manager, &mut descriptor, true); + assert!(!channel_handler_called!(&test_ctx, peer_connected)); + assert!(!channel_handler_called!(&test_ctx, peer_disconnected)); + } + + // Test that an inbound connection with a connected Transport and queued Init Message: + // * read_event() calls the peer_connected channel manager callback + // * get_peer_node_ids() contains the node_id + #[test] + fn inbound_connected_transport_after_init_in_get_peer_node_ids() { + let test_ctx = TestCtx::::new(); + let mut descriptor = SocketDescriptorMock::new(); + let mut transport = new_connected_transport!(&test_ctx); + let peer_manager = new_peer_manager_for_test!(&test_ctx); + transport.borrow_mut().add_incoming_message(Message::Init(Init { features: InitFeatures::known() })); + + new_inbound!(peer_manager, descriptor, &mut transport); + + assert_matches!(peer_manager.read_event(&mut descriptor, &[]), Ok(_)); + + assert!(peer_manager.get_peer_node_ids().contains(&test_ctx.their_node_id)); + assert!(channel_handler_called!(&test_ctx, peer_connected)); + } + + // Test that an outbound connection with a connected Transport and queued Init Message: + // * read_event() calls the peer_connected channel manager callback + // * get_peer_node_ids() contains the node_id + #[test] + fn outbound_connected_transport_after_init_in_get_peer_node_ids() { + let test_ctx = TestCtx::::new(); + let mut descriptor = SocketDescriptorMock::new(); + let mut transport = new_connected_transport!(&test_ctx); + let peer_manager = new_peer_manager_for_test!(&test_ctx); + transport.borrow_mut().add_incoming_message(Message::Init(Init { features: InitFeatures::known() })); + + new_outbound!(peer_manager, descriptor, &mut transport); + + assert_matches!(peer_manager.read_event(&mut descriptor, &[]), Ok(_)); + + assert!(peer_manager.get_peer_node_ids().contains(&test_ctx.their_node_id)); + assert!(channel_handler_called!(&test_ctx, peer_connected)); + } + + // Test that a post-Init connection: + // * read_event() propagates an error coming out of Transport + // * read_event() calls the peer_disconnected channel manager callback + // * get_peer_node_ids() does not contain the node_id + #[test] + fn post_init_connected_after_error_not_in_get_peer_node_ids() { + let test_ctx = TestCtx::::new(); + let mut descriptor = SocketDescriptorMock::new(); + let transport = new_connected_transport!(&test_ctx); + let peer_manager = new_peer_manager_post_init!(&test_ctx, &mut descriptor, &transport); + + // Set transport to return an error + transport.borrow_mut().process_returns_error(); + + // Verify errors out and removed from get_peer_node_ids() + assert_read_event_errors!(peer_manager, &mut descriptor, false); + assert!(channel_handler_called!(&test_ctx, peer_disconnected)); + assert!(peer_manager.get_peer_node_ids().is_empty()); + } + + // Test that a post-Init duplicate connection: + // * read_event() returns an error + // * get_peer_node_ids() contains the original node_id + #[test] + fn post_init_duplicate_connection_errors_and_original_keeps_existing() { + let test_ctx = TestCtx::::new(); + let mut descriptor = SocketDescriptorMock::new(); + let transport = new_connected_transport!(&test_ctx); + + // Create a duplicate connection from the same node_id w/ pending Init message + let mut duplicate_connection_descriptor = SocketDescriptorMock::new(); + let mut duplicate_connection_transport = RefCell::new(TransportStubBuilder::new() + .set_connected(&test_ctx.their_node_id) + .finish()); + duplicate_connection_transport.borrow_mut().add_incoming_message(Message::Init(Init { features: InitFeatures::known() })); + + let peer_manager = new_peer_manager_post_init!(&test_ctx, &mut descriptor, &transport); + + assert!(peer_manager.get_peer_node_ids().contains(&test_ctx.their_node_id)); + + // Duplicate connection errors out + new_outbound!(peer_manager, duplicate_connection_descriptor, &mut duplicate_connection_transport); + assert_read_event_errors!(peer_manager, &mut duplicate_connection_descriptor, false); + + // And any queued messages such as an outgoing Init are never sent + peer_manager.process_events(); + duplicate_connection_descriptor.assert_called_with(vec![]); + + // But the original still exists in get_peer_node_ids() + assert!(peer_manager.get_peer_node_ids().contains(&test_ctx.their_node_id)); + } + + // __ __ _____ _ _ + // | \/ | ___ ___ ___ __ _ __ _ ___ |_ _|__ ___| |_(_)_ __ __ _ + // | |\/| |/ _ \/ __/ __|/ _` |/ _` |/ _ \ | |/ _ \/ __| __| | '_ \ / _` | + // | | | | __/\__ \__ \ (_| | (_| | __/ | | __/\__ \ |_| | | | | (_| | + // |_| |_|\___||___/___/\__,_|\__, |\___| |_|\___||___/\__|_|_| |_|\__, | + // |___/ |___/ + + // Test that a post-Init connection: + // * read_event() returns an error if it receives a second Init message + // * read_event() calls the peer_disconnected channel manager callback + #[test] + fn post_init_second_init_fails() { + let test_ctx = TestCtx::::new(); + let mut descriptor = SocketDescriptorMock::new(); + let transport = new_connected_transport!(&test_ctx); + let peer_manager = new_peer_manager_post_init!(&test_ctx, &mut descriptor, &transport); + + transport.borrow_mut().add_incoming_message(Message::Init(Init { features: InitFeatures::known() })); + + assert_read_event_errors!(peer_manager, &mut descriptor, false); + assert!(channel_handler_called!(&test_ctx, peer_disconnected)); + } + + // Test that a post-Init connection: + // * read_event() does not propagate an Error Message with no printable + // * read_event() calls the handle_error channel manager callback + #[test] + fn post_init_error_message_without_printable() { + let test_ctx = TestCtx::::new(); + let mut descriptor = SocketDescriptorMock::new(); + let transport = new_connected_transport!(&test_ctx); + let peer_manager = new_peer_manager_post_init!(&test_ctx, &mut descriptor, &transport); + + transport.borrow_mut().add_incoming_message(Message::Error(ErrorMessage { channel_id: [1; 32], data: "".to_string() })); + + assert_matches!(peer_manager.read_event(&mut descriptor, &[]), Ok(_)); + assert!(channel_handler_called!(&test_ctx, handle_error)); + } + + // Test that a post-Init connection: + // * read_event() does not propagate an Error Message with printable + // * read_event() calls the handle_error channel manager callback + #[test] + fn post_init_error_message_with_printable() { + let test_ctx = TestCtx::::new(); + let mut descriptor = SocketDescriptorMock::new(); + let transport = new_connected_transport!(&test_ctx); + let peer_manager = new_peer_manager_post_init!(&test_ctx, &mut descriptor, &transport); + + transport.borrow_mut().add_incoming_message(Message::Error(ErrorMessage { channel_id: [1; 32], data: "error".to_string() })); + + assert_matches!(peer_manager.read_event(&mut descriptor, &[]), Ok(_)); + assert!(channel_handler_called!(&test_ctx, handle_error)); + } + + // Test that a post-Init connection: + // * read_event() does not propagate an Error Message with a control character + // * read_event() calls the handle_error channel manager callback + #[test] + fn post_init_error_message_with_non_ascii_ignored() { + let test_ctx = TestCtx::::new(); + let mut descriptor = SocketDescriptorMock::new(); + let transport = new_connected_transport!(&test_ctx); + let peer_manager = new_peer_manager_post_init!(&test_ctx, &mut descriptor, &transport); + + transport.borrow_mut().add_incoming_message(Message::Error(ErrorMessage { channel_id: [1; 32], data: "\x00".to_string() })); + + assert_matches!(peer_manager.read_event(&mut descriptor, &[]), Ok(_)); + assert!(channel_handler_called!(&test_ctx, handle_error)); + } + + // Test that a post-Init connection: + // * read_event() returns an error when it receives an Error Message with a 0 channel_id + // * read_event() calls the handle_error channel manager callback + #[test] + fn post_init_error_message_with_zero_channel_id() { + let test_ctx = TestCtx::::new(); + let mut descriptor = SocketDescriptorMock::new(); + let transport = new_connected_transport!(&test_ctx); + let peer_manager = new_peer_manager_post_init!(&test_ctx, &mut descriptor, &transport); + + transport.borrow_mut().add_incoming_message(Message::Error(ErrorMessage { channel_id: [0; 32], data: "".to_string() })); + + assert_read_event_errors!(peer_manager, &mut descriptor, true); + assert!(channel_handler_called!(&test_ctx, handle_error)); + } + + // Test that a post-Init connection: + // * read_event() returns an error when it receives Message::Unknown (even) + #[test] + fn post_init_unknown_message_even() { + let test_ctx = TestCtx::::new(); + let mut descriptor = SocketDescriptorMock::new(); + let transport = new_connected_transport!(&test_ctx); + let peer_manager = new_peer_manager_post_init!(&test_ctx, &mut descriptor, &transport); + + transport.borrow_mut().add_incoming_message(Message::Unknown(wire::MessageType(254))); + + assert_read_event_errors!(peer_manager, &mut descriptor, true); + } + + // Test that a post-Init connection: + // * read_event() ignores Message::Unknown (odd) + #[test] + fn post_init_unknown_message_odd() { + let test_ctx = TestCtx::::new(); + let mut descriptor = SocketDescriptorMock::new(); + let transport = new_connected_transport!(&test_ctx); + let peer_manager = new_peer_manager_post_init!(&test_ctx, &mut descriptor, &transport); + + transport.borrow_mut().add_incoming_message(Message::Unknown(wire::MessageType(255))); + + assert_matches!(peer_manager.read_event(&mut descriptor, &[]), Ok(_)); + } + + // Test that a post-init connection: + // * read_event() calls the correct ChannelMessageHandler callback given the correct message type + macro_rules! generate_handle_message_test { + ($expected_cb: ident, $msg: expr) => { + #[test] + fn $expected_cb() { + let test_ctx = TestCtx::::new(); + let mut descriptor = SocketDescriptorMock::new(); + let transport = new_connected_transport!(&test_ctx); + let peer_manager = new_peer_manager_post_init!(&test_ctx, &mut descriptor, &transport); + transport.borrow_mut().add_incoming_message($msg); + + assert_matches!(peer_manager.read_event(&mut descriptor, &[]), Ok(_)); + assert!(channel_handler_called!(&test_ctx, $expected_cb)); + } + } + } + + generate_handle_message_test!(handle_open_channel, Message::OpenChannel(fake_open_channel_msg!())); + generate_handle_message_test!(handle_accept_channel, Message::AcceptChannel(fake_accept_channel_msg!())); + generate_handle_message_test!(handle_funding_created, Message::FundingCreated(fake_funding_created_msg!())); + generate_handle_message_test!(handle_funding_signed, Message::FundingSigned(fake_funding_signed_msg!())); + generate_handle_message_test!(handle_funding_locked, Message::FundingLocked(fake_funding_locked_msg!())); + generate_handle_message_test!(handle_shutdown, Message::Shutdown(fake_shutdown_msg!())); + generate_handle_message_test!(handle_closing_signed, Message::ClosingSigned(fake_closing_signed_msg!())); + generate_handle_message_test!(handle_update_add_htlc, Message::UpdateAddHTLC(fake_update_add_htlc_msg!())); + generate_handle_message_test!(handle_update_fulfill_htlc, Message::UpdateFulfillHTLC(fake_update_fulfill_htlc_msg!())); + generate_handle_message_test!(handle_update_fail_htlc, Message::UpdateFailHTLC(fake_update_fail_htlc_msg!())); + generate_handle_message_test!(handle_update_fail_malformed_htlc, Message::UpdateFailMalformedHTLC(fake_update_fail_malformed_htlc_msg!())); + generate_handle_message_test!(handle_commitment_signed, Message::CommitmentSigned(fake_commitment_signed_msg!())); + generate_handle_message_test!(handle_revoke_and_ack, Message::RevokeAndACK(fake_revoke_and_ack_msg!())); + generate_handle_message_test!(handle_update_fee, Message::UpdateFee(fake_update_fee_msg!())); + generate_handle_message_test!(handle_channel_reestablish, Message::ChannelReestablish(fake_channel_reestablish_msg!())); + generate_handle_message_test!(handle_announcement_signatures, Message::AnnouncementSignatures(fake_announcement_signatures_msg!())); + + // Test that a post-Init connection: + // * read_event() returns an error if a ChannelAnnouncement message is received and the routing handler + // returns ErrorAction::DisconnectPeer + // * read_event() calls the peer_disconnected channel manager callback + // * read_event() does not call disconnect_socket() is not called on the SocketDescriptor + #[test] + fn post_init_handle_channel_announcement_disconnect_peer() { + let mut routing_handler = RoutingMessageHandlerTestStub::new(); + routing_handler.handle_channel_announcement_return = Err(msgs::LightningError { err: "".to_string(), action: msgs::ErrorAction::DisconnectPeer { msg: None } }); + let test_ctx = TestCtx::::with_routing_handler(routing_handler); + let mut descriptor = SocketDescriptorMock::new(); + let transport = new_connected_transport!(&test_ctx); + let peer_manager = new_peer_manager_post_init!(&test_ctx, &mut descriptor, &transport); + + transport.borrow_mut().add_incoming_message(Message::ChannelAnnouncement(fake_channel_announcement_msg!(0, fake_public_key!(), fake_public_key!()))); + + assert_read_event_errors!(peer_manager, &mut descriptor, false); + assert!(peer_manager.get_peer_node_ids().is_empty()); + assert!(channel_handler_called!(&test_ctx, peer_disconnected)); + assert!(!descriptor.disconnect_called()); + } + + // Test generator macro to reduce duplication across the broadcast message cases. + // (test name, expression that returns a routing handler, message that will be queued, closure taking (descriptor) that does the validation) + macro_rules! generate_broadcast_message_test { + ($test_name: ident, $routing_handler: expr, $message: expr, $validation: tt) => { + #[test] + fn $test_name() { + let test_ctx = TestCtx::::with_routing_handler($routing_handler); + let mut descriptor = SocketDescriptorMock::new(); + let transport = new_connected_transport!(&test_ctx); + let peer_manager = new_peer_manager_post_init!(&test_ctx, &mut descriptor, &transport); + + transport.borrow_mut().add_incoming_message($message); + assert_matches!(peer_manager.read_event(&mut descriptor, &[]), Ok(_)); + peer_manager.process_events(); + + $validation(descriptor) + } + } + } + + // Test that a post-Init connection: + // * read_event() returns Ok(_) if a ChannelAnnouncement message is received and the routing handler + // returns ErrorAction::IgnoreError + generate_broadcast_message_test!(post_init_handle_channel_announcement_ignore_error, { + let mut routing_handler = RoutingMessageHandlerTestStub::new(); + routing_handler.handle_channel_announcement_return = Err(msgs::LightningError { err: "".to_string(), action: msgs::ErrorAction::IgnoreError }); + routing_handler + }, + Message::ChannelAnnouncement(fake_channel_announcement_msg!(0, fake_public_key!(), fake_public_key!())), + (| _descriptor | { }) + ); + + // Test that a post-Init connection: + // * read_event() returns Ok(_) if a ChannelAnnouncement message is received and the routing handler + // returns ErrorAction::IgnoreError + // * process_events() sends an ErrorMessage + generate_broadcast_message_test!(post_init_handle_channel_announcement_send_error_message, { + let mut routing_handler = RoutingMessageHandlerTestStub::new(); + routing_handler.handle_channel_announcement_return = Err(msgs::LightningError { err: "".to_string(), action: msgs::ErrorAction::SendErrorMessage { msg: ErrorMessage { channel_id: [0; 32], data: "".to_string() } } }); + routing_handler + }, + Message::ChannelAnnouncement(fake_channel_announcement_msg!(0, fake_public_key!(), fake_public_key!())), + (| descriptor: SocketDescriptorMock | { + let recording = descriptor.get_recording(); + assert_matches_message!(&recording[0].0, Message::Error(_)) + } + )); + + // Test that a post-Init connection: + // * read_event() returns Ok(_) if a ChannelAnnouncement message is received and the routing handler + // returns true + generate_broadcast_message_test!(post_init_handle_channel_announcement_should_forward, { + let mut routing_handler = RoutingMessageHandlerTestStub::new(); + routing_handler.handle_channel_announcement_return = Ok(true); + routing_handler + }, + Message::ChannelAnnouncement(fake_channel_announcement_msg!(0, fake_public_key!(), fake_public_key!())), + (| _descriptor | { }) + ); + + // Test that a post-Init connection: + // * read_event() returns Ok(_) if a ChannelAnnouncement message is received and the routing handler + // returns false + generate_broadcast_message_test!(post_init_handle_channel_announcement_should_not_forward, { + let mut routing_handler = RoutingMessageHandlerTestStub::new(); + routing_handler.handle_channel_announcement_return = Ok(false); + routing_handler + }, + Message::ChannelAnnouncement(fake_channel_announcement_msg!(0, fake_public_key!(), fake_public_key!())), + (| _descriptor | { }) + ); + + // Test that a post-Init connection: + // * read_event() returns Ok(_) if a NodeAnnouncement message is received and the routing handler + // returns ErrorAction::IgnoreError + generate_broadcast_message_test!(post_init_handle_node_announcement_ignore_error, { + let mut routing_handler = RoutingMessageHandlerTestStub::new(); + routing_handler.handle_node_announcement_return = Err(msgs::LightningError { err: "".to_string(), action: msgs::ErrorAction::IgnoreError }); + routing_handler + }, + Message::NodeAnnouncement(fake_node_announcement_msg!()), + (| _descriptor | { } + )); + + // Test that a post-Init connection: + // * read_event() returns Ok(_) if a NodeAnnouncement message is received and the routing handler + // returns ErrorAction::IgnoreError + // * process_events() sends an ErrorMessage + generate_broadcast_message_test!(post_init_handle_node_announcement_send_error_message, { + let mut routing_handler = RoutingMessageHandlerTestStub::new(); + routing_handler.handle_node_announcement_return = Err(msgs::LightningError { err: "".to_string(), action: msgs::ErrorAction::SendErrorMessage { msg: ErrorMessage { channel_id: [0; 32], data: "".to_string() } } }); + routing_handler + }, + Message::NodeAnnouncement(fake_node_announcement_msg!()), + (| descriptor: SocketDescriptorMock | { + let recording = descriptor.get_recording(); + assert_matches_message!(&recording[0].0, Message::Error(_)) + } + )); + + // Test that a post-Init connection: + // * read_event() returns Ok(_) if a NodeAnnouncement message is received and the routing handler + // returns true + generate_broadcast_message_test!(post_init_handle_node_announcement_should_forward, { + let mut routing_handler = RoutingMessageHandlerTestStub::new(); + routing_handler.handle_node_announcement_return = Ok(true); + routing_handler + }, + Message::NodeAnnouncement(fake_node_announcement_msg!()), + (| _descriptor | { }) + ); + + // Test that a post-Init connection: + // * read_event() returns Ok(_) if a NodeAnnouncement message is received and the routing handler + // returns false + generate_broadcast_message_test!(post_init_handle_node_announcement_should_not_forward, { + let mut routing_handler = RoutingMessageHandlerTestStub::new(); + routing_handler.handle_node_announcement_return = Ok(false); + routing_handler + }, + Message::NodeAnnouncement(fake_node_announcement_msg!()), + (| _descriptor | { }) + ); + + // Test that a post-Init connection: + // * read_event() returns Ok(_) if a ChannelUpdate message is received and the routing handler + // returns ErrorAction::IgnoreError + generate_broadcast_message_test!(post_init_handle_channel_update_ignore_error, { + let mut routing_handler = RoutingMessageHandlerTestStub::new(); + routing_handler.handle_channel_update_return = Err(msgs::LightningError { err: "".to_string(), action: msgs::ErrorAction::IgnoreError }); + routing_handler + }, + Message::ChannelUpdate(fake_channel_update_msg!()), + (| _descriptor | { }) + ); + + // Test that a post-Init connection: + // * read_event() returns Ok(_) if a ChannelUpdate message is received and the routing handler + // returns ErrorAction::IgnoreError + // * process_events() sends an ErrorMessage + generate_broadcast_message_test!(post_init_handle_channel_update_send_error_message, { + let mut routing_handler = RoutingMessageHandlerTestStub::new(); + routing_handler.handle_channel_update_return = Err(msgs::LightningError { err: "".to_string(), action: msgs::ErrorAction::SendErrorMessage { msg: ErrorMessage { channel_id: [0; 32], data: "".to_string() } } }); + routing_handler + }, + Message::ChannelUpdate(fake_channel_update_msg!()), + (| descriptor: SocketDescriptorMock | { + let recording = descriptor.get_recording(); + assert_matches_message!(&recording[0].0, Message::Error(_)) + } + )); + + // Test that a post-Init connection: + // * read_event() returns Ok(_) if a ChannelUpdate message is received and the routing handler + // returns true + generate_broadcast_message_test!(post_init_handle_channel_update_should_forward, { + let mut routing_handler = RoutingMessageHandlerTestStub::new(); + routing_handler.handle_channel_update_return = Ok(true); + routing_handler + }, + Message::ChannelUpdate(fake_channel_update_msg!()), + (| _descriptor | { }) + ); + + // Test that a post-Init connection: + // * read_event() returns Ok(_) if a ChannelUpdate message is received and the routing handler + // returns false + generate_broadcast_message_test!(post_init_handle_channel_update_should_not_forward, { + let mut routing_handler = RoutingMessageHandlerTestStub::new(); + routing_handler.handle_channel_update_return = Ok(false); + routing_handler + }, + Message::ChannelUpdate(fake_channel_update_msg!()), + (| _descriptor | { } + )); + + // _____ _ _____ _ _ + // | ____|_ _____ _ __ | |_ |_ _|__ ___| |_(_)_ __ __ _ + // | _| \ \ / / _ \ '_ \| __| | |/ _ \/ __| __| | '_ \ / _` | + // | |___ \ V / __/ | | | |_ | | __/\__ \ |_| | | | | (_| | + // |_____| \_/ \___|_| |_|\__| |_|\___||___/\__|_|_| |_|\__, | + // |___/ + + // To reduce test expansion, the unknown, unconnected, and connected variants are only run + // on one event type. All handlers use the same accessor to retrieve the connected node so one + // test of those paths should be sufficient. The initialized variant is run on all types which + // is where the interesting code is run. Once features are added to take action on unconnected + // nodes, this should be revisited. + + // Test that a post-Init connection: + // * process_events() does not send an OpenChannel message when it receives a SendOpenChannel + // event if the peer is unknown + #[test] + fn unknown_node_send_open_channel_event() { + let channel_handler = TestChannelMessageHandler::new(); + channel_handler.pending_events.lock().unwrap().push(MessageSendEvent::SendOpenChannel { + node_id: fake_public_key!(), + msg: fake_open_channel_msg!() + }); + let test_ctx = TestCtx::::with_channel_handler(channel_handler); + let mut descriptor = SocketDescriptorMock::new(); + let transport = new_connected_transport!(&test_ctx); + let peer_manager = new_peer_manager_post_init!(&test_ctx, &mut descriptor, &transport); + + peer_manager.process_events(); + assert!(descriptor.get_recording().is_empty()); + } + + // Test that a post-Init connection: + // * process_events() does not send an OpenChannel message when it receives a SendOpenChannel + // event if the peer is known, but the NOISE handshake is not complete + #[test] + fn unconnected_transport_send_open_channel_event() { + let channel_handler = TestChannelMessageHandler::new(); + channel_handler.pending_events.lock().unwrap().push(MessageSendEvent::SendOpenChannel { + node_id: fake_public_key!(), + msg: fake_open_channel_msg!() + }); + let test_ctx = TestCtx::::with_channel_handler(channel_handler); + let descriptor = SocketDescriptorMock::new(); + let mut transport = new_unconnected_transport!(); + let peer_manager = new_peer_manager_for_test!(&test_ctx); + new_outbound!(peer_manager, descriptor, &mut transport); + + peer_manager.process_events(); + + assert!(descriptor.get_recording().is_empty()); + } + + // Test that a post-Init connection: + // * process_events() does not send an OpenChannel message when it receives a SendOpenChannel + // event if the peer is known, but the Init message has not been received + #[test] + fn connected_transport_send_open_channel_event() { + let channel_handler = TestChannelMessageHandler::new(); + channel_handler.pending_events.lock().unwrap().push(MessageSendEvent::SendOpenChannel { + node_id: fake_public_key!(), + msg: fake_open_channel_msg!() + }); + let test_ctx = TestCtx::::with_channel_handler(channel_handler); + let descriptor = SocketDescriptorMock::new(); + let mut transport = new_connected_transport!(&test_ctx); + let peer_manager = new_peer_manager_for_test!(&test_ctx); + new_outbound!(peer_manager, descriptor, &mut transport); + + peer_manager.process_events(); + + assert!(descriptor.get_recording().is_empty()); + } + + // Test generator macro to reduce duplication across the event handlers that just enqueue a message + // (test name, event to send, expected sent message) + macro_rules! generate_event_handler_test { + ($test_name: ident, $event: expr, $expected_message: pat) => { + #[test] + fn $test_name() { + let channel_handler = TestChannelMessageHandler::new(); + let test_ctx = TestCtx::<&TestChannelMessageHandler, RoutingMessageHandlerTestStub>::with_channel_handler(&channel_handler); + let mut descriptor = SocketDescriptorMock::new(); + let transport = new_connected_transport!(&test_ctx); + let peer_manager = new_peer_manager_post_init!(&test_ctx, &mut descriptor, &transport); + + channel_handler.pending_events.lock().unwrap().push($event); + + peer_manager.process_events(); + + let recording = descriptor.get_recording(); + assert_matches_message!(&recording[0].0, $expected_message); + } + } + } + + // Test that a post-Init connection: + // * process_events() sends an OpenChannel message when it receives a SendOpenChannel event for + // an initialized node + generate_event_handler_test!(post_init_send_open_channel, + SendOpenChannel { + node_id: test_ctx_their_node_id!(), + msg: fake_open_channel_msg!(), + }, + Message::OpenChannel(_) + ); + + // Test that a post-Init connection: + // * process_events() sends an AcceptChannel message when it receives a SendAcceptChannel event + // for an initialized node + generate_event_handler_test!(post_init_send_accept_channel, + SendAcceptChannel { + node_id: test_ctx_their_node_id!(), + msg: fake_accept_channel_msg!(), + }, + Message::AcceptChannel(_) + ); + + // Test that a post-Init connection: + // * process_events() sends an AcceptChannel message when it receives a SendAcceptChannel event + // for an initialized node + generate_event_handler_test!(post_init_send_funding_created, + SendFundingCreated { + node_id: test_ctx_their_node_id!(), + msg: fake_funding_created_msg!(), + }, + Message::FundingCreated(_) + ); + + // Test that a post-Init connection: + // * process_events() sends an FundingSigned message when it receives a SendFundingSigned event + // for an initialized node + generate_event_handler_test!(post_init_send_funding_signed, + SendFundingSigned { + node_id: test_ctx_their_node_id!(), + msg: fake_funding_signed_msg!(), + }, + Message::FundingSigned(_) + ); + + // Test that a post-Init connection: + // * process_events() sends an FundingLocked message when it receives a SendFundingLocked event + // for an initialized node + generate_event_handler_test!(post_init_send_funding_locked, + SendFundingLocked { + node_id: test_ctx_their_node_id!(), + msg: fake_funding_locked_msg!(), + }, + Message::FundingLocked(_) + ); + + // Test that a post-Init connection: + // * process_events() sends an AnnouncementSignatures message when it receives a + // SendAnnouncementSignatures event for an initialized node + generate_event_handler_test!(post_init_send_announcement_signatures, + SendAnnouncementSignatures { + node_id: test_ctx_their_node_id!(), + msg: fake_announcement_signatures_msg!(), + }, + Message::AnnouncementSignatures(_) + ); + + // Test that a post-Init connection: + // * process_events() sends an RevokeAndACK message when it receives a SendRevokeAndACK event + // for an initialized node + generate_event_handler_test!(post_init_send_revoke_ack, + SendRevokeAndACK { + node_id: test_ctx_their_node_id!(), + msg: fake_revoke_and_ack_msg!(), + }, + Message::RevokeAndACK(_) + ); + + // Test that a post-Init connection: + // * process_events() sends an ClosingSigned message when it receives a SendClosingSigned event + // for an initialized node + generate_event_handler_test!(post_init_send_closing_signed, + SendClosingSigned { + node_id: test_ctx_their_node_id!(), + msg: fake_closing_signed_msg!(), + }, + Message::ClosingSigned(_) + ); + + // Test that a post-Init connection: + // * process_events() sends an Shutdown message when it receives a Shutdown event for an + // initialized node + generate_event_handler_test!(post_init_send_shutdown, + SendShutdown { + node_id: test_ctx_their_node_id!(), + msg: fake_shutdown_msg!(), + }, + Message::Shutdown(_) + ); + + // Test that a post-Init connection: + // * process_events() sends an ChannelReestablish message when it receives a + // SendChannelReestablish event for an initialized node + generate_event_handler_test!(post_init_send_channel_reestablish, + SendChannelReestablish { + node_id: test_ctx_their_node_id!(), + msg: fake_channel_reestablish_msg!() + }, + Message::ChannelReestablish(_) + ); + + // Test that a post-Init connection: + // * process_events() sends relevant HTLC messages when it receives a UpdateHTLC event for an + // initialized node + #[test] + fn post_init_send_update_htlcs() { + let channel_handler = TestChannelMessageHandler::new(); + let test_ctx = TestCtx::<&TestChannelMessageHandler, RoutingMessageHandlerTestStub>::with_channel_handler(&channel_handler); + let mut descriptor = SocketDescriptorMock::new(); + let transport = new_connected_transport!(&test_ctx); + let peer_manager = new_peer_manager_post_init!(&test_ctx, &mut descriptor, &transport); + + channel_handler.pending_events.lock().unwrap().push(UpdateHTLCs { + node_id: test_ctx_their_node_id!(), + updates: CommitmentUpdate { + update_add_htlcs: vec![fake_update_add_htlc_msg!()], + update_fulfill_htlcs: vec![fake_update_fulfill_htlc_msg!()], + update_fail_htlcs: vec![fake_update_fail_htlc_msg!()], + update_fail_malformed_htlcs: vec![fake_update_fail_malformed_htlc_msg!()], + update_fee: Some(fake_update_fee_msg!()), + commitment_signed: fake_commitment_signed_msg!() + } + }); + + peer_manager.process_events(); + + let recording = descriptor.get_recording(); + assert_matches_message!(&recording[0].0, Message::UpdateAddHTLC(_)); + assert_matches_message!(&recording[1].0, Message::UpdateFulfillHTLC(_)); + assert_matches_message!(&recording[2].0, Message::UpdateFailHTLC(_)); + assert_matches_message!(&recording[3].0, Message::UpdateFailMalformedHTLC(_)); + assert_matches_message!(&recording[4].0, Message::UpdateFee(_)); + assert_matches_message!(&recording[5].0, Message::CommitmentSigned(_)); + } + + // Test that a post-Init connection: + // * process_events() sends nothing when it receives a BroadcastChannelAnnouncement if the + // route_handler.handle_channel_announcement errors + #[test] + fn post_init_broadcast_channel_announcement_route_handler_handle_announcement_errors() { + let channel_handler = TestChannelMessageHandler::new(); + let mut routing_handler = RoutingMessageHandlerTestStub::new(); + routing_handler.handle_channel_announcement_return = Err(msgs::LightningError { err: "".to_string(), action: msgs::ErrorAction::IgnoreError }); + channel_handler.pending_events.lock().unwrap().push(BroadcastChannelAnnouncement { + msg: fake_channel_announcement_msg!(0, fake_public_key!(), fake_public_key!()), + update_msg: fake_channel_update_msg!() + }); + + let test_ctx = TestCtx::::with_channel_and_routing_handlers(channel_handler, routing_handler); + let mut descriptor = SocketDescriptorMock::new(); + let transport = new_connected_transport!(&test_ctx); + let peer_manager = new_peer_manager_post_init!(&test_ctx, &mut descriptor, &transport); + + peer_manager.process_events(); + assert!(descriptor.get_recording().is_empty()); + } + + // Test that a post-Init connection: + // * process_events() sends nothing when it receives a BroadcastChannelAnnouncement if the + // route_handler.handle_channel_update errors + #[test] + fn post_init_broadcast_channel_announcement_route_handler_handle_update_errors() { + let channel_handler = TestChannelMessageHandler::new(); + let mut routing_handler = RoutingMessageHandlerTestStub::new(); + routing_handler.handle_channel_update_return = Err(msgs::LightningError { err: "".to_string(), action: msgs::ErrorAction::IgnoreError }); + channel_handler.pending_events.lock().unwrap().push(BroadcastChannelAnnouncement { + msg: fake_channel_announcement_msg!(0, fake_public_key!(), fake_public_key!()), + update_msg: fake_channel_update_msg!() + }); + + let test_ctx = TestCtx::::with_channel_and_routing_handlers(channel_handler, routing_handler); + let mut descriptor = SocketDescriptorMock::new(); + let transport = new_connected_transport!(&test_ctx); + let peer_manager = new_peer_manager_post_init!(&test_ctx, &mut descriptor, &transport); + + peer_manager.process_events(); + assert!(descriptor.get_recording().is_empty()); + } + + // Test that a post-Init connection: + // * process_events() sends nothing when it receives a BroadcastChannelAnnouncement if the + // route_handler.handle_channel_announcement returns false + #[test] + fn post_init_broadcast_channel_announcement_route_handler_handle_announcement_returns_false() { + let channel_handler = TestChannelMessageHandler::new(); + let mut routing_handler = RoutingMessageHandlerTestStub::new(); + routing_handler.handle_channel_announcement_return = Ok(false); + channel_handler.pending_events.lock().unwrap().push(BroadcastChannelAnnouncement { + msg: fake_channel_announcement_msg!(0, fake_public_key!(), fake_public_key!()), + update_msg: fake_channel_update_msg!() + }); + + let test_ctx = TestCtx::::with_channel_and_routing_handlers(channel_handler, routing_handler); + let mut descriptor = SocketDescriptorMock::new(); + let transport = new_connected_transport!(&test_ctx); + let peer_manager = new_peer_manager_post_init!(&test_ctx, &mut descriptor, &transport); + + peer_manager.process_events(); + assert!(descriptor.get_recording().is_empty()); + } + + // Test that a post-Init connection: + // * process_events() sends nothing when it receives a BroadcastChannelAnnouncement if the + // route_handler.handle_channel_update returns false + #[test] + fn post_init_broadcast_channel_announcement_route_handle_update_returns_false() { + let channel_handler = TestChannelMessageHandler::new(); + let mut routing_handler = RoutingMessageHandlerTestStub::new(); + routing_handler.handle_channel_update_return = Ok(false); + channel_handler.pending_events.lock().unwrap().push(BroadcastChannelAnnouncement { + msg: fake_channel_announcement_msg!(0, fake_public_key!(), fake_public_key!()), + update_msg: fake_channel_update_msg!() + }); + + let test_ctx = TestCtx::::with_channel_and_routing_handlers(channel_handler, routing_handler); + let mut descriptor = SocketDescriptorMock::new(); + let transport = new_connected_transport!(&test_ctx); + let peer_manager = new_peer_manager_post_init!(&test_ctx, &mut descriptor, &transport); + + peer_manager.process_events(); + assert!(descriptor.get_recording().is_empty()); + } + + // To reduce test expansion, the unconnected and connected transport tests are only run on one + // broadcast variant. All broadcast implementations use the same API to determine whether or not + // the peer wants the announcement forwarded. + + // Test that a post-Init connection: + // * process_events() sends nothing when it receives a BroadcastChannelAnnouncement if the peer + // has not completed the NOISE handshake + #[test] + fn unconnected_transport_broadcast_channel_announcement() { + let channel_handler = TestChannelMessageHandler::new(); + let mut routing_handler = RoutingMessageHandlerTestStub::new(); + routing_handler.handle_channel_update_return = Ok(false); + channel_handler.pending_events.lock().unwrap().push(BroadcastChannelAnnouncement { + msg: fake_channel_announcement_msg!(0, fake_public_key!(), fake_public_key!()), + update_msg: fake_channel_update_msg!() + }); + + let test_ctx = TestCtx::::with_channel_and_routing_handlers(channel_handler, routing_handler); + let mut descriptor = SocketDescriptorMock::new(); + let transport = new_unconnected_transport!(); + let peer_manager = new_peer_manager_for_test!(&test_ctx); + new_outbound!(peer_manager, &mut descriptor, &transport); + + peer_manager.process_events(); + assert!(descriptor.get_recording().is_empty()); + } + + // Test that a post-Init connection: + // * process_events() sends nothing when it receives a BroadcastChannelAnnouncement if the peer + // has not received an Init message + #[test] + fn connected_transport_broadcast_channel_announcement() { + let channel_handler = TestChannelMessageHandler::new(); + let mut routing_handler = RoutingMessageHandlerTestStub::new(); + routing_handler.handle_channel_update_return = Ok(false); + channel_handler.pending_events.lock().unwrap().push(BroadcastChannelAnnouncement { + msg: fake_channel_announcement_msg!(0, fake_public_key!(), fake_public_key!()), + update_msg: fake_channel_update_msg!() + }); + + let test_ctx = TestCtx::::with_channel_and_routing_handlers(channel_handler, routing_handler); + let mut descriptor = SocketDescriptorMock::new(); + let transport = new_connected_transport!(&test_ctx); + let peer_manager = new_peer_manager_for_test!(&test_ctx); + new_outbound!(peer_manager, &mut descriptor, &transport); + + peer_manager.process_events(); + assert!(descriptor.get_recording().is_empty()); + } + + // Test that a post-Init connection: + // * process_events() sends nothing when it receives a BroadcastChannelAnnouncement if the peer + // is initialized, but Peer::should_forward_channel_announcement returns false + #[test] + fn connected_transport_broadcast_channel_announcement_short_channel_id_larger_than_current_sync() { + let channel_handler = TestChannelMessageHandler::new(); + let routing_handler = RoutingMessageHandlerTestStub::new(); + channel_handler.pending_events.lock().unwrap().push(BroadcastChannelAnnouncement { + msg: fake_channel_announcement_msg!(10000, fake_public_key!(), fake_public_key!()), + update_msg: fake_channel_update_msg!() + }); + + let test_ctx = TestCtx::::with_channel_and_routing_handlers(channel_handler, routing_handler); + let mut descriptor = SocketDescriptorMock::new(); + let transport = new_connected_transport!(&test_ctx); + let peer_manager = new_peer_manager_for_test!(&test_ctx); + new_outbound!(peer_manager, &mut descriptor, &transport); + + // Use an Init sequence with initial_routing_sync and use an arbitrarily high short + // channel_id in the fake_channel_announcement_msg to create the state. This test knows a bit too + // much and future refactoring can make this much better. + transport.borrow_mut().add_incoming_message(Message::Init(Init { features: InitFeatures::known() })); + peer_manager.process_events(); + assert!(descriptor.get_recording().is_empty()); + } + + // Test that a post-Init connection: + // * process_events() sends nothing when it receives a BroadcastChannelAnnouncement if the peer + // is node_id_1 + #[test] + fn post_init_broadcast_channel_announcement_skip_node_id_1() { + let channel_handler = TestChannelMessageHandler::new(); + channel_handler.pending_events.lock().unwrap().push(BroadcastChannelAnnouncement { + msg: fake_channel_announcement_msg!(0, test_ctx_their_node_id!(), fake_public_key!()), + update_msg: fake_channel_update_msg!() + }); + + let test_ctx = TestCtx::::with_channel_handler(channel_handler); + let mut descriptor = SocketDescriptorMock::new(); + let transport = new_connected_transport!(&test_ctx); + let peer_manager = new_peer_manager_post_init!(&test_ctx, &mut descriptor, &transport); + + peer_manager.process_events(); + assert!(descriptor.get_recording().is_empty()); + } + + // Test that a post-Init connection: + // * process_events() sends nothing when it receives a BroadcastChannelAnnouncement if the peer + // is node_id_2 + #[test] + fn post_init_broadcast_channel_announcement_skip_node_id_2() { + let channel_handler = TestChannelMessageHandler::new(); + channel_handler.pending_events.lock().unwrap().push(BroadcastChannelAnnouncement { + msg: fake_channel_announcement_msg!(0, fake_public_key!(), test_ctx_their_node_id!()), + update_msg: fake_channel_update_msg!() + }); + + let test_ctx = TestCtx::::with_channel_handler(channel_handler); + let mut descriptor = SocketDescriptorMock::new(); + let transport = new_connected_transport!(&test_ctx); + let peer_manager = new_peer_manager_post_init!(&test_ctx, &mut descriptor, &transport); + + peer_manager.process_events(); + assert!(descriptor.get_recording().is_empty()); + } + + // Test that a post-Init connection: + // * process_events() sends the relevant messages when it receives a BroadcastChannelAnnouncement + #[test] + fn post_init_broadcast_channel_announcement() { + let channel_handler = TestChannelMessageHandler::new(); + let test_ctx = TestCtx::<&TestChannelMessageHandler, RoutingMessageHandlerTestStub>::with_channel_handler(&channel_handler); + let mut descriptor = SocketDescriptorMock::new(); + let transport = new_connected_transport!(&test_ctx); + let peer_manager = new_peer_manager_post_init!(&test_ctx, &mut descriptor, &transport); + + channel_handler.pending_events.lock().unwrap().push(BroadcastChannelAnnouncement { + msg: fake_channel_announcement_msg!(0, fake_public_key!(), fake_public_key!()), + update_msg: fake_channel_update_msg!() + }); + + peer_manager.process_events(); + + let recording = descriptor.get_recording(); + assert_matches_message!(&recording[0].0, Message::ChannelAnnouncement(_)); + assert_matches_message!(&recording[1].0, Message::ChannelUpdate(_)); + } + + // Test that a post-Init connection: + // * process_events() sends nothing when it receives a BroadcastNodeAnnouncement if the + // route_handler.handle_node_announcement errors + #[test] + fn post_init_broadcast_node_announcement_route_handler_handle_announcement_errors() { + let channel_handler = TestChannelMessageHandler::new(); + let mut routing_handler = RoutingMessageHandlerTestStub::new(); + routing_handler.handle_node_announcement_return = Err(msgs::LightningError { err: "".to_string(), action: msgs::ErrorAction::IgnoreError }); + channel_handler.pending_events.lock().unwrap().push(BroadcastNodeAnnouncement { + msg: fake_node_announcement_msg!() + }); + + let test_ctx = TestCtx::::with_channel_and_routing_handlers(channel_handler, routing_handler); + let mut descriptor = SocketDescriptorMock::new(); + let transport = new_connected_transport!(&test_ctx); + let peer_manager = new_peer_manager_post_init!(&test_ctx, &mut descriptor, &transport); + + peer_manager.process_events(); + assert!(descriptor.get_recording().is_empty()); + } + + // Test that a post-Init connection: + // * process_events() sends nothing when it receives a BroadcastNodeAnnouncement if the + // route_handler.handle_node_announcement returns false + #[test] + fn post_init_broadcast_node_announcement_route_handler_handle_announcement_returns_false() { + let channel_handler = TestChannelMessageHandler::new(); + let mut routing_handler = RoutingMessageHandlerTestStub::new(); + routing_handler.handle_node_announcement_return = Ok(false); + channel_handler.pending_events.lock().unwrap().push(BroadcastNodeAnnouncement { + msg: fake_node_announcement_msg!() + }); + + let test_ctx = TestCtx::::with_channel_and_routing_handlers(channel_handler, routing_handler); + let mut descriptor = SocketDescriptorMock::new(); + let transport = new_connected_transport!(&test_ctx); + let peer_manager = new_peer_manager_post_init!(&test_ctx, &mut descriptor, &transport); + + peer_manager.process_events(); + assert!(descriptor.get_recording().is_empty()); + } + + // Test that a post-Init connection: + // * process_events() sends the relevant messages when it receives a BroadcastNodeAnnouncement + #[test] + fn post_init_broadcast_node_announcement() { + let channel_handler = TestChannelMessageHandler::new(); + let test_ctx = TestCtx::<&TestChannelMessageHandler, RoutingMessageHandlerTestStub>::with_channel_handler(&channel_handler); + let mut descriptor = SocketDescriptorMock::new(); + let transport = new_connected_transport!(&test_ctx); + let peer_manager = new_peer_manager_post_init!(&test_ctx, &mut descriptor, &transport); + + channel_handler.pending_events.lock().unwrap().push(BroadcastNodeAnnouncement { + msg: fake_node_announcement_msg!() + }); + + peer_manager.process_events(); + + let recording = descriptor.get_recording(); + assert_matches_message!(&recording[0].0, Message::NodeAnnouncement(_)); + } + + + // Test that a post-Init connection: + // * process_events() sends nothing when it receives a BroadcastChannelUpdate if the + // route_handler.handle_channel_update errors + #[test] + fn post_init_broadcast_channel_update_route_handler_handle_update_errors() { + let channel_handler = TestChannelMessageHandler::new(); + let mut routing_handler = RoutingMessageHandlerTestStub::new(); + routing_handler.handle_channel_update_return = Err(msgs::LightningError { err: "".to_string(), action: msgs::ErrorAction::IgnoreError }); + channel_handler.pending_events.lock().unwrap().push(BroadcastChannelUpdate { + msg: fake_channel_update_msg!() + }); + + let test_ctx = TestCtx::::with_channel_and_routing_handlers(channel_handler, routing_handler); + let mut descriptor = SocketDescriptorMock::new(); + let transport = new_connected_transport!(&test_ctx); + let peer_manager = new_peer_manager_post_init!(&test_ctx, &mut descriptor, &transport); + + peer_manager.process_events(); + assert!(descriptor.get_recording().is_empty()); + } + + // Test that a post-Init connection: + // * process_events() sends nothing when it receives a BroadcastChannelUpdate if the + // route_handler.handle_channel_update returns false + #[test] + fn post_init_broadcast_channel_update_route_handler_handle_update_returns_false() { + let channel_handler = TestChannelMessageHandler::new(); + let mut routing_handler = RoutingMessageHandlerTestStub::new(); + routing_handler.handle_channel_update_return = Ok(false); + channel_handler.pending_events.lock().unwrap().push(BroadcastChannelUpdate { + msg: fake_channel_update_msg!() + }); + + let test_ctx = TestCtx::::with_channel_and_routing_handlers(channel_handler, routing_handler); + let mut descriptor = SocketDescriptorMock::new(); + let transport = new_connected_transport!(&test_ctx); + let peer_manager = new_peer_manager_post_init!(&test_ctx, &mut descriptor, &transport); + + peer_manager.process_events(); + assert!(descriptor.get_recording().is_empty()); + } + + // Test that a post-Init connection: + // * process_events() sends the relevant messages when it receives a BroadcastChannelAnnouncement + #[test] + fn post_init_broadcast_channel_update() { + let channel_handler = TestChannelMessageHandler::new(); + let test_ctx = TestCtx::<&TestChannelMessageHandler, RoutingMessageHandlerTestStub>::with_channel_handler(&channel_handler); + let mut descriptor = SocketDescriptorMock::new(); + let transport = new_connected_transport!(&test_ctx); + let peer_manager = new_peer_manager_post_init!(&test_ctx, &mut descriptor, &transport); + + channel_handler.pending_events.lock().unwrap().push(BroadcastChannelUpdate { + msg: fake_channel_update_msg!() + }); + + peer_manager.process_events(); + + let recording = descriptor.get_recording(); + assert_matches_message!(&recording[0].0, Message::ChannelUpdate(_)); + } + + // Test that a post-Init connection: + // * process_events() calls the correct route handler callback when it receives a + // PaymentFailureNetworkUpdate event + #[test] + fn post_init_payment_failure_network_update() { + let routing_handler = RoutingMessageHandlerTestSpy::new(); + let channel_handler = TestChannelMessageHandler::new(); + channel_handler.pending_events.lock().unwrap().push(PaymentFailureNetworkUpdate { + update: HTLCFailChannelUpdate::ChannelUpdateMessage { + msg: fake_channel_update_msg!() + } + }); + + let test_ctx = TestCtx::::with_channel_and_routing_handlers(channel_handler, routing_handler); + let mut descriptor = SocketDescriptorMock::new(); + let transport = new_connected_transport!(&test_ctx); + let peer_manager = new_peer_manager_post_init!(&test_ctx, &mut descriptor, &transport); + + peer_manager.process_events(); + + assert!(route_handler_called!(&test_ctx, handle_htlc_fail_channel_update)); + } + + // Test that a post-Init connection: + // * process_events() ignores a HandleErrorEvent::DisconnectPeer for an unknown peer + #[test] + fn post_init_handle_error_event_disconnect_unknown_peer() { + let channel_handler = TestChannelMessageHandler::new(); + channel_handler.pending_events.lock().unwrap().push(HandleError { + node_id: fake_public_key!(), + action: ErrorAction::DisconnectPeer { msg: None } + }); + + let test_ctx = TestCtx::::with_channel_handler(channel_handler); + let mut descriptor = SocketDescriptorMock::new(); + let transport = new_connected_transport!(&test_ctx); + let peer_manager = new_peer_manager_post_init!(&test_ctx, &mut descriptor, &transport); + + peer_manager.process_events(); + + assert!(!descriptor.disconnect_called()); + assert!(descriptor.get_recording().is_empty()); + assert!(!peer_manager.get_peer_node_ids().is_empty()); + } + + // Test that a post-Init connection: + // * When process_events() receives a HandleErrorEvent::DisconnectPeer for an initialized peer w/ no message + // * get_peer_node_id() does not contain node_id + // * process_events() calls socket_disconnected() on the SocketDescriptor + #[test] + fn post_init_handle_error_event_disconnect_no_message() { + let channel_handler = TestChannelMessageHandler::new(); + channel_handler.pending_events.lock().unwrap().push(HandleError { + node_id: test_ctx_their_node_id!(), + action: ErrorAction::DisconnectPeer { msg: None } + }); + + let test_ctx = TestCtx::::with_channel_handler(channel_handler); + let mut descriptor = SocketDescriptorMock::new(); + let transport = new_connected_transport!(&test_ctx); + let peer_manager = new_peer_manager_post_init!(&test_ctx, &mut descriptor, &transport); + + peer_manager.process_events(); + + assert!(descriptor.disconnect_called()); + assert!(descriptor.get_recording().is_empty()); + assert!(peer_manager.get_peer_node_ids().is_empty()); + } + + // Test that a post-Init connection: + // * When process_events() receives a HandleErrorEvent::DisconnectPeer for an initialized peer w/ a message + // * process_events() sends error message is sent through SocketDescriptor (attempted) + // * process_events() calls socket_disconnected() on the SocketDescriptor + // * get_peer_node_id() does not contain node_id + #[test] + fn post_init_handle_error_event_disconnect_message() { + let channel_handler = TestChannelMessageHandler::new(); + let test_ctx = TestCtx::<&TestChannelMessageHandler, RoutingMessageHandlerTestStub>::with_channel_handler(&channel_handler); + let mut descriptor = SocketDescriptorMock::new(); + let transport = new_connected_transport!(&test_ctx); + let peer_manager = new_peer_manager_post_init!(&test_ctx, &mut descriptor, &transport); + + channel_handler.pending_events.lock().unwrap().push(HandleError { + node_id: test_ctx_their_node_id!(), + action: ErrorAction::DisconnectPeer { msg: Some(ErrorMessage { + channel_id: [0; 32], + data: "".to_string() + })} + }); + + peer_manager.process_events(); + + let recording = descriptor.get_recording(); + assert_matches_message!(&recording[0].0, Message::Error(_)); + assert!(descriptor.disconnect_called()); + assert!(peer_manager.get_peer_node_ids().is_empty()); + } + + // Test that a post-Init connection: + // * process_events() ignores a HandleErrorEvent::IgnoreError for an initialized peer + #[test] + fn post_init_handle_error_event_ignore_error() { + let channel_handler = TestChannelMessageHandler::new(); + channel_handler.pending_events.lock().unwrap().push(HandleError { + node_id: test_ctx_their_node_id!(), + action: ErrorAction::IgnoreError + }); + + let test_ctx = TestCtx::::with_channel_handler(channel_handler); + let mut descriptor = SocketDescriptorMock::new(); + let transport = new_connected_transport!(&test_ctx); + let peer_manager = new_peer_manager_post_init!(&test_ctx, &mut descriptor, &transport); + + peer_manager.process_events(); + + assert!(!descriptor.disconnect_called()); + assert!(descriptor.get_recording().is_empty()); + assert!(!peer_manager.get_peer_node_ids().is_empty()); + } + + // Test that a post-Init connection: + // * process_events() sends an error when it receives a HandleErrorEvent::SendErrorMessage for + // an initialized peer + #[test] + fn post_init_handle_error_event_send_error_message() { + let channel_handler = TestChannelMessageHandler::new(); + let test_ctx = TestCtx::<&TestChannelMessageHandler, RoutingMessageHandlerTestStub>::with_channel_handler(&channel_handler); + let mut descriptor = SocketDescriptorMock::new(); + let transport = new_connected_transport!(&test_ctx); + let peer_manager = new_peer_manager_post_init!(&test_ctx, &mut descriptor, &transport); + + channel_handler.pending_events.lock().unwrap().push(HandleError { + node_id: test_ctx_their_node_id!(), + action: ErrorAction::SendErrorMessage { + msg: ErrorMessage { channel_id: [0; 32], data: "".to_string() } + } + }); + + peer_manager.process_events(); + + let recording = descriptor.get_recording(); + assert_matches_message!(&recording[0].0, Message::Error(_)); + assert!(!descriptor.disconnect_called()); + assert!(!peer_manager.get_peer_node_ids().is_empty()); + } + + // ____ _ _____ _ _ + // | _ \(_)_ __ __ _ |_ _|__ ___| |_(_)_ __ __ _ + // | |_) | | '_ \ / _` | | |/ _ \/ __| __| | '_ \ / _` | + // | __/| | | | | (_| | | | __/\__ \ |_| | | | | (_| | + // |_| |_|_| |_|\__, | |_|\___||___/\__|_|_| |_|\__, | + // |___/ |___/ + + // Test that a post-Init connection: + // * read_event()/process_events() sends a Pong when it receives a Ping + #[test] + fn post_init_ping_creates_pong() { + let test_ctx = TestCtx::::new(); + let mut descriptor = SocketDescriptorMock::new(); + let transport = new_connected_transport!(&test_ctx); + let peer_manager = new_peer_manager_post_init!(&test_ctx, &mut descriptor, &transport); + + transport.borrow_mut().add_incoming_message(Message::Ping(Ping { ponglen: 1, byteslen: 0 })); + + assert_matches!(peer_manager.read_event(&mut descriptor, &[]), Ok(_)); + + peer_manager.process_events(); + + let recording = descriptor.get_recording(); + assert_matches_message!(&recording[0].0, Message::Pong(Pong { byteslen: 1})); + } + + // Test that a post-Init connection: + // * read_event()/process_events() ignores a Pong with ponglen > 65531 + #[test] + fn post_init_ping_ignores_large_pong() { + let test_ctx = TestCtx::::new(); + let mut descriptor = SocketDescriptorMock::new(); + let transport = new_connected_transport!(&test_ctx); + let peer_manager = new_peer_manager_post_init!(&test_ctx, &mut descriptor, &transport); + + transport.borrow_mut().add_incoming_message(Message::Ping(Ping { ponglen: 65532, byteslen: 0 })); + assert_matches!(peer_manager.read_event(&mut descriptor, &[]), Ok(_)); + descriptor.assert_called_with(vec![]); + + peer_manager.process_events(); + descriptor.assert_called_with(vec![]); + } + + // Test that a post-Init connection: + // * timer_tick_occurred() generates a Ping + #[test] + fn post_init_timer_tick_occurred_generates_ping() { + let test_ctx = TestCtx::::new(); + let mut descriptor = SocketDescriptorMock::new(); + let transport = new_connected_transport!(&test_ctx); + let peer_manager = new_peer_manager_post_init!(&test_ctx, &mut descriptor, &transport); + + peer_manager.timer_tick_occured(); + + let recording = descriptor.get_recording(); + assert_matches_message!(&recording[0].0, Message::Ping(_)); + } + + // Test that a post-Init connection: + // * timer_tick_occurred() calls socket_disconnected() on the SocketDescriptor + // * timer_tick_occurred() calls the peer_disconnected channel manager callback + // * get_peer_node_ids() does not contain disconnected node_id + #[test] + fn post_init_ping_no_pong_disconnects() { + let test_ctx = TestCtx::::new(); + let mut descriptor = SocketDescriptorMock::new(); + let transport = new_connected_transport!(&test_ctx); + let peer_manager = new_peer_manager_post_init!(&test_ctx, &mut descriptor, &transport); + + peer_manager.timer_tick_occured(); + + // Elapsed time with no Pong + + peer_manager.timer_tick_occured(); + + assert!(descriptor.disconnect_called()); + assert!(channel_handler_called!(&test_ctx, peer_disconnected)); + assert!(!peer_manager.get_peer_node_ids().contains(&test_ctx.their_node_id)); + } + + // Test that a post-Init connection: + // * timer_tick_occurred() does not call socket_disconnected() if a Pong was received + // * get_peer_node_ids() contains node_id + #[test] + fn post_init_ping_with_pong() { + let test_ctx = TestCtx::::new(); + let mut descriptor = SocketDescriptorMock::new(); + let transport = new_connected_transport!(&test_ctx); + let peer_manager = new_peer_manager_post_init!(&test_ctx, &mut descriptor, &transport); + + peer_manager.timer_tick_occured(); + + transport.borrow_mut().add_incoming_message(Message::Pong(Pong { byteslen: 64 })); + assert_matches!(peer_manager.read_event(&mut descriptor, &[]), Ok(_)); + + // Should notice the Pong and resend Ping + peer_manager.timer_tick_occured(); + + let recording = descriptor.get_recording(); + assert_matches_message!(&recording[1].0, Message::Ping(_)); + assert!(peer_manager.get_peer_node_ids().contains(&test_ctx.their_node_id)); + } + + // Test that a post-Init connection: + // * socket_disconnected() removes the node_id from get_peer_node_ids() + // * socket_disconnected() does not call disconnect_socket() on the SocketDescriptor + // * socket_disconnected() calls the peer_disconnected channel manager callback + #[test] + fn post_init_socket_disconnected() { + let test_ctx = TestCtx::::new(); + let mut descriptor = SocketDescriptorMock::new(); + let transport = new_connected_transport!(&test_ctx); + let peer_manager = new_peer_manager_post_init!(&test_ctx, &mut descriptor, &transport); + + peer_manager.socket_disconnected(&descriptor); + + assert!(peer_manager.get_peer_node_ids().is_empty()); + assert!(!descriptor.disconnect_called()); + assert!(channel_handler_called!(&test_ctx, peer_disconnected)); + } +} + +#[cfg(test)] +mod tests { + use ln::peers::handler::{PeerManager, MessageHandler, SocketDescriptor}; + use ln::msgs; + use util::events; + use util::test_utils; + + use bitcoin::secp256k1::Secp256k1; + use bitcoin::secp256k1::key::{SecretKey, PublicKey}; + + use std; + use std::sync::{Arc, Mutex}; + use std::sync::atomic::Ordering; + + #[derive(Clone)] + struct FileDescriptor { + fd: u16, + outbound_data: Arc>>, + } + impl PartialEq for FileDescriptor { + fn eq(&self, other: &Self) -> bool { + self.fd == other.fd + } + } + impl Eq for FileDescriptor { } + impl std::hash::Hash for FileDescriptor { + fn hash(&self, hasher: &mut H) { + self.fd.hash(hasher) + } + } + + impl SocketDescriptor for FileDescriptor { + fn send_data(&mut self, data: &[u8], _resume_read: bool) -> usize { + self.outbound_data.lock().unwrap().extend_from_slice(data); + data.len() + } + + fn disconnect_socket(&mut self) {} + } + + struct PeerManagerCfg { + chan_handler: test_utils::TestChannelMessageHandler, + routing_handler: test_utils::TestRoutingMessageHandler, + logger: test_utils::TestLogger, + } + + fn create_peermgr_cfgs(peer_count: usize) -> Vec { + let mut cfgs = Vec::new(); + for _ in 0..peer_count { + cfgs.push( + PeerManagerCfg{ + chan_handler: test_utils::TestChannelMessageHandler::new(), + logger: test_utils::TestLogger::new(), + routing_handler: test_utils::TestRoutingMessageHandler::new(), + } + ); + } + + cfgs + } + + fn create_network<'a>(peer_count: usize, cfgs: &'a Vec) -> Vec> { + let mut peers = Vec::new(); + + for i in 0..peer_count { + let node_secret = SecretKey::from_slice(&[42 + i as u8; 32]).unwrap(); + let ephemeral_bytes = [i as u8; 32]; + let msg_handler = MessageHandler { chan_handler: &cfgs[i].chan_handler, route_handler: &cfgs[i].routing_handler }; + let peer = PeerManager::new(msg_handler, node_secret, &ephemeral_bytes, &cfgs[i].logger); + peers.push(peer); + } + + peers + } + + fn establish_connection<'a>(peer_a: &PeerManager, peer_b: &PeerManager) -> (FileDescriptor, FileDescriptor) { + let secp_ctx = Secp256k1::new(); + let a_id = PublicKey::from_secret_key(&secp_ctx, &peer_a.inner.our_node_secret); + let mut fd_a = FileDescriptor { fd: 1, outbound_data: Arc::new(Mutex::new(Vec::new())) }; + let mut fd_b = FileDescriptor { fd: 1, outbound_data: Arc::new(Mutex::new(Vec::new())) }; + let initial_data = peer_b.new_outbound_connection(a_id, fd_b.clone()).unwrap(); + peer_a.new_inbound_connection(fd_a.clone()).unwrap(); + assert_eq!(peer_a.read_event(&mut fd_a, &initial_data).unwrap(), false); + peer_a.process_events(); + assert_eq!(peer_b.read_event(&mut fd_b, &fd_a.outbound_data.lock().unwrap().split_off(0)).unwrap(), false); + peer_b.process_events(); + assert_eq!(peer_a.read_event(&mut fd_a, &fd_b.outbound_data.lock().unwrap().split_off(0)).unwrap(), false); + peer_a.process_events(); + (fd_a.clone(), fd_b.clone()) + } + + fn establish_connection_and_read_events<'a>(peer_a: &PeerManager, peer_b: &PeerManager) -> (FileDescriptor, FileDescriptor) { + let (mut fd_a, mut fd_b) = establish_connection(peer_a, peer_b); + assert_eq!(peer_b.read_event(&mut fd_b, &fd_a.outbound_data.lock().unwrap().split_off(0)).unwrap(), false); + peer_b.process_events(); + assert_eq!(peer_a.read_event(&mut fd_a, &fd_b.outbound_data.lock().unwrap().split_off(0)).unwrap(), false); + peer_a.process_events(); + (fd_a.clone(), fd_b.clone()) + } + + #[test] + fn test_disconnect_peer() { + // Simple test which builds a network of PeerManager, connects and brings them to NoiseState::Finished and + // push a DisconnectPeer event to remove the node flagged by id + let cfgs = create_peermgr_cfgs(2); + let chan_handler = test_utils::TestChannelMessageHandler::new(); + let mut peers = create_network(2, &cfgs); + establish_connection(&peers[0], &peers[1]); + assert_eq!(peers[0].inner.peers.lock().unwrap().peers.len(), 1); + + let secp_ctx = Secp256k1::new(); + let their_id = PublicKey::from_secret_key(&secp_ctx, &peers[1].inner.our_node_secret); + + chan_handler.pending_events.lock().unwrap().push(events::MessageSendEvent::HandleError { + node_id: their_id, + action: msgs::ErrorAction::DisconnectPeer { msg: None }, + }); + assert_eq!(chan_handler.pending_events.lock().unwrap().len(), 1); + peers[0].inner.message_handler.chan_handler = &chan_handler; + + peers[0].process_events(); + assert_eq!(peers[0].inner.peers.lock().unwrap().peers.len(), 0); + } + + #[test] + fn test_timer_tick_occurred() { + // Create peers, a vector of two peer managers, perform initial set up and check that peers[0] has one Peer. + let cfgs = create_peermgr_cfgs(2); + let peers = create_network(2, &cfgs); + establish_connection(&peers[0], &peers[1]); + assert_eq!(peers[0].inner.peers.lock().unwrap().peers.len(), 1); + + // peers[0] awaiting_pong is set to true, but the Peer is still connected + peers[0].timer_tick_occured(); + assert_eq!(peers[0].inner.peers.lock().unwrap().peers.len(), 1); + + // Since timer_tick_occured() is called again when awaiting_pong is true, all Peers are disconnected + peers[0].timer_tick_occured(); + assert_eq!(peers[0].inner.peers.lock().unwrap().peers.len(), 0); + } + + #[test] + fn test_do_attempt_write_data() { + // Create 2 peers with custom TestRoutingMessageHandlers and connect them. + let cfgs = create_peermgr_cfgs(2); + cfgs[0].routing_handler.request_full_sync.store(true, Ordering::Release); + cfgs[1].routing_handler.request_full_sync.store(true, Ordering::Release); + let peers = create_network(2, &cfgs); + + // By calling establish_connect, we trigger do_attempt_write_data between + // the peers. Previously this function would mistakenly enter an infinite loop + // when there were more channel messages available than could fit into a peer's + // buffer. This issue would now be detected by this test (because we use custom + // RoutingMessageHandlers that intentionally return more channel messages + // than can fit into a peer's buffer). + let (mut fd_a, mut fd_b) = establish_connection(&peers[0], &peers[1]); + + // Make each peer to read the messages that the other peer just wrote to them. + peers[1].read_event(&mut fd_b, &fd_a.outbound_data.lock().unwrap().split_off(0)).unwrap(); + peers[1].process_events(); + peers[0].read_event(&mut fd_a, &fd_b.outbound_data.lock().unwrap().split_off(0)).unwrap(); + peers[0].process_events(); + + // Check that each peer has received the expected number of channel updates and channel + // announcements. + assert_eq!(cfgs[0].routing_handler.chan_upds_recvd.load(Ordering::Acquire), 100); + assert_eq!(cfgs[0].routing_handler.chan_anns_recvd.load(Ordering::Acquire), 50); + assert_eq!(cfgs[1].routing_handler.chan_upds_recvd.load(Ordering::Acquire), 100); + assert_eq!(cfgs[1].routing_handler.chan_anns_recvd.load(Ordering::Acquire), 50); + } + + #[test] + fn limit_initial_routing_sync_requests() { + // Inbound peer 0 requests initial_routing_sync, but outbound peer 1 does not. + { + let cfgs = create_peermgr_cfgs(2); + cfgs[0].routing_handler.request_full_sync.store(true, Ordering::Release); + let peers = create_network(2, &cfgs); + let (fd_0_to_1, fd_1_to_0) = establish_connection_and_read_events(&peers[0], &peers[1]); + + let peer_0 = peers[0].inner.peers.lock().unwrap(); + let peer_1 = peers[1].inner.peers.lock().unwrap(); + + let peer_0_features = peer_1.peers.get(&fd_1_to_0).unwrap().post_init_state.as_ref().unwrap(); + let peer_1_features = peer_0.peers.get(&fd_0_to_1).unwrap().post_init_state.as_ref().unwrap(); + + assert!(peer_0_features.their_features.initial_routing_sync()); + assert!(!peer_1_features.their_features.initial_routing_sync()); + } + + // Outbound peer 1 requests initial_routing_sync, but inbound peer 0 does not. + { + let cfgs = create_peermgr_cfgs(2); + cfgs[1].routing_handler.request_full_sync.store(true, Ordering::Release); + let peers = create_network(2, &cfgs); + let (fd_0_to_1, fd_1_to_0) = establish_connection_and_read_events(&peers[0], &peers[1]); + + let peer_0 = peers[0].inner.peers.lock().unwrap(); + let peer_1 = peers[1].inner.peers.lock().unwrap(); + + let peer_0_features = peer_1.peers.get(&fd_1_to_0).unwrap().post_init_state.as_ref().unwrap(); + let peer_1_features = peer_0.peers.get(&fd_0_to_1).unwrap().post_init_state.as_ref().unwrap(); + + assert!(!peer_0_features.their_features.initial_routing_sync()); + assert!(peer_1_features.their_features.initial_routing_sync()); + } + } +} diff --git a/lightning/src/ln/peers/handshake/acts.rs b/lightning/src/ln/peers/handshake/acts.rs new file mode 100644 index 00000000000..c868bcf2261 --- /dev/null +++ b/lightning/src/ln/peers/handshake/acts.rs @@ -0,0 +1,182 @@ +// This file is Copyright its original authors, visible in version control +// history. +// +// This file is licensed under the Apache License, Version 2.0 or the MIT license +// , at your option. +// You may not use this file except in accordance with one or both of these +// licenses. + +//! Helper library for working with NOISE handshake Act data. Contains utilities for passing Act +//! objects around and building them from received data. +//! Act objects are thin wrappers about raw arrays for stack-based processing as well as convenient +//! coercion to slices for flexible use by the higher-level modules. + +use std::{cmp, ops}; + +pub const ACT_ONE_LENGTH: usize = 50; +pub const ACT_TWO_LENGTH: usize = 50; +pub const ACT_THREE_LENGTH: usize = 66; +pub const EMPTY_ACT_ONE: ActOne = [0; ACT_ONE_LENGTH]; +pub const EMPTY_ACT_TWO: ActTwo = [0; ACT_TWO_LENGTH]; +pub const EMPTY_ACT_THREE: ActThree = [0; ACT_THREE_LENGTH]; +type ActOne = [u8; ACT_ONE_LENGTH]; +type ActTwo = [u8; ACT_TWO_LENGTH]; +type ActThree = [u8; ACT_THREE_LENGTH]; + +/// Wrapper for any act message +pub(super) enum Act { + One(ActOne), + Two(ActTwo), + Three(ActThree) +} + +impl Act { + /// Returns the size of the underlying array + fn len(&self) -> usize { + self.as_ref().len() + } +} + +impl From for Act { + /// Convert a finished ActBuilder into an Act + fn from(act_builder: ActBuilder) -> Self { + assert!(act_builder.is_finished()); + act_builder.partial_act + } +} + +impl ops::Deref for Act { + type Target = [u8]; + + /// Allows automatic coercion to slices in function calls + /// &Act -> &[u8] + fn deref(&self) -> &Self::Target { + match self { + &Act::One(ref act) => { + act + } + &Act::Two(ref act) => { + act + } + &Act::Three(ref act) => { + act + } + } + } +} + +impl AsRef<[u8]> for Act { + /// Allow convenient exposure of the underlying array through as_ref() + /// Act.as_ref() -> &[u8] + fn as_ref(&self) -> &[u8] { + &self + } +} + +/// Light wrapper around an Act that allows multiple fill() calls before finally +/// converting to an Act via Act::from(act_builder). Handles all of the bookkeeping +/// and edge cases of the array fill +pub(super) struct ActBuilder { + partial_act: Act, + write_pos: usize +} + +impl ActBuilder { + /// Returns a new ActBuilder for Act::One + pub(super) fn new(empty_act: Act) -> Self { + Self { + partial_act: empty_act, + write_pos: 0 + } + } + + /// Fills the Act with bytes from input and returns the unprocessed bytes + pub(super) fn fill(&mut self, input: &[u8]) -> usize { + // Simple fill implementation for both almost-identical structs to deduplicate code + // $act: Act[One|Two|Three], $input: &[u8]; returns &[u8] of remaining input that was not processed + macro_rules! fill_act_content { + ($act:expr, $write_pos:expr, $input:expr) => {{ + let fill_amount = cmp::min($act.len() - $write_pos, $input.len()); + + $act[$write_pos..$write_pos + fill_amount].copy_from_slice(&$input[..fill_amount]); + + $write_pos += fill_amount; + fill_amount + }} + } + + match &mut self.partial_act { + &mut Act::One(ref mut act) => { + fill_act_content!(act, self.write_pos, input) + } + &mut Act::Two(ref mut act) => { + fill_act_content!(act, self.write_pos, input) + } + &mut Act::Three(ref mut act) => { + fill_act_content!(act, self.write_pos, input) + } + } + } + + /// Returns true if the Act is finished building (enough bytes via fill()) + pub(super) fn is_finished(&self) -> bool { + self.write_pos == self.partial_act.len() + } +} + +#[cfg(test)] +mod tests { + use super::*; + + // Test bookkeeping of partial fill + #[test] + fn partial_fill() { + let mut builder = ActBuilder::new(Act::One(EMPTY_ACT_ONE)); + + let input = [1, 2, 3]; + let bytes_read = builder.fill(&input); + assert_eq!(builder.partial_act.len(), ACT_ONE_LENGTH); + assert_eq!(builder.write_pos, 3); + assert!(!builder.is_finished()); + assert_eq!(bytes_read, input.len()); + } + + // Test bookkeeping of exact fill + #[test] + fn exact_fill() { + let mut builder = ActBuilder::new(Act::One(EMPTY_ACT_ONE)); + + let input = [0; ACT_ONE_LENGTH]; + let bytes_read = builder.fill(&input); + assert_eq!(builder.partial_act.len(), ACT_ONE_LENGTH); + assert_eq!(builder.write_pos, ACT_ONE_LENGTH); + assert!(builder.is_finished()); + assert_eq!(Act::from(builder).as_ref(), &input[..]); + assert_eq!(bytes_read, input.len()); + } + + // Test bookkeeping of overfill + #[test] + fn over_fill() { + let mut builder = ActBuilder::new(Act::One(EMPTY_ACT_ONE)); + + let input = [0; ACT_ONE_LENGTH + 1]; + let bytes_read = builder.fill(&input); + + assert_eq!(builder.partial_act.len(), ACT_ONE_LENGTH); + assert_eq!(builder.write_pos, ACT_ONE_LENGTH); + assert!(builder.is_finished()); + assert_eq!(Act::from(builder).as_ref(), &input[..ACT_ONE_LENGTH]); + assert_eq!(bytes_read, ACT_ONE_LENGTH); + } + + // Converting an unfinished ActBuilder panics + #[test] + #[should_panic(expected="assertion failed: act_builder.is_finished()")] + fn convert_not_finished_panics() { + let builder = ActBuilder::new(Act::One(EMPTY_ACT_ONE)); + let _should_panic = Act::from(builder); + } +} + diff --git a/lightning/src/ln/peers/handshake/mod.rs b/lightning/src/ln/peers/handshake/mod.rs new file mode 100644 index 00000000000..a8ab38ccf01 --- /dev/null +++ b/lightning/src/ln/peers/handshake/mod.rs @@ -0,0 +1,254 @@ +// This file is Copyright its original authors, visible in version control +// history. +// +// This file is licensed under the Apache License, Version 2.0 or the MIT license +// , at your option. +// You may not use this file except in accordance with one or both of these +// licenses. + +//! Execute handshakes for peer-to-peer connection establishment. +//! Handshake states can be advanced automatically, or by manually calling the appropriate step. +//! Once complete, returns an instance of CompletedHandshakeInfo. + +use bitcoin::secp256k1::{PublicKey, SecretKey}; + +use ln::peers::encryption::{Decryptor, Encryptor}; +use ln::peers::handshake::acts::Act; +use ln::peers::handshake::states::HandshakeState; +use ln::peers::transport::IPeerHandshake; + +mod acts; +mod states; + +/// Interface used by PeerHandshake to interact with NOISE state machine. +/// State may transition to the same state in the event there are not yet enough bytes to move +/// forward with the handshake. +trait IHandshakeState { + /// Returns the next HandshakeState after processing the input bytes + fn next(self, input: &[u8]) -> Result<(Option, HandshakeState), String>; +} + +/// Object for managing handshakes. +/// Currently requires explicit ephemeral private key specification. +pub struct PeerHandshake { + state: Option, + ready_to_process: bool, +} + +/// Container for the information returned from a successfully completed handshake +pub struct CompletedHandshakeInfo { + pub decryptor: Decryptor, + pub encryptor: Encryptor, + pub their_node_id: PublicKey, +} + +impl IPeerHandshake for PeerHandshake { + /// Instantiate a handshake given the peer's static public key. The ephemeral private key MUST + /// generate a new session with strong cryptographic randomness. + fn new_outbound(initiator_static_private_key: &SecretKey, responder_static_public_key: &PublicKey, initiator_ephemeral_private_key: &SecretKey) -> Self { + let state = HandshakeState::new_initiator(initiator_static_private_key, responder_static_public_key, initiator_ephemeral_private_key); + + Self { + state: Some(state), + ready_to_process: false, + } + } + + /// Initializes the outbound handshake and provides the initial bytes to send to the responder + fn set_up_outbound(&mut self) -> Vec { + assert!(!self.ready_to_process); + self.ready_to_process = true; + + // This transition does not have a failure path + let (response_vec_option, completed_handshake_info) = self.process_act(&[]).unwrap(); + assert!(completed_handshake_info.is_none()); + + response_vec_option.unwrap() + } + + /// Instantiate a new handshake in anticipation of a peer's first handshake act + fn new_inbound(responder_static_private_key: &SecretKey, responder_ephemeral_private_key: &SecretKey) -> Self { + Self { + state: Some(HandshakeState::new_responder(responder_static_private_key, responder_ephemeral_private_key)), + ready_to_process: true, + } + } + + /// Process act dynamically + /// # Arguments + /// `input`: Byte slice received from peer as part of the handshake protocol + /// + /// # Return values + /// Returns a tuple with the following components: + /// `.0`: Byte vector containing the next act to send back to the peer per the handshake protocol + /// `.1`: Some(CompleteHandshakeInfo) if the handshake was just processed to completion and messages can now be encrypted and decrypted + fn process_act(&mut self, input: &[u8]) -> Result<(Option>, Option), String> { + assert!(self.ready_to_process); + let cur_state = self.state.take().unwrap(); + + let (act_option, mut next_state) = match cur_state.next(input)? { + (Some(act), next_state) => (Some(act.to_vec()), next_state), + (None, next_state) => (None, next_state) + }; + + let result = match next_state { + HandshakeState::Complete(ref mut complete_handshake_info) => { + Ok((act_option, complete_handshake_info.take())) + }, + _ => { Ok((act_option, None)) } + }; + + self.state = Some(next_state); + + result + } +} + +#[cfg(test)] +mod test { + use super::*; + + use bitcoin::secp256k1; + use bitcoin::secp256k1::key::{PublicKey, SecretKey}; + + struct TestCtx { + act1: Vec, + outbound_handshake: PeerHandshake, + outbound_static_public_key: PublicKey, + inbound_handshake: PeerHandshake, + inbound_static_public_key: PublicKey + } + + impl TestCtx { + fn new() -> TestCtx { + let curve = secp256k1::Secp256k1::new(); + + let outbound_static_private_key = SecretKey::from_slice(&[0x_11_u8; 32]).unwrap(); + let outbound_static_public_key = PublicKey::from_secret_key(&curve, &outbound_static_private_key); + let outbound_ephemeral_private_key = SecretKey::from_slice(&[0x_12_u8; 32]).unwrap(); + + let inbound_static_private_key = SecretKey::from_slice(&[0x_21_u8; 32]).unwrap(); + let inbound_static_public_key = PublicKey::from_secret_key(&curve, &inbound_static_private_key); + let inbound_ephemeral_private_key = SecretKey::from_slice(&[0x_22_u8; 32]).unwrap(); + + let mut outbound_handshake= PeerHandshake::new_outbound(&outbound_static_private_key, &inbound_static_public_key, &outbound_ephemeral_private_key); + let act1 = outbound_handshake.set_up_outbound(); + let inbound_handshake = PeerHandshake::new_inbound(&inbound_static_private_key, &inbound_ephemeral_private_key); + + TestCtx { + act1, + outbound_handshake, + outbound_static_public_key, + inbound_handshake, + inbound_static_public_key, + } + } + } + + macro_rules! do_process_act_or_panic { + ($handshake:expr, $input:expr) => { + $handshake.process_act($input).unwrap().0.unwrap() + } + } + + // Test that the outbound needs to call set_up_outbound() before process_act() + #[test] + #[should_panic(expected = "assertion failed: self.ready_to_process")] + fn new_outbound_no_set_up_panics() { + let curve = secp256k1::Secp256k1::new(); + + let outbound_static_private_key = SecretKey::from_slice(&[0x_11_u8; 32]).unwrap(); + let outbound_ephemeral_private_key = SecretKey::from_slice(&[0x_12_u8; 32]).unwrap(); + let inbound_static_private_key = SecretKey::from_slice(&[0x_21_u8; 32]).unwrap(); + let inbound_static_public_key = PublicKey::from_secret_key(&curve, &inbound_static_private_key); + + let mut outbound_handshake= PeerHandshake::new_outbound(&outbound_static_private_key, &inbound_static_public_key, &outbound_ephemeral_private_key); + outbound_handshake.process_act(&[]).unwrap(); + } + + // Test that calling set_up_outbound() on the inbound panics + #[test] + #[should_panic(expected = "assertion failed: !self.ready_to_process")] + fn new_inbound_calling_set_up_panics() { + let inbound_static_private_key = SecretKey::from_slice(&[0x_21_u8; 32]).unwrap(); + let inbound_ephemeral_private_key = SecretKey::from_slice(&[0x_22_u8; 32]).unwrap(); + + let mut inbound_handshake = PeerHandshake::new_inbound(&inbound_static_private_key, &inbound_ephemeral_private_key); + inbound_handshake.set_up_outbound(); + } + + // Default Outbound::Uninitiated + #[test] + fn new_outbound() { + let test_ctx = TestCtx::new(); + + assert_matches!(test_ctx.outbound_handshake.state, Some(HandshakeState::InitiatorAwaitingActTwo(_))); + } + + // Default Inbound::AwaitingActOne + #[test] + fn new_inbound() { + let test_ctx = TestCtx::new(); + + assert_matches!(test_ctx.inbound_handshake.state, Some(HandshakeState::ResponderAwaitingActOne(_))); + } + + /* + * PeerHandshake::process_act() tests + */ + + // Full sequence from initiator and responder as a sanity test. State machine is tested in states.rs + #[test] + fn full_sequence_sanity_test() { + let mut test_ctx = TestCtx::new(); + let act2 = do_process_act_or_panic!(test_ctx.inbound_handshake, &test_ctx.act1); + + let (act3, inbound_remote_pubkey) = if let (Some(act3), Some(completed_handshake_info)) = test_ctx.outbound_handshake.process_act(&act2).unwrap() { + (act3, completed_handshake_info.their_node_id) + } else { + panic!(); + }; + + let outbound_remote_pubkey = if let (None, Some(completed_handshake_info)) = test_ctx.inbound_handshake.process_act(&act3).unwrap() { + completed_handshake_info.their_node_id + } else { + panic!(); + }; + + assert_eq!(inbound_remote_pubkey, test_ctx.inbound_static_public_key); + assert_eq!(outbound_remote_pubkey, test_ctx.outbound_static_public_key); + } + + // Test that the internal state object matches the return from state_machine.next() + // This could make use of a mocking library to remove the dependency on the state machine. All + // that needs to be tested is that the expected state (returned) from state_machine.next() matchse + // the internal set state. + #[test] + fn process_act_properly_updates_state() { + let mut test_ctx = TestCtx::new(); + do_process_act_or_panic!(test_ctx.inbound_handshake, &test_ctx.act1); + assert_matches!(test_ctx.inbound_handshake.state, Some(HandshakeState::ResponderAwaitingActThree(_))); + } + + // Test that any errors from the state machine are passed back to the caller + // This could make use of a mocking library to remove the dependency on the state machine + // logic. All that needs to be tested is that an error from state_machine.next() + // results in an error in process_act() + #[test] + fn errors_properly_returned() { + let mut test_ctx = TestCtx::new(); + let invalid_act1 = [0; 50]; + assert_matches!(test_ctx.inbound_handshake.process_act(&invalid_act1).err(), Some(_)); + } + + // Test that any use of the PeerHandshake after returning an error panics + #[test] + #[should_panic(expected = "called `Option::unwrap()` on a `None` value")] + fn use_after_error_panics() { + let mut test_ctx = TestCtx::new(); + let invalid_act1 = [0; 50]; + assert_matches!(test_ctx.inbound_handshake.process_act(&invalid_act1).err(), Some(_)); + test_ctx.inbound_handshake.process_act(&[]).unwrap(); + } +} diff --git a/lightning/src/ln/peers/handshake/states.rs b/lightning/src/ln/peers/handshake/states.rs new file mode 100644 index 00000000000..1ec2a911e02 --- /dev/null +++ b/lightning/src/ln/peers/handshake/states.rs @@ -0,0 +1,909 @@ +// This file is Copyright its original authors, visible in version control +// history. +// +// This file is licensed under the Apache License, Version 2.0 or the MIT license +// , at your option. +// You may not use this file except in accordance with one or both of these +// licenses. + +use bitcoin::secp256k1; + +use bitcoin::hashes::{Hash, HashEngine}; +use bitcoin::hashes::sha256::Hash as Sha256; +use bitcoin::secp256k1::{SecretKey, PublicKey}; + +use ln::peers::{chacha, hkdf5869rfc}; +use ln::peers::encryption::{SymmetricKey, create_encryptor_decryptor}; +use ln::peers::handshake::acts::{Act, ActBuilder, ACT_ONE_LENGTH, ACT_TWO_LENGTH, ACT_THREE_LENGTH, EMPTY_ACT_ONE, EMPTY_ACT_TWO, EMPTY_ACT_THREE}; +use ln::peers::handshake::{CompletedHandshakeInfo, IHandshakeState}; + +// Alias type to help differentiate between temporary key and chaining key when passing bytes around +type ChainingKey = [u8; 32]; + +// Generate a SHA-256 hash from one or more elements concatenated together +macro_rules! concat_then_sha256 { + ( $( $x:expr ),+ ) => {{ + let mut sha = Sha256::engine(); + $( + sha.input($x.as_ref()); + )+ + Sha256::from_engine(sha) + }} +} + +pub(super) enum HandshakeState { + InitiatorStarting(InitiatorStartingState), + ResponderAwaitingActOne(ResponderAwaitingActOneState), + InitiatorAwaitingActTwo(InitiatorAwaitingActTwoState), + ResponderAwaitingActThree(ResponderAwaitingActThreeState), + Complete(Option), +} + +// Enum dispatch for state machine. Single public interface can statically dispatch to all states +impl HandshakeState { + pub(super) fn new_initiator(initiator_static_private_key: &SecretKey, responder_static_public_key: &PublicKey, initiator_ephemeral_private_key: &SecretKey) -> Self { + HandshakeState::InitiatorStarting(InitiatorStartingState::new(initiator_static_private_key.clone(), initiator_ephemeral_private_key.clone(), responder_static_public_key.clone())) + } + pub(super) fn new_responder(responder_static_private_key: &SecretKey, responder_ephemeral_private_key: &SecretKey) -> Self { + HandshakeState::ResponderAwaitingActOne(ResponderAwaitingActOneState::new(responder_static_private_key.clone(), responder_ephemeral_private_key.clone())) + } +} + +impl IHandshakeState for HandshakeState { + fn next(self, input: &[u8]) -> Result<(Option, HandshakeState), String> { + match self { + HandshakeState::InitiatorStarting(state) => { state.next(input) }, + HandshakeState::ResponderAwaitingActOne(state) => { state.next(input) }, + HandshakeState::InitiatorAwaitingActTwo(state) => { state.next(input) }, + HandshakeState::ResponderAwaitingActThree(state) => { state.next(input) }, + HandshakeState::Complete(_completed_handshake_info) => { panic!("no acts left to process") } + } + } +} + +// Handshake state of the Initiator prior to generating Act 1 +pub(super) struct InitiatorStartingState { + initiator_static_private_key: SecretKey, + initiator_static_public_key: PublicKey, + initiator_ephemeral_private_key: SecretKey, + initiator_ephemeral_public_key: PublicKey, + responder_static_public_key: PublicKey, + chaining_key: Sha256, + hash: Sha256 +} + +// Handshake state of the Responder prior to receiving Act 1 +pub(super) struct ResponderAwaitingActOneState { + responder_static_private_key: SecretKey, + responder_ephemeral_private_key: SecretKey, + responder_ephemeral_public_key: PublicKey, + chaining_key: Sha256, + hash: Sha256, + act_one_builder: ActBuilder +} + +// Handshake state of the Initiator prior to receiving Act 2 +pub(super) struct InitiatorAwaitingActTwoState { + initiator_static_private_key: SecretKey, + initiator_static_public_key: PublicKey, + initiator_ephemeral_private_key: SecretKey, + responder_static_public_key: PublicKey, + chaining_key: ChainingKey, + hash: Sha256, + act_two_builder: ActBuilder +} + +// Handshake state of the Responder prior to receiving Act 3 +pub(super) struct ResponderAwaitingActThreeState { + hash: Sha256, + responder_ephemeral_private_key: SecretKey, + chaining_key: ChainingKey, + temporary_key: [u8; 32], + act_three_builder: ActBuilder +} + +impl InitiatorStartingState { + pub(crate) fn new(initiator_static_private_key: SecretKey, initiator_ephemeral_private_key: SecretKey, responder_static_public_key: PublicKey) -> Self { + let initiator_static_public_key = private_key_to_public_key(&initiator_static_private_key); + let (hash, chaining_key) = handshake_state_initialization(&responder_static_public_key); + let initiator_ephemeral_public_key = private_key_to_public_key(&initiator_ephemeral_private_key); + InitiatorStartingState { + initiator_static_private_key, + initiator_static_public_key, + initiator_ephemeral_private_key, + initiator_ephemeral_public_key, + responder_static_public_key, + chaining_key, + hash + } + } +} + +impl IHandshakeState for InitiatorStartingState { + // https://github.com/lightningnetwork/lightning-rfc/blob/master/08-transport.md#act-one (sender) + fn next(self, input: &[u8]) -> Result<(Option, HandshakeState), String> { + + if input.len() > 0 { + return Err("first call for initiator must be empty".to_string()); + } + + let initiator_static_private_key = self.initiator_static_private_key; + let initiator_static_public_key = self.initiator_static_public_key; + let initiator_ephemeral_private_key = self.initiator_ephemeral_private_key; + let initiator_ephemeral_public_key = self.initiator_ephemeral_public_key; + let responder_static_public_key = self.responder_static_public_key; + let chaining_key = self.chaining_key; + let hash = self.hash; + + // serialize act one + let mut act_one = EMPTY_ACT_ONE; + let (hash, chaining_key, _) = calculate_act_message( + &initiator_ephemeral_private_key, + &initiator_ephemeral_public_key, + &responder_static_public_key, + chaining_key.into_inner(), + hash, + &mut act_one + ); + + Ok(( + Some(Act::One(act_one)), + HandshakeState::InitiatorAwaitingActTwo(InitiatorAwaitingActTwoState { + initiator_static_private_key, + initiator_static_public_key, + initiator_ephemeral_private_key, + responder_static_public_key, + chaining_key, + hash, + act_two_builder: ActBuilder::new(Act::Two(EMPTY_ACT_TWO)) + }) + )) + } +} + +impl ResponderAwaitingActOneState { + pub(crate) fn new(responder_static_private_key: SecretKey, responder_ephemeral_private_key: SecretKey) -> Self { + let responder_static_public_key = private_key_to_public_key(&responder_static_private_key); + let (hash, chaining_key) = handshake_state_initialization(&responder_static_public_key); + let responder_ephemeral_public_key = private_key_to_public_key(&responder_ephemeral_private_key); + + ResponderAwaitingActOneState { + responder_static_private_key, + responder_ephemeral_private_key, + responder_ephemeral_public_key, + chaining_key, + hash, + act_one_builder: ActBuilder::new(Act::One(EMPTY_ACT_ONE)) + } + } +} + +impl IHandshakeState for ResponderAwaitingActOneState { + // https://github.com/lightningnetwork/lightning-rfc/blob/master/08-transport.md#act-one (receiver) + // https://github.com/lightningnetwork/lightning-rfc/blob/master/08-transport.md#act-two (sender) + fn next(self, input: &[u8]) -> Result<(Option, HandshakeState), String> { + let mut act_one_builder = self.act_one_builder; + let bytes_read = act_one_builder.fill(input); + + // Any payload that is not fully consumed by the builder indicates a bad peer since responder + // data is required to generate act3 (so it can't come before we transition) + if bytes_read < input.len() { + return Err("Act One too large".to_string()); + } + + // In the event of a partial fill, stay in the same state and wait for more data + if !act_one_builder.is_finished() { + assert_eq!(bytes_read, input.len()); + return Ok(( + None, + HandshakeState::ResponderAwaitingActOne(Self { + responder_static_private_key: self.responder_static_private_key, + responder_ephemeral_private_key: self.responder_ephemeral_private_key, + responder_ephemeral_public_key: self.responder_ephemeral_public_key, + chaining_key: self.chaining_key, + hash: self.hash, + act_one_builder + }) + )); + } + + let hash = self.hash; + let responder_static_private_key = self.responder_static_private_key; + let chaining_key = self.chaining_key; + let responder_ephemeral_private_key = self.responder_ephemeral_private_key; + let responder_ephemeral_public_key = self.responder_ephemeral_public_key; + let act_one = Act::from(act_one_builder); + + let (initiator_ephemeral_public_key, hash, chaining_key, _) = process_act_message( + &act_one, + &responder_static_private_key, + chaining_key.into_inner(), + hash, + )?; + + let mut act_two = EMPTY_ACT_TWO; + let (hash, chaining_key, temporary_key) = calculate_act_message( + &responder_ephemeral_private_key, + &responder_ephemeral_public_key, + &initiator_ephemeral_public_key, + chaining_key, + hash, + &mut act_two + ); + + Ok(( + Some(Act::Two(act_two)), + HandshakeState::ResponderAwaitingActThree(ResponderAwaitingActThreeState { + hash, + responder_ephemeral_private_key, + chaining_key, + temporary_key, + act_three_builder: ActBuilder::new(Act::Three(EMPTY_ACT_THREE)) + }) + )) + } +} + +impl IHandshakeState for InitiatorAwaitingActTwoState { + // https://github.com/lightningnetwork/lightning-rfc/blob/master/08-transport.md#act-two (receiver) + // https://github.com/lightningnetwork/lightning-rfc/blob/master/08-transport.md#act-three (sender) + fn next(self, input: &[u8]) -> Result<(Option, HandshakeState), String> { + let mut act_two_builder = self.act_two_builder; + let bytes_read = act_two_builder.fill(input); + + // Any payload that is not fully consumed by the builder indicates a bad peer since responder data + // is required to generate post-authentication messages (so it can't come before we transition) + if bytes_read < input.len() { + return Err("Act Two too large".to_string()); + } + + // In the event of a partial fill, stay in the same state and wait for more data + if !act_two_builder.is_finished() { + assert_eq!(bytes_read, input.len()); + return Ok(( + None, + HandshakeState::InitiatorAwaitingActTwo(Self { + initiator_static_private_key: self.initiator_static_private_key, + initiator_static_public_key: self.initiator_static_public_key, + initiator_ephemeral_private_key: self.initiator_ephemeral_private_key, + responder_static_public_key: self.responder_static_public_key, + chaining_key: self.chaining_key, + hash: self.hash, + act_two_builder + }) + )); + } + + let initiator_static_private_key = self.initiator_static_private_key; + let initiator_static_public_key = self.initiator_static_public_key; + let initiator_ephemeral_private_key = self.initiator_ephemeral_private_key; + let responder_static_public_key = self.responder_static_public_key; + let hash = self.hash; + let chaining_key = self.chaining_key; + let act_two = Act::from(act_two_builder); + + let (responder_ephemeral_public_key, hash, chaining_key, temporary_key) = process_act_message( + &act_two, + &initiator_ephemeral_private_key, + chaining_key, + hash, + )?; + + let mut act_three = EMPTY_ACT_THREE; + + // start serializing act three + // 1. c = encryptWithAD(temp_k2, 1, h, s.pub.serializeCompressed()) + chacha::encrypt(&temporary_key, 1, &hash, &initiator_static_public_key.serialize(), &mut act_three[1..50]); + + // 2. h = SHA-256(h || c) + let hash = concat_then_sha256!(hash, act_three[1..50]); + + // 3. se = ECDH(s.priv, re) + let ecdh = ecdh(&initiator_static_private_key, &responder_ephemeral_public_key); + + // 4. ck, temp_k3 = HKDF(ck, se) + let (chaining_key, temporary_key) = hkdf5869rfc::derive(&chaining_key, &ecdh); + + // 5. t = encryptWithAD(temp_k3, 0, h, zero) + chacha::encrypt(&temporary_key, 0, &hash, &[0; 0], &mut act_three[50..]); + + // 6. sk, rk = HKDF(ck, zero) + let (sending_key, receiving_key) = hkdf5869rfc::derive(&chaining_key, &[0; 0]); + + // 7. rn = 0, sn = 0 + // - done by encryptor/decryptor initialization + let (encryptor, decryptor) = create_encryptor_decryptor(sending_key, receiving_key, chaining_key); + + // 8. Send m = 0 || c || t + act_three[0] = 0; + Ok(( + Some(Act::Three(act_three)), + HandshakeState::Complete(Some( + CompletedHandshakeInfo { + decryptor, + encryptor, + their_node_id: responder_static_public_key + } + )) + )) + } +} + +impl IHandshakeState for ResponderAwaitingActThreeState { + // https://github.com/lightningnetwork/lightning-rfc/blob/master/08-transport.md#act-three (receiver) + fn next(self, input: &[u8]) -> Result<(Option, HandshakeState), String> { + let mut act_three_builder = self.act_three_builder; + let bytes_read = act_three_builder.fill(input); + + // In the event of a partial fill, stay in the same state and wait for more data + if !act_three_builder.is_finished() { + assert_eq!(bytes_read, input.len()); + return Ok(( + None, + HandshakeState::ResponderAwaitingActThree(Self { + hash: self.hash, + responder_ephemeral_private_key: self.responder_ephemeral_private_key, + chaining_key: self.chaining_key, + temporary_key: self.temporary_key, + act_three_builder + }) + )); + } + + let hash = self.hash; + let temporary_key = self.temporary_key; + let responder_ephemeral_private_key = self.responder_ephemeral_private_key; + let chaining_key = self.chaining_key; + + // 1. Read exactly 66 bytes from the network buffer + let act_three_bytes = Act::from(act_three_builder); + assert_eq!(act_three_bytes.len(), ACT_THREE_LENGTH); + + // 2. Parse the read message (m) into v, c, and t + let version = act_three_bytes[0]; + let tagged_encrypted_pubkey = &act_three_bytes[1..50]; + let chacha_tag = &act_three_bytes[50..]; + + // 3. If v is an unrecognized handshake version, then the responder MUST abort the connection attempt. + if version != 0 { + // this should not crash the process, hence no panic + return Err("unexpected version".to_string()); + } + + // 4. rs = decryptWithAD(temp_k2, 1, h, c) + let mut remote_pubkey = [0; 33]; + chacha::decrypt(&temporary_key, 1, &hash, &tagged_encrypted_pubkey, &mut remote_pubkey)?; + let initiator_pubkey = if let Ok(public_key) = PublicKey::from_slice(&remote_pubkey) { + public_key + } else { + return Err("invalid remote public key".to_string()); + }; + + // 5. h = SHA-256(h || c) + let hash = concat_then_sha256!(hash, tagged_encrypted_pubkey); + + // 6. se = ECDH(e.priv, rs) + let ecdh = ecdh(&responder_ephemeral_private_key, &initiator_pubkey); + + // 7. ck, temp_k3 = HKDF(ck, se) + let (chaining_key, temporary_key) = hkdf5869rfc::derive(&chaining_key, &ecdh); + + // 8. p = decryptWithAD(temp_k3, 0, h, t) + chacha::decrypt(&temporary_key, 0, &hash, &chacha_tag, &mut [0; 0])?; + + // 9. rk, sk = HKDF(ck, zero) + let (receiving_key, sending_key) = hkdf5869rfc::derive(&chaining_key, &[0; 0]); + + // 10. rn = 0, sn = 0 + // - done by encryptor/decryptor initialization + let (encryptor, mut decryptor) = create_encryptor_decryptor(sending_key, receiving_key, chaining_key); + + // Any remaining data in the read buffer would be encrypted, so transfer ownership + // to the Decryptor for future use. + decryptor.read(&input[bytes_read..])?; + + Ok(( + None, + HandshakeState::Complete(Some( + CompletedHandshakeInfo { + decryptor, + encryptor, + their_node_id: initiator_pubkey + } + )) + )) + } +} + +// https://github.com/lightningnetwork/lightning-rfc/blob/master/08-transport.md#handshake-state-initialization +fn handshake_state_initialization(responder_static_public_key: &PublicKey) -> (Sha256, Sha256) { + let protocol_name = b"Noise_XK_secp256k1_ChaChaPoly_SHA256"; + let prologue = b"lightning"; + + // 1. h = SHA-256(protocolName) + // 2. ck = h + let chaining_key = concat_then_sha256!(protocol_name); + + // 3. h = SHA-256(h || prologue) + let hash = concat_then_sha256!(chaining_key, prologue); + + // h = SHA-256(h || responderPublicKey) + let hash = concat_then_sha256!(hash, responder_static_public_key.serialize()); + + (hash, chaining_key) +} + +// Due to the very high similarity of acts 1 and 2, this method is used to process both +// https://github.com/lightningnetwork/lightning-rfc/blob/master/08-transport.md#act-one (sender) +// https://github.com/lightningnetwork/lightning-rfc/blob/master/08-transport.md#act-two (sender) +fn calculate_act_message(local_private_ephemeral_key: &SecretKey, local_public_ephemeral_key: &PublicKey, remote_public_key: &PublicKey, chaining_key: ChainingKey, hash: Sha256, act_out: &mut [u8]) -> (Sha256, SymmetricKey, SymmetricKey) { + // 1. e = generateKey() (passed in) + // 2. h = SHA-256(h || e.pub.serializeCompressed()) + let serialized_local_public_key = local_public_ephemeral_key.serialize(); + let hash = concat_then_sha256!(hash, serialized_local_public_key); + + // 3. ACT1: es = ECDH(e.priv, rs) + // 3. ACT2: es = ECDH(e.priv, re) + let ecdh = ecdh(local_private_ephemeral_key, &remote_public_key); + + // 4. ACT1: ck, temp_k1 = HKDF(ck, es) + // 4. ACT2: ck, temp_k2 = HKDF(ck, ee) + let (chaining_key, temporary_key) = hkdf5869rfc::derive(&chaining_key, &ecdh); + + // 5. ACT1: c = encryptWithAD(temp_k1, 0, h, zero) + // 5. ACT2: c = encryptWithAD(temp_k2, 0, h, zero) + chacha::encrypt(&temporary_key, 0, &hash, &[0; 0], &mut act_out[34..]); + + // 6. h = SHA-256(h || c) + let hash = concat_then_sha256!(hash, &act_out[34..]); + + // Send m = 0 || e.pub.serializeCompressed() || c + act_out[0] = 0; + act_out[1..34].copy_from_slice(&serialized_local_public_key); + + (hash, chaining_key, temporary_key) +} + +// Due to the very high similarity of acts 1 and 2, this method is used to process both +// https://github.com/lightningnetwork/lightning-rfc/blob/master/08-transport.md#act-one (receiver) +// https://github.com/lightningnetwork/lightning-rfc/blob/master/08-transport.md#act-two (receiver) +fn process_act_message(act_bytes: &[u8], local_private_key: &SecretKey, chaining_key: ChainingKey, hash: Sha256) -> Result<(PublicKey, Sha256, SymmetricKey, SymmetricKey), String> { + // 1. Read exactly 50 bytes from the network buffer + // Partial act messages are handled by the callers. By the time it gets here, it + // must be the correct size. + assert_eq!(act_bytes.len(), ACT_ONE_LENGTH); + assert_eq!(act_bytes.len(), ACT_TWO_LENGTH); + + // 2.Parse the read message (m) into v, re, and c + let version = act_bytes[0]; + let ephemeral_public_key_bytes = &act_bytes[1..34]; + let chacha_tag = &act_bytes[34..]; + + let ephemeral_public_key = if let Ok(public_key) = PublicKey::from_slice(&ephemeral_public_key_bytes) { + public_key + } else { + return Err("invalid remote ephemeral public key".to_string()); + }; + + // 3. If v is an unrecognized handshake version, then the responder MUST abort the connection attempt + if version != 0 { + // this should not crash the process, hence no panic + return Err("unexpected version".to_string()); + } + + // 4. h = SHA-256(h || re.serializeCompressed()) + let hash = concat_then_sha256!(hash, ephemeral_public_key_bytes); + + // 5. Act1: es = ECDH(s.priv, re) + // 5. Act2: ee = ECDH(e.priv, ee) + let ecdh = ecdh(local_private_key, &ephemeral_public_key); + + // 6. Act1: ck, temp_k1 = HKDF(ck, es) + // 6. Act2: ck, temp_k2 = HKDF(ck, ee) + let (chaining_key, temporary_key) = hkdf5869rfc::derive(&chaining_key, &ecdh); + + // 7. Act1: p = decryptWithAD(temp_k1, 0, h, c) + // 7. Act2: p = decryptWithAD(temp_k2, 0, h, c) + chacha::decrypt(&temporary_key, 0, &hash, &chacha_tag, &mut [0; 0])?; + + // 8. h = SHA-256(h || c) + let hash = concat_then_sha256!(hash, chacha_tag); + + Ok((ephemeral_public_key, hash, chaining_key, temporary_key)) +} + +fn private_key_to_public_key(private_key: &SecretKey) -> PublicKey { + let curve = secp256k1::Secp256k1::new(); + let pk_object = PublicKey::from_secret_key(&curve, &private_key); + pk_object +} + +fn ecdh(private_key: &SecretKey, public_key: &PublicKey) -> SymmetricKey { + let curve = secp256k1::Secp256k1::new(); + let mut pk_object = public_key.clone(); + pk_object.mul_assign(&curve, &private_key[..]).expect("invalid multiplication"); + + let preimage = pk_object.serialize(); + concat_then_sha256!(preimage).into_inner() +} + +#[cfg(test)] +// Reference RFC test vectors for hard-coded values +// https://github.com/lightningnetwork/lightning-rfc/blob/master/08-transport.md#appendix-a-transport-test-vectors +mod test { + use super::*; + use super::HandshakeState::*; + + use hex; + + use bitcoin::secp256k1; + use bitcoin::secp256k1::{PublicKey, SecretKey}; + + struct TestCtx { + initiator: HandshakeState, + initiator_public_key: PublicKey, + responder: HandshakeState, + responder_static_public_key: PublicKey, + valid_act1: Vec, + valid_act2: Vec, + valid_act3: Vec, + + } + + impl TestCtx { + fn new() -> Self { + let curve = secp256k1::Secp256k1::new(); + let initiator_static_private_key = SecretKey::from_slice(&[0x_11_u8; 32]).unwrap(); + let initiator_public_key = PublicKey::from_secret_key(&curve, &initiator_static_private_key); + let initiator_ephemeral_private_key = SecretKey::from_slice(&[0x_12_u8; 32]).unwrap(); + + let responder_static_private_key = SecretKey::from_slice(&[0x_21_u8; 32]).unwrap(); + let responder_static_public_key = PublicKey::from_secret_key(&curve, &responder_static_private_key); + let responder_ephemeral_private_key = SecretKey::from_slice(&[0x_22_u8; 32]).unwrap(); + + let initiator = InitiatorStartingState::new(initiator_static_private_key, initiator_ephemeral_private_key, responder_static_public_key); + let responder = ResponderAwaitingActOneState::new(responder_static_private_key, responder_ephemeral_private_key); + + TestCtx { + initiator: InitiatorStarting(initiator), + initiator_public_key, + responder: ResponderAwaitingActOne(responder), + responder_static_public_key, + valid_act1: hex::decode("00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").unwrap(), + valid_act2: hex::decode("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap(), + valid_act3: hex::decode("00b9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139ba").unwrap() + } + } + } + + macro_rules! do_next_or_panic { + ($state:expr, $input:expr) => { + if let (Some(output_act), next_state) = $state.next($input).unwrap() { + (output_act, next_state) + } else { + panic!(); + } + } + } + + macro_rules! assert_matches { + ($e:expr, $state_match:pat) => { + match $e { + $state_match => (), + _ => panic!() + } + } + } + + // Initiator::Starting -> AwaitingActTwo + #[test] + fn starting_to_awaiting_act_two() { + let test_ctx = TestCtx::new(); + let (act1, awaiting_act_two_state) = do_next_or_panic!(test_ctx.initiator, &[]); + + assert_eq!(act1.as_ref(), test_ctx.valid_act1.as_slice()); + assert_matches!(awaiting_act_two_state, InitiatorAwaitingActTwo(_)); + } + + // Initiator::Starting -> AwaitingActTwo (extra bytes in argument) + #[test] + fn starting_to_awaiting_act_two_extra_bytes() { + let test_ctx = TestCtx::new(); + + assert_eq!(test_ctx.initiator.next(&[1]).err(), Some(String::from("first call for initiator must be empty"))); + } + + // Responder::AwaitingActOne -> AwaitingActThree + // RFC test vector: transport-responder successful handshake + #[test] + fn awaiting_act_one_to_awaiting_act_three() { + let test_ctx = TestCtx::new(); + let (act2, awaiting_act_three_state) = test_ctx.responder.next(&test_ctx.valid_act1).unwrap(); + + assert_eq!(act2.unwrap().as_ref(), test_ctx.valid_act2.as_slice()); + assert_matches!(awaiting_act_three_state, ResponderAwaitingActThree(_)); + } + + // Responder::AwaitingActOne -> AwaitingActThree (bad peer) + // Act2 requires data from the initiator. If we receive a payload for act1 that is larger than + // expected it indicates a bad peer + #[test] + fn awaiting_act_one_to_awaiting_act_three_input_extra_bytes() { + let test_ctx = TestCtx::new(); + let mut act1 = test_ctx.valid_act1; + act1.extend_from_slice(&[1]); + + assert_eq!(test_ctx.responder.next(&act1).err(), Some(String::from("Act One too large"))); + } + + // Responder::AwaitingActOne -> AwaitingActThree (segmented calls) + // RFC test vector: transport-responder act1 short read test + // Divergence from RFC tests due to not reading directly from the socket (partial message OK) + #[test] + fn awaiting_act_one_to_awaiting_act_three_segmented() { + let test_ctx = TestCtx::new(); + let act1_partial1 = &test_ctx.valid_act1[..25]; + let act1_partial2 = &test_ctx.valid_act1[25..]; + + let next_state = test_ctx.responder.next(&act1_partial1).unwrap(); + assert_matches!(next_state, (None, ResponderAwaitingActOne(_))); + assert_matches!(next_state.1.next(&act1_partial2).unwrap(), (Some(_), ResponderAwaitingActThree(_))); + } + + // Responder::AwaitingActOne -> Error (bad version byte) + // RFC test vector: transport-responder act1 bad version test + #[test] + fn awaiting_act_one_to_awaiting_act_three_input_bad_version() { + let test_ctx = TestCtx::new(); + let act1 = hex::decode("01036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").unwrap(); + + assert_eq!(test_ctx.responder.next(&act1).err(), Some(String::from("unexpected version"))); + } + + // Responder::AwaitingActOne -> Error (invalid remote ephemeral key) + // RFC test vector: transport-responder act1 bad key serialization test + #[test] + fn awaiting_act_one_to_awaiting_act_three_invalid_remote_ephemeral_key() { + let test_ctx = TestCtx::new(); + let act1 = hex::decode("00046360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").unwrap(); + + assert_eq!(test_ctx.responder.next(&act1).err(), Some(String::from("invalid remote ephemeral public key"))); + } + + // Responder::AwaitingActOne -> Error (invalid hmac) + // RFC test vector: transport-responder act1 bad MAC test + #[test] + fn awaiting_act_one_to_awaiting_act_three_invalid_hmac() { + let test_ctx = TestCtx::new(); + let act1 = hex::decode("00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6b").unwrap(); + + assert_eq!(test_ctx.responder.next(&act1).err(), Some(String::from("invalid hmac"))); + } + + // Initiator::AwaitingActTwo -> Complete (bad peer) + // Initiator data is required to generate post-authentication messages. This means any extra + // data indicates a bad peer. + #[test] + fn awaiting_act_two_to_complete_extra_bytes() { + let test_ctx = TestCtx::new(); + let (_act1, awaiting_act_two_state) = do_next_or_panic!(test_ctx.initiator, &[]); + let mut act2 = test_ctx.valid_act2; + act2.extend_from_slice(&[1]); + + assert_eq!(awaiting_act_two_state.next(&act2).err(), Some(String::from("Act Two too large"))); + } + + // Initiator::AwaitingActTwo -> Complete + // RFC test vector: transport-initiator successful handshake + #[test] + fn awaiting_act_two_to_complete() { + let test_ctx = TestCtx::new(); + let (_act1, awaiting_act_two_state) = do_next_or_panic!(test_ctx.initiator, &[]); + let (act3, complete_state) = do_next_or_panic!(awaiting_act_two_state, &test_ctx.valid_act2); + + let completed_handshake_info = if let Complete(Some(completed_handshake_info)) = complete_state { + completed_handshake_info + } else { + panic!(); + }; + + assert_eq!(act3.as_ref(), test_ctx.valid_act3.as_slice()); + assert_eq!(completed_handshake_info.their_node_id, test_ctx.responder_static_public_key); + assert_eq!(0, completed_handshake_info.decryptor.read_buffer_length()); + } + + // Initiator::AwaitingActTwo -> Complete (segmented calls) + // RFC test vector: transport-initiator act2 short read test + // Divergence from RFC tests due to not reading directly from the socket (partial message OK) + #[test] + fn awaiting_act_two_to_complete_segmented() { + let test_ctx = TestCtx::new(); + let (_act1, awaiting_act_two_state) = do_next_or_panic!(test_ctx.initiator, &[]); + + let act2_partial1 = &test_ctx.valid_act2[..25]; + let act2_partial2 = &test_ctx.valid_act2[25..]; + + let next_state = awaiting_act_two_state.next(&act2_partial1).unwrap(); + assert_matches!(next_state, (None, InitiatorAwaitingActTwo(_))); + assert_matches!(next_state.1.next(&act2_partial2).unwrap(), (Some(_), Complete(_))); + } + + // Initiator::AwaitingActTwo -> Error (bad version byte) + // RFC test vector: transport-initiator act2 bad version test + #[test] + fn awaiting_act_two_bad_version_byte() { + let test_ctx = TestCtx::new(); + let (_act1, awaiting_act_two_state) = do_next_or_panic!(test_ctx.initiator, &[]); + let act2 = hex::decode("0102466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap(); + + assert_eq!(awaiting_act_two_state.next(&act2).err(), Some(String::from("unexpected version"))); + } + + // Initiator::AwaitingActTwo -> Error (invalid ephemeral public key) + // RFC test vector: transport-initiator act2 bad key serialization test + #[test] + fn awaiting_act_two_invalid_ephemeral_public_key() { + let test_ctx = TestCtx::new(); + let (_act1, awaiting_act_two_state) = do_next_or_panic!(test_ctx.initiator, &[]); + let act2 = hex::decode("0004466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap(); + + assert_eq!(awaiting_act_two_state.next(&act2).err(), Some(String::from("invalid remote ephemeral public key"))); + } + + // Initiator::AwaitingActTwo -> Error (invalid hmac) + // RFC test vector: transport-initiator act2 bad MAC test + #[test] + fn awaiting_act_two_invalid_hmac() { + let test_ctx = TestCtx::new(); + let (_act1, awaiting_act_two_state) = do_next_or_panic!(test_ctx.initiator, &[]); + let act2 = hex::decode("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730af").unwrap(); + + assert_eq!(awaiting_act_two_state.next(&act2).err(), Some(String::from("invalid hmac"))); + } + + // Responder::AwaitingActThree -> Complete + // RFC test vector: transport-responder successful handshake + #[test] + fn awaiting_act_three_to_complete() { + let test_ctx = TestCtx::new(); + let (_act2, awaiting_act_three_state) = do_next_or_panic!(test_ctx.responder, &test_ctx.valid_act1); + + let completed_handshake_info = if let (None, Complete(Some(completed_handshake_info))) = awaiting_act_three_state.next(&test_ctx.valid_act3).unwrap() { + completed_handshake_info + } else { + panic!(); + }; + + assert_eq!(completed_handshake_info.their_node_id, test_ctx.initiator_public_key); + assert_eq!(0, completed_handshake_info.decryptor.read_buffer_length()); + } + + // Responder::AwaitingActThree -> None (with extra bytes) + // Ensures that any remaining data in the read buffer is transferred to the Decryptor once + // the handshake is complete + #[test] + fn awaiting_act_three_excess_bytes_after_complete_are_in_decryptor() { + let test_ctx = TestCtx::new(); + let (_act2, awaiting_act_three_state) = do_next_or_panic!(test_ctx.responder, &test_ctx.valid_act1); + let mut act3 = test_ctx.valid_act3; + act3.extend_from_slice(&[2; 16]); + + let completed_handshake_info = if let (None, Complete(Some(completed_handshake_info))) = awaiting_act_three_state.next(&act3).unwrap() { + completed_handshake_info + } else { + panic!(); + }; + + assert_eq!(completed_handshake_info.their_node_id, test_ctx.initiator_public_key); + assert_eq!(16, completed_handshake_info.decryptor.read_buffer_length()); + } + + // Responder::AwaitingActThree -> Error (bad version bytes) + // RFC test vector: transport-responder act3 bad version test + #[test] + fn awaiting_act_three_bad_version_bytes() { + let test_ctx = TestCtx::new(); + let (_act2, awaiting_act_three_state) = do_next_or_panic!(test_ctx.responder, &test_ctx.valid_act1); + let act3 = hex::decode("01b9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139ba").unwrap(); + + assert_eq!(awaiting_act_three_state.next(&act3).err(), Some(String::from("unexpected version"))); + } + + // Responder::AwaitingActThree -> Complete (segmented calls) + // RFC test vector: transport-responder act3 short read test + // Divergence from RFC tests due to not reading directly from the socket (partial message OK) + #[test] + fn awaiting_act_three_to_complete_segmented() { + let test_ctx = TestCtx::new(); + let (_act2, awaiting_act_three_state) = do_next_or_panic!(test_ctx.responder, &test_ctx.valid_act1); + + let act3_partial1 = &test_ctx.valid_act3[..35]; + let act3_partial2 = &test_ctx.valid_act3[35..]; + + let next_state = awaiting_act_three_state.next(&act3_partial1).unwrap(); + assert_matches!(next_state, (None, ResponderAwaitingActThree(_))); + assert_matches!(next_state.1.next(&act3_partial2), Ok((None, Complete(_)))); + } + + // Responder::AwaitingActThree -> Error (invalid hmac) + // RFC test vector: transport-responder act3 bad MAC for ciphertext test + #[test] + fn awaiting_act_three_invalid_hmac() { + let test_ctx = TestCtx::new(); + let (_act2, awaiting_act_three_state) = do_next_or_panic!(test_ctx.responder, &test_ctx.valid_act1); + let act3 = hex::decode("00c9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139ba").unwrap(); + + assert_eq!(awaiting_act_three_state.next(&act3).err(), Some(String::from("invalid hmac"))); + } + + // Responder::AwaitingActThree -> Error (invalid remote_static_key) + // RFC test vector: transport-responder act3 bad rs test + #[test] + fn awaiting_act_three_invalid_rs() { + let test_ctx = TestCtx::new(); + let (_act2, awaiting_act_three_state) = do_next_or_panic!(test_ctx.responder, &test_ctx.valid_act1); + let act3 = hex::decode("00bfe3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa2235536ad09a8ee351870c2bb7f78b754a26c6cef79a98d25139c856d7efd252c2ae73c").unwrap(); + + assert_eq!(awaiting_act_three_state.next(&act3).err(), Some(String::from("invalid remote public key"))); + } + + // Responder::AwaitingActThree -> Error (invalid tag hmac) + // RFC test vector: transport-responder act3 bad MAC test + #[test] + fn awaiting_act_three_invalid_tag_hmac() { + let test_ctx = TestCtx::new(); + let (_act2, awaiting_act_three_state) = do_next_or_panic!(test_ctx.responder, &test_ctx.valid_act1); + let act3 = hex::decode("00b9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139bb").unwrap(); + + assert_eq!(awaiting_act_three_state.next(&act3).err(), Some(String::from("invalid hmac"))); + } + + // Initiator::Complete -> Error + #[test] + #[should_panic(expected = "no acts left to process")] + fn initiator_complete_next_fail() { + let test_ctx = TestCtx::new(); + let (act1, awaiting_act_two_state) = do_next_or_panic!(test_ctx.initiator, &[]); + let (act2, _awaiting_act_three_state) = do_next_or_panic!(test_ctx.responder, &act1); + let (_act3, complete_state) = do_next_or_panic!(awaiting_act_two_state, &act2); + + complete_state.next(&[]).unwrap(); + } + + // Initiator::Complete -> Error + #[test] + #[should_panic(expected = "no acts left to process")] + fn responder_complete_next_fail() { + let test_ctx = TestCtx::new(); + let (act1, awaiting_act_two_state) = do_next_or_panic!(test_ctx.initiator, &[]); + let (act2, awaiting_act_three_state) = do_next_or_panic!(test_ctx.responder, &act1); + let (act3, _complete_state) = do_next_or_panic!(awaiting_act_two_state, &act2); + + let complete_state = if let (None, complete_state) = awaiting_act_three_state.next(&act3).unwrap() { + complete_state + } else { + panic!(); + }; + + complete_state.next(&[]).unwrap(); + } + + // Test the Act byte generation against known good hard-coded values in case the implementation + // changes in a symmetric way that makes the other tests useless + #[test] + fn test_acts_against_reference_bytes() { + let test_ctx = TestCtx::new(); + let (act1, awaiting_act_two_state) = do_next_or_panic!(test_ctx.initiator, &[]); + let (act2, _awaiting_act_three_state) = do_next_or_panic!(test_ctx.responder, &act1); + let (act3, _complete_state) = do_next_or_panic!(awaiting_act_two_state, &act2); + + assert_eq!(hex::encode(&act1), + "00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a"); + assert_eq!(hex::encode(&act2), + "0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae"); + assert_eq!(hex::encode(&act3), + "00b9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139ba"); + } +} + diff --git a/lightning/src/ln/peers/hkdf5869rfc.rs b/lightning/src/ln/peers/hkdf5869rfc.rs new file mode 100644 index 00000000000..1d9f66ab1cb --- /dev/null +++ b/lightning/src/ln/peers/hkdf5869rfc.rs @@ -0,0 +1,80 @@ +// This file is Copyright its original authors, visible in version control +// history. +// +// This file is licensed under the Apache License, Version 2.0 or the MIT license +// , at your option. +// You may not use this file except in accordance with one or both of these +// licenses. + +use bitcoin::hashes::{Hash, HashEngine, Hmac, HmacEngine}; +use bitcoin::hashes::sha256::Hash as Sha256; + +// Allows 1 or more inputs and "concatenates" them together using the input() function +// of HmacEngine:: +macro_rules! hmac_sha256 { + ( $salt:expr, ($( $input:expr ),+ )) => {{ + let mut engine = HmacEngine::::new($salt); + $( + engine.input($input); + )+ + Hmac::from_engine(engine).into_inner() + }} +} + +/// Implements HKDF defined in [BOLT #8](https://github.com/lightningnetwork/lightning-rfc/blob/master/08-transport.md#handshake-state) +/// [RFC 5869](https://tools.ietf.org/html/rfc5869pub) +/// Returns the first 64 octets as two 32 byte arrays +pub(super) fn derive(salt: &[u8], ikm: &[u8]) -> ([u8; 32], [u8; 32]) { + // 2.1. Notation + // + // HMAC-Hash denotes the HMAC function [HMAC] instantiated with hash + // function 'Hash'. HMAC always has two arguments: the first is a key + // and the second an input (or message). (Note that in the extract + // step, 'IKM' is used as the HMAC input, not as the HMAC key.) + // + // When the message is composed of several elements we use concatenation + // (denoted |) in the second argument; for example, HMAC(K, elem1 | + // elem2 | elem3). + + // 2.2. Step 1: Extract + // HKDF-Extract(salt, IKM) -> PRK + // PRK = HMAC-Hash(salt, IKM) + let prk = hmac_sha256!(salt, (ikm)); + + // 2.3. Step 2: Expand + // HKDF-Expand(PRK, info, L) -> OKM + // N = ceil(L/HashLen) + // T = T(1) | T(2) | T(3) | ... | T(N) + // OKM = first L octets of T + // + // where: + // T(0) = empty string (zero length) + // T(1) = HMAC-Hash(PRK, T(0) | info | 0x01) + let t1 = hmac_sha256!(&prk, (&[1])); + // T(2) = HMAC-Hash(PRK, T(1) | info | 0x02) + let t2 = hmac_sha256!(&prk, (&t1, &[2])); + + return (t1, t2) +} + +// Appendix A. Test Vectors +#[cfg(test)] +mod test { + use hex; + use ln::peers::hkdf5869rfc::derive; + + // Test with SHA-256 and zero-length salt/info + // Our implementation uses a zero-length info field and returns the first 64 octets. As a result, + // this test will be a prefix match on the vector provided by the RFC which is 42 bytes. + #[test] + fn rfc_5869_test_vector_3() { + let ikm = hex::decode("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b").unwrap(); + let (t1, t2) = derive(&[], &ikm); + + let mut calculated_okm = t1.to_vec(); + calculated_okm.extend_from_slice(&t2); + calculated_okm.truncate(42); + assert_eq!(calculated_okm, hex::decode("8da4e775a563c18f715f802a063c5a31b8a11f5c5ee1879ec3454e5f3c738d2d9d201395faa4b61a96c8").unwrap()); + } +} \ No newline at end of file diff --git a/lightning/src/ln/peers/mod.rs b/lightning/src/ln/peers/mod.rs new file mode 100644 index 00000000000..9acd0039a96 --- /dev/null +++ b/lightning/src/ln/peers/mod.rs @@ -0,0 +1,42 @@ +// This file is Copyright its original authors, visible in version control +// history. +// +// This file is licensed under the Apache License, Version 2.0 or the MIT license +// , at your option. +// You may not use this file except in accordance with one or both of these +// licenses. + +//! Everything that has to do with over-the-wire peer communication. +//! The handshake module exposes mechanisms to conduct inbound and outbound handshakes. +//! When a handshake completes, it returns an instance of CompletedPeerHandshake containing an +//! Encryptor/Decryptor used for encrypted communication and the remote static public key used for +//! identification. + +#[cfg(test)] +#[macro_use] +mod test_util; + +#[cfg(test)] +#[macro_use] +mod test_message_macros; + +mod chacha; +pub mod handler; +mod hkdf5869rfc; +mod outbound_queue; + +#[cfg(feature = "fuzztarget")] +pub mod encryption; +#[cfg(not(feature = "fuzztarget"))] +mod encryption; + +#[cfg(feature = "fuzztarget")] +pub mod handshake; +#[cfg(not(feature = "fuzztarget"))] +mod handshake; + +#[cfg(feature = "fuzztarget")] +pub mod transport; +#[cfg(not(feature = "fuzztarget"))] +mod transport; diff --git a/lightning/src/ln/peers/outbound_queue.rs b/lightning/src/ln/peers/outbound_queue.rs new file mode 100644 index 00000000000..4ad8e8b3da9 --- /dev/null +++ b/lightning/src/ln/peers/outbound_queue.rs @@ -0,0 +1,264 @@ +// This file is Copyright its original authors, visible in version control +// history. +// +// This file is licensed under the Apache License, Version 2.0 or the MIT license +// , at your option. +// You may not use this file except in accordance with one or both of these +// licenses. + +/// Abstracts the buffer used to write data through a SocketDescriptor handling partial writes and +/// flow control. + +use ln::peers::handler::{SocketDescriptor, SocketDescriptorFlusher}; +use ln::peers::transport::PayloadQueuer; +use std::collections::LinkedList; +use std::cmp; + +pub(super) struct OutboundQueue { + blocked: bool, + soft_limit: usize, + buffer: LinkedList>, + buffer_first_msg_offset: usize, +} + +impl PayloadQueuer for OutboundQueue { + /// Unconditionally queue item. May increase queue above soft limit. + fn push_back(&mut self, item: Vec) { + self.buffer.push_back(item); + } + + /// Returns true if the queue is empty + fn is_empty(&self) -> bool { + self.buffer.is_empty() + } + + /// Returns the amount of free space in the queue before the soft limit + fn queue_space(&self) -> usize { + self.soft_limit - cmp::min(self.soft_limit, self.buffer.len()) + } +} + +impl SocketDescriptorFlusher for OutboundQueue { + fn try_flush_one(&mut self, descriptor: &mut impl SocketDescriptor) -> bool { + // Exit early if a previous full write failed and haven't heard that there may be more + // room available + if self.blocked { + return false; + } + + let full_write_succeeded = match self.buffer.front() { + None => true, + Some(next_buff) => { + let should_be_reading = self.buffer.len() < self.soft_limit; + let pending = &next_buff[self.buffer_first_msg_offset..]; + let data_sent = descriptor.send_data(pending, should_be_reading); + self.buffer_first_msg_offset += data_sent; + self.buffer_first_msg_offset == next_buff.len() + } + }; + + if full_write_succeeded { + self.buffer_first_msg_offset = 0; + self.buffer.pop_front(); + } else { + self.blocked = true; + } + + full_write_succeeded + } + + fn unblock(&mut self) { + self.blocked = false; + } + + fn is_blocked(&self) -> bool { + self.blocked + } +} + +impl OutboundQueue { + + /// Create a new writer with a soft limit that is used to notify the SocketDescriptor when + /// it is OK to resume reading if it was paused + pub(super) fn new(soft_limit: usize) -> Self { + Self { + blocked: false, + soft_limit, + buffer: LinkedList::new(), + buffer_first_msg_offset: 0, + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use ln::peers::test_util::*; + + // Test that a try_flush_one() call with no queued data doesn't write anything + #[test] + fn empty_does_not_write() { + let mut descriptor = SocketDescriptorMock::new(); + let mut empty = OutboundQueue::new(10); + + assert!(empty.try_flush_one(&mut descriptor)); + descriptor.assert_called_with(vec![]); + + } + + // Test that try_flush_one() sends the push_back + #[test] + fn push_back_drain() { + let mut descriptor = SocketDescriptorMock::new(); + let mut queue = OutboundQueue::new(10); + + queue.push_back(vec![1]); + assert!(queue.try_flush_one(&mut descriptor)); + + descriptor.assert_called_with(vec![(vec![1], true)]); + } + + // Test that try_flush_one() sends just first push_back + #[test] + fn push_back_push_back_drain_drain() { + let mut descriptor = SocketDescriptorMock::new(); + let mut queue = OutboundQueue::new(10); + + queue.push_back(vec![1]); + queue.push_back(vec![2]); + assert!(queue.try_flush_one(&mut descriptor)); + + descriptor.assert_called_with(vec![(vec![1], true)]); + } + + // Test that descriptor that can't write all bytes returns valid response + #[test] + fn push_back_drain_partial() { + let mut descriptor = SocketDescriptorMock::with_fixed_size(1); + let mut queue = OutboundQueue::new(10); + + queue.push_back(vec![1, 2, 3]); + assert!(!queue.try_flush_one(&mut descriptor)); + + descriptor.assert_called_with(vec![(vec![1, 2, 3], true)]); + } + + // Test the bookkeeping for multiple partial writes + #[test] + fn push_back_drain_partial_drain_partial_try_flush_one() { + let mut descriptor = SocketDescriptorMock::with_fixed_size(1); + let mut queue = OutboundQueue::new(10); + + queue.push_back(vec![1, 2, 3]); + assert!(!queue.try_flush_one(&mut descriptor)); + + descriptor.make_room(1); + queue.unblock(); + assert!(!queue.try_flush_one(&mut descriptor)); + + descriptor.make_room(1); + queue.unblock(); + assert!(queue.try_flush_one(&mut descriptor)); + + descriptor.assert_called_with(vec![(vec![1, 2, 3], true), (vec![2, 3], true), (vec![3], true)]); + } + + #[test] + fn push_back_drain_blocks() { + let mut descriptor = SocketDescriptorMock::with_fixed_size(0); + let mut queue = OutboundQueue::new(10); + + // Fail write and move to blocked state + queue.push_back(vec![1, 2]); + assert!(!queue.try_flush_one(&mut descriptor)); + descriptor.assert_called_with(vec![(vec![1, 2], true)]); + + // Make room but don't signal + descriptor.make_room(1); + assert!(!queue.try_flush_one(&mut descriptor)); + assert!(queue.is_blocked()); + descriptor.assert_called_with(vec![(vec![1, 2], true)]); + + // Unblock and try again + queue.unblock(); + + // Partial write will succeed, but still move to blocked + assert!(!queue.try_flush_one(&mut descriptor)); + assert!(queue.is_blocked()); + descriptor.assert_called_with(vec![(vec![1, 2], true), (vec![1, 2], true)]); + + // Make room and signal which will succeed in writing the final piece + descriptor.make_room(1); + queue.unblock(); + assert!(queue.try_flush_one(&mut descriptor)); + assert!(!queue.is_blocked()); + descriptor.assert_called_with(vec![(vec![1, 2], true), (vec![1, 2], true), (vec![2], true)]); + } + + // Test resume_reading argument to send_data when queue is above soft limit + #[test] + fn push_back_above_limit_resume_reading_false() { + let mut descriptor = SocketDescriptorMock::with_fixed_size(10); + let mut queue = OutboundQueue::new(1); + + queue.push_back(vec![1]); + assert!(queue.try_flush_one(&mut descriptor)); + descriptor.assert_called_with(vec![(vec![1], false)]); + } + + // Test that push_back works above soft limit, but send_read() is informed of the correct state + #[test] + fn push_back_above_limit_is_ok() { + let mut descriptor = SocketDescriptorMock::with_fixed_size(10); + let mut queue = OutboundQueue::new(2); + + queue.push_back(vec![1]); + queue.push_back(vec![2]); + queue.push_back(vec![3]); + assert!(queue.try_flush_one(&mut descriptor)); + assert!(queue.try_flush_one(&mut descriptor)); + assert!(queue.try_flush_one(&mut descriptor)); + descriptor.assert_called_with(vec![(vec![1], false), (vec![2], false), (vec![3], true)]); + } + + // Test is_empty() + #[test] + fn is_empty() { + let mut descriptor = SocketDescriptorMock::with_fixed_size(10); + let mut queue = OutboundQueue::new(1); + assert!(queue.is_empty()); + + queue.push_back(vec![1]); + assert!(!queue.is_empty()); + + assert!(queue.try_flush_one(&mut descriptor)); + assert!(queue.is_empty()); + } + + // Test queue_space() + #[test] + fn queue_space() { + let mut descriptor = SocketDescriptorMock::with_fixed_size(10); + let mut queue = OutboundQueue::new(1); + + // below soft limit + assert_eq!(queue.queue_space(), 1); + + // at soft limit + queue.push_back(vec![1]); + assert_eq!(queue.queue_space(), 0); + + // above soft limit + queue.push_back(vec![2]); + assert_eq!(queue.queue_space(), 0); + + // at soft limit + assert!(queue.try_flush_one(&mut descriptor)); + assert_eq!(queue.queue_space(), 0); + + // below soft limt + assert!(queue.try_flush_one(&mut descriptor)); + assert_eq!(queue.queue_space(), 1); + } +} \ No newline at end of file diff --git a/lightning/src/ln/peers/test_message_macros.rs b/lightning/src/ln/peers/test_message_macros.rs new file mode 100644 index 00000000000..b5751d1511a --- /dev/null +++ b/lightning/src/ln/peers/test_message_macros.rs @@ -0,0 +1,278 @@ +// This file is Copyright its original authors, visible in version control +// history. +// +// This file is licensed under the Apache License, Version 2.0 or the MIT license +// , at your option. +// You may not use this file except in accordance with one or both of these +// licenses. + +/// Helper macros that construct fake Messages. Useful in tests that don't care about the contents. + +macro_rules! fake_public_key { + () => {{ + let their_node_secret = SecretKey::from_slice(&[0x_11_u8; 32]).unwrap(); + PublicKey::from_secret_key(&Secp256k1::new(), &their_node_secret) + }} +} + +macro_rules! fake_valid_sig { + () => {{ + use bitcoin::secp256k1::ffi::Signature as FFISignature; + Signature::from(FFISignature::new()) + }} +} + +macro_rules! fake_open_channel_msg { + () => {{ + OpenChannel { + chain_hash: Default::default(), + temporary_channel_id: [0; 32], + funding_satoshis: 0, + push_msat: 0, + dust_limit_satoshis: 0, + max_htlc_value_in_flight_msat: 0, + channel_reserve_satoshis: 0, + htlc_minimum_msat: 0, + feerate_per_kw: 0, + to_self_delay: 0, + max_accepted_htlcs: 0, + funding_pubkey: fake_public_key!(), + revocation_basepoint: fake_public_key!(), + delayed_payment_basepoint: fake_public_key!(), + htlc_basepoint: fake_public_key!(), + payment_point: fake_public_key!(), + first_per_commitment_point: fake_public_key!(), + channel_flags: 0, + shutdown_scriptpubkey: OptionalField::Absent + } + }} +} + +macro_rules! fake_accept_channel_msg { + () => {{ + AcceptChannel { + temporary_channel_id: [0; 32], + dust_limit_satoshis: 0, + max_htlc_value_in_flight_msat: 0, + channel_reserve_satoshis: 0, + htlc_minimum_msat: 0, + minimum_depth: 0, + to_self_delay: 0, + max_accepted_htlcs: 0, + funding_pubkey: fake_public_key!(), + revocation_basepoint: fake_public_key!(), + payment_point: fake_public_key!(), + delayed_payment_basepoint: fake_public_key!(), + htlc_basepoint: fake_public_key!(), + first_per_commitment_point: fake_public_key!(), + shutdown_scriptpubkey: OptionalField::Absent + } + }} +} +macro_rules! fake_funding_created_msg { + () => {{ + FundingCreated { + temporary_channel_id: [0; 32], + funding_txid: Default::default(), + funding_output_index: 0, + signature: fake_valid_sig!() + } + }} +} + +macro_rules! fake_funding_signed_msg { + () => {{ + FundingSigned { + channel_id: [0; 32], + signature: fake_valid_sig!() + } + }} +} + +macro_rules! fake_funding_locked_msg { + () => {{ + FundingLocked { + channel_id: [0; 32], + next_per_commitment_point: fake_public_key!() + } + }} +} + +macro_rules! fake_shutdown_msg { + () => {{ + Shutdown { + channel_id: [0; 32], + scriptpubkey: Default::default() + } + }} +} + +macro_rules! fake_closing_signed_msg { + () => {{ + ClosingSigned { + channel_id: [0; 32], + fee_satoshis: 0, + signature: fake_valid_sig!() + } + }} +} + +macro_rules! fake_update_add_htlc_msg { + () => {{ + UpdateAddHTLC { + channel_id: [0; 32], + htlc_id: 0, + amount_msat: 0, + payment_hash: PaymentHash([0; 32]), + cltv_expiry: 0, + onion_routing_packet: OnionPacket { + version: 0, + public_key: Ok(fake_public_key!()), + hop_data: [0; 1300], + hmac: [0; 32] + } + } + }} +} + +macro_rules! fake_update_fulfill_htlc_msg { + () => {{ + UpdateFulfillHTLC { + channel_id: [0; 32], + htlc_id: 0, + payment_preimage: PaymentPreimage([0; 32]) + } + }} +} + + +macro_rules! fake_update_fail_htlc_msg { + () => {{ + UpdateFailHTLC { + channel_id: [0; 32], + htlc_id: 0, + reason: OnionErrorPacket { data: vec![] } + } + }} +} + +macro_rules! fake_update_fail_malformed_htlc_msg { + () => { + UpdateFailMalformedHTLC { + channel_id: [0; 32], + htlc_id: 0, + sha256_of_onion: [0; 32], + failure_code: 0 + } + } +} + +macro_rules! fake_commitment_signed_msg { + () => {{ + CommitmentSigned { + channel_id: [0; 32], + signature: fake_valid_sig!(), + htlc_signatures: vec![] + } + }} +} + +macro_rules! fake_revoke_and_ack_msg { + () => {{ + RevokeAndACK { + channel_id: [0; 32], + per_commitment_secret: [0; 32], + next_per_commitment_point: fake_public_key!() + } + }} +} +macro_rules! fake_update_fee_msg { + () => {{ + UpdateFee { + channel_id: [0; 32], + feerate_per_kw: 0 + } + }} +} + +macro_rules! fake_channel_reestablish_msg { + () => {{ + ChannelReestablish { + channel_id: [0; 32], + next_local_commitment_number: 0, + next_remote_commitment_number: 0, + data_loss_protect: OptionalField::Absent + } + }} +} + +macro_rules! fake_announcement_signatures_msg { + () => {{ + AnnouncementSignatures { + channel_id: [0;32], + short_channel_id: 0, + node_signature: fake_valid_sig!(), + bitcoin_signature: fake_valid_sig!() + } + }} +} + +macro_rules! fake_channel_announcement_msg { + ($channel_id: expr, $node_id_1: expr, $node_id_2: expr) => {{ + ChannelAnnouncement { + node_signature_1: fake_valid_sig!(), + node_signature_2: fake_valid_sig!(), + bitcoin_signature_1: fake_valid_sig!(), + bitcoin_signature_2: fake_valid_sig!(), + contents: UnsignedChannelAnnouncement { + features: ChannelFeatures::empty(), + chain_hash: Default::default(), + short_channel_id: $channel_id, + node_id_1: $node_id_1, + node_id_2: $node_id_2, + bitcoin_key_1: fake_public_key!(), + bitcoin_key_2: fake_public_key!(), + excess_data: vec![] + } + } + }} +} + +macro_rules! fake_node_announcement_msg { + () => {{ + NodeAnnouncement { + signature: fake_valid_sig!(), + contents: UnsignedNodeAnnouncement { + features: NodeFeatures::empty(), + timestamp: 0, + node_id: fake_public_key!(), + rgb: [0; 3], + alias: [0; 32], + addresses: vec![], + excess_address_data: vec![], + excess_data: vec![] + } + } + }} +} + +macro_rules! fake_channel_update_msg { + () => {{ + ChannelUpdate { + signature: fake_valid_sig!(), + contents: UnsignedChannelUpdate { + chain_hash: Default::default(), + short_channel_id: 0, + timestamp: 0, + flags: 0, + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: OptionalField::Absent, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: vec![] + } + } + }} +} diff --git a/lightning/src/ln/peers/test_util.rs b/lightning/src/ln/peers/test_util.rs new file mode 100644 index 00000000000..fc824f17466 --- /dev/null +++ b/lightning/src/ln/peers/test_util.rs @@ -0,0 +1,391 @@ +// This file is Copyright its original authors, visible in version control +// history. +// +// This file is licensed under the Apache License, Version 2.0 or the MIT license +// , at your option. +// You may not use this file except in accordance with one or both of these +// licenses. + +/// Test library for test doubles used in the various peers unit tests + +use bitcoin::secp256k1; +use bitcoin::secp256k1::key::{PublicKey, SecretKey}; + +use ln::peers::encryption::{create_encryptor_decryptor}; +use ln::peers::handler::{SocketDescriptor, ITransport, PeerHandleError, MessageQueuer}; +use ln::peers::handshake::CompletedHandshakeInfo; +use ln::peers::transport::{IPeerHandshake, PayloadQueuer}; + +use std::rc::Rc; +use std::cell::{RefCell}; +use std::hash::Hash; +use std::cmp; +use ln::wire::{Message, Encode}; +use bitcoin::hashes::core::ops::Deref; +use util::logger::Logger; +use util::ser::{Writeable, VecWriter}; +use ln::wire; + +macro_rules! assert_matches { + ($actual:expr, $expected:pat) => { + match $actual { + $expected => (), + _ => panic!() + } + } +} + +/// Stub implementation of IPeerHandshake that returns an error for process_act() +pub(super) struct PeerHandshakeTestStubFail { } + +impl IPeerHandshake for PeerHandshakeTestStubFail { + fn new_outbound(_initiator_static_private_key: &SecretKey, _responder_static_public_key: &PublicKey, _initiator_ephemeral_private_key: &SecretKey) -> Self { + PeerHandshakeTestStubFail { } + } + + fn set_up_outbound(&mut self) -> Vec { + vec![] + } + + fn new_inbound(_responder_static_private_key: &SecretKey, _responder_ephemeral_private_key: &SecretKey) -> Self { + PeerHandshakeTestStubFail { } + } + + fn process_act(&mut self, _input: &[u8]) -> Result<(Option>, Option), String> { + Err("Oh no!".to_string()) + } +} + +/// Stub implementation of IPeerHandshake that returns &[1] from process_act() +pub(super) struct PeerHandshakeTestStubBytes { } + +impl PeerHandshakeTestStubBytes { + pub(crate) const RETURNED_BYTES: [u8; 1] = [1]; +} + +impl IPeerHandshake for PeerHandshakeTestStubBytes { + + fn new_outbound(_initiator_static_private_key: &SecretKey, _responder_static_public_key: &PublicKey, _initiator_ephemeral_private_key: &SecretKey) -> Self { + PeerHandshakeTestStubBytes { } + } + + fn set_up_outbound(&mut self) -> Vec { + vec![] + } + + fn new_inbound(_responder_static_private_key: &SecretKey, _responder_ephemeral_private_key: &SecretKey) -> Self { + PeerHandshakeTestStubBytes { } + } + + fn process_act(&mut self, _input: &[u8]) -> Result<(Option>, Option), String> { + Ok((Some(Self::RETURNED_BYTES[..].to_vec()), None)) + } +} + +/// Stub implementation of IPeerhandshake that returns Some(CompletedHandshakeInfo) +pub(super) struct PeerHandshakeTestStubComplete { } + +impl IPeerHandshake for PeerHandshakeTestStubComplete { + fn new_outbound(_initiator_static_private_key: &SecretKey, _responder_static_public_key: &PublicKey, _initiator_ephemeral_private_key: &SecretKey) -> Self { + PeerHandshakeTestStubComplete { } + } + + fn set_up_outbound(&mut self) -> Vec { + vec![] + } + + fn new_inbound(_responder_static_private_key: &SecretKey, _responder_ephemeral_private_key: &SecretKey) -> Self { + PeerHandshakeTestStubComplete { } + } + + fn process_act(&mut self, _input: &[u8]) -> Result<(Option>, Option), String> { + let curve = secp256k1::Secp256k1::new(); + let private_key = SecretKey::from_slice(&[0x_21_u8; 32]).unwrap(); + let public_key = PublicKey::from_secret_key(&curve, &private_key); + let (encryptor, decryptor) = create_encryptor_decryptor([0;32], [0;32], [0;32]); + + Ok((None, Some( + CompletedHandshakeInfo { + decryptor, + encryptor, + their_node_id: public_key + } + ))) + } +} + +/// Mock implementation of the SocketDescriptor trait that can be used in tests to finely control +/// the send_data() behavior. +/// +/// Additionally, records the actual calls to send_data() for later validation. +#[derive(Debug, Eq)] +pub(super) struct SocketDescriptorMock { + /// If true, all send_data() calls will succeed + unbounded: Rc>, + + /// Amount of free space in the descriptor for send_data() bytes + free_space: Rc>, + + /// Vector of arguments and return values to send_data() used for validation + send_recording: Rc, bool)>>>, + + /// Record if disconnect() was called on the Mock + disconnect_called: Rc>, +} + +impl SocketDescriptorMock { + /// Basic unbounded implementation where send_data() will always succeed + pub(super) fn new() -> Self { + Self { + unbounded: Rc::new(RefCell::new(true)), + send_recording: Rc::new(RefCell::new(Vec::new())), + free_space: Rc::new(RefCell::new(0)), + disconnect_called: Rc::new(RefCell::new(false)) + } + } + + /// Used for tests that want to return partial sends after a certain amount of data is sent through send_data() + pub(super) fn with_fixed_size(limit: usize) -> Self { + let mut descriptor = Self::new(); + descriptor.unbounded = Rc::new(RefCell::new(false)); + descriptor.free_space = Rc::new(RefCell::new(limit)); + + descriptor + } + + /// Standard Mock api to verify actual vs. expected calls + pub(super) fn assert_called_with(&self, expectation: Vec<(Vec, bool)>) { + assert_eq!(expectation.as_slice(), self.send_recording.borrow().as_slice()) + } + + /// Retrieve the underlying recording for use in pattern matching or more complex value validation + pub(super) fn get_recording(&self) -> Vec<(Vec, bool)> { + self.send_recording.borrow().clone() + } + + pub(super) fn disconnect_called(&self) -> bool { + *self.disconnect_called.borrow_mut() + } + + /// Allow future send_data() calls to succeed for the next added_room bytes. Not valid for + /// unbounded mock descriptors + pub(super) fn make_room(&mut self, added_room: usize) { + assert!(!*self.unbounded.borrow()); + let mut free_space = self.free_space.borrow_mut(); + + *free_space += added_room; + } + + /// Clear the saved recording. Useful for resetting state between test phases. + pub(super) fn clear_recording(&mut self) { + self.send_recording.borrow_mut().clear(); + } +} + +impl SocketDescriptor for SocketDescriptorMock { + fn send_data(&mut self, data: &[u8], resume_read: bool) -> usize { + self.send_recording.borrow_mut().push((data.to_vec(), resume_read)); + + let mut free_space = self.free_space.borrow_mut(); + + // Unbounded just flush everything + return if *self.unbounded.borrow() { + data.len() + } + // Bounded flush up to the free_space limit + else { + let write_len = cmp::min(data.len(), *free_space); + *free_space -= write_len; + write_len + } + } + + fn disconnect_socket(&mut self) { + let mut val = self.disconnect_called.borrow_mut(); + assert!(!*val, "disconnect_socket() was alraedy called"); + *val = true; + } +} + +impl Clone for SocketDescriptorMock { + fn clone(&self) -> Self { + Self { + unbounded: self.unbounded.clone(), + send_recording: self.send_recording.clone(), + free_space: self.free_space.clone(), + disconnect_called: self.disconnect_called.clone(), + } + } +} + +impl PartialEq for SocketDescriptorMock { + fn eq(&self, o: &Self) -> bool { + Rc::ptr_eq(&self.send_recording, &o.send_recording) + } +} +impl Hash for SocketDescriptorMock { + fn hash(&self, state: &mut H) { + self.send_recording.as_ptr().hash(state) + } +} + +/// Implement PayloadQueuer for Vec> so it can be used as a Spy in tests +impl PayloadQueuer for Vec> { + fn push_back(&mut self, item: Vec) { + self.push(item) + } + + fn is_empty(&self) -> bool { + self.is_empty() + } + + fn queue_space(&self) -> usize { + unimplemented!() + } +} + +// Builder for TransportTestStub that allows tests to easily construct the Transport layer they +// want to use for their test. +pub(super) struct TransportStubBuilder { + stub: TransportStub, +} + +impl TransportStubBuilder { + pub(super) fn new() -> Self { + Self { + stub: TransportStub { + is_connected: false, + messages: vec![], + process_returns_error: false, + returned_newly_connected: false, + their_node_id: None, + } + } + } + + pub(super) fn set_connected(mut self, their_node_id: &PublicKey) -> Self { + self.stub.is_connected = true; + self.stub.their_node_id = Some(their_node_id.clone()); + self + } + + pub(super) fn process_returns_error(mut self) -> Self { + self.stub.process_returns_error(); + self + } + + pub(super) fn finish(self) -> TransportStub { + self.stub + } +} + +pub(super) struct TransportStub { + is_connected: bool, + messages: Vec, + process_returns_error: bool, + returned_newly_connected: bool, + their_node_id: Option, +} + +// &RefCell passthrough to allow unit tests to pass in a Transport to the PeerManager, but later +// modify it to fail, return messages, etc. +impl<'a> ITransport for &'a RefCell { + fn new_outbound(_initiator_static_private_key: &SecretKey, _responder_static_public_key: &PublicKey, _initiator_ephemeral_private_key: &SecretKey) -> Self { + unimplemented!() + } + + fn set_up_outbound(&mut self) -> Vec { + self.borrow_mut().set_up_outbound() + } + + fn new_inbound(_responder_static_private_key: &SecretKey, _responder_ephemeral_private_key: &SecretKey) -> Self { + unimplemented!() + } + + fn process_input(&mut self, input: &[u8], output_buffer: &mut impl PayloadQueuer) -> Result { + self.borrow_mut().process_input(input, output_buffer) + } + + fn is_connected(&self) -> bool { + self.borrow().is_connected() + } + + fn get_their_node_id(&self) -> PublicKey { + self.borrow().get_their_node_id() + } + + fn drain_messages(&mut self, logger: L) -> Result, PeerHandleError> where L::Target: Logger { + self.borrow_mut().drain_messages(logger) + } +} + +impl<'a> MessageQueuer for &'a RefCell { + fn enqueue_message(&mut self, message: &M, output_buffer: &mut Q, logger: L) where L::Target: Logger { + self.borrow_mut().enqueue_message(message, output_buffer, logger) + } +} + +impl TransportStub { + pub(super) fn process_returns_error(&mut self) { + self.process_returns_error = true; + } + + pub(super) fn add_incoming_message(&mut self, message: Message) { + assert!(self.is_connected, "Can't set messages on unconnected Transport"); + self.messages.push(message); + } +} + +// Stub implementation for ITransport with a fixed connection state. All enqueue_message() calls +// are placed directly into the PayloadQueuer unencrypted for easier test validation. +impl ITransport for TransportStub { + fn new_outbound(_initiator_static_private_key: &SecretKey, _responder_static_public_key: &PublicKey, _initiator_ephemeral_private_key: &SecretKey) -> Self { + unimplemented!() + } + + fn set_up_outbound(&mut self) -> Vec { + vec![] + } + + fn new_inbound(_responder_static_private_key: &SecretKey, _responder_ephemeral_private_key: &SecretKey) -> Self { + unimplemented!() + } + + fn process_input(&mut self, _input: &[u8], _output_buffer: &mut impl PayloadQueuer) -> Result { + if self.process_returns_error { + Err("Oh no!".to_string()) + } else { + if self.is_connected() { + + // Simulate the newly_connected behavior by returning Ok(true) on the first call + if !self.returned_newly_connected { + self.returned_newly_connected = true; + return Ok(true) + } + } + return Ok(false) + } + } + + fn is_connected(&self) -> bool { + self.their_node_id.is_some() + } + + fn get_their_node_id(&self) -> PublicKey { + self.their_node_id.unwrap() + } + + fn drain_messages(&mut self, _logger: L) -> Result, PeerHandleError> where L::Target: Logger { + Ok(self.messages.drain(..).collect()) + } +} + +impl MessageQueuer for TransportStub { + fn enqueue_message(&mut self, message: &M, output_buffer: &mut Q, _logger: L) + where L::Target: Logger { + let mut buffer = VecWriter(Vec::new()); + wire::write(message, &mut buffer).unwrap(); + output_buffer.push_back(buffer.0); + } +} \ No newline at end of file diff --git a/lightning/src/ln/peers/transport.rs b/lightning/src/ln/peers/transport.rs new file mode 100644 index 00000000000..68b284db0ba --- /dev/null +++ b/lightning/src/ln/peers/transport.rs @@ -0,0 +1,390 @@ +// This file is Copyright its original authors, visible in version control +// history. +// +// This file is licensed under the Apache License, Version 2.0 or the MIT license +// , at your option. +// You may not use this file except in accordance with one or both of these +// licenses. + +/// Abstraction for the transport layer as described by Bolt #8 [https://github.com/lightningnetwork/lightning-rfc/blob/master/08-transport.md] + +use bitcoin::secp256k1::{SecretKey, PublicKey}; + +use ln::peers::handler::{ITransport, PeerHandleError, MessageQueuer}; +use ln::peers::handshake::{CompletedHandshakeInfo, PeerHandshake}; +use ln::{wire, msgs}; +use ln::wire::{Encode, Message}; + +use util::ser::{Writeable, VecWriter}; +use util::logger::Logger; +use std::ops::Deref; + +/// Interface used by Transport to interact with a handshake object +pub trait IPeerHandshake { + /// Instantiate a new outbound handshake + fn new_outbound(initiator_static_private_key: &SecretKey, responder_static_public_key: &PublicKey, initiator_ephemeral_private_key: &SecretKey) -> Self; + + /// Set up the handshake receiving any bytes that need to be sent to the peer + fn set_up_outbound(&mut self) -> Vec; + + /// Instantiate a new inbound handshake + fn new_inbound(responder_static_private_key: &SecretKey, responder_ephemeral_private_key: &SecretKey) -> Self; + + /// Progress the handshake given bytes received from the peer. Returns Some(CompletedHandshakeInfo) when the handshake + /// is complete. + fn process_act(&mut self, input: &[u8]) -> Result<(Option>, Option), String>; +} + +/// Trait representing a container that allows enqueuing of Vec<[u8]> +pub(super) trait PayloadQueuer { + /// Enqueue item to the queue + fn push_back(&mut self, item: Vec); + + /// Returns true if the queue is empty + fn is_empty(&self) -> bool; + + /// Returns the amount of available space in queue + fn queue_space(&self) -> usize; +} + +pub(super) struct Transport { + handshake: PeerHandshakeImpl, + completed_handshake_info: Option +} + +impl ITransport for Transport { + fn new_outbound(initiator_static_private_key: &SecretKey, responder_static_public_key: &PublicKey, initiator_ephemeral_private_key: &SecretKey) -> Self { + Self { + completed_handshake_info: None, + handshake: PeerHandshakeImpl::new_outbound(initiator_static_private_key, responder_static_public_key, initiator_ephemeral_private_key), + } + } + + fn set_up_outbound(&mut self) -> Vec { + self.handshake.set_up_outbound().to_vec() + } + + fn new_inbound(responder_static_private_key: &SecretKey, responder_ephemeral_private_key: &SecretKey) -> Self { + Self { + completed_handshake_info: None, + handshake: PeerHandshakeImpl::new_inbound(responder_static_private_key, responder_ephemeral_private_key), + } + } + + fn process_input(&mut self, input: &[u8], output_buffer: &mut impl PayloadQueuer) -> Result { + match self.completed_handshake_info { + // Continue handshake + None => { + let (response_option, completed_handshake_info_option) = self.handshake.process_act(input)?; + + // Any response generated by the handshake sequence is put into the response buffer + if let Some(response) = response_option { + output_buffer.push_back(response.to_vec()); + } + + // If handshake is complete change the state + if let Some(completed_handshake_info) = completed_handshake_info_option { + self.completed_handshake_info = Some(completed_handshake_info); + Ok(true) // newly connected + } else { + Ok(false) // newly connected + } + } + Some(ref mut completed_handshake_info) => { + completed_handshake_info.decryptor.read(input)?; + Ok(false) // newly connected + } + } + } + + fn drain_messages(&mut self, logger: L) -> Result, PeerHandleError> + where L::Target: Logger { + + let mut received_messages = vec![]; + + match self.completed_handshake_info { + None => {} + Some(ref mut completed_handshake_info) => { + for msg_data in &mut completed_handshake_info.decryptor { + let mut reader = ::std::io::Cursor::new(&msg_data[..]); + let message_result = wire::read(&mut reader); + let message = match message_result { + Ok(x) => x, + Err(e) => { + match e { + msgs::DecodeError::UnknownVersion => return Err(PeerHandleError { no_connection_possible: false }), + msgs::DecodeError::UnknownRequiredFeature => { + log_debug!(logger, "Got a channel/node announcement with an known required feature flag, you may want to update!"); + continue; + } + msgs::DecodeError::InvalidValue => { + log_debug!(logger, "Got an invalid value while deserializing message"); + return Err(PeerHandleError { no_connection_possible: false }); + } + msgs::DecodeError::ShortRead => { + log_debug!(logger, "Deserialization failed due to shortness of message"); + return Err(PeerHandleError { no_connection_possible: false }); + } + msgs::DecodeError::BadLengthDescriptor => return Err(PeerHandleError { no_connection_possible: false }), + msgs::DecodeError::Io(_) => return Err(PeerHandleError { no_connection_possible: false }), + } + } + }; + + received_messages.push(message); + } + } + } + + Ok(received_messages) + } + + fn is_connected(&self) -> bool { + self.completed_handshake_info.is_some() + } + + fn get_their_node_id(&self) -> PublicKey { + assert!(self.is_connected(), "Retrieving the remote node_id is only supported after transport is connected"); + self.completed_handshake_info.as_ref().unwrap().their_node_id + } +} + +impl MessageQueuer for Transport { + fn enqueue_message(&mut self, message: &M, output_buffer: &mut Q, logger: L) + where L::Target: Logger { + + match self.completed_handshake_info { + None => panic!("Enqueueing messages only supported after transport is connected"), + Some(ref mut completed_handshake_info) => { + log_trace!(logger, "Enqueueing message of type {} to {}", message.type_id(), log_pubkey!(completed_handshake_info.their_node_id)); + + let mut buffer = VecWriter(Vec::new()); + wire::write(message, &mut buffer).unwrap(); + output_buffer.push_back(completed_handshake_info.encryptor.encrypt(&buffer.0)); + } + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use ln::peers::test_util::*; + + use bitcoin::secp256k1; + use bitcoin::secp256k1::key::{PublicKey, SecretKey}; + use ln::msgs; + use util::test_utils::TestLogger; + + fn create_outbound_for_test() -> Transport { + let curve = secp256k1::Secp256k1::new(); + let outbound_static_private_key = SecretKey::from_slice(&[0x_11_u8; 32]).unwrap(); + let outbound_ephemeral_private_key = SecretKey::from_slice(&[0x_12_u8; 32]).unwrap(); + let inbound_static_private_key = SecretKey::from_slice(&[0x_21_u8; 32]).unwrap(); + let inbound_static_public_key = PublicKey::from_secret_key(&curve, &inbound_static_private_key); + + Transport::::new_outbound(&outbound_static_private_key, &inbound_static_public_key, &outbound_ephemeral_private_key) + } + + fn create_inbound_for_test() -> Transport { + let inbound_static_private_key = SecretKey::from_slice(&[0x_21_u8; 32]).unwrap(); + let inbound_ephemeral_private_key = SecretKey::from_slice(&[0x_22_u8; 32]).unwrap(); + + Transport::::new_inbound(&inbound_static_private_key, &inbound_ephemeral_private_key) + } + + // Test initial states start off unconnected + #[test] + fn inbound_unconnected() { + let transport = create_inbound_for_test::(); + + assert!(!transport.is_connected()); + } + + #[test] + fn outbound_unconnected() { + let mut transport = create_outbound_for_test::(); + transport.set_up_outbound(); + + assert!(!transport.is_connected()); + } + + // Test that errors in the handshake code are reraised through the transport + #[test] + fn inbound_handshake_error_reraises() { + let mut transport = create_inbound_for_test::(); + let mut spy = Vec::new(); + + assert_eq!(transport.process_input(&[], &mut spy).err(), Some("Oh no!".to_string())); + } + + #[test] + fn outbound_handshake_error_reraises() { + let mut transport = create_outbound_for_test::(); + let mut spy = Vec::new(); + + assert_eq!(transport.process_input(&[], &mut spy).err(), Some("Oh no!".to_string())); + } + + #[test] + fn inbound_handshake_data_goes_to_queue() { + let mut transport = create_inbound_for_test::(); + let mut spy = Vec::new(); + + assert_eq!(transport.process_input(&[], &mut spy), Ok(false)); + assert!(!transport.is_connected()); + + assert_matches!(&spy[..], [_]); + } + + // Test that data returned from the in-progress handshake code makes it through to the outbound buffer + #[test] + fn outbound_handshake_data_goes_to_queue() { + let mut transport = create_outbound_for_test::(); + let mut spy = Vec::new(); + + assert_eq!(transport.process_input(&[], &mut spy), Ok(false)); + assert!(!transport.is_connected()); + + assert_matches!(&spy[..], [_]); + } + + #[test] + fn inbound_handshake_complete_ready_for_encryption() { + let mut transport = create_inbound_for_test::(); + let mut spy = Vec::new(); + + assert_eq!(transport.process_input(&[], &mut spy), Ok(true)); + assert!(transport.is_connected()); + } + + // Test get_their_node_id() in unconnected and connected scenarios + #[test] + #[should_panic(expected = "Retrieving the remote node_id is only supported after transport is connected")] + fn inbound_unconnected_get_their_node_id_panics() { + let transport = create_inbound_for_test::(); + + let _should_panic = transport.get_their_node_id(); + } + + #[test] + #[should_panic(expected = "Retrieving the remote node_id is only supported after transport is connected")] + fn outbound_unconnected_get_their_node_id_panics() { + let mut transport = create_outbound_for_test::(); + transport.set_up_outbound(); + + let _should_panic = transport.get_their_node_id(); + } + + #[test] + fn inbound_unconnected_get_their_node_id() { + let mut transport = create_inbound_for_test::(); + let mut spy = Vec::new(); + + assert_eq!(transport.process_input(&[], &mut spy), Ok(true)); + let _no_panic = transport.get_their_node_id(); + } + + #[test] + fn outbound_unconnected_get_their_node_id() { + let mut transport = create_inbound_for_test::(); + let mut spy = Vec::new(); + + assert_eq!(transport.process_input(&[], &mut spy), Ok(true)); + let _no_panic = transport.get_their_node_id(); + } + + // Test that when a handshake completes is_connected() is correct + #[test] + fn outbound_handshake_complete_ready_for_encryption() { + let mut transport = create_outbound_for_test::(); + let mut spy = Vec::new(); + + assert_eq!(transport.process_input(&[], &mut spy), Ok(true)); + assert!(transport.is_connected()); + let _no_panic = transport.get_their_node_id(); + } + + #[test] + #[should_panic(expected = "Enqueueing messages only supported after transport is connected")] + fn inbound_enqueue_message_panic() { + let logger = TestLogger::new(); + let mut transport = create_inbound_for_test::(); + let mut spy = Vec::new(); + + let ping = msgs::Ping { + ponglen: 0, + byteslen: 64, + }; + transport.enqueue_message(&ping, &mut spy, &logger); + } + + // Test that enqueue_message() panics in the wrong state + #[test] + #[should_panic(expected = "Enqueueing messages only supported after transport is connected")] + fn outbound_enqueue_message_panic() { + let logger = TestLogger::new(); + let mut transport = create_outbound_for_test::(); + let mut spy = Vec::new(); + + let ping = msgs::Ping { + ponglen: 0, + byteslen: 64, + }; + transport.enqueue_message(&ping, &mut spy, &logger); + } + + // Test that enqueue_message() puts something into the outbound buffer + #[test] + fn inbound_enqueue_message_encrypts() { + let logger = TestLogger::new(); + let mut transport = create_inbound_for_test::(); + let mut spy = Vec::new(); + + assert_eq!(transport.process_input(&[], &mut spy), Ok(true)); + + let ping = msgs::Ping { + ponglen: 0, + byteslen: 64, + }; + transport.enqueue_message(&ping, &mut spy, &logger); + + assert_matches!(&spy[..], [_]); + } + + #[test] + fn outbound_enqueue_message_encrypts() { + let logger = TestLogger::new(); + let mut transport = create_outbound_for_test::(); + let mut spy = Vec::new(); + + assert_eq!(transport.process_input(&[], &mut spy), Ok(true)); + + let ping = msgs::Ping { + ponglen: 0, + byteslen: 64, + }; + transport.enqueue_message(&ping, &mut spy, &logger); + + assert_matches!(&spy[..], [_]); + } + + #[test] + fn inbound_not_connected_empty() { + let logger = TestLogger::new(); + let mut transport = create_inbound_for_test::(); + + let messages = transport.drain_messages(&logger).unwrap(); + assert_eq!(messages.len(), 0); + } + + #[test] + fn outbound_not_connected_empty() { + let logger = TestLogger::new(); + let mut transport = create_outbound_for_test::(); + + let messages = transport.drain_messages(&logger).unwrap(); + assert_eq!(messages.len(), 0); + } +} \ No newline at end of file diff --git a/lightning/src/ln/wire.rs b/lightning/src/ln/wire.rs index 86d8bfdd494..432619bd659 100644 --- a/lightning/src/ln/wire.rs +++ b/lightning/src/ln/wire.rs @@ -61,7 +61,7 @@ pub enum Message { /// A number identifying a message to determine how it is encoded on the wire. #[derive(Clone, Copy)] -pub struct MessageType(u16); +pub struct MessageType(pub u16); impl Message { /// Returns the type that was used to decode the message payload. diff --git a/lightning/src/util/test_utils.rs b/lightning/src/util/test_utils.rs index bdd4620cb3f..83dff2efa31 100644 --- a/lightning/src/util/test_utils.rs +++ b/lightning/src/util/test_utils.rs @@ -14,7 +14,7 @@ use chain::keysinterface; use ln::channelmonitor; use ln::features::{ChannelFeatures, InitFeatures}; use ln::msgs; -use ln::msgs::OptionalField; +use ln::msgs::*; use ln::channelmonitor::MonitorEvent; use util::enforcing_trait_impls::EnforcingChannelKeys; use util::events; @@ -142,6 +142,144 @@ impl chaininterface::BroadcasterInterface for TestBroadcaster { } } +/// Test Spy infrastructure for the ChannelMessageHandler trait that tests can use to validate +/// the correct callbacks were called. +macro_rules! generate_message_handler_called_fns { + ($($name: ident,)*) => { + pub struct ChannelMessageHandlerTestSpyCalledFns { + $( + pub $name: bool, + )* + } + impl ChannelMessageHandlerTestSpyCalledFns { + pub fn new() -> Self { + Self { + $( + $name: false, + )* + } + } + } + } +} +generate_message_handler_called_fns! { + handle_open_channel, + handle_accept_channel, + handle_funding_created, + handle_funding_signed, + handle_funding_locked, + handle_shutdown, + handle_closing_signed, + handle_update_add_htlc, + handle_update_fulfill_htlc, + handle_update_fail_htlc, + handle_update_fail_malformed_htlc, + handle_commitment_signed, + handle_revoke_and_ack, + handle_update_fee, + handle_announcement_signatures, + handle_channel_reestablish, + handle_error, + peer_connected, + peer_disconnected, +} + +pub struct ChannelMessageHandlerTestSpy { + pub called: Mutex +} + +impl ChannelMessageHandlerTestSpy { + pub fn new() -> Self { + Self { + called: Mutex::new(ChannelMessageHandlerTestSpyCalledFns::new()) + } + } +} + +impl msgs::ChannelMessageHandler for ChannelMessageHandlerTestSpy { + fn handle_open_channel(&self, _their_node_id: &PublicKey, _their_features: InitFeatures, _msg: &OpenChannel) { + self.called.lock().unwrap().handle_open_channel = true; + } + + fn handle_accept_channel(&self, _their_node_id: &PublicKey, _their_features: InitFeatures, _msg: &AcceptChannel) { + self.called.lock().unwrap().handle_accept_channel = true; + } + + fn handle_funding_created(&self, _their_node_id: &PublicKey, _msg: &FundingCreated) { + self.called.lock().unwrap().handle_funding_created = true; + } + + fn handle_funding_signed(&self, _their_node_id: &PublicKey, _msg: &FundingSigned) { + self.called.lock().unwrap().handle_funding_signed = true; + } + + fn handle_funding_locked(&self, _their_node_id: &PublicKey, _msg: &FundingLocked) { + self.called.lock().unwrap().handle_funding_locked = true; + } + + fn handle_shutdown(&self, _their_node_id: &PublicKey, _msg: &Shutdown) { + self.called.lock().unwrap().handle_shutdown = true; + } + + fn handle_closing_signed(&self, _their_node_id: &PublicKey, _msg: &ClosingSigned) { + self.called.lock().unwrap().handle_closing_signed = true; + } + + fn handle_update_add_htlc(&self, _their_node_id: &PublicKey, _msg: &UpdateAddHTLC) { + self.called.lock().unwrap().handle_update_add_htlc = true; + } + + fn handle_update_fulfill_htlc(&self, _their_node_id: &PublicKey, _msg: &UpdateFulfillHTLC) { + self.called.lock().unwrap().handle_update_fulfill_htlc = true; + } + + fn handle_update_fail_htlc(&self, _their_node_id: &PublicKey, _msg: &UpdateFailHTLC) { + self.called.lock().unwrap().handle_update_fail_htlc = true; + } + + fn handle_update_fail_malformed_htlc(&self, _their_node_id: &PublicKey, _msg: &UpdateFailMalformedHTLC) { + self.called.lock().unwrap().handle_update_fail_malformed_htlc = true; + } + + fn handle_commitment_signed(&self, _their_node_id: &PublicKey, _msg: &CommitmentSigned) { + self.called.lock().unwrap().handle_commitment_signed = true; + } + + fn handle_revoke_and_ack(&self, _their_node_id: &PublicKey, _msg: &RevokeAndACK) { + self.called.lock().unwrap().handle_revoke_and_ack = true; + } + + fn handle_update_fee(&self, _their_node_id: &PublicKey, _msg: &UpdateFee) { + self.called.lock().unwrap().handle_update_fee = true; + } + + fn handle_announcement_signatures(&self, _their_node_id: &PublicKey, _msg: &AnnouncementSignatures) { + self.called.lock().unwrap().handle_announcement_signatures = true; + } + + fn peer_disconnected(&self, _their_node_id: &PublicKey, _no_connection_possible: bool) { + self.called.lock().unwrap().peer_disconnected = true; + } + + fn peer_connected(&self, _their_node_id: &PublicKey, _msg: &Init) { + self.called.lock().unwrap().peer_connected = true; + } + + fn handle_channel_reestablish(&self, _their_node_id: &PublicKey, _msg: &ChannelReestablish) { + self.called.lock().unwrap().handle_channel_reestablish = true; + } + + fn handle_error(&self, _their_node_id: &PublicKey, _msg: &ErrorMessage) { + self.called.lock().unwrap().handle_error = true; + } +} + +impl events::MessageSendEventsProvider for ChannelMessageHandlerTestSpy { + fn get_and_clear_pending_msg_events(&self) -> Vec { + vec![] + } +} + pub struct TestChannelMessageHandler { pub pending_events: Mutex>, } @@ -185,6 +323,91 @@ impl events::MessageSendEventsProvider for TestChannelMessageHandler { } } +// &TestChannelMessageHandler passthroughs so TypeParameters can be either a value or ref in test object containers +impl<'a> ChannelMessageHandler for &'a TestChannelMessageHandler { + fn handle_open_channel(&self, their_node_id: &PublicKey, their_features: InitFeatures, msg: &OpenChannel) { + TestChannelMessageHandler::handle_open_channel(self, their_node_id, their_features, msg); + } + + fn handle_accept_channel(&self, their_node_id: &PublicKey, their_features: InitFeatures, msg: &AcceptChannel) { + TestChannelMessageHandler::handle_accept_channel(self, their_node_id, their_features, msg); + } + + fn handle_funding_created(&self, their_node_id: &PublicKey, msg: &FundingCreated) { + TestChannelMessageHandler::handle_funding_created(self, their_node_id, msg); + } + + fn handle_funding_signed(&self, their_node_id: &PublicKey, msg: &FundingSigned) { + TestChannelMessageHandler::handle_funding_signed(self, their_node_id, msg); + } + + fn handle_funding_locked(&self, their_node_id: &PublicKey, msg: &FundingLocked) { + TestChannelMessageHandler::handle_funding_locked(self, their_node_id, msg); + } + + fn handle_shutdown(&self, their_node_id: &PublicKey, msg: &Shutdown) { + TestChannelMessageHandler::handle_shutdown(self, their_node_id, msg); + } + + fn handle_closing_signed(&self, their_node_id: &PublicKey, msg: &ClosingSigned) { + TestChannelMessageHandler::handle_closing_signed(self, their_node_id, msg); + } + + fn handle_update_add_htlc(&self, their_node_id: &PublicKey, msg: &UpdateAddHTLC) { + TestChannelMessageHandler::handle_update_add_htlc(self, their_node_id, msg); + } + + fn handle_update_fulfill_htlc(&self, their_node_id: &PublicKey, msg: &UpdateFulfillHTLC) { + TestChannelMessageHandler::handle_update_fulfill_htlc(self, their_node_id, msg); + } + + fn handle_update_fail_htlc(&self, their_node_id: &PublicKey, msg: &UpdateFailHTLC) { + TestChannelMessageHandler::handle_update_fail_htlc(self, their_node_id, msg); + } + + fn handle_update_fail_malformed_htlc(&self, their_node_id: &PublicKey, msg: &UpdateFailMalformedHTLC) { + TestChannelMessageHandler::handle_update_fail_malformed_htlc(self, their_node_id, msg); + } + + fn handle_commitment_signed(&self, their_node_id: &PublicKey, msg: &CommitmentSigned) { + TestChannelMessageHandler::handle_commitment_signed(self, their_node_id, msg); + } + + fn handle_revoke_and_ack(&self, their_node_id: &PublicKey, msg: &RevokeAndACK) { + TestChannelMessageHandler::handle_revoke_and_ack(self, their_node_id, msg); + } + + fn handle_update_fee(&self, their_node_id: &PublicKey, msg: &UpdateFee) { + TestChannelMessageHandler::handle_update_fee(self, their_node_id, msg); + } + + fn handle_announcement_signatures(&self, their_node_id: &PublicKey, msg: &AnnouncementSignatures) { + TestChannelMessageHandler::handle_announcement_signatures(self, their_node_id, msg); + } + + fn peer_disconnected(&self, their_node_id: &PublicKey, no_connection_possible: bool) { + TestChannelMessageHandler::peer_disconnected(self, their_node_id, no_connection_possible); + } + + fn peer_connected(&self, their_node_id: &PublicKey, msg: &Init) { + TestChannelMessageHandler::peer_connected(self, their_node_id, msg); + } + + fn handle_channel_reestablish(&self, their_node_id: &PublicKey, msg: &ChannelReestablish) { + TestChannelMessageHandler::handle_channel_reestablish(self, their_node_id, msg); + } + + fn handle_error(&self, their_node_id: &PublicKey, msg: &ErrorMessage) { + TestChannelMessageHandler::handle_error(self, their_node_id, msg); + } +} + +impl<'a> events::MessageSendEventsProvider for &'a TestChannelMessageHandler { + fn get_and_clear_pending_msg_events(&self) -> Vec { + TestChannelMessageHandler::get_and_clear_pending_msg_events(self, ) + } +} + fn get_dummy_channel_announcement(short_chan_id: u64) -> msgs::ChannelAnnouncement { use bitcoin::secp256k1::ffi::Signature as FFISignature; let secp_ctx = Secp256k1::new(); @@ -233,6 +456,132 @@ fn get_dummy_channel_update(short_chan_id: u64) -> msgs::ChannelUpdate { } } +/// Test Stub for the RoutingMessageHandler. +pub struct RoutingMessageHandlerTestStub { + pub handle_node_announcement_return: Result, + pub handle_channel_announcement_return: Result, + pub handle_channel_update_return: Result, + pub should_request_full_sync_return: bool +} + +impl RoutingMessageHandlerTestStub { + pub fn new() -> Self { + Self { + handle_node_announcement_return: Ok(true), + handle_channel_announcement_return: Ok(true), + handle_channel_update_return: Ok(true), + should_request_full_sync_return: true + } + } +} + +impl RoutingMessageHandler for RoutingMessageHandlerTestStub { + fn handle_node_announcement(&self, _msg: &NodeAnnouncement) -> Result { + self.handle_node_announcement_return.clone() + } + + fn handle_channel_announcement(&self, _msg: &ChannelAnnouncement) -> Result { + self.handle_channel_announcement_return.clone() + } + + fn handle_channel_update(&self, _msg: &ChannelUpdate) -> Result { + self.handle_channel_update_return.clone() + } + + fn handle_htlc_fail_channel_update(&self, _update: &HTLCFailChannelUpdate) { } + + fn get_next_channel_announcements(&self, _starting_point: u64, _batch_amount: u8) -> Vec<(ChannelAnnouncement, Option, Option)> { + vec![] + } + + fn get_next_node_announcements(&self, _starting_point: Option<&PublicKey>, _batch_amount: u8) -> Vec { + vec![] + } + + fn should_request_full_sync(&self, _node_id: &PublicKey) -> bool { + self.should_request_full_sync_return + } +} + +/// Test Spy infrastructure for the RoutingMessageHandler trait that tests can use to validate +/// the correct callbacks were called. +macro_rules! generate_routing_handler_called_fns { + ($($name: ident,)*) => { + pub struct RoutingMessageHandlerTestSpyCalledFns { + $( + pub $name: bool, + )* + } + impl RoutingMessageHandlerTestSpyCalledFns { + pub fn new() -> Self { + Self { + $( + $name: false, + )* + } + } + } + } +} + +generate_routing_handler_called_fns!( + handle_node_announcement, + handle_channel_announcement, + handle_channel_update, + handle_htlc_fail_channel_update, + get_next_channel_announcements, + get_next_node_announcements, + should_request_full_sync, +); + +pub struct RoutingMessageHandlerTestSpy { + pub called: Mutex +} + +impl RoutingMessageHandlerTestSpy { + pub fn new() -> Self { + Self { + called: Mutex::new(RoutingMessageHandlerTestSpyCalledFns::new()) + } + } +} + +impl RoutingMessageHandler for RoutingMessageHandlerTestSpy { + fn handle_node_announcement(&self, _msg: &NodeAnnouncement) -> Result { + self.called.lock().unwrap().handle_node_announcement = true; + Ok(true) + } + + fn handle_channel_announcement(&self, _msg: &ChannelAnnouncement) -> Result { + self.called.lock().unwrap().handle_channel_announcement = true; + Ok(true) + } + + fn handle_channel_update(&self, _msg: &ChannelUpdate) -> Result { + self.called.lock().unwrap().handle_channel_update = true; + Ok(true) + } + + fn handle_htlc_fail_channel_update(&self, _update: &HTLCFailChannelUpdate) { + self.called.lock().unwrap().handle_htlc_fail_channel_update = true; + } + + fn get_next_channel_announcements(&self, _starting_point: u64, _batch_amount: u8) -> Vec<(ChannelAnnouncement, Option, Option)> { + self.called.lock().unwrap().get_next_channel_announcements = true; + vec![] + } + + fn get_next_node_announcements(&self, _starting_point: Option<&PublicKey>, _batch_amount: u8) -> Vec { + self.called.lock().unwrap().get_next_node_announcements = true; + vec![] + } + + fn should_request_full_sync(&self, _node_id: &PublicKey) -> bool { + self.called.lock().unwrap().should_request_full_sync = true; + true + } +} + pub struct TestRoutingMessageHandler { pub chan_upds_recvd: AtomicUsize, pub chan_anns_recvd: AtomicUsize,