github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/swarm/pss/forwarding_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:44</date>
    10  //</624450116555640832>
    11  
    12  package pss
    13  
    14  import (
    15  	"fmt"
    16  	"math/rand"
    17  	"testing"
    18  	"time"
    19  
    20  	"github.com/ethereum/go-ethereum/crypto"
    21  	"github.com/ethereum/go-ethereum/p2p"
    22  	"github.com/ethereum/go-ethereum/p2p/enode"
    23  	"github.com/ethereum/go-ethereum/p2p/protocols"
    24  	"github.com/ethereum/go-ethereum/swarm/network"
    25  	"github.com/ethereum/go-ethereum/swarm/pot"
    26  	whisper "github.com/ethereum/go-ethereum/whisper/whisperv5"
    27  )
    28  
    29  type testCase struct {
    30  	name      string
    31  	recipient []byte
    32  	peers     []pot.Address
    33  	expected  []int
    34  	exclusive bool
    35  	nFails    int
    36  	success   bool
    37  	errors    string
    38  }
    39  
    40  var testCases []testCase
    41  
    42  //此测试的目的是查看pss.forward()函数是否正确。
    43  //根据邮件地址选择邮件转发的对等方
    44  //和卡德米利亚星座。
    45  func TestForwardBasic(t *testing.T) {
    46  	baseAddrBytes := make([]byte, 32)
    47  	for i := 0; i < len(baseAddrBytes); i++ {
    48  		baseAddrBytes[i] = 0xFF
    49  	}
    50  	var c testCase
    51  	base := pot.NewAddressFromBytes(baseAddrBytes)
    52  	var peerAddresses []pot.Address
    53  	const depth = 10
    54  	for i := 0; i <= depth; i++ {
    55  //为每个接近顺序添加两个对等点
    56  		a := pot.RandomAddressAt(base, i)
    57  		peerAddresses = append(peerAddresses, a)
    58  		a = pot.RandomAddressAt(base, i)
    59  		peerAddresses = append(peerAddresses, a)
    60  	}
    61  
    62  //跳过一个级别,在更深的一个级别添加一个对等。
    63  //因此,我们将在最近的邻居的垃圾箱中发现一个三个同行的边缘案例。
    64  	peerAddresses = append(peerAddresses, pot.RandomAddressAt(base, depth+2))
    65  
    66  	kad := network.NewKademlia(base[:], network.NewKadParams())
    67  	ps := createPss(t, kad)
    68  	addPeers(kad, peerAddresses)
    69  
    70  const firstNearest = depth * 2 //在最近邻居的垃圾桶里最浅的人
    71  	nearestNeighbours := []int{firstNearest, firstNearest + 1, firstNearest + 2}
    72  var all []int //所有同行的指数
    73  	for i := 0; i < len(peerAddresses); i++ {
    74  		all = append(all, i)
    75  	}
    76  
    77  	for i := 0; i < len(peerAddresses); i++ {
    78  //直接将消息发送到已知的对等方(收件人地址==对等方地址)
    79  		c = testCase{
    80  			name:      fmt.Sprintf("Send direct to known, id: [%d]", i),
    81  			recipient: peerAddresses[i][:],
    82  			peers:     peerAddresses,
    83  			expected:  []int{i},
    84  			exclusive: false,
    85  		}
    86  		testCases = append(testCases, c)
    87  	}
    88  
    89  	for i := 0; i < firstNearest; i++ {
    90  //随机发送带有邻近订单的消息,与每个垃圾箱的采购订单相对应,
    91  //一个对等机更接近收件人地址
    92  		a := pot.RandomAddressAt(peerAddresses[i], 64)
    93  		c = testCase{
    94  			name:      fmt.Sprintf("Send random to each PO, id: [%d]", i),
    95  			recipient: a[:],
    96  			peers:     peerAddresses,
    97  			expected:  []int{i},
    98  			exclusive: false,
    99  		}
   100  		testCases = append(testCases, c)
   101  	}
   102  
   103  	for i := 0; i < firstNearest; i++ {
   104  //随机发送带有邻近订单的消息,与每个垃圾箱的采购订单相对应,
   105  //相对于收件人地址随机接近
   106  		po := i / 2
   107  		a := pot.RandomAddressAt(base, po)
   108  		c = testCase{
   109  			name:      fmt.Sprintf("Send direct to known, id: [%d]", i),
   110  			recipient: a[:],
   111  			peers:     peerAddresses,
   112  			expected:  []int{po * 2, po*2 + 1},
   113  			exclusive: true,
   114  		}
   115  		testCases = append(testCases, c)
   116  	}
   117  
   118  	for i := firstNearest; i < len(peerAddresses); i++ {
   119  //收信人地址落在最近邻居的箱子里
   120  		a := pot.RandomAddressAt(base, i)
   121  		c = testCase{
   122  			name:      fmt.Sprintf("recipient address falls into the nearest neighbours' bin, id: [%d]", i),
   123  			recipient: a[:],
   124  			peers:     peerAddresses,
   125  			expected:  nearestNeighbours,
   126  			exclusive: false,
   127  		}
   128  		testCases = append(testCases, c)
   129  	}
   130  
   131  //发送带有邻近命令的消息比最深的最近邻居深得多
   132  	a2 := pot.RandomAddressAt(base, 77)
   133  	c = testCase{
   134  		name:      "proximity order much deeper than the deepest nearest neighbour",
   135  		recipient: a2[:],
   136  		peers:     peerAddresses,
   137  		expected:  nearestNeighbours,
   138  		exclusive: false,
   139  	}
   140  	testCases = append(testCases, c)
   141  
   142  //部分地址测试
   143  	const part = 12
   144  
   145  	for i := 0; i < firstNearest; i++ {
   146  //发送部分地址属于不同邻近顺序的消息
   147  		po := i / 2
   148  		if i%8 != 0 {
   149  			c = testCase{
   150  				name:      fmt.Sprintf("partial address falling into different proximity orders, id: [%d]", i),
   151  				recipient: peerAddresses[i][:i],
   152  				peers:     peerAddresses,
   153  				expected:  []int{po * 2, po*2 + 1},
   154  				exclusive: true,
   155  			}
   156  			testCases = append(testCases, c)
   157  		}
   158  		c = testCase{
   159  			name:      fmt.Sprintf("extended partial address falling into different proximity orders, id: [%d]", i),
   160  			recipient: peerAddresses[i][:part],
   161  			peers:     peerAddresses,
   162  			expected:  []int{po * 2, po*2 + 1},
   163  			exclusive: true,
   164  		}
   165  		testCases = append(testCases, c)
   166  	}
   167  
   168  	for i := firstNearest; i < len(peerAddresses); i++ {
   169  //部分地址落在最近邻居的箱子里。
   170  		c = testCase{
   171  			name:      fmt.Sprintf("partial address falls into the nearest neighbours' bin, id: [%d]", i),
   172  			recipient: peerAddresses[i][:part],
   173  			peers:     peerAddresses,
   174  			expected:  nearestNeighbours,
   175  			exclusive: false,
   176  		}
   177  		testCases = append(testCases, c)
   178  	}
   179  
   180  //部分地址,邻近顺序比任何最近邻居都深
   181  	a3 := pot.RandomAddressAt(base, part)
   182  	c = testCase{
   183  		name:      "partial address with proximity order deeper than any of the nearest neighbour",
   184  		recipient: a3[:part],
   185  		peers:     peerAddresses,
   186  		expected:  nearestNeighbours,
   187  		exclusive: false,
   188  	}
   189  	testCases = append(testCases, c)
   190  
   191  //部分地址与大量对等点匹配的特殊情况
   192  
   193  //地址为零字节,应将消息传递给所有对等方
   194  	c = testCase{
   195  		name:      "zero bytes of address is given",
   196  		recipient: []byte{},
   197  		peers:     peerAddresses,
   198  		expected:  all,
   199  		exclusive: false,
   200  	}
   201  	testCases = append(testCases, c)
   202  
   203  //发光半径8位,接近顺序8
   204  	indexAtPo8 := 16
   205  	c = testCase{
   206  		name:      "luminous radius of 8 bits",
   207  		recipient: []byte{0xFF},
   208  		peers:     peerAddresses,
   209  		expected:  all[indexAtPo8:],
   210  		exclusive: false,
   211  	}
   212  	testCases = append(testCases, c)
   213  
   214  //发光半径256位,接近8级
   215  	a4 := pot.Address{}
   216  	a4[0] = 0xFF
   217  	c = testCase{
   218  		name:      "luminous radius of 256 bits",
   219  		recipient: a4[:],
   220  		peers:     peerAddresses,
   221  		expected:  []int{indexAtPo8, indexAtPo8 + 1},
   222  		exclusive: true,
   223  	}
   224  	testCases = append(testCases, c)
   225  
   226  //如果发送失败,请检查行为是否正确
   227  	for i := 2; i < firstNearest-3; i += 2 {
   228  		po := i / 2
   229  //随机发送带有邻近订单的消息,与每个垃圾箱的采购订单相对应,
   230  //尝试失败的次数不同。
   231  //只有一个较深的对等方应接收消息。
   232  		a := pot.RandomAddressAt(base, po)
   233  		c = testCase{
   234  			name:      fmt.Sprintf("Send direct to known, id: [%d]", i),
   235  			recipient: a[:],
   236  			peers:     peerAddresses,
   237  			expected:  all[i+1:],
   238  			exclusive: true,
   239  			nFails:    rand.Int()%3 + 2,
   240  		}
   241  		testCases = append(testCases, c)
   242  	}
   243  
   244  	for _, c := range testCases {
   245  		testForwardMsg(t, ps, &c)
   246  	}
   247  }
   248  
   249  //此功能测试单个邮件的转发。收件人地址作为参数传递,
   250  //以及所有对等方的地址,以及期望接收消息的对等方的索引。
   251  func testForwardMsg(t *testing.T, ps *Pss, c *testCase) {
   252  	recipientAddr := c.recipient
   253  	peers := c.peers
   254  	expected := c.expected
   255  	exclusive := c.exclusive
   256  	nFails := c.nFails
   257  tries := 0 //上次失败的尝试次数
   258  
   259  	resultMap := make(map[pot.Address]int)
   260  
   261  	defer func() { sendFunc = sendMsg }()
   262  	sendFunc = func(_ *Pss, sp *network.Peer, _ *PssMsg) bool {
   263  		if tries < nFails {
   264  			tries++
   265  			return false
   266  		}
   267  		a := pot.NewAddressFromBytes(sp.Address())
   268  		resultMap[a]++
   269  		return true
   270  	}
   271  
   272  	msg := newTestMsg(recipientAddr)
   273  	ps.forward(msg)
   274  
   275  //检查测试结果
   276  	var fail bool
   277  	precision := len(recipientAddr)
   278  	if precision > 4 {
   279  		precision = 4
   280  	}
   281  	s := fmt.Sprintf("test [%s]\nmsg address: %x..., radius: %d", c.name, recipientAddr[:precision], 8*len(recipientAddr))
   282  
   283  //错误否定(预期消息未到达对等端)
   284  	if exclusive {
   285  		var cnt int
   286  		for _, i := range expected {
   287  			a := peers[i]
   288  			cnt += resultMap[a]
   289  			resultMap[a] = 0
   290  		}
   291  		if cnt != 1 {
   292  			s += fmt.Sprintf("\n%d messages received by %d peers with indices: [%v]", cnt, len(expected), expected)
   293  			fail = true
   294  		}
   295  	} else {
   296  		for _, i := range expected {
   297  			a := peers[i]
   298  			received := resultMap[a]
   299  			if received != 1 {
   300  				s += fmt.Sprintf("\npeer number %d [%x...] received %d messages", i, a[:4], received)
   301  				fail = true
   302  			}
   303  			resultMap[a] = 0
   304  		}
   305  	}
   306  
   307  //误报(到达对等端的意外消息)
   308  	for k, v := range resultMap {
   309  		if v != 0 {
   310  //查找假阳性对等体的索引
   311  			var j int
   312  			for j = 0; j < len(peers); j++ {
   313  				if peers[j] == k {
   314  					break
   315  				}
   316  			}
   317  			s += fmt.Sprintf("\npeer number %d [%x...] received %d messages", j, k[:4], v)
   318  			fail = true
   319  		}
   320  	}
   321  
   322  	if fail {
   323  		t.Fatal(s)
   324  	}
   325  }
   326  
   327  func addPeers(kad *network.Kademlia, addresses []pot.Address) {
   328  	for _, a := range addresses {
   329  		p := newTestDiscoveryPeer(a, kad)
   330  		kad.On(p)
   331  	}
   332  }
   333  
   334  func createPss(t *testing.T, kad *network.Kademlia) *Pss {
   335  	privKey, err := crypto.GenerateKey()
   336  	pssp := NewPssParams().WithPrivateKey(privKey)
   337  	ps, err := NewPss(kad, pssp)
   338  	if err != nil {
   339  		t.Fatal(err.Error())
   340  	}
   341  	return ps
   342  }
   343  
   344  func newTestDiscoveryPeer(addr pot.Address, kad *network.Kademlia) *network.Peer {
   345  	rw := &p2p.MsgPipeRW{}
   346  	p := p2p.NewPeer(enode.ID{}, "test", []p2p.Cap{})
   347  	pp := protocols.NewPeer(p, rw, &protocols.Spec{})
   348  	bp := &network.BzzPeer{
   349  		Peer: pp,
   350  		BzzAddr: &network.BzzAddr{
   351  			OAddr: addr.Bytes(),
   352  			UAddr: []byte(fmt.Sprintf("%x", addr[:])),
   353  		},
   354  	}
   355  	return network.NewPeer(bp, kad)
   356  }
   357  
   358  func newTestMsg(addr []byte) *PssMsg {
   359  	msg := newPssMsg(&msgParams{})
   360  	msg.To = addr[:]
   361  	msg.Expire = uint32(time.Now().Add(time.Second * 60).Unix())
   362  	msg.Payload = &whisper.Envelope{
   363  		Topic: [4]byte{},
   364  		Data:  []byte("i have nothing to hide"),
   365  	}
   366  	return msg
   367  }
   368