+
+ #[test]
+ fn decode_onion_hop_data_len_as_bigsize() {
+ // Tests that we can decode an onion payload that is >253 bytes.
+ // Previously, receiving a payload of this size could've caused us to fail to decode a valid
+ // payload, because we were decoding the length (a BigSize, big-endian) as a VarInt
+ // (little-endian).
+
+ // Encode a test onion payload with a big custom TLV such that it's >253 bytes, forcing the
+ // 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[..]);
+
+ 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> {
+ use crate::util::ser::HighZeroBytesDroppedBigSize;
+ let payload = msgs::OutboundOnionPayload::Forward {
+ short_channel_id: 0xdeadbeef1bad1dea,
+ amt_to_forward: 1000,
+ outgoing_cltv_value: 0xffffffff,
+ };
+ let mut encoded_payload = Vec::new();
+ let test_bytes = vec![42u8; 1000];
+ if let msgs::OutboundOnionPayload::Forward { short_channel_id, amt_to_forward, outgoing_cltv_value } = payload {
+ _encode_varint_length_prefixed_tlv!(&mut encoded_payload, {
+ (1, test_bytes, required_vec),
+ (2, HighZeroBytesDroppedBigSize(amt_to_forward), required),
+ (4, HighZeroBytesDroppedBigSize(outgoing_cltv_value), required),
+ (6, short_channel_id, required)
+ });
+ }
+ Ok(encoded_payload)
+ }
+
+ #[test]
+ #[cfg(feature = "std")]
+ fn test_socket_address_from_str() {
+ let tcpip_v4 = SocketAddress::TcpIpV4 {
+ addr: Ipv4Addr::new(127, 0, 0, 1).octets(),
+ port: 1234,
+ };
+ 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());
+
+ let tcpip_v6 = SocketAddress::TcpIpV6 {
+ addr: Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).octets(),
+ port: 1234,
+ };
+ 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,
+ };
+ 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
+ };
+ 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>());
+ assert!(SocketAddress::from_str("pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscryd.onion.onion:9735:94").is_err());
+ assert!(SocketAddress::from_str("wrong$%#.com:1234").is_err());
+ assert_eq!(Err(SocketAddressParseError::InvalidPort), SocketAddress::from_str("example.com:wrong"));
+ assert!("localhost".parse::<SocketAddress>().is_err());
+ assert!("localhost:invalid-port".parse::<SocketAddress>().is_err());
+ assert!( "invalid-onion-v3-hostname.onion:8080".parse::<SocketAddress>().is_err());
+ assert!("b32.example.onion:invalid-port".parse::<SocketAddress>().is_err());
+ 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());
+ }