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