github.com/decred/dcrlnd@v0.7.6/lncfg/address_test.go (about) 1 //go:build !rpctest 2 // +build !rpctest 3 4 package lncfg 5 6 import ( 7 "bytes" 8 "encoding/hex" 9 "net" 10 "testing" 11 12 "github.com/decred/dcrd/dcrec/secp256k1/v4" 13 "github.com/stretchr/testify/require" 14 ) 15 16 // addressTest defines a test vector for an address that contains the non- 17 // normalized input and the expected normalized output. 18 type addressTest struct { 19 address string 20 expectedNetwork string 21 expectedAddress string 22 isLoopback bool 23 isUnix bool 24 } 25 26 var ( 27 defaultTestPort = "1234" 28 addressTestVectors = []addressTest{ 29 {"tcp://127.0.0.1:9735", "tcp", "127.0.0.1:9735", true, false}, 30 {"tcp:127.0.0.1:9735", "tcp", "127.0.0.1:9735", true, false}, 31 {"127.0.0.1:9735", "tcp", "127.0.0.1:9735", true, false}, 32 {":9735", "tcp", ":9735", false, false}, 33 {"", "tcp", ":1234", false, false}, 34 {":", "tcp", ":1234", false, false}, 35 {"tcp4://127.0.0.1:9735", "tcp", "127.0.0.1:9735", true, false}, 36 {"tcp4:127.0.0.1:9735", "tcp", "127.0.0.1:9735", true, false}, 37 {"127.0.0.1", "tcp", "127.0.0.1:1234", true, false}, 38 {"[::1]", "tcp", "[::1]:1234", true, false}, 39 {"::1", "tcp", "[::1]:1234", true, false}, 40 {"tcp6://::1", "tcp", "[::1]:1234", true, false}, 41 {"tcp6:::1", "tcp", "[::1]:1234", true, false}, 42 {"localhost:9735", "tcp", "127.0.0.1:9735", true, false}, 43 {"localhost", "tcp", "127.0.0.1:1234", true, false}, 44 {"unix:///tmp/lnd.sock", "unix", "/tmp/lnd.sock", false, true}, 45 {"unix:/tmp/lnd.sock", "unix", "/tmp/lnd.sock", false, true}, 46 {"123", "tcp", "127.0.0.1:123", true, false}, 47 { 48 "4acth47i6kxnvkewtm6q7ib2s3ufpo5sqbsnzjpbi7utijcltosqemad.onion", 49 "tcp", 50 "4acth47i6kxnvkewtm6q7ib2s3ufpo5sqbsnzjpbi7utijcltosqemad.onion:1234", 51 false, 52 false, 53 }, 54 { 55 "4acth47i6kxnvkewtm6q7ib2s3ufpo5sqbsnzjpbi7utijcltosqemad.onion:9735", 56 "tcp", 57 "4acth47i6kxnvkewtm6q7ib2s3ufpo5sqbsnzjpbi7utijcltosqemad.onion:9735", 58 false, 59 false, 60 }, 61 { 62 "3g2upl4pq6kufc4m.onion", 63 "tcp", 64 "3g2upl4pq6kufc4m.onion:1234", 65 false, 66 false, 67 }, 68 { 69 "3g2upl4pq6kufc4m.onion:9735", 70 "tcp", 71 "3g2upl4pq6kufc4m.onion:9735", 72 false, 73 false, 74 }, 75 } 76 invalidTestVectors = []string{ 77 "some string", 78 "://", 79 "12.12.12.12.12", 80 } 81 ) 82 83 // TestAddresses ensures that all supported address formats can be parsed and 84 // normalized correctly. 85 func TestAddresses(t *testing.T) { 86 // First, test all correct addresses. 87 for _, test := range addressTestVectors { 88 t.Run(test.address, func(t *testing.T) { 89 testAddress(t, test) 90 }) 91 } 92 93 // Finally, test invalid inputs to see if they are handled correctly. 94 for _, invalidAddr := range invalidTestVectors { 95 t.Run(invalidAddr, func(t *testing.T) { 96 testInvalidAddress(t, invalidAddr) 97 }) 98 } 99 } 100 101 // testAddress parses an address from its string representation, and 102 // asserts that the parsed net.Addr is correct against the given test case. 103 func testAddress(t *testing.T, test addressTest) { 104 addr := []string{test.address} 105 normalized, err := NormalizeAddresses( 106 addr, defaultTestPort, net.ResolveTCPAddr, 107 ) 108 if err != nil { 109 t.Fatalf("unable to normalize address %s: %v", 110 test.address, err) 111 } 112 113 if len(addr) == 0 { 114 t.Fatalf("no normalized addresses returned") 115 } 116 117 netAddr := normalized[0] 118 validateAddr(t, netAddr, test) 119 } 120 121 // testInvalidAddress asserts that parsing the invalidAddr string using 122 // NormalizeAddresses results in an error. 123 func testInvalidAddress(t *testing.T, invalidAddr string) { 124 addr := []string{invalidAddr} 125 _, err := NormalizeAddresses( 126 addr, defaultTestPort, net.ResolveTCPAddr, 127 ) 128 if err == nil { 129 t.Fatalf("expected error when parsing %v", invalidAddr) 130 } 131 } 132 133 var ( 134 pubKeyBytes = []byte{0x03, 135 0xc7, 0x82, 0x86, 0xd0, 0xbf, 0xe0, 0xb2, 0x33, 136 0x77, 0xe3, 0x47, 0xd7, 0xd9, 0x63, 0x94, 0x3c, 137 0x4f, 0x57, 0x5d, 0xdd, 0xd5, 0x7e, 0x2f, 0x1d, 138 0x52, 0xa5, 0xbe, 0x1e, 0xb7, 0xf6, 0x25, 0xa4, 139 } 140 141 pubKeyHex = hex.EncodeToString(pubKeyBytes) 142 143 pubKey, _ = secp256k1.ParsePubKey(pubKeyBytes) 144 ) 145 146 type lnAddressCase struct { 147 lnAddress string 148 expectedPubKey *secp256k1.PublicKey 149 150 addressTest 151 } 152 153 // lnAddressTests constructs valid LNAddress test vectors from the existing set 154 // of valid address test vectors. All addresses will use the same public key for 155 // the positive tests. 156 var lnAddressTests = func() []lnAddressCase { 157 var cases []lnAddressCase 158 for _, addrTest := range addressTestVectors { 159 cases = append(cases, lnAddressCase{ 160 lnAddress: pubKeyHex + "@" + addrTest.address, 161 expectedPubKey: pubKey, 162 addressTest: addrTest, 163 }) 164 } 165 166 return cases 167 }() 168 169 var invalidLNAddressTests = []string{ 170 "", // empty string 171 "@", // empty pubkey 172 "nonhexpubkey@", // non-hex public key 173 pubKeyHex[:len(pubKeyHex)-2] + "@", // pubkey too short 174 pubKeyHex + "aa@", // pubkey too long 175 pubKeyHex[:len(pubKeyHex)-1] + "7@", // pubkey not on curve 176 pubKeyHex + "@some string", // invalid address 177 pubKeyHex + "@://", // invalid address 178 pubKeyHex + "@21.21.21.21.21", // invalid address 179 } 180 181 // TestLNAddresses performs both positive and negative tests against 182 // ParseLNAddressString. 183 func TestLNAddresses(t *testing.T) { 184 for _, test := range lnAddressTests { 185 t.Run(test.lnAddress, func(t *testing.T) { 186 testLNAddress(t, test) 187 }) 188 } 189 190 for _, invalidAddr := range invalidLNAddressTests { 191 t.Run(invalidAddr, func(t *testing.T) { 192 testInvalidLNAddress(t, invalidAddr) 193 }) 194 } 195 } 196 197 // testLNAddress parses an LNAddress from its string representation, and asserts 198 // that the parsed IdentityKey and Address are correct according to its test 199 // case. 200 func testLNAddress(t *testing.T, test lnAddressCase) { 201 // Parse the LNAddress using the default port and TCP resolver. 202 lnAddr, err := ParseLNAddressString( 203 test.lnAddress, defaultTestPort, net.ResolveTCPAddr, 204 ) 205 if err != nil { 206 t.Fatalf("unable to parse ln address: %v", err) 207 } 208 209 // Assert that the public key matches the expected public key. 210 pkBytes := lnAddr.IdentityKey.SerializeCompressed() 211 if !bytes.Equal(pkBytes, pubKeyBytes) { 212 t.Fatalf("mismatched pubkey, want: %x, got: %v", 213 pubKeyBytes, pkBytes) 214 } 215 216 // Assert that the address after the @ is parsed properly, as if it were 217 // just a standalone address parsed by ParseAddressString. 218 validateAddr(t, lnAddr.Address, test.addressTest) 219 } 220 221 // testLNAddressCase asserts that parsing the given invalidAddr string results 222 // in an error when parsed with ParseLNAddressString. 223 func testInvalidLNAddress(t *testing.T, invalidAddr string) { 224 _, err := ParseLNAddressString( 225 invalidAddr, defaultTestPort, net.ResolveTCPAddr, 226 ) 227 if err == nil { 228 t.Fatalf("expected error when parsing invalid lnaddress: %v", 229 invalidAddr) 230 } 231 } 232 233 // validateAddr asserts that an addr parsed by ParseAddressString matches the 234 // properties expected by its addressTest. In particular, it validates that the 235 // Network() and String() methods match the expectedNetwork and expectedAddress, 236 // respectively. Further, we test the IsLoopback and IsUnix detection methods 237 // against addr and assert that they match the expected values in the test case. 238 func validateAddr(t *testing.T, addr net.Addr, test addressTest) { 239 240 t.Helper() 241 242 // Assert that the parsed network and address match what we expect. 243 if addr.Network() != test.expectedNetwork || 244 addr.String() != test.expectedAddress { 245 t.Fatalf("mismatched address: expected %s://%s, "+ 246 "got %s://%s", 247 test.expectedNetwork, test.expectedAddress, 248 addr.Network(), addr.String(), 249 ) 250 } 251 252 // Assert whether we expect this address to be a loopback address. 253 isAddrLoopback := IsLoopback(addr.String()) 254 if test.isLoopback != isAddrLoopback { 255 t.Fatalf("mismatched loopback detection: expected "+ 256 "%v, got %v for addr %s", 257 test.isLoopback, isAddrLoopback, test.address, 258 ) 259 } 260 261 // Assert whether we expect this address to be a unix address. 262 isAddrUnix := IsUnix(addr) 263 if test.isUnix != isAddrUnix { 264 t.Fatalf("mismatched unix detection: expected "+ 265 "%v, got %v for addr %s", 266 test.isUnix, isAddrUnix, test.address, 267 ) 268 } 269 } 270 271 func TestIsPrivate(t *testing.T) { 272 nonPrivateIPList := []net.IP{ 273 net.IPv4(169, 255, 0, 0), 274 {0xfe, 0x79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 275 net.IPv4(225, 0, 0, 0), 276 {0xff, 0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 277 net.IPv4(11, 0, 0, 0), 278 net.IPv4(172, 15, 0, 0), 279 net.IPv4(192, 169, 0, 0), 280 {0xfe, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 281 net.IPv4(8, 8, 8, 8), 282 {2, 0, 0, 1, 4, 8, 6, 0, 4, 8, 6, 0, 8, 8, 8, 8}, 283 } 284 privateIPList := []net.IP{ 285 net.IPv4(169, 254, 0, 0), 286 {0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 287 net.IPv4(224, 0, 0, 0), 288 {0xff, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 289 net.IPv4(10, 0, 0, 1), 290 net.IPv4(172, 16, 0, 1), 291 net.IPv4(172, 31, 255, 255), 292 net.IPv4(192, 168, 0, 1), 293 {0xfc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 294 } 295 296 testParams := []struct { 297 name string 298 ipList []net.IP 299 private bool 300 }{ 301 { 302 "Non-private addresses should return false", 303 nonPrivateIPList, false, 304 }, 305 { 306 "Private addresses should return true", 307 privateIPList, true, 308 }, 309 } 310 311 for _, tt := range testParams { 312 test := tt 313 t.Run(test.name, func(t *testing.T) { 314 for _, ip := range test.ipList { 315 addr := &net.TCPAddr{IP: ip} 316 require.Equal( 317 t, test.private, IsPrivate(addr), 318 "expected IP: %s to be %v", ip, test.private, 319 ) 320 } 321 }) 322 } 323 }