X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Futil%2Fser.rs;h=928cc61946e46f358a70e82672b06bda1dec4867;hb=153d831ccc931683dbd505bdd07c915409e9a9e1;hp=44725e722321cab2c99f0888a2a939442090e9b3;hpb=b75a558a1de8e575bd501ccc64382e5b075c471e;p=rust-lightning diff --git a/lightning/src/util/ser.rs b/lightning/src/util/ser.rs index 44725e72..928cc619 100644 --- a/lightning/src/util/ser.rs +++ b/lightning/src/util/ser.rs @@ -383,6 +383,40 @@ impl Readable for BigSize { } } +/// The lightning protocol uses u16s for lengths in most cases. As our serialization framework +/// primarily targets that, we must as well. However, because we may serialize objects that have +/// more than 65K entries, we need to be able to store larger values. Thus, we define a variable +/// length integer here that is backwards-compatible for values < 0xffff. We treat 0xffff as +/// "read eight more bytes". +/// +/// To ensure we only have one valid encoding per value, we add 0xffff to values written as eight +/// bytes. Thus, 0xfffe is serialized as 0xfffe, whereas 0xffff is serialized as +/// 0xffff0000000000000000 (i.e. read-eight-bytes then zero). +struct CollectionLength(pub u64); +impl Writeable for CollectionLength { + #[inline] + fn write(&self, writer: &mut W) -> Result<(), io::Error> { + if self.0 < 0xffff { + (self.0 as u16).write(writer) + } else { + 0xffffu16.write(writer)?; + (self.0 - 0xffff).write(writer) + } + } +} + +impl Readable for CollectionLength { + #[inline] + fn read(r: &mut R) -> Result { + let mut val: u64 = ::read(r)? as u64; + if val == 0xffff { + val = ::read(r)? + .checked_add(0xffff).ok_or(DecodeError::InvalidValue)?; + } + Ok(CollectionLength(val)) + } +} + /// In TLV we occasionally send fields which only consist of, or potentially end with, a /// variable-length integer which is simply truncated by skipping high zero bytes. This type /// encapsulates such integers implementing [`Readable`]/[`Writeable`] for them. @@ -590,6 +624,26 @@ impl<'a, T> From<&'a Vec> for WithoutLength<&'a Vec> { fn from(v: &'a Vec) -> Self { Self(v) } } +#[derive(Debug)] +pub(crate) struct Iterable<'a, I: Iterator + Clone, T: 'a>(pub I); + +impl<'a, I: Iterator + Clone, T: 'a + Writeable> Writeable for Iterable<'a, I, T> { + #[inline] + fn write(&self, writer: &mut W) -> Result<(), io::Error> { + for ref v in self.0.clone() { + v.write(writer)?; + } + Ok(()) + } +} + +#[cfg(test)] +impl<'a, I: Iterator + Clone, T: 'a + PartialEq> PartialEq for Iterable<'a, I, T> { + fn eq(&self, other: &Self) -> bool { + self.0.clone().collect::>() == other.0.clone().collect::>() + } +} + macro_rules! impl_for_map { ($ty: ident, $keybound: ident, $constr: expr) => { impl Writeable for $ty @@ -597,7 +651,7 @@ macro_rules! impl_for_map { { #[inline] fn write(&self, w: &mut W) -> Result<(), io::Error> { - (self.len() as u16).write(w)?; + CollectionLength(self.len() as u64).write(w)?; for (key, value) in self.iter() { key.write(w)?; value.write(w)?; @@ -611,9 +665,9 @@ macro_rules! impl_for_map { { #[inline] fn read(r: &mut R) -> Result { - let len: u16 = Readable::read(r)?; - let mut ret = $constr(len as usize); - for _ in 0..len { + let len: CollectionLength = Readable::read(r)?; + let mut ret = $constr(len.0 as usize); + for _ in 0..len.0 { let k = K::read(r)?; let v_opt = V::read(r)?; if let Some(v) = v_opt { @@ -637,7 +691,7 @@ where T: Writeable + Eq + Hash { #[inline] fn write(&self, w: &mut W) -> Result<(), io::Error> { - (self.len() as u16).write(w)?; + CollectionLength(self.len() as u64).write(w)?; for item in self.iter() { item.write(w)?; } @@ -650,9 +704,9 @@ where T: Readable + Eq + Hash { #[inline] fn read(r: &mut R) -> Result { - let len: u16 = Readable::read(r)?; - let mut ret = HashSet::with_capacity(len as usize); - for _ in 0..len { + let len: CollectionLength = Readable::read(r)?; + let mut ret = HashSet::with_capacity(cmp::min(len.0 as usize, MAX_BUF_SIZE / core::mem::size_of::())); + for _ in 0..len.0 { if !ret.insert(T::read(r)?) { return Err(DecodeError::InvalidValue) } @@ -667,7 +721,7 @@ macro_rules! impl_for_vec { impl<$($name : Writeable),*> Writeable for Vec<$ty> { #[inline] fn write(&self, w: &mut W) -> Result<(), io::Error> { - (self.len() as u16).write(w)?; + CollectionLength(self.len() as u64).write(w)?; for elem in self.iter() { elem.write(w)?; } @@ -678,9 +732,9 @@ macro_rules! impl_for_vec { impl<$($name : Readable),*> Readable for Vec<$ty> { #[inline] fn read(r: &mut R) -> Result { - let len: u16 = Readable::read(r)?; - let mut ret = Vec::with_capacity(cmp::min(len as usize, MAX_BUF_SIZE / core::mem::size_of::<$ty>())); - for _ in 0..len { + let len: CollectionLength = Readable::read(r)?; + let mut ret = Vec::with_capacity(cmp::min(len.0 as usize, MAX_BUF_SIZE / core::mem::size_of::<$ty>())); + for _ in 0..len.0 { if let Some(val) = MaybeReadable::read(r)? { ret.push(val); } @@ -694,7 +748,7 @@ macro_rules! impl_for_vec { impl Writeable for Vec { #[inline] fn write(&self, w: &mut W) -> Result<(), io::Error> { - (self.len() as u16).write(w)?; + CollectionLength(self.len() as u64).write(w)?; w.write_all(&self) } } @@ -702,10 +756,15 @@ impl Writeable for Vec { 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)?; + let mut len: CollectionLength = Readable::read(r)?; + let mut ret = Vec::new(); + while len.0 > 0 { + let readamt = cmp::min(len.0 as usize, MAX_BUF_SIZE); + let readstart = ret.len(); + ret.resize(readstart + readamt, 0); + r.read_exact(&mut ret[readstart..])?; + len.0 -= readamt as u64; + } Ok(ret) } } @@ -1026,6 +1085,24 @@ impl Writeable for (A, B, C) { } } +impl Readable for (A, B, C, D) { + fn read(r: &mut R) -> Result { + let a: A = Readable::read(r)?; + let b: B = Readable::read(r)?; + let c: C = Readable::read(r)?; + let d: D = Readable::read(r)?; + Ok((a, b, c, d)) + } +} +impl Writeable for (A, B, C, D) { + fn write(&self, w: &mut W) -> Result<(), io::Error> { + self.0.write(w)?; + self.1.write(w)?; + self.2.write(w)?; + self.3.write(w) + } +} + impl Writeable for () { fn write(&self, _: &mut W) -> Result<(), io::Error> { Ok(()) @@ -1040,7 +1117,7 @@ impl Readable for () { impl Writeable for String { #[inline] fn write(&self, w: &mut W) -> Result<(), io::Error> { - (self.len() as u16).write(w)?; + CollectionLength(self.len() as u64).write(w)?; w.write_all(self.as_bytes()) } }