github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/swarm/network/networkid_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  //版权所有2018 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 network
    26  
    27  import (
    28  	"bytes"
    29  	"context"
    30  	"flag"
    31  	"fmt"
    32  	"math/rand"
    33  	"strings"
    34  	"testing"
    35  	"time"
    36  
    37  	"github.com/ethereum/go-ethereum/log"
    38  	"github.com/ethereum/go-ethereum/node"
    39  	"github.com/ethereum/go-ethereum/p2p"
    40  	"github.com/ethereum/go-ethereum/p2p/discover"
    41  	"github.com/ethereum/go-ethereum/p2p/simulations"
    42  	"github.com/ethereum/go-ethereum/p2p/simulations/adapters"
    43  	"github.com/ethereum/go-ethereum/rpc"
    44  )
    45  
    46  var (
    47  	currentNetworkID int
    48  	cnt              int
    49  	nodeMap          map[int][]discover.NodeID
    50  	kademlias        map[discover.NodeID]*Kademlia
    51  )
    52  
    53  const (
    54  	NumberOfNets = 4
    55  	MaxTimeout   = 6
    56  )
    57  
    58  func init() {
    59  	flag.Parse()
    60  	rand.Seed(time.Now().Unix())
    61  }
    62  
    63  /*
    64  运行网络ID测试。
    65  测试创建一个模拟。网络实例,
    66  多个节点,然后在此网络中彼此连接节点。
    67  
    68  每个节点都得到一个根据网络数量分配的网络ID。
    69  拥有更多的网络ID只是为了排除
    70  误报。
    71  
    72  节点只能与具有相同网络ID的其他节点连接。
    73  在设置阶段之后,测试将检查每个节点是否具有
    74  预期的节点连接(不包括那些不共享网络ID的连接)。
    75  **/
    76  
    77  func TestNetworkID(t *testing.T) {
    78  	log.Debug("Start test")
    79  //任意设置节点数。可以是任何号码
    80  	numNodes := 24
    81  //nodemap用相同的网络ID(key)映射所有节点(切片值)
    82  	nodeMap = make(map[int][]discover.NodeID)
    83  //设置网络并连接节点
    84  	net, err := setupNetwork(numNodes)
    85  	if err != nil {
    86  		t.Fatalf("Error setting up network: %v", err)
    87  	}
    88  	defer func() {
    89  //关闭快照网络
    90  		log.Trace("Shutting down network")
    91  		net.Shutdown()
    92  	}()
    93  //让我们休眠以确保所有节点都已连接
    94  	time.Sleep(1 * time.Second)
    95  //对于共享相同网络ID的每个组…
    96  	for _, netIDGroup := range nodeMap {
    97  		log.Trace("netIDGroup size", "size", len(netIDGroup))
    98  //…检查他们的花冠尺寸是否符合预期尺寸
    99  //假设它应该是组的大小减去1(节点本身)。
   100  		for _, node := range netIDGroup {
   101  			if kademlias[node].addrs.Size() != len(netIDGroup)-1 {
   102  				t.Fatalf("Kademlia size has not expected peer size. Kademlia size: %d, expected size: %d", kademlias[node].addrs.Size(), len(netIDGroup)-1)
   103  			}
   104  			kademlias[node].EachAddr(nil, 0, func(addr OverlayAddr, _ int, _ bool) bool {
   105  				found := false
   106  				for _, nd := range netIDGroup {
   107  					p := ToOverlayAddr(nd.Bytes())
   108  					if bytes.Equal(p, addr.Address()) {
   109  						found = true
   110  					}
   111  				}
   112  				if !found {
   113  					t.Fatalf("Expected node not found for node %s", node.String())
   114  				}
   115  				return true
   116  			})
   117  		}
   118  	}
   119  	log.Info("Test terminated successfully")
   120  }
   121  
   122  //使用bzz/discovery和pss服务设置模拟网络。
   123  //连接圆中的节点
   124  //如果设置了allowraw,则启用了省略内置PSS加密(请参阅PSSPARAMS)
   125  func setupNetwork(numnodes int) (net *simulations.Network, err error) {
   126  	log.Debug("Setting up network")
   127  	quitC := make(chan struct{})
   128  	errc := make(chan error)
   129  	nodes := make([]*simulations.Node, numnodes)
   130  	if numnodes < 16 {
   131  		return nil, fmt.Errorf("Minimum sixteen nodes in network")
   132  	}
   133  	adapter := adapters.NewSimAdapter(newServices())
   134  //创建网络
   135  	net = simulations.NewNetwork(adapter, &simulations.NetworkConfig{
   136  		ID:             "NetworkIdTestNet",
   137  		DefaultService: "bzz",
   138  	})
   139  	log.Debug("Creating networks and nodes")
   140  
   141  	var connCount int
   142  
   143  //创建节点并相互连接
   144  	for i := 0; i < numnodes; i++ {
   145  		log.Trace("iteration: ", "i", i)
   146  		nodeconf := adapters.RandomNodeConfig()
   147  		nodes[i], err = net.NewNodeWithConfig(nodeconf)
   148  		if err != nil {
   149  			return nil, fmt.Errorf("error creating node %d: %v", i, err)
   150  		}
   151  		err = net.Start(nodes[i].ID())
   152  		if err != nil {
   153  			return nil, fmt.Errorf("error starting node %d: %v", i, err)
   154  		}
   155  		client, err := nodes[i].Client()
   156  		if err != nil {
   157  			return nil, fmt.Errorf("create node %d rpc client fail: %v", i, err)
   158  		}
   159  //现在设置并开始事件监视,以了解何时可以上载
   160  		ctx, watchCancel := context.WithTimeout(context.Background(), MaxTimeout*time.Second)
   161  		defer watchCancel()
   162  		watchSubscriptionEvents(ctx, nodes[i].ID(), client, errc, quitC)
   163  //在每次迭代中,我们都连接到以前的所有迭代
   164  		for k := i - 1; k >= 0; k-- {
   165  			connCount++
   166  			log.Debug(fmt.Sprintf("Connecting node %d with node %d; connection count is %d", i, k, connCount))
   167  			err = net.Connect(nodes[i].ID(), nodes[k].ID())
   168  			if err != nil {
   169  				if !strings.Contains(err.Error(), "already connected") {
   170  					return nil, fmt.Errorf("error connecting nodes: %v", err)
   171  				}
   172  			}
   173  		}
   174  	}
   175  //现在等待,直到完成预期订阅的数量
   176  //`watchsubscriptionEvents`将用'nil'值写入errc
   177  	for err := range errc {
   178  		if err != nil {
   179  			return nil, err
   180  		}
   181  //收到“nil”,递减计数
   182  		connCount--
   183  		log.Trace("count down", "cnt", connCount)
   184  //收到的所有订阅
   185  		if connCount == 0 {
   186  			close(quitC)
   187  			break
   188  		}
   189  	}
   190  	log.Debug("Network setup phase terminated")
   191  	return net, nil
   192  }
   193  
   194  func newServices() adapters.Services {
   195  	kademlias = make(map[discover.NodeID]*Kademlia)
   196  	kademlia := func(id discover.NodeID) *Kademlia {
   197  		if k, ok := kademlias[id]; ok {
   198  			return k
   199  		}
   200  		addr := NewAddrFromNodeID(id)
   201  		params := NewKadParams()
   202  		params.MinProxBinSize = 2
   203  		params.MaxBinSize = 3
   204  		params.MinBinSize = 1
   205  		params.MaxRetries = 1000
   206  		params.RetryExponent = 2
   207  		params.RetryInterval = 1000000
   208  		kademlias[id] = NewKademlia(addr.Over(), params)
   209  		return kademlias[id]
   210  	}
   211  	return adapters.Services{
   212  		"bzz": func(ctx *adapters.ServiceContext) (node.Service, error) {
   213  			addr := NewAddrFromNodeID(ctx.Config.ID)
   214  			hp := NewHiveParams()
   215  			hp.Discovery = false
   216  			cnt++
   217  //分配网络ID
   218  			currentNetworkID = cnt % NumberOfNets
   219  			if ok := nodeMap[currentNetworkID]; ok == nil {
   220  				nodeMap[currentNetworkID] = make([]discover.NodeID, 0)
   221  			}
   222  //将此节点添加到共享相同网络ID的组中
   223  			nodeMap[currentNetworkID] = append(nodeMap[currentNetworkID], ctx.Config.ID)
   224  			log.Debug("current network ID:", "id", currentNetworkID)
   225  			config := &BzzConfig{
   226  				OverlayAddr:  addr.Over(),
   227  				UnderlayAddr: addr.Under(),
   228  				HiveParams:   hp,
   229  				NetworkID:    uint64(currentNetworkID),
   230  			}
   231  			return NewBzz(config, kademlia(ctx.Config.ID), nil, nil, nil), nil
   232  		},
   233  	}
   234  }
   235  
   236  func watchSubscriptionEvents(ctx context.Context, id discover.NodeID, client *rpc.Client, errc chan error, quitC chan struct{}) {
   237  	events := make(chan *p2p.PeerEvent)
   238  	sub, err := client.Subscribe(context.Background(), "admin", events, "peerEvents")
   239  	if err != nil {
   240  		log.Error(err.Error())
   241  		errc <- fmt.Errorf("error getting peer events for node %v: %s", id, err)
   242  		return
   243  	}
   244  	go func() {
   245  		defer func() {
   246  			sub.Unsubscribe()
   247  			log.Trace("watch subscription events: unsubscribe", "id", id)
   248  		}()
   249  
   250  		for {
   251  			select {
   252  			case <-quitC:
   253  				return
   254  			case <-ctx.Done():
   255  				select {
   256  				case errc <- ctx.Err():
   257  				case <-quitC:
   258  				}
   259  				return
   260  			case e := <-events:
   261  				if e.Type == p2p.PeerEventTypeAdd {
   262  					errc <- nil
   263  				}
   264  			case err := <-sub.Err():
   265  				if err != nil {
   266  					select {
   267  					case errc <- fmt.Errorf("error getting peer events for node %v: %v", id, err):
   268  					case <-quitC:
   269  					}
   270  					return
   271  				}
   272  			}
   273  		}
   274  	}()
   275  }