github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/p2p/protocols/protocol_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 //版权所有2017 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 protocols 26 27 import ( 28 "context" 29 "errors" 30 "fmt" 31 "testing" 32 "time" 33 34 "github.com/ethereum/go-ethereum/p2p" 35 "github.com/ethereum/go-ethereum/p2p/discover" 36 "github.com/ethereum/go-ethereum/p2p/simulations/adapters" 37 p2ptest "github.com/ethereum/go-ethereum/p2p/testing" 38 ) 39 40 //握手消息类型 41 type hs0 struct { 42 C uint 43 } 44 45 //用nodeid终止/删除对等机的消息 46 type kill struct { 47 C discover.NodeID 48 } 49 50 //断开连接的消息 51 type drop struct { 52 } 53 54 ///protochandshake表示协议与模块无关的方面,并且 55 //第一个消息对等端作为初始交换的一部分发送和接收 56 type protoHandshake struct { 57 Version uint //本地和远程对等机应具有相同的版本 58 NetworkID string //本地和远程对等机应具有相同的网络ID 59 } 60 61 //检查协议握手验证本地和远程协议握手是否匹配 62 func checkProtoHandshake(testVersion uint, testNetworkID string) func(interface{}) error { 63 return func(rhs interface{}) error { 64 remote := rhs.(*protoHandshake) 65 if remote.NetworkID != testNetworkID { 66 return fmt.Errorf("%s (!= %s)", remote.NetworkID, testNetworkID) 67 } 68 69 if remote.Version != testVersion { 70 return fmt.Errorf("%d (!= %d)", remote.Version, testVersion) 71 } 72 return nil 73 } 74 } 75 76 //新协议设置协议 77 //这里的run函数演示了使用peerpool和handshake的典型协议 78 //以及注册到处理程序的消息 79 func newProtocol(pp *p2ptest.TestPeerPool) func(*p2p.Peer, p2p.MsgReadWriter) error { 80 spec := &Spec{ 81 Name: "test", 82 Version: 42, 83 MaxMsgSize: 10 * 1024, 84 Messages: []interface{}{ 85 protoHandshake{}, 86 hs0{}, 87 kill{}, 88 drop{}, 89 }, 90 } 91 return func(p *p2p.Peer, rw p2p.MsgReadWriter) error { 92 peer := NewPeer(p, rw, spec) 93 94 //启动一次性协议握手并检查有效性 95 ctx, cancel := context.WithTimeout(context.Background(), time.Second) 96 defer cancel() 97 phs := &protoHandshake{42, "420"} 98 hsCheck := checkProtoHandshake(phs.Version, phs.NetworkID) 99 _, err := peer.Handshake(ctx, phs, hsCheck) 100 if err != nil { 101 return err 102 } 103 104 lhs := &hs0{42} 105 //模块握手演示同一类型消息的简单可重复交换 106 hs, err := peer.Handshake(ctx, lhs, nil) 107 if err != nil { 108 return err 109 } 110 111 if rmhs := hs.(*hs0); rmhs.C > lhs.C { 112 return fmt.Errorf("handshake mismatch remote %v > local %v", rmhs.C, lhs.C) 113 } 114 115 handle := func(ctx context.Context, msg interface{}) error { 116 switch msg := msg.(type) { 117 118 case *protoHandshake: 119 return errors.New("duplicate handshake") 120 121 case *hs0: 122 rhs := msg 123 if rhs.C > lhs.C { 124 return fmt.Errorf("handshake mismatch remote %v > local %v", rhs.C, lhs.C) 125 } 126 lhs.C += rhs.C 127 return peer.Send(ctx, lhs) 128 129 case *kill: 130 //演示使用对等池,终止另一个对等连接作为对消息的响应 131 id := msg.C 132 pp.Get(id).Drop(errors.New("killed")) 133 return nil 134 135 case *drop: 136 //对于测试,我们可以在接收到丢弃消息时触发自诱导断开。 137 return errors.New("dropped") 138 139 default: 140 return fmt.Errorf("unknown message type: %T", msg) 141 } 142 } 143 144 pp.Add(peer) 145 defer pp.Remove(peer) 146 return peer.Run(handle) 147 } 148 } 149 150 func protocolTester(t *testing.T, pp *p2ptest.TestPeerPool) *p2ptest.ProtocolTester { 151 conf := adapters.RandomNodeConfig() 152 return p2ptest.NewProtocolTester(t, conf.ID, 2, newProtocol(pp)) 153 } 154 155 func protoHandshakeExchange(id discover.NodeID, proto *protoHandshake) []p2ptest.Exchange { 156 157 return []p2ptest.Exchange{ 158 { 159 Expects: []p2ptest.Expect{ 160 { 161 Code: 0, 162 Msg: &protoHandshake{42, "420"}, 163 Peer: id, 164 }, 165 }, 166 }, 167 { 168 Triggers: []p2ptest.Trigger{ 169 { 170 Code: 0, 171 Msg: proto, 172 Peer: id, 173 }, 174 }, 175 }, 176 } 177 } 178 179 func runProtoHandshake(t *testing.T, proto *protoHandshake, errs ...error) { 180 pp := p2ptest.NewTestPeerPool() 181 s := protocolTester(t, pp) 182 //托多:多做一次握手 183 id := s.IDs[0] 184 if err := s.TestExchanges(protoHandshakeExchange(id, proto)...); err != nil { 185 t.Fatal(err) 186 } 187 var disconnects []*p2ptest.Disconnect 188 for i, err := range errs { 189 disconnects = append(disconnects, &p2ptest.Disconnect{Peer: s.IDs[i], Error: err}) 190 } 191 if err := s.TestDisconnected(disconnects...); err != nil { 192 t.Fatal(err) 193 } 194 } 195 196 func TestProtoHandshakeVersionMismatch(t *testing.T) { 197 runProtoHandshake(t, &protoHandshake{41, "420"}, errorf(ErrHandshake, errorf(ErrHandler, "(msg code 0): 41 (!= 42)").Error())) 198 } 199 200 func TestProtoHandshakeNetworkIDMismatch(t *testing.T) { 201 runProtoHandshake(t, &protoHandshake{42, "421"}, errorf(ErrHandshake, errorf(ErrHandler, "(msg code 0): 421 (!= 420)").Error())) 202 } 203 204 func TestProtoHandshakeSuccess(t *testing.T) { 205 runProtoHandshake(t, &protoHandshake{42, "420"}) 206 } 207 208 func moduleHandshakeExchange(id discover.NodeID, resp uint) []p2ptest.Exchange { 209 210 return []p2ptest.Exchange{ 211 { 212 Expects: []p2ptest.Expect{ 213 { 214 Code: 1, 215 Msg: &hs0{42}, 216 Peer: id, 217 }, 218 }, 219 }, 220 { 221 Triggers: []p2ptest.Trigger{ 222 { 223 Code: 1, 224 Msg: &hs0{resp}, 225 Peer: id, 226 }, 227 }, 228 }, 229 } 230 } 231 232 func runModuleHandshake(t *testing.T, resp uint, errs ...error) { 233 pp := p2ptest.NewTestPeerPool() 234 s := protocolTester(t, pp) 235 id := s.IDs[0] 236 if err := s.TestExchanges(protoHandshakeExchange(id, &protoHandshake{42, "420"})...); err != nil { 237 t.Fatal(err) 238 } 239 if err := s.TestExchanges(moduleHandshakeExchange(id, resp)...); err != nil { 240 t.Fatal(err) 241 } 242 var disconnects []*p2ptest.Disconnect 243 for i, err := range errs { 244 disconnects = append(disconnects, &p2ptest.Disconnect{Peer: s.IDs[i], Error: err}) 245 } 246 if err := s.TestDisconnected(disconnects...); err != nil { 247 t.Fatal(err) 248 } 249 } 250 251 func TestModuleHandshakeError(t *testing.T) { 252 runModuleHandshake(t, 43, fmt.Errorf("handshake mismatch remote 43 > local 42")) 253 } 254 255 func TestModuleHandshakeSuccess(t *testing.T) { 256 runModuleHandshake(t, 42) 257 } 258 259 //在多个对等点上测试复杂的交互、中继、丢弃 260 func testMultiPeerSetup(a, b discover.NodeID) []p2ptest.Exchange { 261 262 return []p2ptest.Exchange{ 263 { 264 Label: "primary handshake", 265 Expects: []p2ptest.Expect{ 266 { 267 Code: 0, 268 Msg: &protoHandshake{42, "420"}, 269 Peer: a, 270 }, 271 { 272 Code: 0, 273 Msg: &protoHandshake{42, "420"}, 274 Peer: b, 275 }, 276 }, 277 }, 278 { 279 Label: "module handshake", 280 Triggers: []p2ptest.Trigger{ 281 { 282 Code: 0, 283 Msg: &protoHandshake{42, "420"}, 284 Peer: a, 285 }, 286 { 287 Code: 0, 288 Msg: &protoHandshake{42, "420"}, 289 Peer: b, 290 }, 291 }, 292 Expects: []p2ptest.Expect{ 293 { 294 Code: 1, 295 Msg: &hs0{42}, 296 Peer: a, 297 }, 298 { 299 Code: 1, 300 Msg: &hs0{42}, 301 Peer: b, 302 }, 303 }, 304 }, 305 306 {Label: "alternative module handshake", Triggers: []p2ptest.Trigger{{Code: 1, Msg: &hs0{41}, Peer: a}, 307 {Code: 1, Msg: &hs0{41}, Peer: b}}}, 308 {Label: "repeated module handshake", Triggers: []p2ptest.Trigger{{Code: 1, Msg: &hs0{1}, Peer: a}}}, 309 {Label: "receiving repeated module handshake", Expects: []p2ptest.Expect{{Code: 1, Msg: &hs0{43}, Peer: a}}}} 310 } 311 312 func runMultiplePeers(t *testing.T, peer int, errs ...error) { 313 pp := p2ptest.NewTestPeerPool() 314 s := protocolTester(t, pp) 315 316 if err := s.TestExchanges(testMultiPeerSetup(s.IDs[0], s.IDs[1])...); err != nil { 317 t.Fatal(err) 318 } 319 //在一些消息交换之后,我们可以测试状态变化 320 //在这里,这只是由Peerpool演示的 321 //握手后,必须将对等方添加到池中 322 //睡眠时间(1) 323 tick := time.NewTicker(10 * time.Millisecond) 324 timeout := time.NewTimer(1 * time.Second) 325 WAIT: 326 for { 327 select { 328 case <-tick.C: 329 if pp.Has(s.IDs[0]) { 330 break WAIT 331 } 332 case <-timeout.C: 333 t.Fatal("timeout") 334 } 335 } 336 if !pp.Has(s.IDs[1]) { 337 t.Fatalf("missing peer test-1: %v (%v)", pp, s.IDs) 338 } 339 340 //peer 0发送索引为peer的kill请求<peer> 341 err := s.TestExchanges(p2ptest.Exchange{ 342 Triggers: []p2ptest.Trigger{ 343 { 344 Code: 2, 345 Msg: &kill{s.IDs[peer]}, 346 Peer: s.IDs[0], 347 }, 348 }, 349 }) 350 351 if err != nil { 352 t.Fatal(err) 353 } 354 355 //未被杀死的对等机发送删除请求 356 err = s.TestExchanges(p2ptest.Exchange{ 357 Triggers: []p2ptest.Trigger{ 358 { 359 Code: 3, 360 Msg: &drop{}, 361 Peer: s.IDs[(peer+1)%2], 362 }, 363 }, 364 }) 365 366 if err != nil { 367 t.Fatal(err) 368 } 369 370 //检查各个对等机上的实际DiscConnect错误 371 var disconnects []*p2ptest.Disconnect 372 for i, err := range errs { 373 disconnects = append(disconnects, &p2ptest.Disconnect{Peer: s.IDs[i], Error: err}) 374 } 375 if err := s.TestDisconnected(disconnects...); err != nil { 376 t.Fatal(err) 377 } 378 //测试是否已从对等池中删除断开连接的对等机 379 if pp.Has(s.IDs[peer]) { 380 t.Fatalf("peer test-%v not dropped: %v (%v)", peer, pp, s.IDs) 381 } 382 383 } 384 func XTestMultiplePeersDropSelf(t *testing.T) { 385 runMultiplePeers(t, 0, 386 fmt.Errorf("subprotocol error"), 387 fmt.Errorf("Message handler error: (msg code 3): dropped"), 388 ) 389 } 390 391 func XTestMultiplePeersDropOther(t *testing.T) { 392 runMultiplePeers(t, 1, 393 fmt.Errorf("Message handler error: (msg code 3): dropped"), 394 fmt.Errorf("subprotocol error"), 395 ) 396 }