github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/p2p/discover/node_test.go (about) 1 2 //<developer> 3 // <name>linapex 曹一峰</name> 4 // <email>linapex@163.com</email> 5 // <wx>superexc</wx> 6 // <qqgroup>128148617</qqgroup> 7 // <url>https://jsq.ink</url> 8 // <role>pku engineer</role> 9 // <date>2019-03-16 12:09:43</date> 10 //</624342655978967040> 11 12 13 package discover 14 15 import ( 16 "bytes" 17 "fmt" 18 "math/big" 19 "math/rand" 20 "net" 21 "reflect" 22 "strings" 23 "testing" 24 "testing/quick" 25 "time" 26 27 "github.com/ethereum/go-ethereum/common" 28 "github.com/ethereum/go-ethereum/crypto" 29 ) 30 31 func ExampleNewNode() { 32 id := MustHexID("1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439") 33 34 //完整节点包含UDP和TCP终结点: 35 n1 := NewNode(id, net.ParseIP("2001:db8:3c4d:15::abcd:ef12"), 52150, 30303) 36 fmt.Println("n1:", n1) 37 fmt.Println("n1.Incomplete() ->", n1.Incomplete()) 38 39 //通过传递零值可以创建不完整的节点 40 //用于除ID以外的所有参数。 41 n2 := NewNode(id, nil, 0, 0) 42 fmt.Println("n2:", n2) 43 fmt.Println("n2.Incomplete() ->", n2.Incomplete()) 44 45 //输出: 46 //n1:enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6c1c64a5c8d659f51fcd512be2435232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@[2001:db8:3c4d:15::abcd:ef12]:30303?磁盘端口=52150 47 //n1.incomplete()->错误 48 //n2:enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6c1c64a5c8d659f51fcd512be2435232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439 49 //n2.incomplete()->真 50 } 51 52 var parseNodeTests = []struct { 53 rawurl string 54 wantError string 55 wantResult *Node 56 }{ 57 { 58 rawurl: "http://“福巴” 59 wantError: `invalid URL scheme, want "enode"`, 60 }, 61 { 62 rawurl: "enode://01010101@123.124.125.126:3“, 63 wantError: `invalid node ID (wrong length, want 128 hex chars)`, 64 }, 65 //使用IP地址完成节点。 66 { 67 rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6c1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@hostname:3“, 68 wantError: `invalid IP address`, 69 }, 70 { 71 rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6c1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@127.0.0.1:foo“, 72 wantError: `invalid port`, 73 }, 74 { 75 rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6c1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@127.0.0.1:3?迪斯科= 76 wantError: `invalid discport in query`, 77 }, 78 { 79 rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6c1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@127.0.0.1:52150“, 80 wantResult: NewNode( 81 MustHexID("0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 82 net.IP{0x7f, 0x0, 0x0, 0x1}, 83 52150, 84 52150, 85 ), 86 }, 87 { 88 rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6c1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@[::]:52150“, 89 wantResult: NewNode( 90 MustHexID("0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 91 net.ParseIP("::"), 92 52150, 93 52150, 94 ), 95 }, 96 { 97 rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6c1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@[2001:db8:3c4d:15::abcd:ef12]:52150“, 98 wantResult: NewNode( 99 MustHexID("0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 100 net.ParseIP("2001:db8:3c4d:15::abcd:ef12"), 101 52150, 102 52150, 103 ), 104 }, 105 { 106 rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6c1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@127.0.0.1:52150?discport=22334“, 107 wantResult: NewNode( 108 MustHexID("0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 109 net.IP{0x7f, 0x0, 0x0, 0x1}, 110 22334, 111 52150, 112 ), 113 }, 114 //没有地址的不完整节点。 115 { 116 rawurl: "1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439", 117 wantResult: NewNode( 118 MustHexID("0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 119 nil, 0, 0, 120 ), 121 }, 122 { 123 rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6c6c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439“, 124 wantResult: NewNode( 125 MustHexID("0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 126 nil, 0, 0, 127 ), 128 }, 129 //无效网址 130 { 131 rawurl: "01010101", 132 wantError: `invalid node ID (wrong length, want 128 hex chars)`, 133 }, 134 { 135 rawurl: "enode://01010101“, 136 wantError: `invalid node ID (wrong length, want 128 hex chars)`, 137 }, 138 { 139 //此测试检查是否处理了URL.Parse中的错误。 140 rawurl: "://“,” 141 wantError: `parse ://foo:缺少协议方案`, 142 }, 143 } 144 145 func TestParseNode(t *testing.T) { 146 for _, test := range parseNodeTests { 147 n, err := ParseNode(test.rawurl) 148 if test.wantError != "" { 149 if err == nil { 150 t.Errorf("test %q:\n got nil error, expected %#q", test.rawurl, test.wantError) 151 continue 152 } else if err.Error() != test.wantError { 153 t.Errorf("test %q:\n got error %#q, expected %#q", test.rawurl, err.Error(), test.wantError) 154 continue 155 } 156 } else { 157 if err != nil { 158 t.Errorf("test %q:\n unexpected error: %v", test.rawurl, err) 159 continue 160 } 161 if !reflect.DeepEqual(n, test.wantResult) { 162 t.Errorf("test %q:\n result mismatch:\ngot: %#v, want: %#v", test.rawurl, n, test.wantResult) 163 } 164 } 165 } 166 } 167 168 func TestNodeString(t *testing.T) { 169 for i, test := range parseNodeTests { 170 if test.wantError == "" && strings.HasPrefix(test.rawurl, "enode://“”{ 171 str := test.wantResult.String() 172 if str != test.rawurl { 173 t.Errorf("test %d: Node.String() mismatch:\ngot: %s\nwant: %s", i, str, test.rawurl) 174 } 175 } 176 } 177 } 178 179 func TestHexID(t *testing.T) { 180 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} 181 id1 := MustHexID("0x000000000000000000000000000000000000000000000000000000000000000000000000000000806ad9b61fa5ae014307ebdc964253adcd9f2c0a392aa11abc") 182 id2 := MustHexID("000000000000000000000000000000000000000000000000000000000000000000000000000000806ad9b61fa5ae014307ebdc964253adcd9f2c0a392aa11abc") 183 184 if id1 != ref { 185 t.Errorf("wrong id1\ngot %v\nwant %v", id1[:], ref[:]) 186 } 187 if id2 != ref { 188 t.Errorf("wrong id2\ngot %v\nwant %v", id2[:], ref[:]) 189 } 190 } 191 192 func TestNodeID_textEncoding(t *testing.T) { 193 ref := NodeID{ 194 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 195 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x20, 196 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x30, 197 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x40, 198 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x50, 199 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x60, 200 0x61, 0x62, 0x63, 0x64, 201 } 202 hex := "01020304050607080910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364" 203 204 text, err := ref.MarshalText() 205 if err != nil { 206 t.Fatal(err) 207 } 208 if !bytes.Equal(text, []byte(hex)) { 209 t.Fatalf("text encoding did not match\nexpected: %s\ngot: %s", hex, text) 210 } 211 212 id := new(NodeID) 213 if err := id.UnmarshalText(text); err != nil { 214 t.Fatal(err) 215 } 216 if *id != ref { 217 t.Fatalf("text decoding did not match\nexpected: %s\ngot: %s", ref, id) 218 } 219 } 220 221 func TestNodeID_recover(t *testing.T) { 222 prv := newkey() 223 hash := make([]byte, 32) 224 sig, err := crypto.Sign(hash, prv) 225 if err != nil { 226 t.Fatalf("signing error: %v", err) 227 } 228 229 pub := PubkeyID(&prv.PublicKey) 230 recpub, err := recoverNodeID(hash, sig) 231 if err != nil { 232 t.Fatalf("recovery error: %v", err) 233 } 234 if pub != recpub { 235 t.Errorf("recovered wrong pubkey:\ngot: %v\nwant: %v", recpub, pub) 236 } 237 238 ecdsa, err := pub.Pubkey() 239 if err != nil { 240 t.Errorf("Pubkey error: %v", err) 241 } 242 if !reflect.DeepEqual(ecdsa, &prv.PublicKey) { 243 t.Errorf("Pubkey mismatch:\n got: %#v\n want: %#v", ecdsa, &prv.PublicKey) 244 } 245 } 246 247 func TestNodeID_pubkeyBad(t *testing.T) { 248 ecdsa, err := NodeID{}.Pubkey() 249 if err == nil { 250 t.Error("expected error for zero ID") 251 } 252 if ecdsa != nil { 253 t.Error("expected nil result") 254 } 255 } 256 257 func TestNodeID_distcmp(t *testing.T) { 258 distcmpBig := func(target, a, b common.Hash) int { 259 tbig := new(big.Int).SetBytes(target[:]) 260 abig := new(big.Int).SetBytes(a[:]) 261 bbig := new(big.Int).SetBytes(b[:]) 262 return new(big.Int).Xor(tbig, abig).Cmp(new(big.Int).Xor(tbig, bbig)) 263 } 264 if err := quick.CheckEqual(distcmp, distcmpBig, quickcfg()); err != nil { 265 t.Error(err) 266 } 267 } 268 269 //随机测试很可能会错过它们相等的情况。 270 func TestNodeID_distcmpEqual(t *testing.T) { 271 base := common.Hash{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15} 272 x := common.Hash{15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0} 273 if distcmp(base, x, x) != 0 { 274 t.Errorf("distcmp(base, x, x) != 0") 275 } 276 } 277 278 func TestNodeID_logdist(t *testing.T) { 279 logdistBig := func(a, b common.Hash) int { 280 abig, bbig := new(big.Int).SetBytes(a[:]), new(big.Int).SetBytes(b[:]) 281 return new(big.Int).Xor(abig, bbig).BitLen() 282 } 283 if err := quick.CheckEqual(logdist, logdistBig, quickcfg()); err != nil { 284 t.Error(err) 285 } 286 } 287 288 //随机测试很可能会错过它们相等的情况。 289 func TestNodeID_logdistEqual(t *testing.T) { 290 x := common.Hash{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15} 291 if logdist(x, x) != 0 { 292 t.Errorf("logdist(x, x) != 0") 293 } 294 } 295 296 func TestNodeID_hashAtDistance(t *testing.T) { 297 //我们不使用quick。请检查这里,因为它的输出不是 298 //当测试失败时非常有用。 299 cfg := quickcfg() 300 for i := 0; i < cfg.MaxCount; i++ { 301 a := gen(common.Hash{}, cfg.Rand).(common.Hash) 302 dist := cfg.Rand.Intn(len(common.Hash{}) * 8) 303 result := hashAtDistance(a, dist) 304 actualdist := logdist(result, a) 305 306 if dist != actualdist { 307 t.Log("a: ", a) 308 t.Log("result:", result) 309 t.Fatalf("#%d: distance of result is %d, want %d", i, actualdist, dist) 310 } 311 } 312 } 313 314 func quickcfg() *quick.Config { 315 return &quick.Config{ 316 MaxCount: 5000, 317 Rand: rand.New(rand.NewSource(time.Now().Unix())), 318 } 319 } 320 321 //TODO:当我们需要go大于等于1.5时,可以删除generate方法。 322 //因为测试/快速学习在1.5中生成数组。 323 324 func (NodeID) Generate(rand *rand.Rand, size int) reflect.Value { 325 var id NodeID 326 m := rand.Intn(len(id)) 327 for i := len(id) - 1; i > m; i-- { 328 id[i] = byte(rand.Uint32()) 329 } 330 return reflect.ValueOf(id) 331 } 332