X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Fmsgs.rs;h=cd93e236a00a5d662c2ebf564a439eb60142fea4;hb=6a620ee340fd1a651e2bd729bdb762df01f49a2f;hp=d4d09dc2ae0ef9ef1beb1c208d369795defb5c59;hpb=aee06996d97de6012ae7c56a4188587654ecee57;p=rust-lightning diff --git a/lightning/src/ln/msgs.rs b/lightning/src/ln/msgs.rs index d4d09dc2a..cd93e236a 100644 --- a/lightning/src/ln/msgs.rs +++ b/lightning/src/ln/msgs.rs @@ -33,6 +33,9 @@ use util::ser::{Readable, Writeable, Writer, FixedLengthReader, HighZeroBytesDro use ln::channelmanager::{PaymentPreimage, PaymentHash}; +/// 21 million * 10^8 * 1000 +pub(crate) const MAX_VALUE_MSAT: u64 = 21_000_000_0000_0000_000; + /// An error in decoding a message or struct. #[derive(Debug)] pub enum DecodeError { @@ -305,6 +308,58 @@ impl NetAddress { } } +/// A "set" of addresses which enforces that there can be only up to one of each net address type. +pub struct NetAddressSet { + v4: Option, + v6: Option, + onion2: Option, + onion3: Option, +} +impl NetAddressSet { + /// Creates a new, empty, NetAddressSet + pub fn new() -> Self { + NetAddressSet { v4: None, v6: None, onion2: None, onion3: None } + } + + /// Sets the IPv4 socket address in this set, overwriting any previous IPv4 socket addresses + /// (if any). + pub fn set_v4(&mut self, addr: [u8; 4], port: u16) { + self.v4 = Some(NetAddress::IPv4 { addr, port }); + } + /// Sets the IPv6 socket address in this set, overwriting any previous IPv4 socket addresses + /// (if any). + pub fn set_v6(&mut self, addr: [u8; 16], port: u16) { + self.v6 = Some(NetAddress::IPv6 { addr, port }); + } + /// Sets the Tor Onion v2 socket address in this set, overwriting any previous IPv4 socket + /// address (if any). + pub fn set_onion_v2(&mut self, addr: [u8; 10], port: u16) { + self.onion2 = Some(NetAddress::OnionV2 { addr, port }); + } + /// Sets the Tor Onion v3 socket address in this set, overwriting any previous IPv4 socket + /// address (if any). + pub fn set_onion_v3(&mut self, ed25519_pubkey: [u8; 32], checksum: u16, version: u8, port: u16) { + self.onion3 = Some(NetAddress::OnionV3 { ed25519_pubkey, checksum, version, port }); + } + + pub(crate) fn to_vec(mut self) -> Vec { + let mut res = Vec::new(); + if let Some(addr) = self.v4.take() { + res.push(addr); + } + if let Some(addr) = self.v6.take() { + res.push(addr); + } + if let Some(addr) = self.onion2.take() { + res.push(addr); + } + if let Some(addr) = self.onion3.take() { + res.push(addr); + } + res + } +} + impl Writeable for NetAddress { fn write(&self, writer: &mut W) -> Result<(), ::std::io::Error> { match self { @@ -609,6 +664,11 @@ pub trait RoutingMessageHandler : Send + Sync { mod fuzzy_internal_msgs { // These types aren't intended to be pub, but are exposed for direct fuzzing (as we deserialize // them from untrusted input): + #[derive(Clone)] + pub(crate) struct FinalOnionHopData { + pub(crate) payment_secret: [u8; 32], + pub(crate) total_msat: u64, + } pub(crate) enum OnionHopDataFormat { Legacy { // aka Realm-0 @@ -617,7 +677,9 @@ mod fuzzy_internal_msgs { NonFinalNode { short_channel_id: u64, }, - FinalNode, + FinalNode { + payment_data: Option, + }, } pub struct OnionHopData { @@ -961,6 +1023,11 @@ impl_writeable!(UpdateAddHTLC, 32+8+8+32+4+1366, { onion_routing_packet }); +impl_writeable!(FinalOnionHopData, 32+8, { + payment_secret, + total_msat +}); + impl Writeable for OnionHopData { fn write(&self, w: &mut W) -> Result<(), ::std::io::Error> { w.size_hint(33); @@ -978,11 +1045,19 @@ impl Writeable for OnionHopData { (6, short_channel_id) }); }, - OnionHopDataFormat::FinalNode => { - encode_varint_length_prefixed_tlv!(w, { - (2, HighZeroBytesDroppedVarInt(self.amt_to_forward)), - (4, HighZeroBytesDroppedVarInt(self.outgoing_cltv_value)) - }); + OnionHopDataFormat::FinalNode { ref payment_data } => { + if let &Some(ref final_data) = payment_data { + encode_varint_length_prefixed_tlv!(w, { + (2, HighZeroBytesDroppedVarInt(self.amt_to_forward)), + (4, HighZeroBytesDroppedVarInt(self.outgoing_cltv_value)), + (8, final_data) + }); + } else { + encode_varint_length_prefixed_tlv!(w, { + (2, HighZeroBytesDroppedVarInt(self.amt_to_forward)), + (4, HighZeroBytesDroppedVarInt(self.outgoing_cltv_value)) + }); + } }, } match self.format { @@ -1008,19 +1083,29 @@ impl Readable for OnionHopData { let mut amt = HighZeroBytesDroppedVarInt(0u64); let mut cltv_value = HighZeroBytesDroppedVarInt(0u32); let mut short_id: Option = None; + let mut payment_data: Option = None; decode_tlv!(&mut rd, { (2, amt), (4, cltv_value) }, { - (6, short_id) + (6, short_id), + (8, payment_data) }); rd.eat_remaining().map_err(|_| DecodeError::ShortRead)?; let format = if let Some(short_channel_id) = short_id { + if payment_data.is_some() { return Err(DecodeError::InvalidValue); } OnionHopDataFormat::NonFinalNode { short_channel_id, } } else { - OnionHopDataFormat::FinalNode + if let &Some(ref data) = &payment_data { + if data.total_msat > MAX_VALUE_MSAT { + return Err(DecodeError::InvalidValue); + } + } + OnionHopDataFormat::FinalNode { + payment_data + } }; (format, amt.0, cltv_value.0) } else { @@ -1029,6 +1114,9 @@ impl Readable for OnionHopData { }; let amt: u64 = Readable::read(r)?; let cltv_value: u32 = Readable::read(r)?; + if amt > MAX_VALUE_MSAT { + return Err(DecodeError::InvalidValue); + } r.read_exact(&mut [0; 12])?; (format, amt, cltv_value) }; @@ -2015,7 +2103,9 @@ mod tests { #[test] fn encoding_final_onion_hop_data() { let mut msg = msgs::OnionHopData { - format: OnionHopDataFormat::FinalNode, + format: OnionHopDataFormat::FinalNode { + payment_data: None, + }, amt_to_forward: 0x0badf00d01020304, outgoing_cltv_value: 0xffffffff, }; @@ -2023,7 +2113,7 @@ mod tests { let target_value = hex::decode("1002080badf00d010203040404ffffffff").unwrap(); assert_eq!(encoded_value, target_value); msg = Readable::read(&mut Cursor::new(&target_value[..])).unwrap(); - if let OnionHopDataFormat::FinalNode = msg.format { } else { panic!(); } + if let OnionHopDataFormat::FinalNode { payment_data: None } = msg.format { } else { panic!(); } assert_eq!(msg.amt_to_forward, 0x0badf00d01020304); assert_eq!(msg.outgoing_cltv_value, 0xffffffff); }