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  }