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