X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=src%2Fln%2Fmsgs.rs;h=1d0ea1c637235c02774fe3e111238c6a25ed15d4;hb=90b545ffe3e6855e09156361ecb1d5384add1e46;hp=6c7c8cfc7281682af919360df1c892342277e820;hpb=7d6aab7f22e8191b1838c3132cd8188c48f2796b;p=rust-lightning diff --git a/src/ln/msgs.rs b/src/ln/msgs.rs index 6c7c8cfc..1d0ea1c6 100644 --- a/src/ln/msgs.rs +++ b/src/ln/msgs.rs @@ -1,5 +1,6 @@ use secp256k1::key::PublicKey; use secp256k1::{Secp256k1, Signature}; +use secp256k1; use bitcoin::util::hash::Sha256dHash; use bitcoin::network::serialize::{deserialize,serialize}; use bitcoin::blockdata::script::Script; @@ -27,6 +28,8 @@ pub trait MsgEncodable { pub enum DecodeError { /// Unknown realm byte in an OnionHopData packet UnknownRealmByte, + /// Unknown feature mandating we fail to parse message + UnknownRequiredFeature, /// Failed to decode a public key (ie it's invalid) BadPublicKey, /// Failed to decode a signature (ie it's invalid) @@ -275,12 +278,16 @@ pub struct UpdateFee { pub feerate_per_kw: u32, } +pub struct DataLossProtect { + pub your_last_per_commitment_secret: [u8; 32], + pub my_current_per_commitment_point: PublicKey, +} + pub struct ChannelReestablish { pub channel_id: [u8; 32], pub next_local_commitment_number: u64, pub next_remote_commitment_number: u64, - pub your_last_per_commitment_secret: Option<[u8; 32]>, - pub my_current_per_commitment_point: PublicKey, + pub data_loss_protect: Option, } #[derive(Clone)] @@ -332,6 +339,8 @@ pub struct UnsignedNodeAnnouncement { /// List of addresses on which this node is reachable. Note that you may only have up to one /// address of each type, if you have more, they may be silently discarded or we may panic! pub addresses: Vec, + pub excess_address_data: Vec, + pub excess_data: Vec, } pub struct NodeAnnouncement { pub signature: Signature, @@ -347,6 +356,7 @@ pub struct UnsignedChannelAnnouncement { pub node_id_2: PublicKey, pub bitcoin_key_1: PublicKey, pub bitcoin_key_2: PublicKey, + pub excess_data: Vec, } #[derive(PartialEq, Clone)] pub struct ChannelAnnouncement { @@ -367,6 +377,7 @@ pub struct UnsignedChannelUpdate { pub htlc_minimum_msat: u64, pub fee_base_msat: u32, pub fee_proportional_millionths: u32, + pub excess_data: Vec, } #[derive(PartialEq, Clone)] pub struct ChannelUpdate { @@ -451,11 +462,11 @@ pub trait ChannelMessageHandler : events::EventsProvider + Send + Sync { } pub trait RoutingMessageHandler : Send + Sync { - fn handle_node_announcement(&self, msg: &NodeAnnouncement) -> Result<(), HandleError>; + fn handle_node_announcement(&self, msg: &NodeAnnouncement) -> Result; /// Handle a channel_announcement message, returning true if it should be forwarded on, false /// or returning an Err otherwise. fn handle_channel_announcement(&self, msg: &ChannelAnnouncement) -> Result; - fn handle_channel_update(&self, msg: &ChannelUpdate) -> Result<(), HandleError>; + fn handle_channel_update(&self, msg: &ChannelUpdate) -> Result; fn handle_htlc_fail_channel_update(&self, update: &HTLCFailChannelUpdate); } @@ -476,7 +487,10 @@ unsafe impl internal_traits::NoDealloc for OnionHopData{} #[derive(Clone)] pub struct OnionPacket { pub version: u8, - pub public_key: PublicKey, + /// In order to ensure we always return an error on Onion decode in compliance with BOLT 4, we + /// have to deserialize OnionPackets contained in UpdateAddHTLCs even if the ephemeral public + /// key (here) is bogus, so we hold a Result instead of a PublicKey as we'd like. + pub public_key: Result, pub hop_data: [u8; 20*65], pub hmac: [u8; 32], } @@ -498,6 +512,7 @@ impl Error for DecodeError { fn description(&self) -> &str { match *self { DecodeError::UnknownRealmByte => "Unknown realm byte in Onion packet", + DecodeError::UnknownRequiredFeature => "Unknown required feature preventing decode", DecodeError::BadPublicKey => "Invalid public key in packet", DecodeError::BadSignature => "Invalid signature in packet", DecodeError::BadText => "Invalid text in packet", @@ -666,10 +681,11 @@ impl MsgDecodable for OpenChannel { } shutdown_scriptpubkey = Some(Script::from(v[321..321+len].to_vec())); } - + let mut temp_channel_id = [0; 32]; + temp_channel_id[..].copy_from_slice(&v[32..64]); Ok(OpenChannel { chain_hash: deserialize(&v[0..32]).unwrap(), - temporary_channel_id: deserialize(&v[32..64]).unwrap(), + temporary_channel_id: temp_channel_id, funding_satoshis: byte_utils::slice_to_be64(&v[64..72]), push_msat: byte_utils::slice_to_be64(&v[72..80]), dust_limit_satoshis: byte_utils::slice_to_be64(&v[80..88]), @@ -1114,48 +1130,42 @@ impl MsgEncodable for UpdateFee { impl MsgDecodable for ChannelReestablish { fn decode(v: &[u8]) -> Result { - if v.len() < 32+2*8+33 { + if v.len() < 32+2*8 { return Err(DecodeError::ShortRead); } - let your_last_per_commitment_secret = if v.len() > 32+2*8+33 { - if v.len() < 32+2*8+33 + 32 { + let data_loss_protect = if v.len() > 32+2*8 { + if v.len() < 32+2*8 + 33+32 { return Err(DecodeError::ShortRead); } let mut inner_array = [0; 32]; inner_array.copy_from_slice(&v[48..48+32]); - Some(inner_array) + Some(DataLossProtect { + your_last_per_commitment_secret: inner_array, + my_current_per_commitment_point: secp_pubkey!(&Secp256k1::without_caps(), &v[48+32..48+32+33]), + }) } else { None }; - let option_size = match &your_last_per_commitment_secret { - &Some(ref _ary) => 32, - &None => 0, - }; Ok(Self { channel_id: deserialize(&v[0..32]).unwrap(), next_local_commitment_number: byte_utils::slice_to_be64(&v[32..40]), next_remote_commitment_number: byte_utils::slice_to_be64(&v[40..48]), - your_last_per_commitment_secret: your_last_per_commitment_secret, - my_current_per_commitment_point: { - let ctx = Secp256k1::without_caps(); - secp_pubkey!(&ctx, &v[48+option_size..48+option_size+33]) - } + data_loss_protect: data_loss_protect, }) } } impl MsgEncodable for ChannelReestablish { fn encode(&self) -> Vec { - let mut res = Vec::with_capacity(if self.your_last_per_commitment_secret.is_some() { 32+2*3+33 + 32 } else { 32+2*8+33 }); + let mut res = Vec::with_capacity(if self.data_loss_protect.is_some() { 32+2*8+33+32 } else { 32+2*8 }); res.extend_from_slice(&serialize(&self.channel_id).unwrap()[..]); res.extend_from_slice(&byte_utils::be64_to_array(self.next_local_commitment_number)); res.extend_from_slice(&byte_utils::be64_to_array(self.next_remote_commitment_number)); - if let &Some(ref ary) = &self.your_last_per_commitment_secret { - res.extend_from_slice(&ary[..]); + if let &Some(ref data_loss_protect) = &self.data_loss_protect { + res.extend_from_slice(&data_loss_protect.your_last_per_commitment_secret[..]); + res.extend_from_slice(&data_loss_protect.my_current_per_commitment_point.serialize()); } - - res.extend_from_slice(&self.my_current_per_commitment_point.serialize()); res } } @@ -1191,6 +1201,10 @@ impl MsgEncodable for AnnouncementSignatures { impl MsgDecodable for UnsignedNodeAnnouncement { fn decode(v: &[u8]) -> Result { let features = GlobalFeatures::decode(&v[..])?; + if features.requires_unknown_bits() { + return Err(DecodeError::UnknownRequiredFeature); + } + if v.len() < features.encoded_len() + 4 + 33 + 3 + 32 + 2 { return Err(DecodeError::ShortRead); } @@ -1213,7 +1227,6 @@ impl MsgDecodable for UnsignedNodeAnnouncement { loop { if addr_read_limit <= read_pos { break; } match v[read_pos] { - 0 => { read_pos += 1; }, 1 => { if addresses.len() > 0 { return Err(DecodeError::ExtraAddressesPerType); @@ -1280,6 +1293,15 @@ impl MsgDecodable for UnsignedNodeAnnouncement { } } + let excess_address_data = if read_pos < addr_read_limit { + let mut excess_address_data = Vec::with_capacity(addr_read_limit - read_pos); + excess_address_data.extend_from_slice(&v[read_pos..addr_read_limit]); + excess_address_data + } else { Vec::new() }; + + let mut excess_data = Vec::with_capacity(v.len() - addr_read_limit); + excess_data.extend_from_slice(&v[addr_read_limit..]); + let secp_ctx = Secp256k1::without_caps(); Ok(Self { features, @@ -1288,13 +1310,15 @@ impl MsgDecodable for UnsignedNodeAnnouncement { rgb, alias, addresses, + excess_address_data, + excess_data, }) } } impl MsgEncodable for UnsignedNodeAnnouncement { fn encode(&self) -> Vec { let features = self.features.encode(); - let mut res = Vec::with_capacity(74 + features.len() + self.addresses.len()); + let mut res = Vec::with_capacity(74 + features.len() + self.addresses.len()*7 + self.excess_address_data.len() + self.excess_data.len()); res.extend_from_slice(&features[..]); res.extend_from_slice(&byte_utils::be32_to_array(self.timestamp)); res.extend_from_slice(&self.node_id.serialize()); @@ -1330,8 +1354,10 @@ impl MsgEncodable for UnsignedNodeAnnouncement { }, } } - res.extend_from_slice(&byte_utils::be16_to_array(addr_slice.len() as u16)); + res.extend_from_slice(&byte_utils::be16_to_array((addr_slice.len() + self.excess_address_data.len()) as u16)); res.extend_from_slice(&addr_slice[..]); + res.extend_from_slice(&self.excess_address_data[..]); + res.extend_from_slice(&self.excess_data[..]); res } } @@ -1362,11 +1388,16 @@ impl MsgEncodable for NodeAnnouncement { impl MsgDecodable for UnsignedChannelAnnouncement { fn decode(v: &[u8]) -> Result { let features = GlobalFeatures::decode(&v[..])?; + if features.requires_unknown_bits() { + return Err(DecodeError::UnknownRequiredFeature); + } if v.len() < features.encoded_len() + 32 + 8 + 33*4 { return Err(DecodeError::ShortRead); } let start = features.encoded_len(); let secp_ctx = Secp256k1::without_caps(); + let mut excess_data = Vec::with_capacity(v.len() - start - 172); + excess_data.extend_from_slice(&v[start + 172..]); Ok(Self { features, chain_hash: deserialize(&v[start..start + 32]).unwrap(), @@ -1375,13 +1406,14 @@ impl MsgDecodable for UnsignedChannelAnnouncement { node_id_2: secp_pubkey!(&secp_ctx, &v[start + 73..start + 106]), bitcoin_key_1: secp_pubkey!(&secp_ctx, &v[start + 106..start + 139]), bitcoin_key_2: secp_pubkey!(&secp_ctx, &v[start + 139..start + 172]), + excess_data, }) } } impl MsgEncodable for UnsignedChannelAnnouncement { fn encode(&self) -> Vec { let features = self.features.encode(); - let mut res = Vec::with_capacity(172 + features.len()); + let mut res = Vec::with_capacity(172 + features.len() + self.excess_data.len()); res.extend_from_slice(&features[..]); res.extend_from_slice(&self.chain_hash[..]); res.extend_from_slice(&byte_utils::be64_to_array(self.short_channel_id)); @@ -1389,6 +1421,7 @@ impl MsgEncodable for UnsignedChannelAnnouncement { res.extend_from_slice(&self.node_id_2.serialize()); res.extend_from_slice(&self.bitcoin_key_1.serialize()); res.extend_from_slice(&self.bitcoin_key_2.serialize()); + res.extend_from_slice(&self.excess_data[..]); res } } @@ -1427,6 +1460,8 @@ impl MsgDecodable for UnsignedChannelUpdate { if v.len() < 32+8+4+2+2+8+4+4 { return Err(DecodeError::ShortRead); } + let mut excess_data = Vec::with_capacity(v.len() - 64); + excess_data.extend_from_slice(&v[64..]); Ok(Self { chain_hash: deserialize(&v[0..32]).unwrap(), short_channel_id: byte_utils::slice_to_be64(&v[32..40]), @@ -1436,12 +1471,13 @@ impl MsgDecodable for UnsignedChannelUpdate { htlc_minimum_msat: byte_utils::slice_to_be64(&v[48..56]), fee_base_msat: byte_utils::slice_to_be32(&v[56..60]), fee_proportional_millionths: byte_utils::slice_to_be32(&v[60..64]), + excess_data }) } } impl MsgEncodable for UnsignedChannelUpdate { fn encode(&self) -> Vec { - let mut res = Vec::with_capacity(64); + let mut res = Vec::with_capacity(64 + self.excess_data.len()); res.extend_from_slice(&self.chain_hash[..]); res.extend_from_slice(&byte_utils::be64_to_array(self.short_channel_id)); res.extend_from_slice(&byte_utils::be32_to_array(self.timestamp)); @@ -1450,6 +1486,7 @@ impl MsgEncodable for UnsignedChannelUpdate { res.extend_from_slice(&byte_utils::be64_to_array(self.htlc_minimum_msat)); res.extend_from_slice(&byte_utils::be32_to_array(self.fee_base_msat)); res.extend_from_slice(&byte_utils::be32_to_array(self.fee_proportional_millionths)); + res.extend_from_slice(&self.excess_data[..]); res } } @@ -1538,7 +1575,7 @@ impl MsgDecodable for OnionPacket { let secp_ctx = Secp256k1::without_caps(); Ok(Self { version: v[0], - public_key: secp_pubkey!(&secp_ctx, &v[1..34]), + public_key: PublicKey::from_slice(&secp_ctx, &v[1..34]), hop_data, hmac, }) @@ -1548,7 +1585,10 @@ impl MsgEncodable for OnionPacket { fn encode(&self) -> Vec { let mut res = Vec::with_capacity(1 + 33 + 20*65 + 32); res.push(self.version); - res.extend_from_slice(&self.public_key.serialize()); + match self.public_key { + Ok(pubkey) => res.extend_from_slice(&pubkey.serialize()), + Err(_) => res.extend_from_slice(&[0; 33]), + } res.extend_from_slice(&self.hop_data); res.extend_from_slice(&self.hmac); res @@ -1652,23 +1692,17 @@ mod tests { #[test] fn encoding_channel_reestablish_no_secret() { - let public_key = { - let secp_ctx = Secp256k1::new(); - PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&secp_ctx, &hex::decode("0101010101010101010101010101010101010101010101010101010101010101").unwrap()[..]).unwrap()) - }; - let cr = msgs::ChannelReestablish { channel_id: [4, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0], next_local_commitment_number: 3, next_remote_commitment_number: 4, - your_last_per_commitment_secret: None, - my_current_per_commitment_point: public_key, + data_loss_protect: None, }; let encoded_value = cr.encode(); assert_eq!( encoded_value, - vec![4, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4, 3, 27, 132, 197, 86, 123, 18, 100, 64, 153, 93, 62, 213, 170, 186, 5, 101, 215, 30, 24, 52, 96, 72, 25, 255, 156, 23, 245, 233, 213, 221, 7, 143] + vec![4, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4] ); } @@ -1683,8 +1717,7 @@ mod tests { channel_id: [4, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0], next_local_commitment_number: 3, next_remote_commitment_number: 4, - your_last_per_commitment_secret: Some([9; 32]), - my_current_per_commitment_point: public_key, + data_loss_protect: Some(msgs::DataLossProtect { your_last_per_commitment_secret: [9;32], my_current_per_commitment_point: public_key}), }; let encoded_value = cr.encode();