Add onion_message::Packet and adapt construct_onion_packet_with_init_noise for it
[rust-lightning] / lightning / src / onion_message / packet.rs
diff --git a/lightning/src/onion_message/packet.rs b/lightning/src/onion_message/packet.rs
new file mode 100644 (file)
index 0000000..37f178f
--- /dev/null
@@ -0,0 +1,82 @@
+// This file is Copyright its original authors, visible in version control
+// history.
+//
+// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
+// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
+// You may not use this file except in accordance with one or both of these
+// licenses.
+
+//! Structs and enums useful for constructing and reading an onion message packet.
+
+use bitcoin::secp256k1::PublicKey;
+
+use ln::msgs::DecodeError;
+use ln::onion_utils;
+use util::ser::{LengthRead, LengthReadable, Readable, Writeable, Writer};
+
+use core::cmp;
+use io;
+use prelude::*;
+
+#[derive(Clone, Debug, PartialEq)]
+pub(crate) struct Packet {
+       version: u8,
+       public_key: PublicKey,
+       // Unlike the onion packets used for payments, onion message packets can have payloads greater
+       // than 1300 bytes.
+       // TODO: if 1300 ends up being the most common size, optimize this to be:
+       // enum { ThirteenHundred([u8; 1300]), VarLen(Vec<u8>) }
+       hop_data: Vec<u8>,
+       hmac: [u8; 32],
+}
+
+impl onion_utils::Packet for Packet {
+       type Data = Vec<u8>;
+       fn new(public_key: PublicKey, hop_data: Vec<u8>, hmac: [u8; 32]) -> Packet {
+               Self {
+                       version: 0,
+                       public_key,
+                       hop_data,
+                       hmac,
+               }
+       }
+}
+
+impl Writeable for Packet {
+       fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
+               self.version.write(w)?;
+               self.public_key.write(w)?;
+               w.write_all(&self.hop_data)?;
+               self.hmac.write(w)?;
+               Ok(())
+       }
+}
+
+impl LengthReadable for Packet {
+       fn read<R: LengthRead>(r: &mut R) -> Result<Self, DecodeError> {
+               const READ_BUFFER_SIZE: usize = 4096;
+
+               let version = Readable::read(r)?;
+               let public_key = Readable::read(r)?;
+
+               let mut hop_data = Vec::new();
+               let hop_data_len = r.total_bytes() as usize - 66; // 1 (version) + 33 (pubkey) + 32 (HMAC) = 66
+               let mut read_idx = 0;
+               while read_idx < hop_data_len {
+                       let mut read_buffer = [0; READ_BUFFER_SIZE];
+                       let read_amt = cmp::min(hop_data_len - read_idx, READ_BUFFER_SIZE);
+                       r.read_exact(&mut read_buffer[..read_amt]);
+                       hop_data.extend_from_slice(&read_buffer[..read_amt]);
+                       read_idx += read_amt;
+               }
+
+               let hmac = Readable::read(r)?;
+               Ok(Packet {
+                       version,
+                       public_key,
+                       hop_data,
+                       hmac,
+               })
+       }
+}