X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=src%2Futil%2Fser.rs;h=575d4668d641875acf4df6a7212aca823e13f9c6;hb=refs%2Fheads%2F2019-01-271-cleanup;hp=299515d9022ed46341754d2eca417a5f48f85fce;hpb=77c26226155fc63ed08de96bd09b03e29c9a8196;p=rust-lightning diff --git a/src/util/ser.rs b/src/util/ser.rs index 299515d9..575d4668 100644 --- a/src/util/ser.rs +++ b/src/util/ser.rs @@ -1,147 +1,199 @@ +//! 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, 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; -pub struct Writer { writer: W } -pub struct Reader { reader: R } - -pub trait Writeable { - fn write(&self, writer: &mut Writer) -> Result<(), DecodeError>; +/// 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); } -pub trait Readable - where Self: Sized, - R: Read -{ - fn read(reader: &mut Reader) -> Result; +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) { } } -impl Writer { - pub fn new(writer: W) -> Writer { - return Writer { writer } - } - pub fn into_inner(self) -> W { self.writer } - pub fn get_ref(&self) -> &W { &self.writer } - fn write_u64(&mut self, v: u64) -> Result<(), DecodeError> { - Ok(self.writer.write_all(&be64_to_array(v))?) - } - fn write_u32(&mut self, v: u32) -> Result<(), DecodeError> { - Ok(self.writer.write_all(&be32_to_array(v))?) +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_u16(&mut self, v: u16) -> Result<(), DecodeError> { - Ok(self.writer.write_all(&be16_to_array(v))?) + fn write(&mut self, buf: &[u8]) -> Result { + self.0.write_all(buf)?; + Ok(buf.len()) } - fn write_u8(&mut self, v: u8) -> Result<(), DecodeError> { - Ok(self.writer.write_all(&[v])?) + fn flush(&mut self) -> Result<(), ::std::io::Error> { + Ok(()) } - fn write_bool(&mut self, v: bool) -> Result<(), DecodeError> { - Ok(self.writer.write_all(&[if v {1} else {0}])?) +} + +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(()) } - pub fn write_all(&mut self, v: &[u8]) -> Result<(), DecodeError> { - Ok(self.writer.write_all(v)?) + fn size_hint(&mut self, size: usize) { + self.0.reserve_exact(size); } } -impl Reader { - pub fn new(reader: R) -> Reader { - return Reader { reader } - } - pub fn into_inner(self) -> R { self.reader } - pub fn get_ref(&self) -> &R { &self.reader } +/// A trait that various rust-lightning types implement allowing them to be written out to a Writer +pub trait Writeable { + /// Writes self out to the given Writer + fn write(&self, writer: &mut W) -> Result<(), ::std::io::Error>; - fn read_u64(&mut self) -> Result { - let mut buf = [0; 8]; - self.reader.read_exact(&mut buf)?; - Ok(slice_to_be64(&buf)) + /// Writes self out to a Vec + fn encode(&self) -> Vec { + let mut msg = VecWriter(Vec::new()); + self.write(&mut msg).unwrap(); + msg.0 } - fn read_u32(&mut self) -> Result { - let mut buf = [0; 4]; - self.reader.read_exact(&mut buf)?; - Ok(slice_to_be32(&buf)) + /// 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 } +} - fn read_u16(&mut self) -> Result { - let mut buf = [0; 2]; - self.reader.read_exact(&mut buf)?; - Ok(slice_to_be16(&buf)) - } +/// A trait that various rust-lightning types implement allowing them to be read in from a Read +pub trait Readable + where Self: Sized, + R: Read +{ + /// Reads a Self in from the given Read + fn read(reader: &mut R) -> Result; +} - fn read_u8(&mut self) -> Result { - let mut buf = [0; 1]; - self.reader.read_exact(&mut buf)?; - Ok(buf[0]) - } - fn read_bool(&mut self) -> Result { - let mut buf = [0; 1]; - self.reader.read_exact(&mut buf)?; - if buf[0] != 0 && buf[0] != 1 { - return Err(DecodeError::InvalidValue); - } - Ok(buf[0] == 1) - } - pub fn read_exact(&mut self, buf: &mut [u8]) -> Result<(), DecodeError> { - Ok(self.reader.read_exact(buf)?) +/// 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)) } - pub fn read_to_end(&mut self, buf: &mut Vec) -> Result { - Ok(self.reader.read_to_end(buf)?) +} +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, $meth_read:ident) => { - impl Writeable for $val_type { + ($val_type:ty, $meth_write:ident, $len: expr, $meth_read:ident) => { + impl Writeable for $val_type { #[inline] - fn write(&self, writer: &mut Writer) -> Result<(), DecodeError> { - writer.$meth_write(*self) + fn write(&self, writer: &mut W) -> Result<(), ::std::io::Error> { + writer.write_all(&$meth_write(*self)) } } - impl Readable for $val_type { + impl Readable for $val_type { #[inline] - fn read(reader: &mut Reader) -> Result<$val_type, DecodeError> { - reader.$meth_read() + fn read(reader: &mut R) -> Result<$val_type, DecodeError> { + let mut buf = [0; $len]; + reader.read_exact(&mut buf)?; + Ok($meth_read(&buf)) } } } } -impl_writeable_primitive!(u64, write_u64, read_u64); -impl_writeable_primitive!(u32, write_u32, read_u32); -impl_writeable_primitive!(u16, write_u16, read_u16); -impl_writeable_primitive!(u8, write_u8, read_u8); -impl_writeable_primitive!(bool, write_bool, read_bool); +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 { + #[inline] + fn write(&self, writer: &mut W) -> Result<(), ::std::io::Error> { + writer.write_all(&[*self]) + } +} +impl Readable for u8 { + #[inline] + fn read(reader: &mut R) -> Result { + let mut buf = [0; 1]; + reader.read_exact(&mut buf)?; + Ok(buf[0]) + } +} + +impl Writeable for bool { + #[inline] + fn write(&self, writer: &mut W) -> Result<(), ::std::io::Error> { + writer.write_all(&[if *self {1} else {0}]) + } +} +impl Readable for bool { + #[inline] + fn read(reader: &mut R) -> Result { + let mut buf = [0; 1]; + reader.read_exact(&mut buf)?; + if buf[0] != 0 && buf[0] != 1 { + return Err(DecodeError::InvalidValue); + } + Ok(buf[0] == 1) + } +} // u8 arrays macro_rules! impl_array { ( $size:expr ) => ( - impl Writeable for [u8; $size] - where W: Write + impl Writeable for [u8; $size] { #[inline] - fn write(&self, w: &mut Writer) -> Result<(), DecodeError> { - w.write_all(self)?; - Ok(()) + fn write(&self, w: &mut W) -> Result<(), ::std::io::Error> { + w.write_all(self) } } - impl Readable for [u8; $size] - where R: Read + impl Readable for [u8; $size] { #[inline] - fn read(r: &mut Reader) -> Result { + fn read(r: &mut R) -> Result { let mut buf = [0u8; $size]; r.read_exact(&mut buf)?; Ok(buf) @@ -151,19 +203,22 @@ macro_rules! impl_array { } //TODO: performance issue with [u8; size] with impl_array!() +impl_array!(3); // for rgb +impl_array!(4); // for IPv4 +impl_array!(10); // for OnionV2 +impl_array!(16); // for IPv6 impl_array!(32); // for channel id & hmac impl_array!(33); // for PublicKey impl_array!(64); // for Signature impl_array!(1300); // for OnionPacket.hop_data // HashMap -impl Writeable for HashMap - where W: Write, - K: Writeable + Eq + Hash, - V: Writeable +impl Writeable for HashMap + where K: Writeable + Eq + Hash, + V: Writeable { #[inline] - fn write(&self, w: &mut Writer) -> 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)?; @@ -179,7 +234,7 @@ impl Readable for HashMap V: Readable { #[inline] - fn read(r: &mut Reader) -> Result { + fn read(r: &mut R) -> Result { let len: u16 = Readable::read(r)?; let mut ret = HashMap::with_capacity(len as usize); for _ in 0..len { @@ -190,17 +245,28 @@ impl Readable for HashMap } // Vectors -impl> Writeable for Vec { +impl Writeable for Vec { #[inline] - fn write(&self, w: &mut Writer) -> 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)?; } @@ -208,30 +274,31 @@ impl> Writeable for Vec { } } -impl> Readable for Vec { +impl Readable for Vec { #[inline] - fn read(r: &mut Reader) -> Result { + 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 Writer) -> 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()) } } impl Readable for Script { - fn read(r: &mut Reader) -> Result { + fn read(r: &mut R) -> Result { let len = >::read(r)? as usize; let mut buf = vec![0; len]; r.read_exact(&mut buf)?; @@ -239,89 +306,117 @@ impl Readable for Script { } } -impl Writeable for Option