X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Futil%2Fser.rs;h=02d4a81b39e4418daf45f6cb6fc6f61180b1785e;hb=4a0010d7393bb32305bdb3d859735b7b563462eb;hp=5ff6dc86a0bf91d20df6fb110f67185f8cd5f355;hpb=150c87a089fedb69510498f28d5181eca1562d49;p=rust-lightning diff --git a/lightning/src/util/ser.rs b/lightning/src/util/ser.rs index 5ff6dc86..02d4a81b 100644 --- a/lightning/src/util/ser.rs +++ b/lightning/src/util/ser.rs @@ -11,7 +11,7 @@ //! as ChannelsManagers and ChannelMonitors. use crate::prelude::*; -use crate::io::{self, Read, Write}; +use crate::io::{self, Read, Seek, Write}; use crate::io_extras::{copy, sink}; use core::hash::Hash; use crate::sync::Mutex; @@ -20,8 +20,10 @@ use core::convert::TryFrom; use core::ops::Deref; use bitcoin::secp256k1::{PublicKey, SecretKey}; -use bitcoin::secp256k1::constants::{PUBLIC_KEY_SIZE, SECRET_KEY_SIZE, COMPACT_SIGNATURE_SIZE}; -use bitcoin::secp256k1::ecdsa::Signature; +use bitcoin::secp256k1::constants::{PUBLIC_KEY_SIZE, SECRET_KEY_SIZE, COMPACT_SIGNATURE_SIZE, SCHNORR_SIGNATURE_SIZE}; +use bitcoin::secp256k1::ecdsa; +use bitcoin::secp256k1::schnorr; +use bitcoin::blockdata::constants::ChainHash; use bitcoin::blockdata::script::Script; use bitcoin::blockdata::transaction::{OutPoint, Transaction, TxOut}; use bitcoin::consensus; @@ -218,6 +220,13 @@ pub trait Readable fn read(reader: &mut R) -> Result; } +/// A trait that various rust-lightning types implement allowing them to be read in from a +/// `Read + Seek`. +pub(crate) trait SeekReadable where Self: Sized { + /// Reads a Self in from the given Read + 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. /// @@ -283,39 +292,6 @@ impl From for OptionDeserWrapper { fn from(t: T) -> OptionDeserWrapper { OptionDeserWrapper(Some(t)) } } -/// Wrapper to write each element of a Vec with no length prefix -pub(crate) struct VecWriteWrapper<'a, T: Writeable>(pub &'a Vec); -impl<'a, T: Writeable> Writeable for VecWriteWrapper<'a, T> { - #[inline] - fn write(&self, writer: &mut W) -> Result<(), io::Error> { - for ref v in self.0.iter() { - v.write(writer)?; - } - Ok(()) - } -} - -/// Wrapper to read elements from a given stream until it reaches the end of the stream. -pub(crate) struct VecReadWrapper(pub Vec); -impl Readable for VecReadWrapper { - #[inline] - fn read(mut reader: &mut R) -> Result { - let mut values = Vec::new(); - loop { - let mut track_read = ReadTrackingReader::new(&mut reader); - match MaybeReadable::read(&mut track_read) { - Ok(Some(v)) => { values.push(v); }, - Ok(None) => { }, - // If we failed to read any bytes at all, we reached the end of our TLV - // stream and have simply exhausted all entries. - Err(ref e) if e == &DecodeError::ShortRead && !track_read.have_read => break, - Err(e) => return Err(e), - } - } - Ok(Self(values)) - } -} - pub(crate) struct U48(pub u64); impl Writeable for U48 { #[inline] @@ -451,9 +427,13 @@ macro_rules! impl_writeable_primitive { } } } + impl From<$val_type> for HighZeroBytesDroppedBigSize<$val_type> { + fn from(val: $val_type) -> Self { Self(val) } + } } } +impl_writeable_primitive!(u128, 16); impl_writeable_primitive!(u64, 8); impl_writeable_primitive!(u32, 4); impl_writeable_primitive!(u16, 2); @@ -514,13 +494,13 @@ macro_rules! impl_array { ); } -impl_array!(3); // for rgb +impl_array!(3); // for rgb, ISO 4712 code impl_array!(4); // for IPv4 impl_array!(12); // for OnionV2 impl_array!(16); // for IPv6 impl_array!(32); // for channel id & hmac impl_array!(PUBLIC_KEY_SIZE); // for PublicKey -impl_array!(COMPACT_SIGNATURE_SIZE); // for Signature +impl_array!(64); // for ecdsa::Signature and schnorr::Signature impl_array!(1300); // for OnionPacket.hop_data impl Writeable for [u16; 8] { @@ -546,6 +526,59 @@ impl Readable for [u16; 8] { } } +/// For variable-length values within TLV record where the length is encoded as part of the record. +/// Used to prevent encoding the length twice. +pub(crate) struct WithoutLength(pub T); + +impl Writeable for WithoutLength<&String> { + #[inline] + fn write(&self, w: &mut W) -> Result<(), io::Error> { + w.write_all(self.0.as_bytes()) + } +} +impl Readable for WithoutLength { + #[inline] + fn read(r: &mut R) -> Result { + let v: WithoutLength> = Readable::read(r)?; + Ok(Self(String::from_utf8(v.0).map_err(|_| DecodeError::InvalidValue)?)) + } +} +impl<'a> From<&'a String> for WithoutLength<&'a String> { + fn from(s: &'a String) -> Self { Self(s) } +} + +impl<'a, T: Writeable> Writeable for WithoutLength<&'a Vec> { + #[inline] + fn write(&self, writer: &mut W) -> Result<(), io::Error> { + for ref v in self.0.iter() { + v.write(writer)?; + } + Ok(()) + } +} + +impl Readable for WithoutLength> { + #[inline] + fn read(mut reader: &mut R) -> Result { + let mut values = Vec::new(); + loop { + let mut track_read = ReadTrackingReader::new(&mut reader); + match MaybeReadable::read(&mut track_read) { + Ok(Some(v)) => { values.push(v); }, + Ok(None) => { }, + // If we failed to read any bytes at all, we reached the end of our TLV + // stream and have simply exhausted all entries. + Err(ref e) if e == &DecodeError::ShortRead && !track_read.have_read => break, + Err(e) => return Err(e), + } + } + Ok(Self(values)) + } +} +impl<'a, T> From<&'a Vec> for WithoutLength<&'a Vec> { + fn from(v: &'a Vec) -> Self { Self(v) } +} + // HashMap impl Writeable for HashMap where K: Writeable + Eq + Hash, @@ -632,7 +665,7 @@ impl Readable for Vec { Ok(ret) } } -impl Writeable for Vec { +impl Writeable for Vec { #[inline] fn write(&self, w: &mut W) -> Result<(), io::Error> { (self.len() as u16).write(w)?; @@ -643,7 +676,7 @@ 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)?; @@ -732,20 +765,32 @@ impl Readable for Sha256dHash { } } -impl Writeable for Signature { +impl Writeable for ecdsa::Signature { fn write(&self, w: &mut W) -> Result<(), io::Error> { self.serialize_compact().write(w) } - #[inline] - fn serialized_length(&self) -> usize { - COMPACT_SIGNATURE_SIZE - } } -impl Readable for Signature { +impl Readable for ecdsa::Signature { fn read(r: &mut R) -> Result { let buf: [u8; COMPACT_SIGNATURE_SIZE] = Readable::read(r)?; - match Signature::from_compact(&buf) { + match ecdsa::Signature::from_compact(&buf) { + Ok(sig) => Ok(sig), + Err(_) => return Err(DecodeError::InvalidValue), + } + } +} + +impl Writeable for schnorr::Signature { + fn write(&self, w: &mut W) -> Result<(), io::Error> { + self.as_ref().write(w) + } +} + +impl Readable for schnorr::Signature { + fn read(r: &mut R) -> Result { + let buf: [u8; SCHNORR_SIGNATURE_SIZE] = Readable::read(r)?; + match schnorr::Signature::from_slice(&buf) { Ok(sig) => Ok(sig), Err(_) => return Err(DecodeError::InvalidValue), } @@ -860,6 +905,19 @@ impl Readable for BlockHash { } } +impl Writeable for ChainHash { + fn write(&self, w: &mut W) -> Result<(), io::Error> { + w.write_all(self.as_bytes()) + } +} + +impl Readable for ChainHash { + fn read(r: &mut R) -> Result { + let buf: [u8; 32] = Readable::read(r)?; + Ok(ChainHash::from(&buf[..])) + } +} + impl Writeable for OutPoint { fn write(&self, w: &mut W) -> Result<(), io::Error> { self.txid.write(w)?;