Consider anchor outputs value on inbound HTLCs
[rust-lightning] / lightning / src / ln / msgs.rs
index 6bd5ec3f7293fcac5c043bf3437e47eb90127d9d..6043bf35b99d4d85ae79a5656cc75b82e7d6c09e 100644 (file)
@@ -29,24 +29,33 @@ use bitcoin::secp256k1::PublicKey;
 use bitcoin::secp256k1::ecdsa::Signature;
 use bitcoin::{secp256k1, Witness};
 use bitcoin::blockdata::script::Script;
-use bitcoin::hash_types::{Txid, BlockHash};
+use bitcoin::hash_types::Txid;
 
+use crate::blinded_path::payment::ReceiveTlvs;
 use crate::ln::{ChannelId, PaymentPreimage, PaymentHash, PaymentSecret};
 use crate::ln::features::{ChannelFeatures, ChannelTypeFeatures, InitFeatures, NodeFeatures};
 use crate::ln::onion_utils;
 use crate::onion_message;
+use crate::sign::{NodeSigner, Recipient};
 
 use crate::prelude::*;
+#[cfg(feature = "std")]
 use core::convert::TryFrom;
 use core::fmt;
 use core::fmt::Debug;
+use core::ops::Deref;
+#[cfg(feature = "std")]
 use core::str::FromStr;
-use crate::io::{self, Read};
+#[cfg(feature = "std")]
+use std::net::SocketAddr;
+use core::fmt::Display;
+use crate::io::{self, Cursor, Read};
 use crate::io_extras::read_to_end;
 
-use crate::events::{MessageSendEventsProvider, OnionMessageProvider};
+use crate::events::MessageSendEventsProvider;
+use crate::util::chacha20poly1305rfc::ChaChaPolyReadAdapter;
 use crate::util::logger;
-use crate::util::ser::{LengthReadable, Readable, ReadableArgs, Writeable, Writer, WithoutLength, FixedLengthReader, HighZeroBytesDroppedBigSize, Hostname, TransactionU16LenLimited, BigSize};
+use crate::util::ser::{LengthReadable, LengthReadableArgs, Readable, ReadableArgs, Writeable, Writer, WithoutLength, FixedLengthReader, HighZeroBytesDroppedBigSize, Hostname, TransactionU16LenLimited, BigSize};
 use crate::util::base32;
 
 use crate::routing::gossip::{NodeAlias, NodeId};
