X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Futil%2Fser.rs;h=1a055701fe3929a9cdcbdf2451571dfb205923ef;hb=0d75a63ead0601ae36e7141834f67c881c31eb85;hp=38133d59670dd5c717a3d1dc850fe3296fc316c6;hpb=32ca8ec13e0928cbb4f7067a3fb6d41f39691d1c;p=rust-lightning diff --git a/lightning/src/util/ser.rs b/lightning/src/util/ser.rs index 38133d59..1a055701 100644 --- a/lightning/src/util/ser.rs +++ b/lightning/src/util/ser.rs @@ -1,33 +1,46 @@ +// This file is Copyright its original authors, visible in version control +// history. +// +// This file is licensed under the Apache License, Version 2.0 or the MIT license +// , at your option. +// You may not use this file except in accordance with one or both of these +// licenses. + //! 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::sync::Mutex; use std::cmp; -use secp256k1::Signature; -use secp256k1::key::{PublicKey, SecretKey}; +use bitcoin::secp256k1::Signature; +use bitcoin::secp256k1::key::{PublicKey, SecretKey}; +use bitcoin::secp256k1::constants::{PUBLIC_KEY_SIZE, COMPACT_SIGNATURE_SIZE}; use bitcoin::blockdata::script::Script; use bitcoin::blockdata::transaction::{OutPoint, Transaction, TxOut}; use bitcoin::consensus; use bitcoin::consensus::Encodable; -use bitcoin_hashes::sha256d::Hash as Sha256dHash; +use bitcoin::hashes::sha256d::Hash as Sha256dHash; +use bitcoin::hash_types::{Txid, BlockHash}; use std::marker::Sized; use ln::msgs::DecodeError; -use ln::channelmanager::{PaymentPreimage, PaymentHash}; +use ln::channelmanager::{PaymentPreimage, PaymentHash, PaymentSecret}; use util::byte_utils; 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; +/// serialization buffer size +pub const MAX_BUF_SIZE: usize = 64 * 1024; /// 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. +/// +/// (C-not exported) as we only export serialization to/from byte arrays instead 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>; @@ -150,6 +163,8 @@ impl Read for ReadTrackingReader { } /// A trait that various rust-lightning types implement allowing them to be written out to a Writer +/// +/// (C-not exported) as we only export serialization to/from byte arrays instead pub trait Writeable { /// Writes self out to the given Writer fn write(&self, writer: &mut W) -> Result<(), ::std::io::Error>; @@ -172,7 +187,13 @@ pub trait Writeable { } } +impl<'a, T: Writeable> Writeable for &'a T { + fn write(&self, writer: &mut W) -> Result<(), ::std::io::Error> { (*self).write(writer) } +} + /// A trait that various rust-lightning types implement allowing them to be read in from a Read +/// +/// (C-not exported) as we only export serialization to/from byte arrays instead pub trait Readable where Self: Sized { @@ -182,6 +203,8 @@ pub trait Readable /// 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. +/// +/// (C-not exported) as we only export serialization to/from byte arrays instead pub trait ReadableArgs

