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