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