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