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  }