github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/p2p/discv5/sim_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  //版权所有2016 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 discv5
    26  
    27  import (
    28  	"crypto/ecdsa"
    29  	"encoding/binary"
    30  	"fmt"
    31  	"math/rand"
    32  	"net"
    33  	"strconv"
    34  	"sync"
    35  	"sync/atomic"
    36  	"testing"
    37  	"time"
    38  
    39  	"github.com/ethereum/go-ethereum/common"
    40  )
    41  
    42  //在这个测试中,节点试图随机地解析彼此。
    43  func TestSimRandomResolve(t *testing.T) {
    44  	t.Skip("boring")
    45  	if runWithPlaygroundTime(t) {
    46  		return
    47  	}
    48  
    49  	sim := newSimulation()
    50  	bootnode := sim.launchNode(false)
    51  
    52  //新节点每10秒联接一次。
    53  	launcher := time.NewTicker(10 * time.Second)
    54  	go func() {
    55  		for range launcher.C {
    56  			net := sim.launchNode(false)
    57  			go randomResolves(t, sim, net)
    58  			if err := net.SetFallbackNodes([]*Node{bootnode.Self()}); err != nil {
    59  				panic(err)
    60  			}
    61  			fmt.Printf("launched @ %v: %x\n", time.Now(), net.Self().ID[:16])
    62  		}
    63  	}()
    64  
    65  	time.Sleep(3 * time.Hour)
    66  	launcher.Stop()
    67  	sim.shutdown()
    68  	sim.printStats()
    69  }
    70  
    71  func TestSimTopics(t *testing.T) {
    72  	t.Skip("NaCl test")
    73  	if runWithPlaygroundTime(t) {
    74  		return
    75  	}
    76  	sim := newSimulation()
    77  	bootnode := sim.launchNode(false)
    78  
    79  	go func() {
    80  		nets := make([]*Network, 1024)
    81  		for i := range nets {
    82  			net := sim.launchNode(false)
    83  			nets[i] = net
    84  			if err := net.SetFallbackNodes([]*Node{bootnode.Self()}); err != nil {
    85  				panic(err)
    86  			}
    87  			time.Sleep(time.Second * 5)
    88  		}
    89  
    90  		for i, net := range nets {
    91  			if i < 256 {
    92  				stop := make(chan struct{})
    93  				go net.RegisterTopic(testTopic, stop)
    94  				go func() {
    95  //时间.睡眠(time.second*36000)
    96  					time.Sleep(time.Second * 40000)
    97  					close(stop)
    98  				}()
    99  				time.Sleep(time.Millisecond * 100)
   100  			}
   101  //时间.睡眠(time.second*10)
   102  //时间.睡眠(时间.秒)
   103     /*F I%500==499
   104      时间.睡眠(time.second*9501)
   105     }否则{
   106      时间.睡眠(时间.秒)
   107     */
   108  
   109  		}
   110  	}()
   111  
   112  //新节点每10秒联接一次。
   113   /*启动程序:=time.newticker(5*time.second)
   114    CNT:=0
   115    var printnet*网络
   116    转到函数()
   117     用于远程发射器.c
   118      碳纳米管+
   119      如果cnt<=1000
   120       日志:=false/(cnt==500)
   121       网络:=sim.launchnode(日志)
   122       如果log {
   123        打印网
   124       }
   125       如果CNT>500 {
   126        go net.registerTopic(测试主题,无)
   127       }
   128       如果错误:=net.setFallbackNodes([]*node bootnode.self());错误!= nIL{
   129        惊慌(错误)
   130       }
   131      }
   132      //fmt.printf(“已启动@%v:%x\n”,time.now(),net.self().id[:16])
   133     }
   134    }()
   135   **/
   136  
   137  	time.Sleep(55000 * time.Second)
   138  //发射器
   139  	sim.shutdown()
   140  //sim.printstats()。
   141  //printnet.log.printlogs()。
   142  }
   143  
   144  /*unc testHierarchicalTopics(i int)[]主题
   145   数字:=strconv.formatint(Int64(256+I/4),4)
   146   回复:=制造([]主题,5)
   147   对于i,:=范围分辨率
   148    res[i]=主题(“foo”+数字[1:i+1])
   149   }
   150   收益率
   151  */
   152  
   153  
   154  func testHierarchicalTopics(i int) []Topic {
   155  	digits := strconv.FormatInt(int64(128+i/8), 2)
   156  	res := make([]Topic, 8)
   157  	for i := range res {
   158  		res[i] = Topic("foo" + digits[1:i+1])
   159  	}
   160  	return res
   161  }
   162  
   163  func TestSimTopicHierarchy(t *testing.T) {
   164  	t.Skip("NaCl test")
   165  	if runWithPlaygroundTime(t) {
   166  		return
   167  	}
   168  	sim := newSimulation()
   169  	bootnode := sim.launchNode(false)
   170  
   171  	go func() {
   172  		nets := make([]*Network, 1024)
   173  		for i := range nets {
   174  			net := sim.launchNode(false)
   175  			nets[i] = net
   176  			if err := net.SetFallbackNodes([]*Node{bootnode.Self()}); err != nil {
   177  				panic(err)
   178  			}
   179  			time.Sleep(time.Second * 5)
   180  		}
   181  
   182  		stop := make(chan struct{})
   183  		for i, net := range nets {
   184  //如果i<256 {
   185  			for _, topic := range testHierarchicalTopics(i)[:5] {
   186  //fmt.println(“注册”,主题)
   187  				go net.RegisterTopic(topic, stop)
   188  			}
   189  			time.Sleep(time.Millisecond * 100)
   190  //}
   191  		}
   192  		time.Sleep(time.Second * 90000)
   193  		close(stop)
   194  	}()
   195  
   196  	time.Sleep(100000 * time.Second)
   197  	sim.shutdown()
   198  }
   199  
   200  func randomResolves(t *testing.T, s *simulation, net *Network) {
   201  	randtime := func() time.Duration {
   202  		return time.Duration(rand.Intn(50)+20) * time.Second
   203  	}
   204  	lookup := func(target NodeID) bool {
   205  		result := net.Resolve(target)
   206  		return result != nil && result.ID == target
   207  	}
   208  
   209  	timer := time.NewTimer(randtime())
   210  	for {
   211  		select {
   212  		case <-timer.C:
   213  			target := s.randomNode().Self().ID
   214  			if !lookup(target) {
   215  				t.Errorf("node %x: target %x not found", net.Self().ID[:8], target[:8])
   216  			}
   217  			timer.Reset(randtime())
   218  		case <-net.closed:
   219  			return
   220  		}
   221  	}
   222  }
   223  
   224  type simulation struct {
   225  	mu      sync.RWMutex
   226  	nodes   map[NodeID]*Network
   227  	nodectr uint32
   228  }
   229  
   230  func newSimulation() *simulation {
   231  	return &simulation{nodes: make(map[NodeID]*Network)}
   232  }
   233  
   234  func (s *simulation) shutdown() {
   235  	s.mu.RLock()
   236  	alive := make([]*Network, 0, len(s.nodes))
   237  	for _, n := range s.nodes {
   238  		alive = append(alive, n)
   239  	}
   240  	defer s.mu.RUnlock()
   241  
   242  	for _, n := range alive {
   243  		n.Close()
   244  	}
   245  }
   246  
   247  func (s *simulation) printStats() {
   248  	s.mu.Lock()
   249  	defer s.mu.Unlock()
   250  	fmt.Println("node counter:", s.nodectr)
   251  	fmt.Println("alive nodes:", len(s.nodes))
   252  
   253  //对于u,n:=范围s.nodes
   254  //fmt.printf(“%x\n”,n.tab.self.id[:8])
   255  //传输:=N.conn.(*SimTransport)
   256  //fmt.println(“已加入:”,transport.jointime)
   257  //fmt.println(“发送:”,transport.hashctr)
   258  //fmt.println(“表格大小:”,n.tab.count)
   259  //}
   260  
   261   /*或u,n:=范围s.nodes
   262    打印文件()
   263    fmt.printf(“***节点%x\n”,n.tab.self.id[:8])
   264    n.log.printlogs()。
   265   */
   266  
   267  
   268  }
   269  
   270  func (s *simulation) randomNode() *Network {
   271  	s.mu.Lock()
   272  	defer s.mu.Unlock()
   273  
   274  	n := rand.Intn(len(s.nodes))
   275  	for _, net := range s.nodes {
   276  		if n == 0 {
   277  			return net
   278  		}
   279  		n--
   280  	}
   281  	return nil
   282  }
   283  
   284  func (s *simulation) launchNode(log bool) *Network {
   285  	var (
   286  		num = s.nodectr
   287  		key = newkey()
   288  		id  = PubkeyID(&key.PublicKey)
   289  		ip  = make(net.IP, 4)
   290  	)
   291  	s.nodectr++
   292  	binary.BigEndian.PutUint32(ip, num)
   293  	ip[0] = 10
   294  	addr := &net.UDPAddr{IP: ip, Port: 30303}
   295  
   296  	transport := &simTransport{joinTime: time.Now(), sender: id, senderAddr: addr, sim: s, priv: key}
   297  	net, err := newNetwork(transport, key.PublicKey, "<no database>", nil)
   298  	if err != nil {
   299  		panic("cannot launch new node: " + err.Error())
   300  	}
   301  
   302  	s.mu.Lock()
   303  	s.nodes[id] = net
   304  	s.mu.Unlock()
   305  
   306  	return net
   307  }
   308  
   309  func (s *simulation) dropNode(id NodeID) {
   310  	s.mu.Lock()
   311  	n := s.nodes[id]
   312  	delete(s.nodes, id)
   313  	s.mu.Unlock()
   314  
   315  	n.Close()
   316  }
   317  
   318  type simTransport struct {
   319  	joinTime   time.Time
   320  	sender     NodeID
   321  	senderAddr *net.UDPAddr
   322  	sim        *simulation
   323  	hashctr    uint64
   324  	priv       *ecdsa.PrivateKey
   325  }
   326  
   327  func (st *simTransport) localAddr() *net.UDPAddr {
   328  	return st.senderAddr
   329  }
   330  
   331  func (st *simTransport) Close() {}
   332  
   333  func (st *simTransport) send(remote *Node, ptype nodeEvent, data interface{}) (hash []byte) {
   334  	hash = st.nextHash()
   335  	var raw []byte
   336  	if ptype == pongPacket {
   337  		var err error
   338  		raw, _, err = encodePacket(st.priv, byte(ptype), data)
   339  		if err != nil {
   340  			panic(err)
   341  		}
   342  	}
   343  
   344  	st.sendPacket(remote.ID, ingressPacket{
   345  		remoteID:   st.sender,
   346  		remoteAddr: st.senderAddr,
   347  		hash:       hash,
   348  		ev:         ptype,
   349  		data:       data,
   350  		rawData:    raw,
   351  	})
   352  	return hash
   353  }
   354  
   355  func (st *simTransport) sendPing(remote *Node, remoteAddr *net.UDPAddr, topics []Topic) []byte {
   356  	hash := st.nextHash()
   357  	st.sendPacket(remote.ID, ingressPacket{
   358  		remoteID:   st.sender,
   359  		remoteAddr: st.senderAddr,
   360  		hash:       hash,
   361  		ev:         pingPacket,
   362  		data: &ping{
   363  			Version:    4,
   364  			From:       rpcEndpoint{IP: st.senderAddr.IP, UDP: uint16(st.senderAddr.Port), TCP: 30303},
   365  			To:         rpcEndpoint{IP: remoteAddr.IP, UDP: uint16(remoteAddr.Port), TCP: 30303},
   366  			Expiration: uint64(time.Now().Unix() + int64(expiration)),
   367  			Topics:     topics,
   368  		},
   369  	})
   370  	return hash
   371  }
   372  
   373  func (st *simTransport) sendPong(remote *Node, pingHash []byte) {
   374  	raddr := remote.addr()
   375  
   376  	st.sendPacket(remote.ID, ingressPacket{
   377  		remoteID:   st.sender,
   378  		remoteAddr: st.senderAddr,
   379  		hash:       st.nextHash(),
   380  		ev:         pongPacket,
   381  		data: &pong{
   382  			To:         rpcEndpoint{IP: raddr.IP, UDP: uint16(raddr.Port), TCP: 30303},
   383  			ReplyTok:   pingHash,
   384  			Expiration: uint64(time.Now().Unix() + int64(expiration)),
   385  		},
   386  	})
   387  }
   388  
   389  func (st *simTransport) sendFindnodeHash(remote *Node, target common.Hash) {
   390  	st.sendPacket(remote.ID, ingressPacket{
   391  		remoteID:   st.sender,
   392  		remoteAddr: st.senderAddr,
   393  		hash:       st.nextHash(),
   394  		ev:         findnodeHashPacket,
   395  		data: &findnodeHash{
   396  			Target:     target,
   397  			Expiration: uint64(time.Now().Unix() + int64(expiration)),
   398  		},
   399  	})
   400  }
   401  
   402  func (st *simTransport) sendTopicRegister(remote *Node, topics []Topic, idx int, pong []byte) {
   403  //fmt.println(“发送”,主题,pong)
   404  	st.sendPacket(remote.ID, ingressPacket{
   405  		remoteID:   st.sender,
   406  		remoteAddr: st.senderAddr,
   407  		hash:       st.nextHash(),
   408  		ev:         topicRegisterPacket,
   409  		data: &topicRegister{
   410  			Topics: topics,
   411  			Idx:    uint(idx),
   412  			Pong:   pong,
   413  		},
   414  	})
   415  }
   416  
   417  func (st *simTransport) sendTopicNodes(remote *Node, queryHash common.Hash, nodes []*Node) {
   418  	rnodes := make([]rpcNode, len(nodes))
   419  	for i := range nodes {
   420  		rnodes[i] = nodeToRPC(nodes[i])
   421  	}
   422  	st.sendPacket(remote.ID, ingressPacket{
   423  		remoteID:   st.sender,
   424  		remoteAddr: st.senderAddr,
   425  		hash:       st.nextHash(),
   426  		ev:         topicNodesPacket,
   427  		data:       &topicNodes{Echo: queryHash, Nodes: rnodes},
   428  	})
   429  }
   430  
   431  func (st *simTransport) sendNeighbours(remote *Node, nodes []*Node) {
   432  //TODO:发送多个数据包
   433  	rnodes := make([]rpcNode, len(nodes))
   434  	for i := range nodes {
   435  		rnodes[i] = nodeToRPC(nodes[i])
   436  	}
   437  	st.sendPacket(remote.ID, ingressPacket{
   438  		remoteID:   st.sender,
   439  		remoteAddr: st.senderAddr,
   440  		hash:       st.nextHash(),
   441  		ev:         neighborsPacket,
   442  		data: &neighbors{
   443  			Nodes:      rnodes,
   444  			Expiration: uint64(time.Now().Unix() + int64(expiration)),
   445  		},
   446  	})
   447  }
   448  
   449  func (st *simTransport) nextHash() []byte {
   450  	v := atomic.AddUint64(&st.hashctr, 1)
   451  	var hash common.Hash
   452  	binary.BigEndian.PutUint64(hash[:], v)
   453  	return hash[:]
   454  }
   455  
   456  const packetLoss = 0 //1/1000
   457  
   458  func (st *simTransport) sendPacket(remote NodeID, p ingressPacket) {
   459  	if rand.Int31n(1000) >= packetLoss {
   460  		st.sim.mu.RLock()
   461  		recipient := st.sim.nodes[remote]
   462  		st.sim.mu.RUnlock()
   463  
   464  		time.AfterFunc(200*time.Millisecond, func() {
   465  			recipient.reqReadPacket(p)
   466  		})
   467  	}
   468  }