github.com/ethereumproject/go-ethereum@v5.5.2+incompatible/p2p/discover/node_test.go (about) 1 // Copyright 2015 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 discover 18 19 import ( 20 "fmt" 21 "math/rand" 22 "net" 23 "reflect" 24 "strings" 25 "testing" 26 "testing/quick" 27 "time" 28 29 "github.com/ethereumproject/go-ethereum/crypto" 30 ) 31 32 func ExampleNewNode() { 33 id := MustHexID("1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439") 34 35 // Complete nodes contain UDP and TCP endpoints: 36 n1 := NewNode(id, net.ParseIP("2001:db8:3c4d:15::abcd:ef12"), 52150, 30303) 37 fmt.Println("n1:", n1) 38 fmt.Println("n1.Incomplete() ->", n1.Incomplete()) 39 40 // An incomplete node can be created by passing zero values 41 // for all parameters except id. 42 n2 := NewNode(id, nil, 0, 0) 43 fmt.Println("n2:", n2) 44 fmt.Println("n2.Incomplete() ->", n2.Incomplete()) 45 46 // Output: 47 // n1: enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@[2001:db8:3c4d:15::abcd:ef12]:30303?discport=52150 48 // n1.Incomplete() -> false 49 // n2: enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439 50 // n2.Incomplete() -> true 51 } 52 53 var parseNodeTests = []struct { 54 rawurl string 55 wantError string 56 wantResult *Node 57 }{ 58 { 59 rawurl: "http://foobar", 60 wantError: `invalid URL scheme, want "enode"`, 61 }, 62 { 63 rawurl: "enode://01010101@123.124.125.126:3", 64 wantError: `invalid node ID (wrong length, want 128 hex chars)`, 65 }, 66 // Complete nodes with IP address. 67 { 68 rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@hostname:3", 69 wantError: `invalid IP address`, 70 }, 71 { 72 rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@127.0.0.1:foo", 73 wantError: `invalid port`, 74 }, 75 { 76 rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@127.0.0.1:3?discport=foo", 77 wantError: `invalid discport in query`, 78 }, 79 { 80 rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@127.0.0.1:52150", 81 wantResult: NewNode( 82 MustHexID("0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 83 net.IP{0x7f, 0x0, 0x0, 0x1}, 84 52150, 85 52150, 86 ), 87 }, 88 { 89 rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@[::]:52150", 90 wantResult: NewNode( 91 MustHexID("0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 92 net.ParseIP("::"), 93 52150, 94 52150, 95 ), 96 }, 97 { 98 rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@[2001:db8:3c4d:15::abcd:ef12]:52150", 99 wantResult: NewNode( 100 MustHexID("0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 101 net.ParseIP("2001:db8:3c4d:15::abcd:ef12"), 102 52150, 103 52150, 104 ), 105 }, 106 { 107 rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@127.0.0.1:52150?discport=22334", 108 wantResult: NewNode( 109 MustHexID("0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 110 net.IP{0x7f, 0x0, 0x0, 0x1}, 111 22334, 112 52150, 113 ), 114 }, 115 // Incomplete nodes with no address. 116 { 117 rawurl: "1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439", 118 wantResult: NewNode( 119 MustHexID("0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 120 nil, 0, 0, 121 ), 122 }, 123 { 124 rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439", 125 wantResult: NewNode( 126 MustHexID("0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 127 nil, 0, 0, 128 ), 129 }, 130 // Invalid URLs 131 { 132 rawurl: "01010101", 133 wantError: `invalid node ID (wrong length, want 128 hex chars)`, 134 }, 135 { 136 rawurl: "enode://01010101", 137 wantError: `invalid node ID (wrong length, want 128 hex chars)`, 138 }, 139 { 140 // This test checks that errors from url.Parse are handled. 141 rawurl: "://foo", 142 wantError: `parse ://foo: missing protocol scheme`, 143 }, 144 } 145 146 func TestParseNode(t *testing.T) { 147 for _, test := range parseNodeTests { 148 n, err := ParseNode(test.rawurl) 149 if test.wantError != "" { 150 if err == nil { 151 t.Errorf("test %q:\n got nil error, expected %#q", test.rawurl, test.wantError) 152 continue 153 } else if err.Error() != test.wantError { 154 t.Errorf("test %q:\n got error %#q, expected %#q", test.rawurl, err.Error(), test.wantError) 155 continue 156 } 157 } else { 158 if err != nil { 159 t.Errorf("test %q:\n unexpected error: %v", test.rawurl, err) 160 continue 161 } 162 if !reflect.DeepEqual(n, test.wantResult) { 163 t.Errorf("test %q:\n result mismatch:\ngot: %#v, want: %#v", test.rawurl, n, test.wantResult) 164 } 165 } 166 } 167 } 168 169 func TestNodeString(t *testing.T) { 170 for i, test := range parseNodeTests { 171 if test.wantError == "" && strings.HasPrefix(test.rawurl, "enode://") { 172 str := test.wantResult.String() 173 if str != test.rawurl { 174 t.Errorf("test %d: Node.String() mismatch:\ngot: %s\nwant: %s", i, str, test.rawurl) 175 } 176 } 177 } 178 } 179 180 func TestHexID(t *testing.T) { 181 ref := NodeID{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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} 182 id1 := MustHexID("0x000000000000000000000000000000000000000000000000000000000000000000000000000000806ad9b61fa5ae014307ebdc964253adcd9f2c0a392aa11abc") 183 id2 := MustHexID("000000000000000000000000000000000000000000000000000000000000000000000000000000806ad9b61fa5ae014307ebdc964253adcd9f2c0a392aa11abc") 184 185 if id1 != ref { 186 t.Errorf("wrong id1\ngot %v\nwant %v", id1[:], ref[:]) 187 } 188 if id2 != ref { 189 t.Errorf("wrong id2\ngot %v\nwant %v", id2[:], ref[:]) 190 } 191 } 192 193 func TestNodeID_recover(t *testing.T) { 194 prv := newkey() 195 hash := make([]byte, 32) 196 sig, err := crypto.Sign(hash, prv) 197 if err != nil { 198 t.Fatalf("signing error: %v", err) 199 } 200 201 pub := PubkeyID(&prv.PublicKey) 202 recpub, err := recoverNodeID(hash, sig) 203 if err != nil { 204 t.Fatalf("recovery error: %v", err) 205 } 206 if pub != recpub { 207 t.Errorf("recovered wrong pubkey:\ngot: %v\nwant: %v", recpub, pub) 208 } 209 210 ecdsa, err := pub.Pubkey() 211 if err != nil { 212 t.Errorf("Pubkey error: %v", err) 213 } 214 if !reflect.DeepEqual(ecdsa, &prv.PublicKey) { 215 t.Errorf("Pubkey mismatch:\n got: %#v\n want: %#v", ecdsa, &prv.PublicKey) 216 } 217 } 218 219 func TestNodeID_pubkeyBad(t *testing.T) { 220 ecdsa, err := NodeID{}.Pubkey() 221 if err == nil { 222 t.Error("expected error for zero ID") 223 } 224 if ecdsa != nil { 225 t.Error("expected nil result") 226 } 227 } 228 229 func quickcfg() *quick.Config { 230 return &quick.Config{ 231 MaxCount: 5000, 232 Rand: rand.New(rand.NewSource(time.Now().Unix())), 233 } 234 } 235 236 // TODO: The Generate method can be dropped when we require Go >= 1.5 237 // because testing/quick learned to generate arrays in 1.5. 238 239 func (NodeID) Generate(rand *rand.Rand, size int) reflect.Value { 240 var id NodeID 241 m := rand.Intn(len(id)) 242 for i := len(id) - 1; i > m; i-- { 243 id[i] = byte(rand.Uint32()) 244 } 245 return reflect.ValueOf(id) 246 }