X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=src%2Futil%2Fser.rs;h=c1d2802a76da834d03555cf73b0e2f88139d52a5;hb=832fc4fd4435fa236f15d3e737bebf64619ff60e;hp=7f795fe46a23defb08494c03f1eef71396bfd670;hpb=1f1f82569a1774d2f6cb84e1de3c55dc733022c8;p=rust-lightning diff --git a/src/util/ser.rs b/src/util/ser.rs index 7f795fe4..c1d2802a 100644 --- a/src/util/ser.rs +++ b/src/util/ser.rs @@ -1,37 +1,91 @@ +//! A very simple serialization framework which is used to serialize/deserialize messages as well +//! as ChannelsManagers and ChannelMonitors. + use std::result::Result; -use std::io::Read; +use std::io::{Read, Write}; use std::collections::HashMap; use std::hash::Hash; -use std::mem; use secp256k1::{Secp256k1, Signature}; -use secp256k1::key::PublicKey; +use secp256k1::key::{PublicKey, SecretKey}; use bitcoin::util::hash::Sha256dHash; use bitcoin::blockdata::script::Script; use std::marker::Sized; use ln::msgs::DecodeError; +use ln::channelmanager::{PaymentPreimage, PaymentHash}; +use util::byte_utils; -use util::byte_utils::{be64_to_array, be32_to_array, be16_to_array, slice_to_be16, slice_to_be32, slice_to_be64}; +use util::byte_utils::{be64_to_array, be48_to_array, be32_to_array, be16_to_array, slice_to_be16, slice_to_be32, slice_to_be48, slice_to_be64}; const MAX_BUF_SIZE: usize = 64 * 1024; -/// A trait that is similar to std::io::Write. -/// An impl is provided for any type that also impls std::io::Write. +/// A trait that is similar to std::io::Write but has one extra function which can be used to size +/// buffers being written into. +/// An impl is provided for any type that also impls std::io::Write which simply ignores size +/// hints. pub trait Writer { /// Writes the given buf out. See std::io::Write::write_all for more fn write_all(&mut self, buf: &[u8]) -> Result<(), ::std::io::Error>; + /// Hints that data of the given size is about the be written. This may not always be called + /// prior to data being written and may be safely ignored. + fn size_hint(&mut self, size: usize); } -impl Writer for W { +impl Writer for W { + #[inline] fn write_all(&mut self, buf: &[u8]) -> Result<(), ::std::io::Error> { ::write_all(self, buf) } + #[inline] + fn size_hint(&mut self, _size: usize) { } +} + +pub(crate) struct WriterWriteAdaptor<'a, W: Writer + 'a>(pub &'a mut W); +impl<'a, W: Writer + 'a> Write for WriterWriteAdaptor<'a, W> { + fn write_all(&mut self, buf: &[u8]) -> Result<(), ::std::io::Error> { + self.0.write_all(buf) + } + fn write(&mut self, buf: &[u8]) -> Result { + self.0.write_all(buf)?; + Ok(buf.len()) + } + fn flush(&mut self) -> Result<(), ::std::io::Error> { + Ok(()) + } +} + +struct VecWriter(Vec); +impl Writer for VecWriter { + fn write_all(&mut self, buf: &[u8]) -> Result<(), ::std::io::Error> { + self.0.extend_from_slice(buf); + Ok(()) + } + fn size_hint(&mut self, size: usize) { + self.0.reserve_exact(size); + } } /// A trait that various rust-lightning types implement allowing them to be written out to a Writer -pub trait Writeable { +pub trait Writeable { /// Writes self out to the given Writer - fn write(&self, writer: &mut W) -> Result<(), DecodeError>; + fn write(&self, writer: &mut W) -> Result<(), ::std::io::Error>; + + /// Writes self out to a Vec + fn encode(&self) -> Vec { + let mut msg = VecWriter(Vec::new()); + self.write(&mut msg).unwrap(); + msg.0 + } + + /// Writes self out to a Vec + fn encode_with_len(&self) -> Vec { + let mut msg = VecWriter(Vec::new()); + 0u16.write(&mut msg).unwrap(); + self.write(&mut msg).unwrap(); + let len = msg.0.len(); + msg.0[..2].copy_from_slice(&byte_utils::be16_to_array(len as u16 - 2)); + msg.0 + } } /// A trait that various rust-lightning types implement allowing them to be read in from a Read @@ -43,12 +97,38 @@ pub trait Readable fn read(reader: &mut R) -> Result; } +/// A trait that various higher-level rust-lightning types implement allowing them to be read in +/// from a Read given some additional set of arguments which is required to deserialize. +pub trait ReadableArgs + where Self: Sized, + R: Read +{ + /// Reads a Self in from the given Read + fn read(reader: &mut R, params: P) -> Result; +} + +pub(crate) struct U48(pub u64); +impl Writeable for U48 { + #[inline] + fn write(&self, writer: &mut W) -> Result<(), ::std::io::Error> { + writer.write_all(&be48_to_array(self.0)) + } +} +impl Readable for U48 { + #[inline] + fn read(reader: &mut R) -> Result { + let mut buf = [0; 6]; + reader.read_exact(&mut buf)?; + Ok(U48(slice_to_be48(&buf))) + } +} + macro_rules! impl_writeable_primitive { ($val_type:ty, $meth_write:ident, $len: expr, $meth_read:ident) => { - impl Writeable for $val_type { + impl Writeable for $val_type { #[inline] - fn write(&self, writer: &mut W) -> Result<(), DecodeError> { - Ok(writer.write_all(&$meth_write(*self))?) + fn write(&self, writer: &mut W) -> Result<(), ::std::io::Error> { + writer.write_all(&$meth_write(*self)) } } impl Readable for $val_type { @@ -66,10 +146,10 @@ impl_writeable_primitive!(u64, be64_to_array, 8, slice_to_be64); impl_writeable_primitive!(u32, be32_to_array, 4, slice_to_be32); impl_writeable_primitive!(u16, be16_to_array, 2, slice_to_be16); -impl Writeable for u8 { +impl Writeable for u8 { #[inline] - fn write(&self, writer: &mut W) -> Result<(), DecodeError> { - Ok(writer.write_all(&[*self])?) + fn write(&self, writer: &mut W) -> Result<(), ::std::io::Error> { + writer.write_all(&[*self]) } } impl Readable for u8 { @@ -81,10 +161,10 @@ impl Readable for u8 { } } -impl Writeable for bool { +impl Writeable for bool { #[inline] - fn write(&self, writer: &mut W) -> Result<(), DecodeError> { - Ok(writer.write_all(&[if *self {1} else {0}])?) + fn write(&self, writer: &mut W) -> Result<(), ::std::io::Error> { + writer.write_all(&[if *self {1} else {0}]) } } impl Readable for bool { @@ -102,12 +182,11 @@ impl Readable for bool { // u8 arrays macro_rules! impl_array { ( $size:expr ) => ( - impl Writeable for [u8; $size] + impl Writeable for [u8; $size] { #[inline] - fn write(&self, w: &mut W) -> Result<(), DecodeError> { - w.write_all(self)?; - Ok(()) + fn write(&self, w: &mut W) -> Result<(), ::std::io::Error> { + w.write_all(self) } } @@ -130,13 +209,12 @@ impl_array!(64); // for Signature impl_array!(1300); // for OnionPacket.hop_data // HashMap -impl Writeable for HashMap - where W: Writer, - K: Writeable + Eq + Hash, - V: Writeable +impl Writeable for HashMap + where K: Writeable + Eq + Hash, + V: Writeable { #[inline] - fn write(&self, w: &mut W) -> Result<(), DecodeError> { + fn write(&self, w: &mut W) -> Result<(), ::std::io::Error> { (self.len() as u16).write(w)?; for (key, value) in self.iter() { key.write(w)?; @@ -163,17 +241,28 @@ impl Readable for HashMap } // Vectors -impl> Writeable for Vec { +impl Writeable for Vec { #[inline] - fn write(&self, w: &mut W) -> Result<(), DecodeError> { - let byte_size = (self.len() as usize) - .checked_mul(mem::size_of::()) - .ok_or(DecodeError::BadLengthDescriptor)?; - if byte_size > MAX_BUF_SIZE { - return Err(DecodeError::BadLengthDescriptor); - } + fn write(&self, w: &mut W) -> Result<(), ::std::io::Error> { + (self.len() as u16).write(w)?; + w.write_all(&self) + } +} + +impl Readable for Vec { + #[inline] + fn read(r: &mut R) -> Result { + let len: u16 = Readable::read(r)?; + let mut ret = Vec::with_capacity(len as usize); + ret.resize(len as usize, 0); + r.read_exact(&mut ret)?; + Ok(ret) + } +} +impl Writeable for Vec { + #[inline] + fn write(&self, w: &mut W) -> Result<(), ::std::io::Error> { (self.len() as u16).write(w)?; - // performance with Vec for e in self.iter() { e.write(w)?; } @@ -181,25 +270,26 @@ impl> Writeable for Vec { } } -impl> Readable for Vec { +impl Readable for Vec { #[inline] fn read(r: &mut R) -> Result { let len: u16 = Readable::read(r)?; let byte_size = (len as usize) - .checked_mul(mem::size_of::()) + .checked_mul(33) .ok_or(DecodeError::BadLengthDescriptor)?; if byte_size > MAX_BUF_SIZE { return Err(DecodeError::BadLengthDescriptor); } let mut ret = Vec::with_capacity(len as usize); - for _ in 0..len { ret.push(T::read(r)?); } + for _ in 0..len { ret.push(Signature::read(r)?); } Ok(ret) } } -impl Writeable for Script { - fn write(&self, w: &mut W) -> Result<(), DecodeError> { - self.to_bytes().to_vec().write(w) +impl Writeable for Script { + fn write(&self, w: &mut W) -> Result<(), ::std::io::Error> { + (self.len() as u16).write(w)?; + w.write_all(self.as_bytes()) } } @@ -212,8 +302,8 @@ impl Readable for Script { } } -impl Writeable for Option