Merge pull request #1107 from dunxen/2021-10-swap-pubkey-for-bytearray
[rust-lightning] / lightning / src / ln / msgs.rs
index fa3c6034e49deefe405bd8dc279ceccaa76f06a5..122dd7737b996507e2d8fb5135af443172fb65f8 100644 (file)
@@ -35,7 +35,8 @@ use ln::features::{ChannelFeatures, InitFeatures, NodeFeatures};
 use prelude::*;
 use core::{cmp, fmt};
 use core::fmt::Debug;
-use std::io::Read;
+use io::{self, Read};
+use io_extras::read_to_end;
 
 use util::events::MessageSendEventsProvider;
 use util::logger;
@@ -64,7 +65,7 @@ pub enum DecodeError {
        BadLengthDescriptor,
        /// Error from std::io
        Io(/// (C-not exported) as ErrorKind doesn't have a reasonable mapping
-        ::std::io::ErrorKind),
+        io::ErrorKind),
        /// The message included zlib-compressed values, which we don't support.
        UnsupportedCompression,
 }
@@ -193,7 +194,7 @@ pub struct FundingCreated {
        pub funding_txid: Txid,
        /// The specific output index funding this channel
        pub funding_output_index: u16,
-       /// The signature of the channel initiator (funder) on the funding transaction
+       /// The signature of the channel initiator (funder) on the initial commitment transaction
        pub signature: Signature,
 }
 