where Self: Sized { @@ -190,6 +213,8 @@ pub trait ReadableArgs

} /// A trait that various rust-lightning types implement allowing them to (maybe) be read in from a Read +/// +/// (C-not exported) as we only export serialization to/from byte arrays instead pub trait MaybeReadable where Self: Sized { @@ -399,8 +424,8 @@ 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!(PUBLIC_KEY_SIZE); // for PublicKey +impl_array!(COMPACT_SIGNATURE_SIZE); // for Signature impl_array!(1300); // for OnionPacket.hop_data // HashMap @@ -469,7 +494,7 @@ impl Readable for Vec { fn read(r: &mut R) -> Result { let len: u16 = Readable::read(r)?; let byte_size = (len as usize) - .checked_mul(33) + .checked_mul(COMPACT_SIGNATURE_SIZE) .ok_or(DecodeError::BadLengthDescriptor)?; if byte_size > MAX_BUF_SIZE { return Err(DecodeError::BadLengthDescriptor); @@ -504,7 +529,7 @@ impl Writeable for PublicKey { impl Readable for PublicKey { fn read(r: &mut R) -> Result { - let buf: [u8; 33] = Readable::read(r)?; + let buf: [u8; PUBLIC_KEY_SIZE] = Readable::read(r)?; match PublicKey::from_slice(&buf) { Ok(key) => Ok(key), Err(_) => return Err(DecodeError::InvalidValue), @@ -538,7 +563,7 @@ impl Writeable for Sha256dHash { impl Readable for Sha256dHash { fn read(r: &mut R) -> Result { - use bitcoin_hashes::Hash; + use bitcoin::hashes::Hash; let buf: [u8; 32] = Readable::read(r)?; Ok(Sha256dHash::from_slice(&buf[..]).unwrap()) @@ -553,7 +578,7 @@ impl Writeable for Signature { impl Readable for Signature { fn read(r: &mut R) -> Result { - let buf: [u8; 64] = Readable::read(r)?; + let buf: [u8; COMPACT_SIGNATURE_SIZE] = Readable::read(r)?; match Signature::from_compact(&buf) { Ok(sig) => Ok(sig), Err(_) => return Err(DecodeError::InvalidValue), @@ -587,12 +612,27 @@ impl Readable for PaymentHash { } } +impl Writeable for PaymentSecret { + fn write(&self, w: &mut W) -> Result<(), ::std::io::Error> { + self.0.write(w) + } +} + +impl Readable for PaymentSecret { + fn read(r: &mut R) -> Result { + let buf: [u8; 32] = Readable::read(r)?; + Ok(PaymentSecret(buf)) + } +} + impl Writeable for Option { fn write(&self, w: &mut W) -> Result<(), ::std::io::Error> { match *self { None => 0u8.write(w)?, Some(ref data) => { - 1u8.write(w)?; + let mut len_calc = LengthCalculatingWriter(0); + data.write(&mut len_calc).expect("No in-memory data may fail to serialize"); + BigSize(len_calc.0 as u64 + 1).write(w)?; data.write(w)?; } } @@ -603,14 +643,46 @@ impl Writeable for Option { impl Readable for Option { fn read(r: &mut R) -> Result { - match ::read(r)? { + match BigSize::read(r)?.0 { 0 => Ok(None), - 1 => Ok(Some(Readable::read(r)?)), - _ => return Err(DecodeError::InvalidValue), + len => { + let mut reader = FixedLengthReader::new(r, len - 1); + Ok(Some(Readable::read(&mut reader)?)) + } } } } +impl Writeable for Txid { + fn write(&self, w: &mut W) -> Result<(), ::std::io::Error> { + w.write_all(&self[..]) + } +} + +impl Readable for Txid { + fn read(r: &mut R) -> Result { + use bitcoin::hashes::Hash; + + let buf: [u8; 32] = Readable::read(r)?; + Ok(Txid::from_slice(&buf[..]).unwrap()) + } +} + +impl Writeable for BlockHash { + fn write(&self, w: &mut W) -> Result<(), ::std::io::Error> { + w.write_all(&self[..]) + } +} + +impl Readable for BlockHash { + fn read(r: &mut R) -> Result { + use bitcoin::hashes::Hash; + + let buf: [u8; 32] = Readable::read(r)?; + Ok(BlockHash::from_slice(&buf[..]).unwrap()) + } +} + impl Writeable for OutPoint { fn write(&self, w: &mut W) -> Result<(), ::std::io::Error> { self.txid.write(w)?; @@ -636,8 +708,7 @@ macro_rules! impl_consensus_ser { fn write(&self, writer: &mut W) -> Result<(), ::std::io::Error> { match self.consensus_encode(WriterWriteAdaptor(writer)) { Ok(_) => Ok(()), - Err(consensus::encode::Error::Io(e)) => Err(e), - Err(_) => panic!("We shouldn't get a consensus::encode::Error unless our Write generated an std::io::Error"), + Err(e) => Err(e), } } } @@ -647,7 +718,7 @@ macro_rules! impl_consensus_ser { match consensus::encode::Decodable::consensus_decode(r) { Ok(t) => Ok(t), Err(consensus::encode::Error::Io(ref e)) if e.kind() == ::std::io::ErrorKind::UnexpectedEof => Err(DecodeError::ShortRead), - Err(consensus::encode::Error::Io(e)) => Err(DecodeError::Io(e)), + Err(consensus::encode::Error::Io(e)) => Err(DecodeError::Io(e.kind())), Err(_) => Err(DecodeError::InvalidValue), } }