github.com/Blockdaemon/celo-blockchain@v0.0.0-20200129231733-e667f6b08419/p2p/enode/urlv4_test.go (about) 1 // Copyright 2018 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package enode 18 19 import ( 20 "bytes" 21 "crypto/ecdsa" 22 "math/big" 23 "net" 24 "reflect" 25 "strings" 26 "testing" 27 "testing/quick" 28 ) 29 30 var parseNodeTests = []struct { 31 rawurl string 32 wantError string 33 wantResult *Node 34 wantPrivate bool 35 }{ 36 { 37 rawurl: "http://foobar", 38 wantError: `invalid URL scheme, want "enode"`, 39 }, 40 { 41 rawurl: "enode://01010101@123.124.125.126:3", 42 wantError: `invalid node ID (wrong length, want 128 hex chars)`, 43 }, 44 // Complete nodes with IP address. 45 { 46 rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@hostname:3", 47 wantError: `invalid IP address`, 48 }, 49 { 50 // net/url.Parse(rawurl) returns an error with rawurl and why the parse failed. 51 rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@127.0.0.1:foo", 52 wantError: `invalid port`, 53 }, 54 { 55 rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@127.0.0.1:3?discport=foo", 56 wantError: `invalid discport in query`, 57 }, 58 { 59 rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@127.0.0.1:52150", 60 wantResult: NewV4( 61 hexPubkey("1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 62 net.IP{0x7f, 0x0, 0x0, 0x1}, 63 52150, 64 52150, 65 ), 66 wantPrivate: true, 67 }, 68 { 69 rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@5.1.1.1:52150", 70 wantResult: NewV4( 71 hexPubkey("1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 72 net.IP{0x5, 0x1, 0x1, 0x1}, 73 52150, 74 52150, 75 ), 76 wantPrivate: false, 77 }, 78 { 79 rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@[::]:52150", 80 wantResult: NewV4( 81 hexPubkey("1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 82 net.ParseIP("::"), 83 52150, 84 52150, 85 ), 86 wantPrivate: true, 87 }, 88 { 89 rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@172.17.0.3:52150", 90 wantResult: NewV4( 91 hexPubkey("1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 92 net.ParseIP("172.17.0.3"), 93 52150, 94 52150, 95 ), 96 wantPrivate: true, 97 }, 98 { 99 rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@[2001:db8:3c4d:15::abcd:ef12]:52150", 100 wantResult: NewV4( 101 hexPubkey("1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 102 net.ParseIP("2001:db8:3c4d:15::abcd:ef12"), 103 52150, 104 52150, 105 ), 106 }, 107 { 108 rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@127.0.0.1:52150?discport=22334", 109 wantResult: NewV4( 110 hexPubkey("1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 111 net.IP{0x7f, 0x0, 0x0, 0x1}, 112 52150, 113 22334, 114 ), 115 wantPrivate: true, 116 }, 117 // Incomplete nodes with no address. 118 { 119 rawurl: "1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439", 120 wantResult: NewV4( 121 hexPubkey("1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 122 nil, 0, 0, 123 ), 124 }, 125 { 126 rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439", 127 wantResult: NewV4( 128 hexPubkey("1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 129 nil, 0, 0, 130 ), 131 }, 132 // Invalid URLs 133 { 134 rawurl: "01010101", 135 wantError: `invalid node ID (wrong length, want 128 hex chars)`, 136 }, 137 { 138 rawurl: "enode://01010101", 139 wantError: `invalid node ID (wrong length, want 128 hex chars)`, 140 }, 141 { 142 // This test checks that errors from url.Parse are handled. 143 rawurl: "://foo", 144 wantError: `parse ://foo: missing protocol scheme`, 145 }, 146 } 147 148 func hexPubkey(h string) *ecdsa.PublicKey { 149 k, err := parsePubkey(h) 150 if err != nil { 151 panic(err) 152 } 153 return k 154 } 155 156 func TestParseNode(t *testing.T) { 157 for _, test := range parseNodeTests { 158 n, err := ParseV4(test.rawurl) 159 if test.wantError != "" { 160 if err == nil { 161 t.Errorf("test %q:\n got nil error, expected %#q", test.rawurl, test.wantError) 162 continue 163 } else if !strings.Contains(err.Error(), test.wantError) { 164 t.Errorf("test %q:\n got error %#q, expected %#q", test.rawurl, err.Error(), test.wantError) 165 continue 166 } 167 } else { 168 if err != nil { 169 t.Errorf("test %q:\n unexpected error: %v", test.rawurl, err) 170 continue 171 } 172 if !reflect.DeepEqual(n, test.wantResult) { 173 t.Errorf("test %q:\n result mismatch:\ngot: %#v\nwant: %#v", test.rawurl, n, test.wantResult) 174 } 175 if !n.Incomplete() && n.IsPrivateIP() != test.wantPrivate { 176 t.Errorf("test %q:\n isPrivate mismatch:\nfor %#v\ngot: %#v\nwant: %#v", test.rawurl, n, n.IsPrivateIP(), test.wantPrivate) 177 } 178 } 179 } 180 } 181 182 func TestNodeString(t *testing.T) { 183 for i, test := range parseNodeTests { 184 if test.wantError == "" && strings.HasPrefix(test.rawurl, "enode://") { 185 str := test.wantResult.String() 186 if str != test.rawurl { 187 t.Errorf("test %d: Node.String() mismatch:\ngot: %s\nwant: %s", i, str, test.rawurl) 188 } 189 } 190 } 191 } 192 193 func TestHexID(t *testing.T) { 194 ref := ID{0, 0, 0, 0, 0, 0, 0, 128, 106, 217, 182, 31, 165, 174, 1, 67, 7, 235, 220, 150, 66, 83, 173, 205, 159, 44, 10, 57, 42, 161, 26, 188} 195 id1 := HexID("0x00000000000000806ad9b61fa5ae014307ebdc964253adcd9f2c0a392aa11abc") 196 id2 := HexID("00000000000000806ad9b61fa5ae014307ebdc964253adcd9f2c0a392aa11abc") 197 198 if id1 != ref { 199 t.Errorf("wrong id1\ngot %v\nwant %v", id1[:], ref[:]) 200 } 201 if id2 != ref { 202 t.Errorf("wrong id2\ngot %v\nwant %v", id2[:], ref[:]) 203 } 204 } 205 206 func TestID_textEncoding(t *testing.T) { 207 ref := ID{ 208 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 209 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x20, 210 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x30, 211 0x31, 0x32, 212 } 213 hex := "0102030405060708091011121314151617181920212223242526272829303132" 214 215 text, err := ref.MarshalText() 216 if err != nil { 217 t.Fatal(err) 218 } 219 if !bytes.Equal(text, []byte(hex)) { 220 t.Fatalf("text encoding did not match\nexpected: %s\ngot: %s", hex, text) 221 } 222 223 id := new(ID) 224 if err := id.UnmarshalText(text); err != nil { 225 t.Fatal(err) 226 } 227 if *id != ref { 228 t.Fatalf("text decoding did not match\nexpected: %s\ngot: %s", ref, id) 229 } 230 } 231 232 func TestNodeID_distcmp(t *testing.T) { 233 distcmpBig := func(target, a, b ID) int { 234 tbig := new(big.Int).SetBytes(target[:]) 235 abig := new(big.Int).SetBytes(a[:]) 236 bbig := new(big.Int).SetBytes(b[:]) 237 return new(big.Int).Xor(tbig, abig).Cmp(new(big.Int).Xor(tbig, bbig)) 238 } 239 if err := quick.CheckEqual(DistCmp, distcmpBig, nil); err != nil { 240 t.Error(err) 241 } 242 } 243 244 // The random tests is likely to miss the case where a and b are equal, 245 // this test checks it explicitly. 246 func TestNodeID_distcmpEqual(t *testing.T) { 247 base := ID{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15} 248 x := ID{15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0} 249 if DistCmp(base, x, x) != 0 { 250 t.Errorf("DistCmp(base, x, x) != 0") 251 } 252 } 253 254 func TestNodeID_logdist(t *testing.T) { 255 logdistBig := func(a, b ID) int { 256 abig, bbig := new(big.Int).SetBytes(a[:]), new(big.Int).SetBytes(b[:]) 257 return new(big.Int).Xor(abig, bbig).BitLen() 258 } 259 if err := quick.CheckEqual(LogDist, logdistBig, nil); err != nil { 260 t.Error(err) 261 } 262 } 263 264 // The random tests is likely to miss the case where a and b are equal, 265 // this test checks it explicitly. 266 func TestNodeID_logdistEqual(t *testing.T) { 267 x := ID{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15} 268 if LogDist(x, x) != 0 { 269 t.Errorf("LogDist(x, x) != 0") 270 } 271 }