github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/eth/handler_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:38</date> 10 //</624342636093771776> 11 12 13 package eth 14 15 import ( 16 "math" 17 "math/big" 18 "math/rand" 19 "testing" 20 "time" 21 22 "github.com/ethereum/go-ethereum/common" 23 "github.com/ethereum/go-ethereum/consensus/ethash" 24 "github.com/ethereum/go-ethereum/core" 25 "github.com/ethereum/go-ethereum/core/state" 26 "github.com/ethereum/go-ethereum/core/types" 27 "github.com/ethereum/go-ethereum/core/vm" 28 "github.com/ethereum/go-ethereum/crypto" 29 "github.com/ethereum/go-ethereum/eth/downloader" 30 "github.com/ethereum/go-ethereum/ethdb" 31 "github.com/ethereum/go-ethereum/event" 32 "github.com/ethereum/go-ethereum/p2p" 33 "github.com/ethereum/go-ethereum/params" 34 ) 35 36 //测试协议版本和操作模式是否正确匹配。 37 func TestProtocolCompatibility(t *testing.T) { 38 //定义兼容性图表 39 tests := []struct { 40 version uint 41 mode downloader.SyncMode 42 compatible bool 43 }{ 44 {61, downloader.FullSync, true}, {62, downloader.FullSync, true}, {63, downloader.FullSync, true}, 45 {61, downloader.FastSync, false}, {62, downloader.FastSync, false}, {63, downloader.FastSync, true}, 46 } 47 //确保我们搞砸的东西都恢复了 48 backup := ProtocolVersions 49 defer func() { ProtocolVersions = backup }() 50 51 //尝试所有可用的兼容性配置并检查错误 52 for i, tt := range tests { 53 ProtocolVersions = []uint{tt.version} 54 55 pm, _, err := newTestProtocolManager(tt.mode, 0, nil, nil) 56 if pm != nil { 57 defer pm.Stop() 58 } 59 if (err == nil && !tt.compatible) || (err != nil && tt.compatible) { 60 t.Errorf("test %d: compatibility mismatch: have error %v, want compatibility %v", i, err, tt.compatible) 61 } 62 } 63 } 64 65 //可以根据用户查询从远程链中检索阻止头的测试。 66 func TestGetBlockHeaders62(t *testing.T) { testGetBlockHeaders(t, 62) } 67 func TestGetBlockHeaders63(t *testing.T) { testGetBlockHeaders(t, 63) } 68 69 func testGetBlockHeaders(t *testing.T, protocol int) { 70 pm, _ := newTestProtocolManagerMust(t, downloader.FullSync, downloader.MaxHashFetch+15, nil, nil) 71 peer, _ := newTestPeer("peer", protocol, pm, true) 72 defer peer.close() 73 74 //为测试创建一个“随机”的未知哈希 75 var unknown common.Hash 76 for i := range unknown { 77 unknown[i] = byte(i) 78 } 79 //为各种方案创建一批测试 80 limit := uint64(downloader.MaxHeaderFetch) 81 tests := []struct { 82 query *getBlockHeadersData //要为头检索执行的查询 83 expect []common.Hash //应为其头的块的哈希 84 }{ 85 //单个随机块也应该可以通过哈希和数字检索。 86 { 87 &getBlockHeadersData{Origin: hashOrNumber{Hash: pm.blockchain.GetBlockByNumber(limit / 2).Hash()}, Amount: 1}, 88 []common.Hash{pm.blockchain.GetBlockByNumber(limit / 2).Hash()}, 89 }, { 90 &getBlockHeadersData{Origin: hashOrNumber{Number: limit / 2}, Amount: 1}, 91 []common.Hash{pm.blockchain.GetBlockByNumber(limit / 2).Hash()}, 92 }, 93 //应可从两个方向检索多个邮件头 94 { 95 &getBlockHeadersData{Origin: hashOrNumber{Number: limit / 2}, Amount: 3}, 96 []common.Hash{ 97 pm.blockchain.GetBlockByNumber(limit / 2).Hash(), 98 pm.blockchain.GetBlockByNumber(limit/2 + 1).Hash(), 99 pm.blockchain.GetBlockByNumber(limit/2 + 2).Hash(), 100 }, 101 }, { 102 &getBlockHeadersData{Origin: hashOrNumber{Number: limit / 2}, Amount: 3, Reverse: true}, 103 []common.Hash{ 104 pm.blockchain.GetBlockByNumber(limit / 2).Hash(), 105 pm.blockchain.GetBlockByNumber(limit/2 - 1).Hash(), 106 pm.blockchain.GetBlockByNumber(limit/2 - 2).Hash(), 107 }, 108 }, 109 //应检索具有跳过列表的多个邮件头 110 { 111 &getBlockHeadersData{Origin: hashOrNumber{Number: limit / 2}, Skip: 3, Amount: 3}, 112 []common.Hash{ 113 pm.blockchain.GetBlockByNumber(limit / 2).Hash(), 114 pm.blockchain.GetBlockByNumber(limit/2 + 4).Hash(), 115 pm.blockchain.GetBlockByNumber(limit/2 + 8).Hash(), 116 }, 117 }, { 118 &getBlockHeadersData{Origin: hashOrNumber{Number: limit / 2}, Skip: 3, Amount: 3, Reverse: true}, 119 []common.Hash{ 120 pm.blockchain.GetBlockByNumber(limit / 2).Hash(), 121 pm.blockchain.GetBlockByNumber(limit/2 - 4).Hash(), 122 pm.blockchain.GetBlockByNumber(limit/2 - 8).Hash(), 123 }, 124 }, 125 //链端点应该是可检索的 126 { 127 &getBlockHeadersData{Origin: hashOrNumber{Number: 0}, Amount: 1}, 128 []common.Hash{pm.blockchain.GetBlockByNumber(0).Hash()}, 129 }, { 130 &getBlockHeadersData{Origin: hashOrNumber{Number: pm.blockchain.CurrentBlock().NumberU64()}, Amount: 1}, 131 []common.Hash{pm.blockchain.CurrentBlock().Hash()}, 132 }, 133 //确保遵守协议限制 134 { 135 &getBlockHeadersData{Origin: hashOrNumber{Number: pm.blockchain.CurrentBlock().NumberU64() - 1}, Amount: limit + 10, Reverse: true}, 136 pm.blockchain.GetBlockHashesFromHash(pm.blockchain.CurrentBlock().Hash(), limit), 137 }, 138 //检查请求是否处理得当 139 { 140 &getBlockHeadersData{Origin: hashOrNumber{Number: pm.blockchain.CurrentBlock().NumberU64() - 4}, Skip: 3, Amount: 3}, 141 []common.Hash{ 142 pm.blockchain.GetBlockByNumber(pm.blockchain.CurrentBlock().NumberU64() - 4).Hash(), 143 pm.blockchain.GetBlockByNumber(pm.blockchain.CurrentBlock().NumberU64()).Hash(), 144 }, 145 }, { 146 &getBlockHeadersData{Origin: hashOrNumber{Number: 4}, Skip: 3, Amount: 3, Reverse: true}, 147 []common.Hash{ 148 pm.blockchain.GetBlockByNumber(4).Hash(), 149 pm.blockchain.GetBlockByNumber(0).Hash(), 150 }, 151 }, 152 //检查请求是否处理得当,即使中间跳过 153 { 154 &getBlockHeadersData{Origin: hashOrNumber{Number: pm.blockchain.CurrentBlock().NumberU64() - 4}, Skip: 2, Amount: 3}, 155 []common.Hash{ 156 pm.blockchain.GetBlockByNumber(pm.blockchain.CurrentBlock().NumberU64() - 4).Hash(), 157 pm.blockchain.GetBlockByNumber(pm.blockchain.CurrentBlock().NumberU64() - 1).Hash(), 158 }, 159 }, { 160 &getBlockHeadersData{Origin: hashOrNumber{Number: 4}, Skip: 2, Amount: 3, Reverse: true}, 161 []common.Hash{ 162 pm.blockchain.GetBlockByNumber(4).Hash(), 163 pm.blockchain.GetBlockByNumber(1).Hash(), 164 }, 165 }, 166 //检查一个角情况,在这种情况下,请求更多可以迭代通过端点 167 { 168 &getBlockHeadersData{Origin: hashOrNumber{Number: 2}, Amount: 5, Reverse: true}, 169 []common.Hash{ 170 pm.blockchain.GetBlockByNumber(2).Hash(), 171 pm.blockchain.GetBlockByNumber(1).Hash(), 172 pm.blockchain.GetBlockByNumber(0).Hash(), 173 }, 174 }, 175 //检查将溢出循环跳回到链起始处的角情况 176 { 177 &getBlockHeadersData{Origin: hashOrNumber{Hash: pm.blockchain.GetBlockByNumber(3).Hash()}, Amount: 2, Reverse: false, Skip: math.MaxUint64 - 1}, 178 []common.Hash{ 179 pm.blockchain.GetBlockByNumber(3).Hash(), 180 }, 181 }, 182 //检查跳过溢出循环返回同一头的角情况 183 { 184 &getBlockHeadersData{Origin: hashOrNumber{Hash: pm.blockchain.GetBlockByNumber(1).Hash()}, Amount: 2, Reverse: false, Skip: math.MaxUint64}, 185 []common.Hash{ 186 pm.blockchain.GetBlockByNumber(1).Hash(), 187 }, 188 }, 189 //检查是否未返回不存在的邮件头 190 { 191 &getBlockHeadersData{Origin: hashOrNumber{Hash: unknown}, Amount: 1}, 192 []common.Hash{}, 193 }, { 194 &getBlockHeadersData{Origin: hashOrNumber{Number: pm.blockchain.CurrentBlock().NumberU64() + 1}, Amount: 1}, 195 []common.Hash{}, 196 }, 197 } 198 //运行每个测试并对照链验证结果 199 for i, tt := range tests { 200 //收集响应中预期的头 201 headers := []*types.Header{} 202 for _, hash := range tt.expect { 203 headers = append(headers, pm.blockchain.GetBlockByHash(hash).Header()) 204 } 205 //发送哈希请求并验证响应 206 p2p.Send(peer.app, 0x03, tt.query) 207 if err := p2p.ExpectMsg(peer.app, 0x04, headers); err != nil { 208 t.Errorf("test %d: headers mismatch: %v", i, err) 209 } 210 //如果测试使用的是数字源,也可以使用哈希进行重复。 211 if tt.query.Origin.Hash == (common.Hash{}) { 212 if origin := pm.blockchain.GetBlockByNumber(tt.query.Origin.Number); origin != nil { 213 tt.query.Origin.Hash, tt.query.Origin.Number = origin.Hash(), 0 214 215 p2p.Send(peer.app, 0x03, tt.query) 216 if err := p2p.ExpectMsg(peer.app, 0x04, headers); err != nil { 217 t.Errorf("test %d: headers mismatch: %v", i, err) 218 } 219 } 220 } 221 } 222 } 223 224 //可以基于哈希从远程链中检索阻止内容的测试。 225 func TestGetBlockBodies62(t *testing.T) { testGetBlockBodies(t, 62) } 226 func TestGetBlockBodies63(t *testing.T) { testGetBlockBodies(t, 63) } 227 228 func testGetBlockBodies(t *testing.T, protocol int) { 229 pm, _ := newTestProtocolManagerMust(t, downloader.FullSync, downloader.MaxBlockFetch+15, nil, nil) 230 peer, _ := newTestPeer("peer", protocol, pm, true) 231 defer peer.close() 232 233 //为各种方案创建一批测试 234 limit := downloader.MaxBlockFetch 235 tests := []struct { 236 random int //从链中随机提取的块数 237 explicit []common.Hash //显式请求的块 238 available []bool //显式请求块的可用性 239 expected int //期望的现有块总数 240 }{ 241 {1, nil, nil, 1}, //单个随机块应该是可检索的 242 {10, nil, nil, 10}, //应可检索多个随机块 243 {limit, nil, nil, limit}, //最大可能的块应该是可检索的 244 {limit + 1, nil, nil, limit}, //不应返回超过可能的块计数 245 {0, []common.Hash{pm.blockchain.Genesis().Hash()}, []bool{true}, 1}, //Genesis区块应该是可回收的。 246 {0, []common.Hash{pm.blockchain.CurrentBlock().Hash()}, []bool{true}, 1}, //链头滑轮应可回收。 247 {0, []common.Hash{{}}, []bool{false}, 0}, //不应返回不存在的块 248 249 //现有和不存在的块交错不应导致问题 250 {0, []common.Hash{ 251 {}, 252 pm.blockchain.GetBlockByNumber(1).Hash(), 253 {}, 254 pm.blockchain.GetBlockByNumber(10).Hash(), 255 {}, 256 pm.blockchain.GetBlockByNumber(100).Hash(), 257 {}, 258 }, []bool{false, true, false, true, false, true, false}, 3}, 259 } 260 //运行每个测试并对照链验证结果 261 for i, tt := range tests { 262 //收集要请求的哈希值和预期的响应 263 hashes, seen := []common.Hash{}, make(map[int64]bool) 264 bodies := []*blockBody{} 265 266 for j := 0; j < tt.random; j++ { 267 for { 268 num := rand.Int63n(int64(pm.blockchain.CurrentBlock().NumberU64())) 269 if !seen[num] { 270 seen[num] = true 271 272 block := pm.blockchain.GetBlockByNumber(uint64(num)) 273 hashes = append(hashes, block.Hash()) 274 if len(bodies) < tt.expected { 275 bodies = append(bodies, &blockBody{Transactions: block.Transactions(), Uncles: block.Uncles()}) 276 } 277 break 278 } 279 } 280 } 281 for j, hash := range tt.explicit { 282 hashes = append(hashes, hash) 283 if tt.available[j] && len(bodies) < tt.expected { 284 block := pm.blockchain.GetBlockByHash(hash) 285 bodies = append(bodies, &blockBody{Transactions: block.Transactions(), Uncles: block.Uncles()}) 286 } 287 } 288 //发送哈希请求并验证响应 289 p2p.Send(peer.app, 0x05, hashes) 290 if err := p2p.ExpectMsg(peer.app, 0x06, bodies); err != nil { 291 t.Errorf("test %d: bodies mismatch: %v", i, err) 292 } 293 } 294 } 295 296 //测试可以基于哈希检索节点状态数据库。 297 func TestGetNodeData63(t *testing.T) { testGetNodeData(t, 63) } 298 299 func testGetNodeData(t *testing.T, protocol int) { 300 //定义三个科目以模拟交易 301 acc1Key, _ := crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a") 302 acc2Key, _ := crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee") 303 acc1Addr := crypto.PubkeyToAddress(acc1Key.PublicKey) 304 acc2Addr := crypto.PubkeyToAddress(acc2Key.PublicKey) 305 306 signer := types.HomesteadSigner{} 307 //用一些简单的事务创建一个链生成器(公然从@fjl/chain_markets_test中被盗) 308 generator := func(i int, block *core.BlockGen) { 309 switch i { 310 case 0: 311 //在块1中,测试银行发送帐户1一些乙醚。 312 tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBank), acc1Addr, big.NewInt(10000), params.TxGas, nil, nil), signer, testBankKey) 313 block.AddTx(tx) 314 case 1: 315 //在区块2中,测试银行向账户1发送更多乙醚。 316 //acc1addr将其传递到account_2。 317 tx1, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBank), acc1Addr, big.NewInt(1000), params.TxGas, nil, nil), signer, testBankKey) 318 tx2, _ := types.SignTx(types.NewTransaction(block.TxNonce(acc1Addr), acc2Addr, big.NewInt(1000), params.TxGas, nil, nil), signer, acc1Key) 319 block.AddTx(tx1) 320 block.AddTx(tx2) 321 case 2: 322 //区块3为空,但由账户2开采。 323 block.SetCoinbase(acc2Addr) 324 block.SetExtra([]byte("yeehaw")) 325 case 3: 326 //块4包括块2和3作为叔叔头(带有修改的额外数据)。 327 b2 := block.PrevBlock(1).Header() 328 b2.Extra = []byte("foo") 329 block.AddUncle(b2) 330 b3 := block.PrevBlock(2).Header() 331 b3.Extra = []byte("foo") 332 block.AddUncle(b3) 333 } 334 } 335 //组装测试环境 336 pm, db := newTestProtocolManagerMust(t, downloader.FullSync, 4, generator, nil) 337 peer, _ := newTestPeer("peer", protocol, pm, true) 338 defer peer.close() 339 340 //现在获取整个链数据库 341 hashes := []common.Hash{} 342 for _, key := range db.Keys() { 343 if len(key) == len(common.Hash{}) { 344 hashes = append(hashes, common.BytesToHash(key)) 345 } 346 } 347 p2p.Send(peer.app, 0x0d, hashes) 348 msg, err := peer.app.ReadMsg() 349 if err != nil { 350 t.Fatalf("failed to read node data response: %v", err) 351 } 352 if msg.Code != 0x0e { 353 t.Fatalf("response packet code mismatch: have %x, want %x", msg.Code, 0x0c) 354 } 355 var data [][]byte 356 if err := msg.Decode(&data); err != nil { 357 t.Fatalf("failed to decode response node data: %v", err) 358 } 359 //验证所有哈希是否与请求的数据对应,并重建状态树 360 for i, want := range hashes { 361 if hash := crypto.Keccak256Hash(data[i]); hash != want { 362 t.Errorf("data hash mismatch: have %x, want %x", hash, want) 363 } 364 } 365 statedb := ethdb.NewMemDatabase() 366 for i := 0; i < len(data); i++ { 367 statedb.Put(hashes[i].Bytes(), data[i]) 368 } 369 accounts := []common.Address{testBank, acc1Addr, acc2Addr} 370 for i := uint64(0); i <= pm.blockchain.CurrentBlock().NumberU64(); i++ { 371 trie, _ := state.New(pm.blockchain.GetBlockByNumber(i).Root(), state.NewDatabase(statedb)) 372 373 for j, acc := range accounts { 374 state, _ := pm.blockchain.State() 375 bw := state.GetBalance(acc) 376 bh := trie.GetBalance(acc) 377 378 if (bw != nil && bh == nil) || (bw == nil && bh != nil) { 379 t.Errorf("test %d, account %d: balance mismatch: have %v, want %v", i, j, bh, bw) 380 } 381 if bw != nil && bh != nil && bw.Cmp(bw) != 0 { 382 t.Errorf("test %d, account %d: balance mismatch: have %v, want %v", i, j, bh, bw) 383 } 384 } 385 } 386 } 387 388 //测试是否可以基于哈希值检索事务回执。 389 func TestGetReceipt63(t *testing.T) { testGetReceipt(t, 63) } 390 391 func testGetReceipt(t *testing.T, protocol int) { 392 //定义三个科目以模拟交易 393 acc1Key, _ := crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a") 394 acc2Key, _ := crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee") 395 acc1Addr := crypto.PubkeyToAddress(acc1Key.PublicKey) 396 acc2Addr := crypto.PubkeyToAddress(acc2Key.PublicKey) 397 398 signer := types.HomesteadSigner{} 399 //用一些简单的事务创建一个链生成器(公然从@fjl/chain_markets_test中被盗) 400 generator := func(i int, block *core.BlockGen) { 401 switch i { 402 case 0: 403 //在块1中,测试银行发送帐户1一些乙醚。 404 tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBank), acc1Addr, big.NewInt(10000), params.TxGas, nil, nil), signer, testBankKey) 405 block.AddTx(tx) 406 case 1: 407 //在区块2中,测试银行向账户1发送更多乙醚。 408 //acc1addr将其传递到account_2。 409 tx1, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBank), acc1Addr, big.NewInt(1000), params.TxGas, nil, nil), signer, testBankKey) 410 tx2, _ := types.SignTx(types.NewTransaction(block.TxNonce(acc1Addr), acc2Addr, big.NewInt(1000), params.TxGas, nil, nil), signer, acc1Key) 411 block.AddTx(tx1) 412 block.AddTx(tx2) 413 case 2: 414 //区块3为空,但由账户2开采。 415 block.SetCoinbase(acc2Addr) 416 block.SetExtra([]byte("yeehaw")) 417 case 3: 418 //块4包括块2和3作为叔叔头(带有修改的额外数据)。 419 b2 := block.PrevBlock(1).Header() 420 b2.Extra = []byte("foo") 421 block.AddUncle(b2) 422 b3 := block.PrevBlock(2).Header() 423 b3.Extra = []byte("foo") 424 block.AddUncle(b3) 425 } 426 } 427 //组装测试环境 428 pm, _ := newTestProtocolManagerMust(t, downloader.FullSync, 4, generator, nil) 429 peer, _ := newTestPeer("peer", protocol, pm, true) 430 defer peer.close() 431 432 //收集要请求的哈希值和预期的响应 433 hashes, receipts := []common.Hash{}, []types.Receipts{} 434 for i := uint64(0); i <= pm.blockchain.CurrentBlock().NumberU64(); i++ { 435 block := pm.blockchain.GetBlockByNumber(i) 436 437 hashes = append(hashes, block.Hash()) 438 receipts = append(receipts, pm.blockchain.GetReceiptsByHash(block.Hash())) 439 } 440 //发送哈希请求并验证响应 441 p2p.Send(peer.app, 0x0f, hashes) 442 if err := p2p.ExpectMsg(peer.app, 0x10, receipts); err != nil { 443 t.Errorf("receipts mismatch: %v", err) 444 } 445 } 446 447 //发布ETH协议握手的测试,启用DAO分叉的客户端也会执行 448 //一个DAO“挑战”验证彼此的DAO分叉头,以确保它们处于打开状态 449 //兼容的链条。 450 func TestDAOChallengeNoVsNo(t *testing.T) { testDAOChallenge(t, false, false, false) } 451 func TestDAOChallengeNoVsPro(t *testing.T) { testDAOChallenge(t, false, true, false) } 452 func TestDAOChallengeProVsNo(t *testing.T) { testDAOChallenge(t, true, false, false) } 453 func TestDAOChallengeProVsPro(t *testing.T) { testDAOChallenge(t, true, true, false) } 454 func TestDAOChallengeNoVsTimeout(t *testing.T) { testDAOChallenge(t, false, false, true) } 455 func TestDAOChallengeProVsTimeout(t *testing.T) { testDAOChallenge(t, true, true, true) } 456 457 func testDAOChallenge(t *testing.T, localForked, remoteForked bool, timeout bool) { 458 //减少DAO握手挑战超时 459 if timeout { 460 defer func(old time.Duration) { daoChallengeTimeout = old }(daoChallengeTimeout) 461 daoChallengeTimeout = 500 * time.Millisecond 462 } 463 //创建DAO感知协议管理器 464 var ( 465 evmux = new(event.TypeMux) 466 pow = ethash.NewFaker() 467 db = ethdb.NewMemDatabase() 468 config = ¶ms.ChainConfig{DAOForkBlock: big.NewInt(1), DAOForkSupport: localForked} 469 gspec = &core.Genesis{Config: config} 470 genesis = gspec.MustCommit(db) 471 blockchain, _ = core.NewBlockChain(db, nil, config, pow, vm.Config{}) 472 ) 473 pm, err := NewProtocolManager(config, downloader.FullSync, DefaultConfig.NetworkId, evmux, new(testTxPool), pow, blockchain, db) 474 if err != nil { 475 t.Fatalf("failed to start test protocol manager: %v", err) 476 } 477 pm.Start(1000) 478 defer pm.Stop() 479 480 //连接新的对等点并检查我们是否收到DAO挑战 481 peer, _ := newTestPeer("peer", eth63, pm, true) 482 defer peer.close() 483 484 challenge := &getBlockHeadersData{ 485 Origin: hashOrNumber{Number: config.DAOForkBlock.Uint64()}, 486 Amount: 1, 487 Skip: 0, 488 Reverse: false, 489 } 490 if err := p2p.ExpectMsg(peer.app, GetBlockHeadersMsg, challenge); err != nil { 491 t.Fatalf("challenge mismatch: %v", err) 492 } 493 //如果没有模拟超时,则创建一个块以答复质询 494 if !timeout { 495 blocks, _ := core.GenerateChain(¶ms.ChainConfig{}, genesis, ethash.NewFaker(), db, 1, func(i int, block *core.BlockGen) { 496 if remoteForked { 497 block.SetExtra(params.DAOForkBlockExtra) 498 } 499 }) 500 if err := p2p.Send(peer.app, BlockHeadersMsg, []*types.Header{blocks[0].Header()}); err != nil { 501 t.Fatalf("failed to answer challenge: %v", err) 502 } 503 time.Sleep(100 * time.Millisecond) //睡眠以避免验证与水滴赛跑 504 } else { 505 //否则,等待测试超时通过 506 time.Sleep(daoChallengeTimeout + 500*time.Millisecond) 507 } 508 //验证是否根据分叉端维护或删除远程对等机 509 if localForked == remoteForked && !timeout { 510 if peers := pm.peers.Len(); peers != 1 { 511 t.Fatalf("peer count mismatch: have %d, want %d", peers, 1) 512 } 513 } else { 514 if peers := pm.peers.Len(); peers != 0 { 515 t.Fatalf("peer count mismatch: have %d, want %d", peers, 0) 516 } 517 } 518 } 519