github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/p2p/discv5/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 discv5 26 27 import ( 28 "fmt" 29 "math/big" 30 "math/rand" 31 "net" 32 "reflect" 33 "strings" 34 "testing" 35 "testing/quick" 36 "time" 37 38 "github.com/ethereum/go-ethereum/common" 39 "github.com/ethereum/go-ethereum/crypto" 40 ) 41 42 func ExampleNewNode() { 43 id := MustHexID("1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439") 44 45 //完整节点包含UDP和TCP终结点: 46 n1 := NewNode(id, net.ParseIP("2001:db8:3c4d:15::abcd:ef12"), 52150, 30303) 47 fmt.Println("n1:", n1) 48 fmt.Println("n1.Incomplete() ->", n1.Incomplete()) 49 50 //通过传递零值可以创建不完整的节点 51 //用于除ID以外的所有参数。 52 n2 := NewNode(id, nil, 0, 0) 53 fmt.Println("n2:", n2) 54 fmt.Println("n2.Incomplete() ->", n2.Incomplete()) 55 56 //输出: 57 //n1:enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6c1c64a5c8d659f51fcd512be2435232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@[2001:db8:3c4d:15::abcd:ef12]:30303?磁盘端口=52150 58 //n1.incomplete()->错误 59 //n2:enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6c1c64a5c8d659f51fcd512be2435232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439 60 //n2.incomplete()->真 61 } 62 63 var parseNodeTests = []struct { 64 rawurl string 65 wantError string 66 wantResult *Node 67 }{ 68 { 69 rawurl: "http://“福巴” 70 wantError: `invalid URL scheme, want "enode"`, 71 }, 72 { 73 rawurl: "enode://01010101@123.124.125.126:3“, 74 wantError: `invalid node ID (wrong length, want 128 hex chars)`, 75 }, 76 //使用IP地址完成节点。 77 { 78 rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6c1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@hostname:3“, 79 wantError: `invalid IP address`, 80 }, 81 { 82 rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6c1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@127.0.0.1:foo“, 83 wantError: `invalid port`, 84 }, 85 { 86 rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6c1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@127.0.0.1:3?迪斯科= 87 wantError: `invalid discport in query`, 88 }, 89 { 90 rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6c1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@127.0.0.1:52150“, 91 wantResult: NewNode( 92 MustHexID("0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 93 net.IP{0x7f, 0x0, 0x0, 0x1}, 94 52150, 95 52150, 96 ), 97 }, 98 { 99 rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6c1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@[::]:52150“, 100 wantResult: NewNode( 101 MustHexID("0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 102 net.ParseIP("::"), 103 52150, 104 52150, 105 ), 106 }, 107 { 108 rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6c1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@[2001:db8:3c4d:15::abcd:ef12]:52150“, 109 wantResult: NewNode( 110 MustHexID("0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 111 net.ParseIP("2001:db8:3c4d:15::abcd:ef12"), 112 52150, 113 52150, 114 ), 115 }, 116 { 117 rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6c1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@127.0.0.1:52150?discport=22334“, 118 wantResult: NewNode( 119 MustHexID("0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 120 net.IP{0x7f, 0x0, 0x0, 0x1}, 121 22334, 122 52150, 123 ), 124 }, 125 //没有地址的不完整节点。 126 { 127 rawurl: "1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439", 128 wantResult: NewNode( 129 MustHexID("0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 130 nil, 0, 0, 131 ), 132 }, 133 { 134 rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6c6c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439“, 135 wantResult: NewNode( 136 MustHexID("0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 137 nil, 0, 0, 138 ), 139 }, 140 //无效网址 141 { 142 rawurl: "01010101", 143 wantError: `invalid node ID (wrong length, want 128 hex chars)`, 144 }, 145 { 146 rawurl: "enode://01010101“, 147 wantError: `invalid node ID (wrong length, want 128 hex chars)`, 148 }, 149 { 150 //此测试检查是否处理了URL.Parse中的错误。 151 rawurl: "://“,” 152 wantError: `parse ://foo:缺少协议方案`, 153 }, 154 } 155 156 func TestParseNode(t *testing.T) { 157 for _, test := range parseNodeTests { 158 n, err := ParseNode(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 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, want: %#v", test.rawurl, n, test.wantResult) 174 } 175 } 176 } 177 } 178 179 func TestNodeString(t *testing.T) { 180 for i, test := range parseNodeTests { 181 if test.wantError == "" && strings.HasPrefix(test.rawurl, "enode://“”{ 182 str := test.wantResult.String() 183 if str != test.rawurl { 184 t.Errorf("test %d: Node.String() mismatch:\ngot: %s\nwant: %s", i, str, test.rawurl) 185 } 186 } 187 } 188 } 189 190 func TestHexID(t *testing.T) { 191 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} 192 id1 := MustHexID("0x000000000000000000000000000000000000000000000000000000000000000000000000000000806ad9b61fa5ae014307ebdc964253adcd9f2c0a392aa11abc") 193 id2 := MustHexID("000000000000000000000000000000000000000000000000000000000000000000000000000000806ad9b61fa5ae014307ebdc964253adcd9f2c0a392aa11abc") 194 195 if id1 != ref { 196 t.Errorf("wrong id1\ngot %v\nwant %v", id1[:], ref[:]) 197 } 198 if id2 != ref { 199 t.Errorf("wrong id2\ngot %v\nwant %v", id2[:], ref[:]) 200 } 201 } 202 203 func TestNodeID_recover(t *testing.T) { 204 prv := newkey() 205 hash := make([]byte, 32) 206 sig, err := crypto.Sign(hash, prv) 207 if err != nil { 208 t.Fatalf("signing error: %v", err) 209 } 210 211 pub := PubkeyID(&prv.PublicKey) 212 recpub, err := recoverNodeID(hash, sig) 213 if err != nil { 214 t.Fatalf("recovery error: %v", err) 215 } 216 if pub != recpub { 217 t.Errorf("recovered wrong pubkey:\ngot: %v\nwant: %v", recpub, pub) 218 } 219 220 ecdsa, err := pub.Pubkey() 221 if err != nil { 222 t.Errorf("Pubkey error: %v", err) 223 } 224 if !reflect.DeepEqual(ecdsa, &prv.PublicKey) { 225 t.Errorf("Pubkey mismatch:\n got: %#v\n want: %#v", ecdsa, &prv.PublicKey) 226 } 227 } 228 229 func TestNodeID_pubkeyBad(t *testing.T) { 230 ecdsa, err := NodeID{}.Pubkey() 231 if err == nil { 232 t.Error("expected error for zero ID") 233 } 234 if ecdsa != nil { 235 t.Error("expected nil result") 236 } 237 } 238 239 func TestNodeID_distcmp(t *testing.T) { 240 distcmpBig := func(target, a, b common.Hash) int { 241 tbig := new(big.Int).SetBytes(target[:]) 242 abig := new(big.Int).SetBytes(a[:]) 243 bbig := new(big.Int).SetBytes(b[:]) 244 return new(big.Int).Xor(tbig, abig).Cmp(new(big.Int).Xor(tbig, bbig)) 245 } 246 if err := quick.CheckEqual(distcmp, distcmpBig, quickcfg()); err != nil { 247 t.Error(err) 248 } 249 } 250 251 //随机测试很可能会错过它们相等的情况。 252 func TestNodeID_distcmpEqual(t *testing.T) { 253 base := common.Hash{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15} 254 x := common.Hash{15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0} 255 if distcmp(base, x, x) != 0 { 256 t.Errorf("distcmp(base, x, x) != 0") 257 } 258 } 259 260 func TestNodeID_logdist(t *testing.T) { 261 logdistBig := func(a, b common.Hash) int { 262 abig, bbig := new(big.Int).SetBytes(a[:]), new(big.Int).SetBytes(b[:]) 263 return new(big.Int).Xor(abig, bbig).BitLen() 264 } 265 if err := quick.CheckEqual(logdist, logdistBig, quickcfg()); err != nil { 266 t.Error(err) 267 } 268 } 269 270 //随机测试很可能会错过它们相等的情况。 271 func TestNodeID_logdistEqual(t *testing.T) { 272 x := common.Hash{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15} 273 if logdist(x, x) != 0 { 274 t.Errorf("logdist(x, x) != 0") 275 } 276 } 277 278 func TestNodeID_hashAtDistance(t *testing.T) { 279 //我们不使用quick。请检查这里,因为它的输出不是 280 //当测试失败时非常有用。 281 cfg := quickcfg() 282 for i := 0; i < cfg.MaxCount; i++ { 283 a := gen(common.Hash{}, cfg.Rand).(common.Hash) 284 dist := cfg.Rand.Intn(len(common.Hash{}) * 8) 285 result := hashAtDistance(a, dist) 286 actualdist := logdist(result, a) 287 288 if dist != actualdist { 289 t.Log("a: ", a) 290 t.Log("result:", result) 291 t.Fatalf("#%d: distance of result is %d, want %d", i, actualdist, dist) 292 } 293 } 294 } 295 296 func quickcfg() *quick.Config { 297 return &quick.Config{ 298 MaxCount: 5000, 299 Rand: rand.New(rand.NewSource(time.Now().Unix())), 300 } 301 } 302 303 //TODO:当我们需要go大于等于1.5时,可以删除generate方法。 304 //因为测试/快速学习在1.5中生成数组。 305 306 func (NodeID) Generate(rand *rand.Rand, size int) reflect.Value { 307 var id NodeID 308 m := rand.Intn(len(id)) 309 for i := len(id) - 1; i > m; i-- { 310 id[i] = byte(rand.Uint32()) 311 } 312 return reflect.ValueOf(id) 313 }