github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/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 19:16:43</date>
    10  //</624450113946783744>
    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/enode"
    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][]enode.ID
    38  	kademlias        map[enode.ID]*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][]enode.ID)
    71  //设置网络并连接节点
    72  	net, err := setupNetwork(numNodes)
    73  	if err != nil {
    74  		t.Fatalf("Error setting up network: %v", err)
    75  	}
    76  //让我们休眠以确保所有节点都已连接
    77  	time.Sleep(1 * time.Second)
    78  //关闭网络以避免竞争条件
    79  //网络节点访问Kademlias全局地图的研究
    80  //正在接受消息
    81  	net.Shutdown()
    82  //对于共享相同网络ID的每个组…
    83  	for _, netIDGroup := range nodeMap {
    84  		log.Trace("netIDGroup size", "size", len(netIDGroup))
    85  //…检查他们的花冠尺寸是否符合预期尺寸
    86  //假设它应该是组的大小减去1(节点本身)。
    87  		for _, node := range netIDGroup {
    88  			if kademlias[node].addrs.Size() != len(netIDGroup)-1 {
    89  				t.Fatalf("Kademlia size has not expected peer size. Kademlia size: %d, expected size: %d", kademlias[node].addrs.Size(), len(netIDGroup)-1)
    90  			}
    91  			kademlias[node].EachAddr(nil, 0, func(addr *BzzAddr, _ int) bool {
    92  				found := false
    93  				for _, nd := range netIDGroup {
    94  					if bytes.Equal(kademlias[nd].BaseAddr(), addr.Address()) {
    95  						found = true
    96  					}
    97  				}
    98  				if !found {
    99  					t.Fatalf("Expected node not found for node %s", node.String())
   100  				}
   101  				return true
   102  			})
   103  		}
   104  	}
   105  	log.Info("Test terminated successfully")
   106  }
   107  
   108  //使用bzz/discovery和pss服务设置模拟网络。
   109  //连接圆中的节点
   110  //如果设置了allowraw,则启用了省略内置PSS加密(请参阅PSSPARAMS)
   111  func setupNetwork(numnodes int) (net *simulations.Network, err error) {
   112  	log.Debug("Setting up network")
   113  	quitC := make(chan struct{})
   114  	errc := make(chan error)
   115  	nodes := make([]*simulations.Node, numnodes)
   116  	if numnodes < 16 {
   117  		return nil, fmt.Errorf("Minimum sixteen nodes in network")
   118  	}
   119  	adapter := adapters.NewSimAdapter(newServices())
   120  //创建网络
   121  	net = simulations.NewNetwork(adapter, &simulations.NetworkConfig{
   122  		ID:             "NetworkIdTestNet",
   123  		DefaultService: "bzz",
   124  	})
   125  	log.Debug("Creating networks and nodes")
   126  
   127  	var connCount int
   128  
   129  //创建节点并相互连接
   130  	for i := 0; i < numnodes; i++ {
   131  		log.Trace("iteration: ", "i", i)
   132  		nodeconf := adapters.RandomNodeConfig()
   133  		nodes[i], err = net.NewNodeWithConfig(nodeconf)
   134  		if err != nil {
   135  			return nil, fmt.Errorf("error creating node %d: %v", i, err)
   136  		}
   137  		err = net.Start(nodes[i].ID())
   138  		if err != nil {
   139  			return nil, fmt.Errorf("error starting node %d: %v", i, err)
   140  		}
   141  		client, err := nodes[i].Client()
   142  		if err != nil {
   143  			return nil, fmt.Errorf("create node %d rpc client fail: %v", i, err)
   144  		}
   145  //现在设置并开始事件监视,以了解何时可以上载
   146  		ctx, watchCancel := context.WithTimeout(context.Background(), MaxTimeout*time.Second)
   147  		defer watchCancel()
   148  		watchSubscriptionEvents(ctx, nodes[i].ID(), client, errc, quitC)
   149  //在每次迭代中,我们都连接到以前的所有迭代
   150  		for k := i - 1; k >= 0; k-- {
   151  			connCount++
   152  			log.Debug(fmt.Sprintf("Connecting node %d with node %d; connection count is %d", i, k, connCount))
   153  			err = net.Connect(nodes[i].ID(), nodes[k].ID())
   154  			if err != nil {
   155  				if !strings.Contains(err.Error(), "already connected") {
   156  					return nil, fmt.Errorf("error connecting nodes: %v", err)
   157  				}
   158  			}
   159  		}
   160  	}
   161  //现在等待,直到完成预期订阅的数量
   162  //`watchsubscriptionEvents`将用'nil'值写入errc
   163  	for err := range errc {
   164  		if err != nil {
   165  			return nil, err
   166  		}
   167  //收到“nil”,递减计数
   168  		connCount--
   169  		log.Trace("count down", "cnt", connCount)
   170  //收到的所有订阅
   171  		if connCount == 0 {
   172  			close(quitC)
   173  			break
   174  		}
   175  	}
   176  	log.Debug("Network setup phase terminated")
   177  	return net, nil
   178  }
   179  
   180  func newServices() adapters.Services {
   181  	kademlias = make(map[enode.ID]*Kademlia)
   182  	kademlia := func(id enode.ID) *Kademlia {
   183  		if k, ok := kademlias[id]; ok {
   184  			return k
   185  		}
   186  		params := NewKadParams()
   187  		params.NeighbourhoodSize = 2
   188  		params.MaxBinSize = 3
   189  		params.MinBinSize = 1
   190  		params.MaxRetries = 1000
   191  		params.RetryExponent = 2
   192  		params.RetryInterval = 1000000
   193  		kademlias[id] = NewKademlia(id[:], params)
   194  		return kademlias[id]
   195  	}
   196  	return adapters.Services{
   197  		"bzz": func(ctx *adapters.ServiceContext) (node.Service, error) {
   198  			addr := NewAddr(ctx.Config.Node())
   199  			hp := NewHiveParams()
   200  			hp.Discovery = false
   201  			cnt++
   202  //分配网络ID
   203  			currentNetworkID = cnt % NumberOfNets
   204  			if ok := nodeMap[currentNetworkID]; ok == nil {
   205  				nodeMap[currentNetworkID] = make([]enode.ID, 0)
   206  			}
   207  //将此节点添加到共享相同网络ID的组中
   208  			nodeMap[currentNetworkID] = append(nodeMap[currentNetworkID], ctx.Config.ID)
   209  			log.Debug("current network ID:", "id", currentNetworkID)
   210  			config := &BzzConfig{
   211  				OverlayAddr:  addr.Over(),
   212  				UnderlayAddr: addr.Under(),
   213  				HiveParams:   hp,
   214  				NetworkID:    uint64(currentNetworkID),
   215  			}
   216  			return NewBzz(config, kademlia(ctx.Config.ID), nil, nil, nil), nil
   217  		},
   218  	}
   219  }
   220  
   221  func watchSubscriptionEvents(ctx context.Context, id enode.ID, client *rpc.Client, errc chan error, quitC chan struct{}) {
   222  	events := make(chan *p2p.PeerEvent)
   223  	sub, err := client.Subscribe(context.Background(), "admin", events, "peerEvents")
   224  	if err != nil {
   225  		log.Error(err.Error())
   226  		errc <- fmt.Errorf("error getting peer events for node %v: %s", id, err)
   227  		return
   228  	}
   229  	go func() {
   230  		defer func() {
   231  			sub.Unsubscribe()
   232  			log.Trace("watch subscription events: unsubscribe", "id", id)
   233  		}()
   234  
   235  		for {
   236  			select {
   237  			case <-quitC:
   238  				return
   239  			case <-ctx.Done():
   240  				select {
   241  				case errc <- ctx.Err():
   242  				case <-quitC:
   243  				}
   244  				return
   245  			case e := <-events:
   246  				if e.Type == p2p.PeerEventTypeAdd {
   247  					errc <- nil
   248  				}
   249  			case err := <-sub.Err():
   250  				if err != nil {
   251  					select {
   252  					case errc <- fmt.Errorf("error getting peer events for node %v: %v", id, err):
   253  					case <-quitC:
   254  					}
   255  					return
   256  				}
   257  			}
   258  		}
   259  	}()
   260  }
   261