@@ -171,7 +180,7 @@ pub struct Pong {
 #[derive(Clone, Debug, PartialEq, Eq)]
 pub struct OpenChannel {
        /// The genesis hash of the blockchain where the channel is to be opened
-       pub chain_hash: BlockHash,
+       pub chain_hash: ChainHash,
        /// A temporary channel ID, until the funding outpoint is announced
        pub temporary_channel_id: ChannelId,
        /// The channel value
@@ -225,7 +234,7 @@ pub struct OpenChannel {
 #[derive(Clone, Debug, PartialEq, Eq)]
 pub struct OpenChannelV2 {
        /// The genesis hash of the blockchain where the channel is to be opened
-       pub chain_hash: BlockHash,
+       pub chain_hash: ChainHash,
        /// A temporary channel ID derived using a zeroed out value for the channel acceptor's revocation basepoint
        pub temporary_channel_id: ChannelId,
        /// The feerate for the funding transaction set by the channel initiator
@@ -627,7 +636,8 @@ pub struct UpdateAddHTLC {
 pub struct OnionMessage {
        /// Used in decrypting the onion packet's payload.
        pub blinding_point: PublicKey,
-       pub(crate) onion_routing_packet: onion_message::Packet,
+       /// The full onion packet including hop data, pubkey, and hmac
+       pub onion_routing_packet: onion_message::Packet,
 }
 
 /// An [`update_fulfill_htlc`] message to be sent to or received from a peer.
@@ -951,7 +961,41 @@ impl From<std::net::SocketAddr> for SocketAddress {
                }
 }
 
-fn parse_onion_address(host: &str, port: u16) -> Result<SocketAddress, SocketAddressParseError> {
+#[cfg(feature = "std")]
+impl std::net::ToSocketAddrs for SocketAddress {
+       type Iter = std::vec::IntoIter<std::net::SocketAddr>;
+
+       fn to_socket_addrs(&self) -> std::io::Result<Self::Iter> {
+               match self {
+                       SocketAddress::TcpIpV4 { addr, port } => {
+                               let ip_addr = std::net::Ipv4Addr::from(*addr);
+                               let socket_addr = SocketAddr::new(ip_addr.into(), *port);
+                               Ok(vec![socket_addr].into_iter())
+                       }
+                       SocketAddress::TcpIpV6 { addr, port } => {
+                               let ip_addr = std::net::Ipv6Addr::from(*addr);
+                               let socket_addr = SocketAddr::new(ip_addr.into(), *port);
+                               Ok(vec![socket_addr].into_iter())
+                       }
+                       SocketAddress::Hostname { ref hostname, port } => {
+                               (hostname.as_str(), *port).to_socket_addrs()
+                       }
+                       SocketAddress::OnionV2(..) => {
+                               Err(std::io::Error::new(std::io::ErrorKind::Other, "Resolution of OnionV2 \
+                               addresses is currently unsupported."))
+                       }
+                       SocketAddress::OnionV3 { .. } => {
+                               Err(std::io::Error::new(std::io::ErrorKind::Other, "Resolution of OnionV3 \
+                               addresses is currently unsupported."))
+                       }
+               }
+       }
+}
+
+/// Parses an OnionV3 host and port into a [`SocketAddress::OnionV3`].
+///
+/// The host part must end with ".onion".
+pub fn parse_onion_address(host: &str, port: u16) -> Result<SocketAddress, SocketAddressParseError> {
        if host.ends_with(".onion") {
                let domain = &host[..host.len() - ".onion".len()];
                if domain.len() != 56 {
@@ -974,6 +1018,35 @@ fn parse_onion_address(host: &str, port: u16) -> Result<SocketAddress, SocketAdd
        }
 }
 
+impl Display for SocketAddress {
+       fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
+               match self {
+                       SocketAddress::TcpIpV4{addr, port} => write!(
+                               f, "{}.{}.{}.{}:{}", addr[0], addr[1], addr[2], addr[3], port)?,
+                       SocketAddress::TcpIpV6{addr, port} => write!(
+                               f,
+                               "[{:02x}{:02x}:{:02x}{:02x}:{:02x}{:02x}:{:02x}{:02x}:{:02x}{:02x}:{:02x}{:02x}:{:02x}{:02x}:{:02x}{:02x}]:{}",
+                               addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7], addr[8], addr[9], addr[10], addr[11], addr[12], addr[13], addr[14], addr[15], port
+                       )?,
+                       SocketAddress::OnionV2(bytes) => write!(f, "OnionV2({:?})", bytes)?,
+                       SocketAddress::OnionV3 {
+                               ed25519_pubkey,
+                               checksum,
+                               version,
+                               port,
+                       } => {
+                               let [first_checksum_flag, second_checksum_flag] = checksum.to_be_bytes();
+                               let mut addr = vec![*version, first_checksum_flag, second_checksum_flag];
+                               addr.extend_from_slice(ed25519_pubkey);
+                               let onion = base32::Alphabet::RFC4648 { padding: false }.encode(&addr);
+                               write!(f, "{}.onion:{}", onion, port)?
+                       },
+                       SocketAddress::Hostname { hostname, port } => write!(f, "{}:{}", hostname, port)?,
+               }
+               Ok(())
+       }
+}
+
 #[cfg(feature = "std")]
 impl FromStr for SocketAddress {
        type Err = SocketAddressParseError;
@@ -1062,7 +1135,7 @@ pub struct UnsignedChannelAnnouncement {
        /// The advertised channel features
        pub features: ChannelFeatures,
        /// The genesis hash of the blockchain where the channel is to be opened
-       pub chain_hash: BlockHash,
+       pub chain_hash: ChainHash,
        /// The short channel ID
        pub short_channel_id: u64,
        /// One of the two `node_id`s which are endpoints of this channel
@@ -1102,7 +1175,7 @@ pub struct ChannelAnnouncement {
 #[derive(Clone, Debug, PartialEq, Eq)]
 pub struct UnsignedChannelUpdate {
        /// The genesis hash of the blockchain where the channel is to be opened
-       pub chain_hash: BlockHash,
+       pub chain_hash: ChainHash,
        /// The short channel ID
        pub short_channel_id: u64,
        /// A strictly monotonic announcement counter, with gaps allowed, specific to this channel
@@ -1154,7 +1227,7 @@ pub struct ChannelUpdate {
 #[derive(Clone, Debug, PartialEq, Eq)]
 pub struct QueryChannelRange {
        /// The genesis hash of the blockchain being queried
-       pub chain_hash: BlockHash,
+       pub chain_hash: ChainHash,
        /// The height of the first block for the channel UTXOs being queried
        pub first_blocknum: u32,
        /// The number of blocks to include in the query results
@@ -1175,7 +1248,7 @@ pub struct QueryChannelRange {
 #[derive(Clone, Debug, PartialEq, Eq)]
 pub struct ReplyChannelRange {
        /// The genesis hash of the blockchain being queried
-       pub chain_hash: BlockHash,
+       pub chain_hash: ChainHash,
        /// The height of the first block in the range of the reply
        pub first_blocknum: u32,
        /// The number of blocks included in the range of the reply
@@ -1200,7 +1273,7 @@ pub struct ReplyChannelRange {
 #[derive(Clone, Debug, PartialEq, Eq)]
 pub struct QueryShortChannelIds {
        /// The genesis hash of the blockchain being queried
-       pub chain_hash: BlockHash,
+       pub chain_hash: ChainHash,
        /// The short_channel_ids that are being queried
        pub short_channel_ids: Vec<u64>,
 }
@@ -1214,7 +1287,7 @@ pub struct QueryShortChannelIds {
 #[derive(Clone, Debug, PartialEq, Eq)]
 pub struct ReplyShortChannelIdsEnd {
        /// The genesis hash of the blockchain that was queried
-       pub chain_hash: BlockHash,
+       pub chain_hash: ChainHash,
        /// Indicates if the query recipient maintains up-to-date channel
        /// information for the `chain_hash`
        pub full_information: bool,
@@ -1228,7 +1301,7 @@ pub struct ReplyShortChannelIdsEnd {
 #[derive(Clone, Debug, PartialEq, Eq)]
 pub struct GossipTimestampFilter {
        /// The genesis hash of the blockchain for channel and node information
-       pub chain_hash: BlockHash,
+       pub chain_hash: ChainHash,
        /// The starting unix timestamp
        pub first_timestamp: u32,
        /// The range of information in seconds
@@ -1410,11 +1483,11 @@ pub trait ChannelMessageHandler : MessageSendEventsProvider {
        /// Note that this method is called before [`Self::peer_connected`].
        fn provided_init_features(&self, their_node_id: &PublicKey) -> InitFeatures;
 
-       /// Gets the genesis hashes for this `ChannelMessageHandler` indicating which chains it supports.
+       /// Gets the chain hashes for this `ChannelMessageHandler` indicating which chains it supports.
        ///
        /// If it's `None`, then no particular network chain hash compatibility will be enforced when
        /// connecting to peers.
-       fn get_genesis_hashes(&self) -> Option<Vec<ChainHash>>;
+       fn get_chain_hashes(&self) -> Option<Vec<ChainHash>>;
 }
 
 /// A trait to describe an object which can receive routing messages.
@@ -1487,10 +1560,14 @@ pub trait RoutingMessageHandler : MessageSendEventsProvider {
        fn provided_init_features(&self, their_node_id: &PublicKey) -> InitFeatures;
 }
 
-/// A trait to describe an object that can receive onion messages.
-pub trait OnionMessageHandler : OnionMessageProvider {
+/// A handler for received [`OnionMessage`]s and for providing generated ones to send.
+pub trait OnionMessageHandler {
        /// Handle an incoming `onion_message` message from the given peer.
        fn handle_onion_message(&self, peer_node_id: &PublicKey, msg: &OnionMessage);
+
+       /// Returns the next pending onion message for the peer with the given node id.
+       fn next_onion_message_for_peer(&self, peer_node_id: PublicKey) -> Option<OnionMessage>;
+
        /// Called when a connection is established with a peer. Can be used to track which peers
        /// advertise onion message support and are online.
        ///
@@ -1498,6 +1575,7 @@ pub trait OnionMessageHandler : OnionMessageProvider {
        /// with us. Implementors should be somewhat conservative about doing so, however, as other
        /// message handlers may still wish to communicate with this peer.
        fn peer_connected(&self, their_node_id: &PublicKey, init: &Init, inbound: bool) -> Result<(), ()>;
+
        /// Indicates a connection to the peer failed/an existing connection was lost. Allows handlers to
        /// drop and refuse to forward onion messages to this peer.
        fn peer_disconnected(&self, their_node_id: &PublicKey);
@@ -1517,6 +1595,8 @@ pub trait OnionMessageHandler : OnionMessageProvider {
 }
 
 mod fuzzy_internal_msgs {
+       use bitcoin::secp256k1::PublicKey;
+       use crate::blinded_path::payment::PaymentConstraints;
        use crate::prelude::*;
        use crate::ln::{PaymentPreimage, PaymentSecret};
 
@@ -1545,6 +1625,14 @@ mod fuzzy_internal_msgs {
                        amt_msat: u64,
                        outgoing_cltv_value: u32,
                },
+               BlindedReceive {
+                       amt_msat: u64,
+                       total_msat: u64,
+                       outgoing_cltv_value: u32,
+                       payment_secret: PaymentSecret,
+                       payment_constraints: PaymentConstraints,
+                       intro_node_blinding_point: PublicKey,
+               }
        }
 
        pub(crate) enum OutboundOnionPayload {
@@ -1562,6 +1650,17 @@ mod fuzzy_internal_msgs {
                        amt_msat: u64,
                        outgoing_cltv_value: u32,
                },
+               BlindedForward {
+                       encrypted_tlvs: Vec<u8>,
+                       intro_node_blinding_point: Option<PublicKey>,
+               },
+               BlindedReceive {
+                       amt_msat: u64,
+                       total_msat: u64,
+                       outgoing_cltv_value: u32,
+                       encrypted_tlvs: Vec<u8>,
+                       intro_node_blinding_point: Option<PublicKey>, // Set if the introduction node of the blinded path is the final node
+               }
        }
 
        pub struct DecodedOnionErrorPacket {
@@ -2097,29 +2196,53 @@ impl Writeable for OutboundOnionPayload {
                                        (16, payment_metadata.as_ref().map(|m| WithoutLength(m)), option)
                                }, custom_tlvs.iter());
                        },
+                       Self::BlindedForward { encrypted_tlvs, intro_node_blinding_point } => {
+                               _encode_varint_length_prefixed_tlv!(w, {
+                                       (10, *encrypted_tlvs, required_vec),
+                                       (12, intro_node_blinding_point, option)
+                               });
+                       },
+                       Self::BlindedReceive {
+                               amt_msat, total_msat, outgoing_cltv_value, encrypted_tlvs,
+                               intro_node_blinding_point,
+                       } => {
+                               _encode_varint_length_prefixed_tlv!(w, {
+                                       (2, HighZeroBytesDroppedBigSize(*amt_msat), required),
+                                       (4, HighZeroBytesDroppedBigSize(*outgoing_cltv_value), required),
+                                       (10, *encrypted_tlvs, required_vec),
+                                       (12, intro_node_blinding_point, option),
+                                       (18, HighZeroBytesDroppedBigSize(*total_msat), required)
+                               });
+                       },
                }
                Ok(())
        }
 }
 
-impl Readable for InboundOnionPayload {
-       fn read<R: Read>(r: &mut R) -> Result<Self, DecodeError> {
-               let mut amt = HighZeroBytesDroppedBigSize(0u64);
-               let mut cltv_value = HighZeroBytesDroppedBigSize(0u32);
+impl<NS: Deref> ReadableArgs<&NS> for InboundOnionPayload where NS::Target: NodeSigner {
+       fn read<R: Read>(r: &mut R, node_signer: &NS) -> Result<Self, DecodeError> {
+               let mut amt = None;
+               let mut cltv_value = None;
                let mut short_id: Option<u64> = None;
                let mut payment_data: Option<FinalOnionHopData> = None;
+               let mut encrypted_tlvs_opt: Option<WithoutLength<Vec<u8>>> = None;
+               let mut intro_node_blinding_point = None;
                let mut payment_metadata: Option<WithoutLength<Vec<u8>>> = None;
+               let mut total_msat = None;
                let mut keysend_preimage: Option<PaymentPreimage> = None;
                let mut custom_tlvs = Vec::new();
 
                let tlv_len = BigSize::read(r)?;
                let rd = FixedLengthReader::new(r, tlv_len.0);
                decode_tlv_stream_with_custom_tlv_decode!(rd, {
-                       (2, amt, required),
-                       (4, cltv_value, required),
+                       (2, amt, (option, encoding: (u64, HighZeroBytesDroppedBigSize))),
+                       (4, cltv_value, (option, encoding: (u32, HighZeroBytesDroppedBigSize))),
                        (6, short_id, option),
                        (8, payment_data, option),
+                       (10, encrypted_tlvs_opt, option),
+                       (12, intro_node_blinding_point, option),
                        (16, payment_metadata, option),
+                       (18, total_msat, (option, encoding: (u64, HighZeroBytesDroppedBigSize))),
                        // See https://github.com/lightning/blips/blob/master/blip-0003.md
                        (5482373484, keysend_preimage, option)
                }, |msg_type: u64, msg_reader: &mut FixedLengthReader<_>| -> Result<bool, DecodeError> {
@@ -2130,16 +2253,44 @@ impl Readable for InboundOnionPayload {
                        Ok(true)
                });
 
-               if amt.0 > MAX_VALUE_MSAT { return Err(DecodeError::InvalidValue) }
-               if let Some(short_channel_id) = short_id {
-                       if payment_data.is_some() { return Err(DecodeError::InvalidValue) }
-                       if payment_metadata.is_some() { return Err(DecodeError::InvalidValue); }
+               if amt.unwrap_or(0) > MAX_VALUE_MSAT { return Err(DecodeError::InvalidValue) }
+
+               if let Some(blinding_point) = intro_node_blinding_point {
+                       if short_id.is_some() || payment_data.is_some() || payment_metadata.is_some() {
+                               return Err(DecodeError::InvalidValue)
+                       }
+                       let enc_tlvs = encrypted_tlvs_opt.ok_or(DecodeError::InvalidValue)?.0;
+                       let enc_tlvs_ss = node_signer.ecdh(Recipient::Node, &blinding_point, None)
+                               .map_err(|_| DecodeError::InvalidValue)?;
+                       let rho = onion_utils::gen_rho_from_shared_secret(&enc_tlvs_ss.secret_bytes());
+                       let mut s = Cursor::new(&enc_tlvs);
+                       let mut reader = FixedLengthReader::new(&mut s, enc_tlvs.len() as u64);
+                       match ChaChaPolyReadAdapter::read(&mut reader, rho)? {
+                               ChaChaPolyReadAdapter { readable: ReceiveTlvs { payment_secret, payment_constraints }} => {
+                                       if total_msat.unwrap_or(0) > MAX_VALUE_MSAT { return Err(DecodeError::InvalidValue) }
+                                       Ok(Self::BlindedReceive {
+                                               amt_msat: amt.ok_or(DecodeError::InvalidValue)?,
+                                               total_msat: total_msat.ok_or(DecodeError::InvalidValue)?,
+                                               outgoing_cltv_value: cltv_value.ok_or(DecodeError::InvalidValue)?,
+                                               payment_secret,
+                                               payment_constraints,
+                                               intro_node_blinding_point: blinding_point,
+                                       })
+                               },
+                       }
+               } else if let Some(short_channel_id) = short_id {
+                       if payment_data.is_some() || payment_metadata.is_some() || encrypted_tlvs_opt.is_some() ||
+                               total_msat.is_some()
+                       { return Err(DecodeError::InvalidValue) }
                        Ok(Self::Forward {
                                short_channel_id,
-                               amt_to_forward: amt.0,
-                               outgoing_cltv_value: cltv_value.0,
+                               amt_to_forward: amt.ok_or(DecodeError::InvalidValue)?,
+                               outgoing_cltv_value: cltv_value.ok_or(DecodeError::InvalidValue)?,
                        })
                } else {
+                       if encrypted_tlvs_opt.is_some() || total_msat.is_some() {
+                               return Err(DecodeError::InvalidValue)
+                       }
                        if let Some(data) = &payment_data {
                                if data.total_msat > MAX_VALUE_MSAT {
                                        return Err(DecodeError::InvalidValue);
@@ -2149,22 +2300,14 @@ impl Readable for InboundOnionPayload {
                                payment_data,
                                payment_metadata: payment_metadata.map(|w| w.0),
                                keysend_preimage,
-                               amt_msat: amt.0,
-                               outgoing_cltv_value: cltv_value.0,
+                               amt_msat: amt.ok_or(DecodeError::InvalidValue)?,
+                               outgoing_cltv_value: cltv_value.ok_or(DecodeError::InvalidValue)?,
                                custom_tlvs,
                        })
                }
        }
 }
 
-// ReadableArgs because we need onion_utils::decode_next_hop to accommodate payment packets and
-// onion message packets.
-impl ReadableArgs<()> for InboundOnionPayload {
-       fn read<R: Read>(r: &mut R, _arg: ()) -> Result<Self, DecodeError> {
-               <Self as Readable>::read(r)
-       }
-}
-
 impl Writeable for Ping {
        fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
                self.ponglen.write(w)?;
@@ -2432,7 +2575,7 @@ impl_writeable!(NodeAnnouncement, {
 
 impl Readable for QueryShortChannelIds {
        fn read<R: Read>(r: &mut R) -> Result<Self, DecodeError> {
-               let chain_hash: BlockHash = Readable::read(r)?;
+               let chain_hash: ChainHash = Readable::read(r)?;
 
                let encoding_len: u16 = Readable::read(r)?;
                let encoding_type: u8 = Readable::read(r)?;
@@ -2508,7 +2651,7 @@ impl_writeable_msg!(QueryChannelRange, {
 
 impl Readable for ReplyChannelRange {
        fn read<R: Read>(r: &mut R) -> Result<Self, DecodeError> {
-               let chain_hash: BlockHash = Readable::read(r)?;
+               let chain_hash: ChainHash = Readable::read(r)?;
                let first_blocknum: u32 = Readable::read(r)?;
                let number_of_blocks: u32 = Readable::read(r)?;
                let sync_complete: bool = Readable::read(r)?;
@@ -2573,7 +2716,6 @@ impl_writeable_msg!(GossipTimestampFilter, {
 #[cfg(test)]
 mod tests {
        use std::convert::TryFrom;
-       use bitcoin::blockdata::constants::ChainHash;
        use bitcoin::{Transaction, PackedLockTime, TxIn, Script, Sequence, Witness, TxOut};
        use hex;
        use crate::ln::{PaymentPreimage, PaymentHash, PaymentSecret};
@@ -2582,14 +2724,16 @@ mod tests {
        use crate::ln::msgs::{self, FinalOnionHopData, OnionErrorPacket};
        use crate::ln::msgs::SocketAddress;
        use crate::routing::gossip::{NodeAlias, NodeId};
-       use crate::util::ser::{Writeable, Readable, Hostname, TransactionU16LenLimited};
+       use crate::util::ser::{Writeable, Readable, ReadableArgs, Hostname, TransactionU16LenLimited};
+       use crate::util::test_utils;
 
        use bitcoin::hashes::hex::FromHex;
        use bitcoin::util::address::Address;
        use bitcoin::network::constants::Network;
+       use bitcoin::blockdata::constants::ChainHash;
        use bitcoin::blockdata::script::Builder;
        use bitcoin::blockdata::opcodes;
-       use bitcoin::hash_types::{Txid, BlockHash};
+       use bitcoin::hash_types::Txid;
 
        use bitcoin::secp256k1::{PublicKey,SecretKey};
        use bitcoin::secp256k1::{Secp256k1, Message};
@@ -2600,7 +2744,8 @@ mod tests {
        use crate::chain::transaction::OutPoint;
 
        #[cfg(feature = "std")]
-       use std::net::{Ipv4Addr, Ipv6Addr};
+       use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs};
+       #[cfg(feature = "std")]
        use crate::ln::msgs::SocketAddressParseError;
 
        #[test]
@@ -2718,7 +2863,7 @@ mod tests {
                }
                let unsigned_channel_announcement = msgs::UnsignedChannelAnnouncement {
                        features,
-                       chain_hash: BlockHash::from_hex("6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000").unwrap(),
+                       chain_hash: ChainHash::using_genesis_block(Network::Bitcoin),
                        short_channel_id: 2316138423780173,
                        node_id_1: NodeId::from_pubkey(&pubkey_1),
                        node_id_2: NodeId::from_pubkey(&pubkey_2),
@@ -2740,7 +2885,7 @@ mod tests {
                } else {
                        target_value.append(&mut hex::decode("0000").unwrap());
                }
-               target_value.append(&mut hex::decode("000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f").unwrap());
+               target_value.append(&mut hex::decode("6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000").unwrap());
                target_value.append(&mut hex::decode("00083a840000034d031b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f024d4b6cd1361032ca9bd2aeb9d900aa4d45d9ead80ac9423374c451a7254d076602531fe6068134503d2723133227c867ac8fa6c83c537e9a44c3c5bdbdcb1fe33703462779ad4aad39514614751a71085f2f10e1c7a593e4e030efb5b8721ce55b0b").unwrap());
                if excess_data {
                        target_value.append(&mut hex::decode("0a00001400001e000028").unwrap());
@@ -2869,7 +3014,7 @@ mod tests {
                let (privkey_1, _) = get_keys_from!("0101010101010101010101010101010101010101010101010101010101010101", secp_ctx);
                let sig_1 = get_sig_on!(privkey_1, secp_ctx, String::from("01010101010101010101010101010101"));
                let unsigned_channel_update = msgs::UnsignedChannelUpdate {
-                       chain_hash: BlockHash::from_hex("6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000").unwrap(),
+                       chain_hash: ChainHash::using_genesis_block(Network::Bitcoin),
                        short_channel_id: 2316138423780173,
                        timestamp: 20190119,
                        flags: if direction { 1 } else { 0 } | if disable { 1 << 1 } else { 0 },
@@ -2886,7 +3031,7 @@ mod tests {
                };
                let encoded_value = channel_update.encode();
                let mut target_value = hex::decode("d977cb9b53d93a6ff64bb5f1e158b4094b66e798fb12911168a3ccdf80a83096340a6a95da0ae8d9f776528eecdbb747eb6b545495a4319ed5378e35b21e073a").unwrap();
-               target_value.append(&mut hex::decode("000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f").unwrap());
+               target_value.append(&mut hex::decode("6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000").unwrap());
                target_value.append(&mut hex::decode("00083a840000034d013413a7").unwrap());
                target_value.append(&mut hex::decode("01").unwrap());
                target_value.append(&mut hex::decode("00").unwrap());
@@ -2927,7 +3072,7 @@ mod tests {
                let (_, pubkey_5) = get_keys_from!("0505050505050505050505050505050505050505050505050505050505050505", secp_ctx);
                let (_, pubkey_6) = get_keys_from!("0606060606060606060606060606060606060606060606060606060606060606", secp_ctx);
                let open_channel = msgs::OpenChannel {
-                       chain_hash: BlockHash::from_hex("6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000").unwrap(),
+                       chain_hash: ChainHash::using_genesis_block(Network::Bitcoin),
                        temporary_channel_id: ChannelId::from_bytes([2; 32]),
                        funding_satoshis: 1311768467284833366,
                        push_msat: 2536655962884945560,
@@ -2950,7 +3095,7 @@ mod tests {
                };
                let encoded_value = open_channel.encode();
                let mut target_value = Vec::new();
-               target_value.append(&mut hex::decode("000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f").unwrap());
+               target_value.append(&mut hex::decode("6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000").unwrap());
                target_value.append(&mut hex::decode("02020202020202020202020202020202020202020202020202020202020202021234567890123456233403289122369832144668701144767633030896203198784335490624111800083a840000034d000c89d4c0bcc0bc031b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f024d4b6cd1361032ca9bd2aeb9d900aa4d45d9ead80ac9423374c451a7254d076602531fe6068134503d2723133227c867ac8fa6c83c537e9a44c3c5bdbdcb1fe33703462779ad4aad39514614751a71085f2f10e1c7a593e4e030efb5b8721ce55b0b0362c0a046dacce86ddd0343c6d3c7c79c2208ba0d9c9cf24a6d046d21d21f90f703f006a18d5653c4edf5391ff23a61f03ff83d237e880ee61187fa9f379a028e0a").unwrap());
                if random_bit {
                        target_value.append(&mut hex::decode("20").unwrap());
@@ -2988,7 +3133,7 @@ mod tests {
                let (_, pubkey_6) = get_keys_from!("0606060606060606060606060606060606060606060606060606060606060606", secp_ctx);
                let (_, pubkey_7) = get_keys_from!("0707070707070707070707070707070707070707070707070707070707070707", secp_ctx);
                let open_channelv2 = msgs::OpenChannelV2 {
-                       chain_hash: BlockHash::from_hex("6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000").unwrap(),
+                       chain_hash: ChainHash::using_genesis_block(Network::Bitcoin),
                        temporary_channel_id: ChannelId::from_bytes([2; 32]),
                        funding_feerate_sat_per_1000_weight: 821716,
                        commitment_feerate_sat_per_1000_weight: 821716,
@@ -3013,7 +3158,7 @@ mod tests {
                };
                let encoded_value = open_channelv2.encode();
                let mut target_value = Vec::new();
-               target_value.append(&mut hex::decode("000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f").unwrap());
+               target_value.append(&mut hex::decode("6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000").unwrap());
                target_value.append(&mut hex::decode("0202020202020202020202020202020202020202020202020202020202020202").unwrap());
                target_value.append(&mut hex::decode("000c89d4").unwrap());
                target_value.append(&mut hex::decode("000c89d4").unwrap());
@@ -3586,7 +3731,7 @@ mod tests {
 
        #[test]
        fn encoding_init() {
-               let mainnet_hash = ChainHash::from_hex("6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000").unwrap();
+               let mainnet_hash = ChainHash::using_genesis_block(Network::Bitcoin);
                assert_eq!(msgs::Init {
                        features: InitFeatures::from_le_bytes(vec![0xFF, 0xFF, 0xFF]),
                        networks: Some(vec![mainnet_hash]),
@@ -3674,8 +3819,11 @@ mod tests {
                let target_value = hex::decode("1a02080badf00d010203040404ffffffff0608deadbeef1bad1dea").unwrap();
                assert_eq!(encoded_value, target_value);
 
-               let inbound_msg = Readable::read(&mut Cursor::new(&target_value[..])).unwrap();
-               if let msgs::InboundOnionPayload::Forward { short_channel_id, amt_to_forward, outgoing_cltv_value } = inbound_msg {
+               let node_signer = test_utils::TestKeysInterface::new(&[42; 32], Network::Testnet);
+               let inbound_msg = ReadableArgs::read(&mut Cursor::new(&target_value[..]), &&node_signer).unwrap();
+               if let msgs::InboundOnionPayload::Forward {
+                       short_channel_id, amt_to_forward, outgoing_cltv_value
+               } = inbound_msg {
                        assert_eq!(short_channel_id, 0xdeadbeef1bad1dea);
                        assert_eq!(amt_to_forward, 0x0badf00d01020304);
                        assert_eq!(outgoing_cltv_value, 0xffffffff);
@@ -3696,8 +3844,11 @@ mod tests {
                let target_value = hex::decode("1002080badf00d010203040404ffffffff").unwrap();
                assert_eq!(encoded_value, target_value);
 
-               let inbound_msg = Readable::read(&mut Cursor::new(&target_value[..])).unwrap();
-               if let msgs::InboundOnionPayload::Receive { payment_data: None, amt_msat, outgoing_cltv_value, .. } = inbound_msg {
+               let node_signer = test_utils::TestKeysInterface::new(&[42; 32], Network::Testnet);
+               let inbound_msg = ReadableArgs::read(&mut Cursor::new(&target_value[..]), &&node_signer).unwrap();
+               if let msgs::InboundOnionPayload::Receive {
+                       payment_data: None, amt_msat, outgoing_cltv_value, ..
+               } = inbound_msg {
                        assert_eq!(amt_msat, 0x0badf00d01020304);
                        assert_eq!(outgoing_cltv_value, 0xffffffff);
                } else { panic!(); }
@@ -3721,7 +3872,8 @@ mod tests {
                let target_value = hex::decode("3602080badf00d010203040404ffffffff082442424242424242424242424242424242424242424242424242424242424242421badca1f").unwrap();
                assert_eq!(encoded_value, target_value);
 
-               let inbound_msg = Readable::read(&mut Cursor::new(&target_value[..])).unwrap();
+               let node_signer = test_utils::TestKeysInterface::new(&[42; 32], Network::Testnet);
+               let inbound_msg = ReadableArgs::read(&mut Cursor::new(&target_value[..]), &&node_signer).unwrap();
                if let msgs::InboundOnionPayload::Receive {
                        payment_data: Some(FinalOnionHopData {
                                payment_secret,
@@ -3756,7 +3908,8 @@ mod tests {
                        outgoing_cltv_value: 0xffffffff,
                };
                let encoded_value = msg.encode();
-               assert!(msgs::InboundOnionPayload::read(&mut Cursor::new(&encoded_value[..])).is_err());
+               let node_signer = test_utils::TestKeysInterface::new(&[42; 32], Network::Testnet);
+               assert!(msgs::InboundOnionPayload::read(&mut Cursor::new(&encoded_value[..]), &&node_signer).is_err());
                let good_type_range_tlvs = vec![
                        ((1 << 16) - 3, vec![42]),
                        ((1 << 16) - 1, vec![42; 32]),
@@ -3765,7 +3918,7 @@ mod tests {
                        *custom_tlvs = good_type_range_tlvs.clone();
                }
                let encoded_value = msg.encode();
-               let inbound_msg = Readable::read(&mut Cursor::new(&encoded_value[..])).unwrap();
+               let inbound_msg = ReadableArgs::read(&mut Cursor::new(&encoded_value[..]), &&node_signer).unwrap();
                match inbound_msg {
                        msgs::InboundOnionPayload::Receive { custom_tlvs, .. } => assert!(custom_tlvs.is_empty()),
                        _ => panic!(),
@@ -3789,7 +3942,8 @@ mod tests {
                let encoded_value = msg.encode();
                let target_value = hex::decode("2e02080badf00d010203040404ffffffffff0000000146c6616b021234ff0000000146c6616f084242424242424242").unwrap();
                assert_eq!(encoded_value, target_value);
-               let inbound_msg: msgs::InboundOnionPayload = Readable::read(&mut Cursor::new(&target_value[..])).unwrap();
+               let node_signer = test_utils::TestKeysInterface::new(&[42; 32], Network::Testnet);
+               let inbound_msg: msgs::InboundOnionPayload = ReadableArgs::read(&mut Cursor::new(&target_value[..]), &&node_signer).unwrap();
                if let msgs::InboundOnionPayload::Receive {
                        payment_data: None,
                        payment_metadata: None,
@@ -3815,7 +3969,7 @@ mod tests {
 
                for (first_blocknum, number_of_blocks, expected) in tests.into_iter() {
                        let sut = msgs::QueryChannelRange {
-                               chain_hash: BlockHash::from_hex("06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f").unwrap(),
+                               chain_hash: ChainHash::using_genesis_block(Network::Regtest),
                                first_blocknum,
                                number_of_blocks,
                        };
@@ -3826,12 +3980,12 @@ mod tests {
        #[test]
        fn encoding_query_channel_range() {
                let mut query_channel_range = msgs::QueryChannelRange {
-                       chain_hash: BlockHash::from_hex("06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f").unwrap(),
+                       chain_hash: ChainHash::using_genesis_block(Network::Regtest),
                        first_blocknum: 100000,
                        number_of_blocks: 1500,
                };
                let encoded_value = query_channel_range.encode();
-               let target_value = hex::decode("0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206000186a0000005dc").unwrap();
+               let target_value = hex::decode("06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f000186a0000005dc").unwrap();
                assert_eq!(encoded_value, target_value);
 
                query_channel_range = Readable::read(&mut Cursor::new(&target_value[..])).unwrap();
@@ -3846,8 +4000,8 @@ mod tests {
        }
 
        fn do_encoding_reply_channel_range(encoding_type: u8) {
-               let mut target_value = hex::decode("0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206000b8a06000005dc01").unwrap();
-               let expected_chain_hash = BlockHash::from_hex("06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f").unwrap();
+               let mut target_value = hex::decode("06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f000b8a06000005dc01").unwrap();
+               let expected_chain_hash = ChainHash::using_genesis_block(Network::Regtest);
                let mut reply_channel_range = msgs::ReplyChannelRange {
                        chain_hash: expected_chain_hash,
                        first_blocknum: 756230,
@@ -3883,8 +4037,8 @@ mod tests {
        }
 
        fn do_encoding_query_short_channel_ids(encoding_type: u8) {
-               let mut target_value = hex::decode("0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206").unwrap();
-               let expected_chain_hash = BlockHash::from_hex("06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f").unwrap();
+               let mut target_value = hex::decode("06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f").unwrap();
+               let expected_chain_hash = ChainHash::using_genesis_block(Network::Regtest);
                let mut query_short_channel_ids = msgs::QueryShortChannelIds {
                        chain_hash: expected_chain_hash,
                        short_channel_ids: vec![0x0000000000008e, 0x0000000000003c69, 0x000000000045a6c4],
@@ -3909,13 +4063,13 @@ mod tests {
 
        #[test]
        fn encoding_reply_short_channel_ids_end() {
-               let expected_chain_hash = BlockHash::from_hex("06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f").unwrap();
+               let expected_chain_hash = ChainHash::using_genesis_block(Network::Regtest);
                let mut reply_short_channel_ids_end = msgs::ReplyShortChannelIdsEnd {
                        chain_hash: expected_chain_hash,
                        full_information: true,
                };
                let encoded_value = reply_short_channel_ids_end.encode();
-               let target_value = hex::decode("0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e220601").unwrap();
+               let target_value = hex::decode("06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f01").unwrap();
                assert_eq!(encoded_value, target_value);
 
                reply_short_channel_ids_end = Readable::read(&mut Cursor::new(&target_value[..])).unwrap();
@@ -3925,14 +4079,14 @@ mod tests {
 
        #[test]
        fn encoding_gossip_timestamp_filter(){
-               let expected_chain_hash = BlockHash::from_hex("06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f").unwrap();
+               let expected_chain_hash = ChainHash::using_genesis_block(Network::Regtest);
                let mut gossip_timestamp_filter = msgs::GossipTimestampFilter {
                        chain_hash: expected_chain_hash,
                        first_timestamp: 1590000000,
                        timestamp_range: 0xffff_ffff,
                };
                let encoded_value = gossip_timestamp_filter.encode();
-               let target_value = hex::decode("0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e22065ec57980ffffffff").unwrap();
+               let target_value = hex::decode("06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f5ec57980ffffffff").unwrap();
                assert_eq!(encoded_value, target_value);
 
                gossip_timestamp_filter = Readable::read(&mut Cursor::new(&target_value[..])).unwrap();
@@ -3952,7 +4106,10 @@ mod tests {
                // payload length to be encoded over multiple bytes rather than a single u8.
                let big_payload = encode_big_payload().unwrap();
                let mut rd = Cursor::new(&big_payload[..]);
-               <msgs::InboundOnionPayload as Readable>::read(&mut rd).unwrap();
+
+               let node_signer = test_utils::TestKeysInterface::new(&[42; 32], Network::Testnet);
+               <msgs::InboundOnionPayload as ReadableArgs<&&test_utils::TestKeysInterface>>
+                       ::read(&mut rd, &&node_signer).unwrap();
        }
        // see above test, needs to be a separate method for use of the serialization macros.
        fn encode_big_payload() -> Result<Vec<u8>, io::Error> {
@@ -3978,32 +4135,41 @@ mod tests {
        #[test]
        #[cfg(feature = "std")]
        fn test_socket_address_from_str() {
-               assert_eq!(SocketAddress::TcpIpV4 {
+               let tcpip_v4 = SocketAddress::TcpIpV4 {
                        addr: Ipv4Addr::new(127, 0, 0, 1).octets(),
                        port: 1234,
-               }, SocketAddress::from_str("127.0.0.1:1234").unwrap());
+               };
+               assert_eq!(tcpip_v4, SocketAddress::from_str("127.0.0.1:1234").unwrap());
+               assert_eq!(tcpip_v4, SocketAddress::from_str(&tcpip_v4.to_string()).unwrap());
 
-               assert_eq!(SocketAddress::TcpIpV6 {
+               let tcpip_v6 = SocketAddress::TcpIpV6 {
                        addr: Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).octets(),
                        port: 1234,
-               }, SocketAddress::from_str("[0:0:0:0:0:0:0:1]:1234").unwrap());
-               assert_eq!(
-                       SocketAddress::Hostname {
+               };
+               assert_eq!(tcpip_v6, SocketAddress::from_str("[0:0:0:0:0:0:0:1]:1234").unwrap());
+               assert_eq!(tcpip_v6, SocketAddress::from_str(&tcpip_v6.to_string()).unwrap());
+
+               let hostname = SocketAddress::Hostname {
                                hostname: Hostname::try_from("lightning-node.mydomain.com".to_string()).unwrap(),
                                port: 1234,
-                       }, SocketAddress::from_str("lightning-node.mydomain.com:1234").unwrap());
-               assert_eq!(
-                       SocketAddress::Hostname {
-                               hostname: Hostname::try_from("example.com".to_string()).unwrap(),
-                               port: 1234,
-                       }, SocketAddress::from_str("example.com:1234").unwrap());
-               assert_eq!(SocketAddress::OnionV3 {
+               };
+               assert_eq!(hostname, SocketAddress::from_str("lightning-node.mydomain.com:1234").unwrap());
+               assert_eq!(hostname, SocketAddress::from_str(&hostname.to_string()).unwrap());
+
+               let onion_v2 = SocketAddress::OnionV2 ([40, 4, 64, 185, 202, 19, 162, 75, 90, 200, 38, 7],);
+               assert_eq!("OnionV2([40, 4, 64, 185, 202, 19, 162, 75, 90, 200, 38, 7])", &onion_v2.to_string());
+               assert_eq!(Err(SocketAddressParseError::InvalidOnionV3), SocketAddress::from_str("FACEBOOKCOREWWWI.onion:9735"));
+
+               let onion_v3 = SocketAddress::OnionV3 {
                        ed25519_pubkey: [37, 24, 75, 5, 25, 73, 117, 194, 139, 102, 182, 107, 4, 105, 247, 246, 85,
                        111, 177, 172, 49, 137, 167, 155, 64, 221, 163, 47, 31, 33, 71, 3],
                        checksum: 48326,
                        version: 121,
                        port: 1234
-               }, SocketAddress::from_str("pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscryd.onion:1234").unwrap());
+               };
+               assert_eq!(onion_v3, SocketAddress::from_str("pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscryd.onion:1234").unwrap());
+               assert_eq!(onion_v3, SocketAddress::from_str(&onion_v3.to_string()).unwrap());
+
                assert_eq!(Err(SocketAddressParseError::InvalidOnionV3), SocketAddress::from_str("pg6mmjiyjmcrsslvykfwnntlaru7p5svn6.onion:1234"));
                assert_eq!(Err(SocketAddressParseError::InvalidInput), SocketAddress::from_str("127.0.0.1@1234"));
                assert_eq!(Err(SocketAddressParseError::InvalidInput), "".parse::<SocketAddress>());
@@ -4017,4 +4183,22 @@ mod tests {
                assert!("invalid-address".parse::<SocketAddress>().is_err());
                assert!(SocketAddress::from_str("pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscryd.onion.onion:1234").is_err());
        }
+
+       #[test]
+       #[cfg(feature = "std")]
+       fn test_socket_address_to_socket_addrs() {
+               assert_eq!(SocketAddress::TcpIpV4 {addr:[0u8; 4], port: 1337,}.to_socket_addrs().unwrap().next().unwrap(),
+                                  SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(0,0,0,0), 1337)));
+               assert_eq!(SocketAddress::TcpIpV6 {addr:[0u8; 16], port: 1337,}.to_socket_addrs().unwrap().next().unwrap(),
+                                  SocketAddr::V6(SocketAddrV6::new(Ipv6Addr::from([0u8; 16]), 1337, 0, 0)));
+               assert_eq!(SocketAddress::Hostname { hostname: Hostname::try_from("0.0.0.0".to_string()).unwrap(), port: 0 }
+                                          .to_socket_addrs().unwrap().next().unwrap(), SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::from([0u8; 4]),0)));
+               assert!(SocketAddress::OnionV2([0u8; 12]).to_socket_addrs().is_err());
+               assert!(SocketAddress::OnionV3{ ed25519_pubkey: [37, 24, 75, 5, 25, 73, 117, 194, 139, 102,
+                       182, 107, 4, 105, 247, 246, 85, 111, 177, 172, 49, 137, 167, 155, 64, 221, 163, 47, 31,
+                       33, 71, 3],
+                       checksum: 48326,
+                       version: 121,
+                       port: 1234 }.to_socket_addrs().is_err());
+       }
 }