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