@@ -202,7 +203,7 @@ pub struct FundingCreated {
 pub struct FundingSigned {
        /// The channel ID
        pub channel_id: [u8; 32],
-       /// The signature of the channel acceptor (fundee) on the funding transaction
+       /// The signature of the channel acceptor (fundee) on the initial commitment transaction
        pub signature: Signature,
 }
 
@@ -225,6 +226,19 @@ pub struct Shutdown {
        pub scriptpubkey: Script,
 }
 
+/// The minimum and maximum fees which the sender is willing to place on the closing transaction.
+/// This is provided in [`ClosingSigned`] by both sides to indicate the fee range they are willing
+/// to use.
+#[derive(Clone, Debug, PartialEq)]
+pub struct ClosingSignedFeeRange {
+       /// The minimum absolute fee, in satoshis, which the sender is willing to place on the closing
+       /// transaction.
+       pub min_fee_satoshis: u64,
+       /// The maximum absolute fee, in satoshis, which the sender is willing to place on the closing
+       /// transaction.
+       pub max_fee_satoshis: u64,
+}
+
 /// A closing_signed message to be sent or received from a peer
 #[derive(Clone, Debug, PartialEq)]
 pub struct ClosingSigned {
@@ -234,6 +248,9 @@ pub struct ClosingSigned {
        pub fee_satoshis: u64,
        /// A signature on the closing transaction
        pub signature: Signature,
+       /// The minimum and maximum fees which the sender is willing to accept, provided only by new
+       /// nodes.
+       pub fee_range: Option<ClosingSignedFeeRange>,
 }
 
 /// An update_add_htlc message to be sent or received from a peer
@@ -420,7 +437,7 @@ impl NetAddress {
 }
 
 impl Writeable for NetAddress {
-       fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ::std::io::Error> {
+       fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
                match self {
                        &NetAddress::IPv4 { ref addr, ref port } => {
                                1u8.write(writer)?;
@@ -728,35 +745,6 @@ pub struct CommitmentUpdate {
        pub commitment_signed: CommitmentSigned,
 }
 
-/// The information we received from a peer along the route of a payment we originated. This is
-/// returned by ChannelMessageHandler::handle_update_fail_htlc to be passed into
-/// RoutingMessageHandler::handle_htlc_fail_channel_update to update our network map.
-#[derive(Clone, Debug, PartialEq)]
-pub enum HTLCFailChannelUpdate {
-       /// We received an error which included a full ChannelUpdate message.
-       ChannelUpdateMessage {
-               /// The unwrapped message we received
-               msg: ChannelUpdate,
-       },
-       /// We received an error which indicated only that a channel has been closed
-       ChannelClosed {
-               /// The short_channel_id which has now closed.
-               short_channel_id: u64,
-               /// when this true, this channel should be permanently removed from the
-               /// consideration. Otherwise, this channel can be restored as new channel_update is received
-               is_permanent: bool,
-       },
-       /// We received an error which indicated only that a node has failed
-       NodeFailure {
-               /// The node_id that has failed.
-               node_id: PublicKey,
-               /// when this true, node should be permanently removed from the
-               /// consideration. Otherwise, the channels connected to this node can be
-               /// restored as new channel_update is received
-               is_permanent: bool,
-       }
-}
-
 /// Messages could have optional fields to use with extended features
 /// As we wish to serialize these differently from Option<T>s (Options get a tag byte, but
 /// OptionalFeild simply gets Present if there are enough bytes to read into it), we have a
@@ -851,8 +839,6 @@ pub trait RoutingMessageHandler : MessageSendEventsProvider {
        /// Handle an incoming channel_update message, returning true if it should be forwarded on,
        /// false or returning an Err otherwise.
        fn handle_channel_update(&self, msg: &ChannelUpdate) -> Result<bool, LightningError>;
-       /// Handle some updates to the route graph that we learned due to an outbound failed payment.
-       fn handle_htlc_fail_channel_update(&self, update: &HTLCFailChannelUpdate);
        /// Gets a subset of the channel announcements and updates required to dump our routing table
        /// to a remote node, starting at the short_channel_id indicated by starting_point and
        /// including the batch_amount entries immediately higher in numerical value than starting_point.
@@ -885,7 +871,7 @@ pub trait RoutingMessageHandler : MessageSendEventsProvider {
 
 mod fuzzy_internal_msgs {
        use prelude::*;
-       use ln::PaymentSecret;
+       use ln::{PaymentPreimage, PaymentSecret};
 
        // These types aren't intended to be pub, but are exposed for direct fuzzing (as we deserialize
        // them from untrusted input):
@@ -906,6 +892,7 @@ mod fuzzy_internal_msgs {
                },
                FinalNode {
                        payment_data: Option<FinalOnionHopData>,
+                       keysend_preimage: Option<PaymentPreimage>,
                },
        }
 
@@ -978,9 +965,9 @@ impl fmt::Display for DecodeError {
        }
 }
 
-impl From<::std::io::Error> for DecodeError {
-       fn from(e: ::std::io::Error) -> Self {
-               if e.kind() == ::std::io::ErrorKind::UnexpectedEof {
+impl From<io::Error> for DecodeError {
+       fn from(e: io::Error) -> Self {
+               if e.kind() == io::ErrorKind::UnexpectedEof {
                        DecodeError::ShortRead
                } else {
                        DecodeError::Io(e.kind())
@@ -989,7 +976,7 @@ impl From<::std::io::Error> for DecodeError {
 }
 
 impl Writeable for OptionalField<Script> {
-       fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
+       fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
                match *self {
                        OptionalField::Present(ref script) => {
                                // Note that Writeable for script includes the 16-bit length tag for us
@@ -1016,7 +1003,7 @@ impl Readable for OptionalField<Script> {
 }
 
 impl Writeable for OptionalField<u64> {
-       fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
+       fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
                match *self {
                        OptionalField::Present(ref value) => {
                                value.write(w)?;
@@ -1035,10 +1022,7 @@ impl Readable for OptionalField<u64> {
 }
 
 
-impl_writeable_len_match!(AcceptChannel, {
-               {AcceptChannel{ shutdown_scriptpubkey: OptionalField::Present(ref script), .. }, 270 + 2 + script.len()},
-               {_, 270}
-       }, {
+impl_writeable_msg!(AcceptChannel, {
        temporary_channel_id,
        dust_limit_satoshis,
        max_htlc_value_in_flight_msat,
@@ -1054,18 +1038,17 @@ impl_writeable_len_match!(AcceptChannel, {
        htlc_basepoint,
        first_per_commitment_point,
        shutdown_scriptpubkey
-});
+}, {});
 
-impl_writeable!(AnnouncementSignatures, 32+8+64*2, {
+impl_writeable_msg!(AnnouncementSignatures, {
        channel_id,
        short_channel_id,
        node_signature,
        bitcoin_signature
-});
+}, {});
 
 impl Writeable for ChannelReestablish {
-       fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
-               w.size_hint(if let OptionalField::Present(..) = self.data_loss_protect { 32+2*8+33+32 } else { 32+2*8 });
+       fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
                self.channel_id.write(w)?;
                self.next_local_commitment_number.write(w)?;
                self.next_remote_commitment_number.write(w)?;
@@ -1101,47 +1084,47 @@ impl Readable for ChannelReestablish{
        }
 }
 
-impl_writeable!(ClosingSigned, 32+8+64, {
-       channel_id,
-       fee_satoshis,
-       signature
+impl_writeable_msg!(ClosingSigned,
+       { channel_id, fee_satoshis, signature },
+       { (1, fee_range, option) }
+);
+
+impl_writeable!(ClosingSignedFeeRange, {
+       min_fee_satoshis,
+       max_fee_satoshis
 });
 
-impl_writeable_len_match!(CommitmentSigned, {
-               { CommitmentSigned { ref htlc_signatures, .. }, 32+64+2+htlc_signatures.len()*64 }
-       }, {
+impl_writeable_msg!(CommitmentSigned, {
        channel_id,
        signature,
        htlc_signatures
-});
+}, {});
 
-impl_writeable_len_match!(DecodedOnionErrorPacket, {
-               { DecodedOnionErrorPacket { ref failuremsg, ref pad, .. }, 32 + 4 + failuremsg.len() + pad.len() }
-       }, {
+impl_writeable!(DecodedOnionErrorPacket, {
        hmac,
        failuremsg,
        pad
 });
 
-impl_writeable!(FundingCreated, 32+32+2+64, {
+impl_writeable_msg!(FundingCreated, {
        temporary_channel_id,
        funding_txid,
        funding_output_index,
        signature
-});
+}, {});
 
-impl_writeable!(FundingSigned, 32+64, {
+impl_writeable_msg!(FundingSigned, {
        channel_id,
        signature
-});
+}, {});
 
-impl_writeable!(FundingLocked, 32+33, {
+impl_writeable_msg!(FundingLocked, {
        channel_id,
-       next_per_commitment_point
-});
+       next_per_commitment_point,
+}, {});
 
 impl Writeable for Init {
-       fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
+       fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
                // global_features gets the bottom 13 bits of our features, and local_features gets all of
                // our relevant feature bits. This keeps us compatible with old nodes.
                self.features.write_up_to_13(w)?;
@@ -1159,10 +1142,7 @@ impl Readable for Init {
        }
 }
 
-impl_writeable_len_match!(OpenChannel, {
-               { OpenChannel { shutdown_scriptpubkey: OptionalField::Present(ref script), .. }, 319 + 2 + script.len() },
-               { _, 319 }
-       }, {
+impl_writeable_msg!(OpenChannel, {
        chain_hash,
        temporary_channel_id,
        funding_satoshis,
@@ -1182,56 +1162,55 @@ impl_writeable_len_match!(OpenChannel, {
        first_per_commitment_point,
        channel_flags,
        shutdown_scriptpubkey
-});
+}, {});
 
-impl_writeable!(RevokeAndACK, 32+32+33, {
+impl_writeable_msg!(RevokeAndACK, {
        channel_id,
        per_commitment_secret,
        next_per_commitment_point
-});
+}, {});
 
-impl_writeable_len_match!(Shutdown, {
-               { Shutdown { ref scriptpubkey, .. }, 32 + 2 + scriptpubkey.len() }
-       }, {
+impl_writeable_msg!(Shutdown, {
        channel_id,
        scriptpubkey
-});
+}, {});
 
-impl_writeable_len_match!(UpdateFailHTLC, {
-               { UpdateFailHTLC { ref reason, .. }, 32 + 10 + reason.data.len() }
-       }, {
+impl_writeable_msg!(UpdateFailHTLC, {
        channel_id,
        htlc_id,
        reason
-});
+}, {});
 
-impl_writeable!(UpdateFailMalformedHTLC, 32+8+32+2, {
+impl_writeable_msg!(UpdateFailMalformedHTLC, {
        channel_id,
        htlc_id,
        sha256_of_onion,
        failure_code
-});
+}, {});
 
-impl_writeable!(UpdateFee, 32+4, {
+impl_writeable_msg!(UpdateFee, {
        channel_id,
        feerate_per_kw
-});
+}, {});
 
-impl_writeable!(UpdateFulfillHTLC, 32+8+32, {
+impl_writeable_msg!(UpdateFulfillHTLC, {
        channel_id,
        htlc_id,
        payment_preimage
-});
+}, {});
 
-impl_writeable_len_match!(OnionErrorPacket, {
-               { OnionErrorPacket { ref data, .. }, 2 + data.len() }
-       }, {
+// Note that this is written as a part of ChannelManager objects, and thus cannot change its
+// serialization format in a way which assumes we know the total serialized length/message end
+// position.
+impl_writeable!(OnionErrorPacket, {
        data
 });
 
+// Note that this is written as a part of ChannelManager objects, and thus cannot change its
+// serialization format in a way which assumes we know the total serialized length/message end
+// position.
 impl Writeable for OnionPacket {
-       fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
-               w.size_hint(1 + 33 + 20*65 + 32);
+       fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
                self.version.write(w)?;
                match self.public_key {
                        Ok(pubkey) => pubkey.write(w)?,
@@ -1258,18 +1237,17 @@ impl Readable for OnionPacket {
        }
 }
 
-impl_writeable!(UpdateAddHTLC, 32+8+8+32+4+1366, {
+impl_writeable_msg!(UpdateAddHTLC, {
        channel_id,
        htlc_id,
        amount_msat,
        payment_hash,
        cltv_expiry,
        onion_routing_packet
-});
+}, {});
 
 impl Writeable for FinalOnionHopData {
-       fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
-               w.size_hint(32 + 8 - (self.total_msat.leading_zeros()/8) as usize);
+       fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
                self.payment_secret.0.write(w)?;
                HighZeroBytesDroppedVarInt(self.total_msat).write(w)
        }
@@ -1284,8 +1262,7 @@ impl Readable for FinalOnionHopData {
 }
 
 impl Writeable for OnionHopData {
-       fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
-               w.size_hint(33);
+       fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
                // Note that this should never be reachable if Rust-Lightning generated the message, as we
                // check values are sane long before we get here, though its possible in the future
                // user-generated messages may hit this.
@@ -1305,14 +1282,15 @@ impl Writeable for OnionHopData {
                                        (6, short_channel_id, required)
                                });
                        },
-                       OnionHopDataFormat::FinalNode { ref payment_data } => {
+                       OnionHopDataFormat::FinalNode { ref payment_data, ref keysend_preimage } => {
                                if let Some(final_data) = payment_data {
                                        if final_data.total_msat > MAX_VALUE_MSAT { panic!("We should never be sending infinite/overflow onion payments"); }
                                }
                                encode_varint_length_prefixed_tlv!(w, {
                                        (2, HighZeroBytesDroppedVarInt(self.amt_to_forward), required),
                                        (4, HighZeroBytesDroppedVarInt(self.outgoing_cltv_value), required),
-                                       (8, payment_data, option)
+                                       (8, payment_data, option),
+                                       (5482373484, keysend_preimage, option)
                                });
                        },
                }
@@ -1335,11 +1313,14 @@ impl Readable for OnionHopData {
                        let mut cltv_value = HighZeroBytesDroppedVarInt(0u32);
                        let mut short_id: Option<u64> = None;
                        let mut payment_data: Option<FinalOnionHopData> = None;
+                       let mut keysend_preimage: Option<PaymentPreimage> = None;
+                       // The TLV type is chosen to be compatible with lnd and c-lightning.
                        decode_tlv_stream!(&mut rd, {
                                (2, amt, required),
                                (4, cltv_value, required),
                                (6, short_id, option),
                                (8, payment_data, option),
+                               (5482373484, keysend_preimage, option)
                        });
                        rd.eat_remaining().map_err(|_| DecodeError::ShortRead)?;
                        let format = if let Some(short_channel_id) = short_id {
@@ -1354,7 +1335,8 @@ impl Readable for OnionHopData {
                                        }
                                }
                                OnionHopDataFormat::FinalNode {
-                                       payment_data
+                                       payment_data,
+                                       keysend_preimage,
                                }
                        };
                        (format, amt.0, cltv_value.0)
@@ -1380,8 +1362,7 @@ impl Readable for OnionHopData {
 }
 
 impl Writeable for Ping {
-       fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
-               w.size_hint(self.byteslen as usize + 4);
+       fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
                self.ponglen.write(w)?;
                vec![0u8; self.byteslen as usize].write(w)?; // size-unchecked write
                Ok(())
@@ -1402,8 +1383,7 @@ impl Readable for Ping {
 }
 
 impl Writeable for Pong {
-       fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
-               w.size_hint(self.byteslen as usize + 2);
+       fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
                vec![0u8; self.byteslen as usize].write(w)?; // size-unchecked write
                Ok(())
        }
@@ -1422,8 +1402,7 @@ impl Readable for Pong {
 }
 
 impl Writeable for UnsignedChannelAnnouncement {
-       fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
-               w.size_hint(2 + 32 + 8 + 4*33 + self.features.byte_count() + self.excess_data.len());
+       fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
                self.features.write(w)?;
                self.chain_hash.write(w)?;
                self.short_channel_id.write(w)?;
@@ -1446,19 +1425,12 @@ impl Readable for UnsignedChannelAnnouncement {
                        node_id_2: Readable::read(r)?,
                        bitcoin_key_1: Readable::read(r)?,
                        bitcoin_key_2: Readable::read(r)?,
-                       excess_data: {
-                               let mut excess_data = vec![];
-                               r.read_to_end(&mut excess_data)?;
-                               excess_data
-                       },
+                       excess_data: read_to_end(r)?,
                })
        }
 }
 
-impl_writeable_len_match!(ChannelAnnouncement, {
-               { ChannelAnnouncement { contents: UnsignedChannelAnnouncement {ref features, ref excess_data, ..}, .. },
-                       2 + 32 + 8 + 4*33 + features.byte_count() + excess_data.len() + 4*64 }
-       }, {
+impl_writeable!(ChannelAnnouncement, {
        node_signature_1,
        node_signature_2,
        bitcoin_signature_1,
@@ -1467,14 +1439,11 @@ impl_writeable_len_match!(ChannelAnnouncement, {
 });
 
 impl Writeable for UnsignedChannelUpdate {
-       fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
-               let mut size = 64 + self.excess_data.len();
+       fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
                let mut message_flags: u8 = 0;
                if let OptionalField::Present(_) = self.htlc_maximum_msat {
-                       size += 8;
                        message_flags = 1;
                }
-               w.size_hint(size);
                self.chain_hash.write(w)?;
                self.short_channel_id.write(w)?;
                self.timestamp.write(w)?;
@@ -1508,26 +1477,18 @@ impl Readable for UnsignedChannelUpdate {
                        fee_base_msat: Readable::read(r)?,
                        fee_proportional_millionths: Readable::read(r)?,
                        htlc_maximum_msat: if has_htlc_maximum_msat { Readable::read(r)? } else { OptionalField::Absent },
-                       excess_data: {
-                               let mut excess_data = vec![];
-                               r.read_to_end(&mut excess_data)?;
-                               excess_data
-                       },
+                       excess_data: read_to_end(r)?,
                })
        }
 }
 
-impl_writeable_len_match!(ChannelUpdate, {
-               { ChannelUpdate { contents: UnsignedChannelUpdate {ref excess_data, ref htlc_maximum_msat, ..}, .. },
-                       64 + 64 + excess_data.len() + if let OptionalField::Present(_) = htlc_maximum_msat { 8 } else { 0 } }
-       }, {
+impl_writeable!(ChannelUpdate, {
        signature,
        contents
 });
 
 impl Writeable for ErrorMessage {
-       fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
-               w.size_hint(32 + 2 + self.data.len());
+       fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
                self.channel_id.write(w)?;
                (self.data.len() as u16).write(w)?;
                w.write_all(self.data.as_bytes())?;
@@ -1541,9 +1502,8 @@ impl Readable for ErrorMessage {
                        channel_id: Readable::read(r)?,
                        data: {
                                let mut sz: usize = <u16 as Readable>::read(r)? as usize;
-                               let mut data = vec![];
-                               let data_len = r.read_to_end(&mut data)?;
-                               sz = cmp::min(data_len, sz);
+                               let data = read_to_end(r)?;
+                               sz = cmp::min(data.len(), sz);
                                match String::from_utf8(data[..sz as usize].to_vec()) {
                                        Ok(s) => s,
                                        Err(_) => return Err(DecodeError::InvalidValue),
@@ -1554,8 +1514,7 @@ impl Readable for ErrorMessage {
 }
 
 impl Writeable for UnsignedNodeAnnouncement {
-       fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
-               w.size_hint(76 + self.features.byte_count() + self.addresses.len()*38 + self.excess_address_data.len() + self.excess_data.len());
+       fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
                self.features.write(w)?;
                self.timestamp.write(w)?;
                self.node_id.write(w)?;
@@ -1624,7 +1583,7 @@ impl Readable for UnsignedNodeAnnouncement {
                        }
                        Vec::new()
                };
-               r.read_to_end(&mut excess_data)?;
+               excess_data.extend(read_to_end(r)?.iter());
                Ok(UnsignedNodeAnnouncement {
                        features,
                        timestamp,
@@ -1638,10 +1597,7 @@ impl Readable for UnsignedNodeAnnouncement {
        }
 }
 
-impl_writeable_len_match!(NodeAnnouncement, <=, {
-               { NodeAnnouncement { contents: UnsignedNodeAnnouncement { ref features, ref addresses, ref excess_address_data, ref excess_data, ..}, .. },
-                       64 + 76 + features.byte_count() + addresses.len()*(NetAddress::MAX_LEN as usize + 1) + excess_address_data.len() + excess_data.len() }
-       }, {
+impl_writeable!(NodeAnnouncement, {
        signature,
        contents
 });
@@ -1681,11 +1637,10 @@ impl Readable for QueryShortChannelIds {
 }
 
 impl Writeable for QueryShortChannelIds {
-       fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
+       fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
                // Calculated from 1-byte encoding_type plus 8-bytes per short_channel_id
                let encoding_len: u16 = 1 + self.short_channel_ids.len() as u16 * 8;
 
-               w.size_hint(32 + 2 + encoding_len as usize);
                self.chain_hash.write(w)?;
                encoding_len.write(w)?;
 
@@ -1700,25 +1655,10 @@ impl Writeable for QueryShortChannelIds {
        }
 }
 
-impl Readable for ReplyShortChannelIdsEnd {
-       fn read<R: Read>(r: &mut R) -> Result<Self, DecodeError> {
-               let chain_hash: BlockHash = Readable::read(r)?;
-               let full_information: bool = Readable::read(r)?;
-               Ok(ReplyShortChannelIdsEnd {
-                       chain_hash,
-                       full_information,
-               })
-       }
-}
-
-impl Writeable for ReplyShortChannelIdsEnd {
-       fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
-               w.size_hint(32 + 1);
-               self.chain_hash.write(w)?;
-               self.full_information.write(w)?;
-               Ok(())
-       }
-}
+impl_writeable_msg!(ReplyShortChannelIdsEnd, {
+       chain_hash,
+       full_information,
+}, {});
 
 impl QueryChannelRange {
        /**
@@ -1733,28 +1673,11 @@ impl QueryChannelRange {
        }
 }
 
-impl Readable for QueryChannelRange {
-       fn read<R: Read>(r: &mut R) -> Result<Self, DecodeError> {
-               let chain_hash: BlockHash = Readable::read(r)?;
-               let first_blocknum: u32 = Readable::read(r)?;
-               let number_of_blocks: u32 = Readable::read(r)?;
-               Ok(QueryChannelRange {
-                       chain_hash,
-                       first_blocknum,
-                       number_of_blocks
-               })
-       }
-}
-
-impl Writeable for QueryChannelRange {
-       fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
-               w.size_hint(32 + 4 + 4);
-               self.chain_hash.write(w)?;
-               self.first_blocknum.write(w)?;
-               self.number_of_blocks.write(w)?;
-               Ok(())
-       }
-}
+impl_writeable_msg!(QueryChannelRange, {
+       chain_hash,
+       first_blocknum,
+       number_of_blocks
+}, {});
 
 impl Readable for ReplyChannelRange {
        fn read<R: Read>(r: &mut R) -> Result<Self, DecodeError> {
@@ -1797,9 +1720,8 @@ impl Readable for ReplyChannelRange {
 }
 
 impl Writeable for ReplyChannelRange {
-       fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
+       fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
                let encoding_len: u16 = 1 + self.short_channel_ids.len() as u16 * 8;
-               w.size_hint(32 + 4 + 4 + 1 + 2 + encoding_len as usize);
                self.chain_hash.write(w)?;
                self.first_blocknum.write(w)?;
                self.number_of_blocks.write(w)?;
@@ -1815,29 +1737,11 @@ impl Writeable for ReplyChannelRange {
        }
 }
 
-impl Readable for GossipTimestampFilter {
-       fn read<R: Read>(r: &mut R) -> Result<Self, DecodeError> {
-               let chain_hash: BlockHash = Readable::read(r)?;
-               let first_timestamp: u32 = Readable::read(r)?;
-               let timestamp_range: u32 = Readable::read(r)?;
-               Ok(GossipTimestampFilter {
-                       chain_hash,
-                       first_timestamp,
-                       timestamp_range,
-               })
-       }
-}
-
-impl Writeable for GossipTimestampFilter {
-       fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
-               w.size_hint(32 + 4 + 4);
-               self.chain_hash.write(w)?;
-               self.first_timestamp.write(w)?;
-               self.timestamp_range.write(w)?;
-               Ok(())
-       }
-}
-
+impl_writeable_msg!(GossipTimestampFilter, {
+       chain_hash,
+       first_timestamp,
+       timestamp_range,
+}, {});
 
 #[cfg(test)]
 mod tests {
@@ -1857,8 +1761,8 @@ mod tests {
        use bitcoin::secp256k1::key::{PublicKey,SecretKey};
        use bitcoin::secp256k1::{Secp256k1, Message};
 
+       use io::Cursor;
        use prelude::*;
-       use std::io::Cursor;
 
        #[test]
        fn encoding_channel_reestablish_no_secret() {
@@ -2325,10 +2229,27 @@ mod tests {
                        channel_id: [2; 32],
                        fee_satoshis: 2316138423780173,
                        signature: sig_1,
+                       fee_range: None,
                };
                let encoded_value = closing_signed.encode();
                let target_value = hex::decode("020202020202020202020202020202020202020202020202020202020202020200083a840000034dd977cb9b53d93a6ff64bb5f1e158b4094b66e798fb12911168a3ccdf80a83096340a6a95da0ae8d9f776528eecdbb747eb6b545495a4319ed5378e35b21e073a").unwrap();
                assert_eq!(encoded_value, target_value);
+               assert_eq!(msgs::ClosingSigned::read(&mut Cursor::new(&target_value)).unwrap(), closing_signed);
+
+               let closing_signed_with_range = msgs::ClosingSigned {
+                       channel_id: [2; 32],
+                       fee_satoshis: 2316138423780173,
+                       signature: sig_1,
+                       fee_range: Some(msgs::ClosingSignedFeeRange {
+                               min_fee_satoshis: 0xdeadbeef,
+                               max_fee_satoshis: 0x1badcafe01234567,
+                       }),
+               };
+               let encoded_value_with_range = closing_signed_with_range.encode();
+               let target_value_with_range = hex::decode("020202020202020202020202020202020202020202020202020202020202020200083a840000034dd977cb9b53d93a6ff64bb5f1e158b4094b66e798fb12911168a3ccdf80a83096340a6a95da0ae8d9f776528eecdbb747eb6b545495a4319ed5378e35b21e073a011000000000deadbeef1badcafe01234567").unwrap();
+               assert_eq!(encoded_value_with_range, target_value_with_range);
+               assert_eq!(msgs::ClosingSigned::read(&mut Cursor::new(&target_value_with_range)).unwrap(),
+                       closing_signed_with_range);
        }
 
        #[test]
@@ -2534,6 +2455,7 @@ mod tests {
                let mut msg = msgs::OnionHopData {
                        format: OnionHopDataFormat::FinalNode {
                                payment_data: None,
+                               keysend_preimage: None,
                        },
                        amt_to_forward: 0x0badf00d01020304,
                        outgoing_cltv_value: 0xffffffff,
@@ -2542,7 +2464,7 @@ mod tests {
                let target_value = hex::decode("1002080badf00d010203040404ffffffff").unwrap();
                assert_eq!(encoded_value, target_value);
                msg = Readable::read(&mut Cursor::new(&target_value[..])).unwrap();
-               if let OnionHopDataFormat::FinalNode { payment_data: None } = msg.format { } else { panic!(); }
+               if let OnionHopDataFormat::FinalNode { payment_data: None, .. } = msg.format { } else { panic!(); }
                assert_eq!(msg.amt_to_forward, 0x0badf00d01020304);
                assert_eq!(msg.outgoing_cltv_value, 0xffffffff);
        }
@@ -2556,6 +2478,7 @@ mod tests {
                                        payment_secret: expected_payment_secret,
                                        total_msat: 0x1badca1f
                                }),
+                               keysend_preimage: None,
                        },
                        amt_to_forward: 0x0badf00d01020304,
                        outgoing_cltv_value: 0xffffffff,
@@ -2568,7 +2491,8 @@ mod tests {
                        payment_data: Some(FinalOnionHopData {
                                payment_secret,
                                total_msat: 0x1badca1f
-                       })
+                       }),
+                       keysend_preimage: None,
                } = msg.format {
                        assert_eq!(payment_secret, expected_payment_secret);
                } else { panic!(); }