github.com/hyperion-hyn/go-ethereum@v2.4.0+incompatible/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 "reflect" 24 "strings" 25 "testing" 26 "testing/quick" 27 ) 28 29 var parseNodeTests = []struct { 30 rawurl string 31 wantError string 32 wantResult *Node 33 }{ 34 { 35 rawurl: "http://foobar", 36 wantError: `invalid URL scheme, want "enode"`, 37 }, 38 { 39 rawurl: "enode://01010101@123.124.125.126:3", 40 wantError: `invalid node ID (wrong length, want 128 hex chars)`, 41 }, 42 // Complete nodes with IP address. 43 { 44 rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@127.0.0.1:foo", 45 wantError: `invalid port`, 46 }, 47 { 48 rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@127.0.0.1:3?discport=foo", 49 wantError: `invalid discport in query`, 50 }, 51 { 52 rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@127.0.0.1:52150", 53 wantResult: NewV4Hostname( 54 hexPubkey("1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 55 "127.0.0.1", 56 52150, 57 52150, 58 0, 59 ), 60 }, 61 { 62 rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@[::]:52150", 63 wantResult: NewV4Hostname( 64 hexPubkey("1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 65 "::", 66 52150, 67 52150, 68 0, 69 ), 70 }, 71 { 72 rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@[2001:db8:3c4d:15::abcd:ef12]:52150", 73 wantResult: NewV4Hostname( 74 hexPubkey("1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 75 "2001:db8:3c4d:15::abcd:ef12", 76 52150, 77 52150, 78 0, 79 ), 80 }, 81 { 82 rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@127.0.0.1:52150?discport=22334", 83 wantResult: NewV4Hostname( 84 hexPubkey("1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 85 "127.0.0.1", 86 52150, 87 22334, 88 0, 89 ), 90 }, 91 // Incomplete nodes with no address. 92 { 93 rawurl: "1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439", 94 wantResult: NewV4( 95 hexPubkey("1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 96 nil, 0, 0, 0, 97 ), 98 }, 99 { 100 rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439", 101 wantResult: NewV4( 102 hexPubkey("1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 103 nil, 0, 0, 0, 104 ), 105 }, 106 // Invalid URLs 107 { 108 rawurl: "01010101", 109 wantError: `invalid node ID (wrong length, want 128 hex chars)`, 110 }, 111 { 112 rawurl: "enode://01010101", 113 wantError: `invalid node ID (wrong length, want 128 hex chars)`, 114 }, 115 { 116 // This test checks that errors from url.Parse are handled. 117 rawurl: "://foo", 118 wantError: `parse ://foo: missing protocol scheme`, 119 }, 120 } 121 122 func hexPubkey(h string) *ecdsa.PublicKey { 123 k, err := parsePubkey(h) 124 if err != nil { 125 panic(err) 126 } 127 return k 128 } 129 130 func TestParseNode(t *testing.T) { 131 extraTests := []struct { 132 rawurl string 133 wantError string 134 wantResult *Node 135 }{ 136 { 137 rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@hostname:3", 138 wantResult: NewV4Hostname(hexPubkey("1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), "hostname", 3, 3, 0, ), 139 }, 140 } 141 142 testNodes := append(parseNodeTests, extraTests...) 143 144 for _, test := range testNodes { 145 n, err := ParseV4(test.rawurl) 146 if test.wantError != "" { 147 if err == nil { 148 t.Errorf("test %q:\n got nil error, expected %#q", test.rawurl, test.wantError) 149 continue 150 } else if !strings.Contains(err.Error(), test.wantError) { 151 t.Errorf("test %q:\n got error %#q, expected %#q", test.rawurl, err.Error(), test.wantError) 152 continue 153 } 154 } else { 155 if err != nil { 156 t.Errorf("test %q:\n unexpected error: %v", test.rawurl, err) 157 continue 158 } 159 if !reflect.DeepEqual(n, test.wantResult) { 160 t.Errorf("test %q:\n result mismatch:\ngot: %#v\nwant: %#v", test.rawurl, n, test.wantResult) 161 } 162 } 163 } 164 } 165 166 func TestNodeString(t *testing.T) { 167 for i, test := range parseNodeTests { 168 if test.wantError == "" && strings.HasPrefix(test.rawurl, "enode://") { 169 str := test.wantResult.String() 170 if str != test.rawurl { 171 t.Errorf("test %d: Node.String() mismatch:\ngot: %s\nwant: %s", i, str, test.rawurl) 172 } 173 } 174 } 175 } 176 177 func TestHexID(t *testing.T) { 178 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} 179 id1 := HexID("0x00000000000000806ad9b61fa5ae014307ebdc964253adcd9f2c0a392aa11abc") 180 id2 := HexID("00000000000000806ad9b61fa5ae014307ebdc964253adcd9f2c0a392aa11abc") 181 182 if id1 != ref { 183 t.Errorf("wrong id1\ngot %v\nwant %v", id1[:], ref[:]) 184 } 185 if id2 != ref { 186 t.Errorf("wrong id2\ngot %v\nwant %v", id2[:], ref[:]) 187 } 188 } 189 190 func TestID_textEncoding(t *testing.T) { 191 ref := ID{ 192 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 193 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x20, 194 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x30, 195 0x31, 0x32, 196 } 197 hex := "0102030405060708091011121314151617181920212223242526272829303132" 198 199 text, err := ref.MarshalText() 200 if err != nil { 201 t.Fatal(err) 202 } 203 if !bytes.Equal(text, []byte(hex)) { 204 t.Fatalf("text encoding did not match\nexpected: %s\ngot: %s", hex, text) 205 } 206 207 id := new(ID) 208 if err := id.UnmarshalText(text); err != nil { 209 t.Fatal(err) 210 } 211 if *id != ref { 212 t.Fatalf("text decoding did not match\nexpected: %s\ngot: %s", ref, id) 213 } 214 } 215 216 func TestNodeID_distcmp(t *testing.T) { 217 distcmpBig := func(target, a, b ID) int { 218 tbig := new(big.Int).SetBytes(target[:]) 219 abig := new(big.Int).SetBytes(a[:]) 220 bbig := new(big.Int).SetBytes(b[:]) 221 return new(big.Int).Xor(tbig, abig).Cmp(new(big.Int).Xor(tbig, bbig)) 222 } 223 if err := quick.CheckEqual(DistCmp, distcmpBig, nil); err != nil { 224 t.Error(err) 225 } 226 } 227 228 // The random tests is likely to miss the case where a and b are equal, 229 // this test checks it explicitly. 230 func TestNodeID_distcmpEqual(t *testing.T) { 231 base := ID{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15} 232 x := ID{15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0} 233 if DistCmp(base, x, x) != 0 { 234 t.Errorf("DistCmp(base, x, x) != 0") 235 } 236 } 237 238 func TestNodeID_logdist(t *testing.T) { 239 logdistBig := func(a, b ID) int { 240 abig, bbig := new(big.Int).SetBytes(a[:]), new(big.Int).SetBytes(b[:]) 241 return new(big.Int).Xor(abig, bbig).BitLen() 242 } 243 if err := quick.CheckEqual(LogDist, logdistBig, nil); err != nil { 244 t.Error(err) 245 } 246 } 247 248 // The random tests is likely to miss the case where a and b are equal, 249 // this test checks it explicitly. 250 func TestNodeID_logdistEqual(t *testing.T) { 251 x := ID{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15} 252 if LogDist(x, x) != 0 { 253 t.Errorf("LogDist(x, x) != 0") 254 } 255 }