github.com/sberex/go-sberex@v1.8.2-0.20181113200658-ed96ac38f7d7/eth/handler_test.go (about) 1 // This file is part of the go-sberex library. The go-sberex library is 2 // free software: you can redistribute it and/or modify it under the terms 3 // of the GNU Lesser General Public License as published by the Free 4 // Software Foundation, either version 3 of the License, or (at your option) 5 // any later version. 6 // 7 // The go-sberex library is distributed in the hope that it will be useful, 8 // but WITHOUT ANY WARRANTY; without even the implied warranty of 9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 10 // General Public License <http://www.gnu.org/licenses/> for more details. 11 12 package eth 13 14 import ( 15 "math" 16 "math/big" 17 "math/rand" 18 "testing" 19 "time" 20 21 "github.com/Sberex/go-sberex/common" 22 "github.com/Sberex/go-sberex/consensus/ethash" 23 "github.com/Sberex/go-sberex/core" 24 "github.com/Sberex/go-sberex/core/state" 25 "github.com/Sberex/go-sberex/core/types" 26 "github.com/Sberex/go-sberex/core/vm" 27 "github.com/Sberex/go-sberex/crypto" 28 "github.com/Sberex/go-sberex/eth/downloader" 29 "github.com/Sberex/go-sberex/ethdb" 30 "github.com/Sberex/go-sberex/event" 31 "github.com/Sberex/go-sberex/p2p" 32 "github.com/Sberex/go-sberex/params" 33 ) 34 35 // Tests that protocol versions and modes of operations are matched up properly. 36 func TestProtocolCompatibility(t *testing.T) { 37 // Define the compatibility chart 38 tests := []struct { 39 version uint 40 mode downloader.SyncMode 41 compatible bool 42 }{ 43 {61, downloader.FullSync, true}, {62, downloader.FullSync, true}, {63, downloader.FullSync, true}, 44 {61, downloader.FastSync, false}, {62, downloader.FastSync, false}, {63, downloader.FastSync, true}, 45 } 46 // Make sure anything we screw up is restored 47 backup := ProtocolVersions 48 defer func() { ProtocolVersions = backup }() 49 50 // Try all available compatibility configs and check for errors 51 for i, tt := range tests { 52 ProtocolVersions = []uint{tt.version} 53 54 pm, _, err := newTestProtocolManager(tt.mode, 0, nil, nil) 55 if pm != nil { 56 defer pm.Stop() 57 } 58 if (err == nil && !tt.compatible) || (err != nil && tt.compatible) { 59 t.Errorf("test %d: compatibility mismatch: have error %v, want compatibility %v", i, err, tt.compatible) 60 } 61 } 62 } 63 64 // Tests that block headers can be retrieved from a remote chain based on user queries. 65 func TestGetBlockHeaders62(t *testing.T) { testGetBlockHeaders(t, 62) } 66 func TestGetBlockHeaders63(t *testing.T) { testGetBlockHeaders(t, 63) } 67 68 func testGetBlockHeaders(t *testing.T, protocol int) { 69 pm, _ := newTestProtocolManagerMust(t, downloader.FullSync, downloader.MaxHashFetch+15, nil, nil) 70 peer, _ := newTestPeer("peer", protocol, pm, true) 71 defer peer.close() 72 73 // Create a "random" unknown hash for testing 74 var unknown common.Hash 75 for i := range unknown { 76 unknown[i] = byte(i) 77 } 78 // Create a batch of tests for various scenarios 79 limit := uint64(downloader.MaxHeaderFetch) 80 tests := []struct { 81 query *getBlockHeadersData // The query to execute for header retrieval 82 expect []common.Hash // The hashes of the block whose headers are expected 83 }{ 84 // A single random block should be retrievable by hash and number too 85 { 86 &getBlockHeadersData{Origin: hashOrNumber{Hash: pm.blockchain.GetBlockByNumber(limit / 2).Hash()}, Amount: 1}, 87 []common.Hash{pm.blockchain.GetBlockByNumber(limit / 2).Hash()}, 88 }, { 89 &getBlockHeadersData{Origin: hashOrNumber{Number: limit / 2}, Amount: 1}, 90 []common.Hash{pm.blockchain.GetBlockByNumber(limit / 2).Hash()}, 91 }, 92 // Multiple headers should be retrievable in both directions 93 { 94 &getBlockHeadersData{Origin: hashOrNumber{Number: limit / 2}, Amount: 3}, 95 []common.Hash{ 96 pm.blockchain.GetBlockByNumber(limit / 2).Hash(), 97 pm.blockchain.GetBlockByNumber(limit/2 + 1).Hash(), 98 pm.blockchain.GetBlockByNumber(limit/2 + 2).Hash(), 99 }, 100 }, { 101 &getBlockHeadersData{Origin: hashOrNumber{Number: limit / 2}, Amount: 3, Reverse: true}, 102 []common.Hash{ 103 pm.blockchain.GetBlockByNumber(limit / 2).Hash(), 104 pm.blockchain.GetBlockByNumber(limit/2 - 1).Hash(), 105 pm.blockchain.GetBlockByNumber(limit/2 - 2).Hash(), 106 }, 107 }, 108 // Multiple headers with skip lists should be retrievable 109 { 110 &getBlockHeadersData{Origin: hashOrNumber{Number: limit / 2}, Skip: 3, Amount: 3}, 111 []common.Hash{ 112 pm.blockchain.GetBlockByNumber(limit / 2).Hash(), 113 pm.blockchain.GetBlockByNumber(limit/2 + 4).Hash(), 114 pm.blockchain.GetBlockByNumber(limit/2 + 8).Hash(), 115 }, 116 }, { 117 &getBlockHeadersData{Origin: hashOrNumber{Number: limit / 2}, Skip: 3, Amount: 3, Reverse: true}, 118 []common.Hash{ 119 pm.blockchain.GetBlockByNumber(limit / 2).Hash(), 120 pm.blockchain.GetBlockByNumber(limit/2 - 4).Hash(), 121 pm.blockchain.GetBlockByNumber(limit/2 - 8).Hash(), 122 }, 123 }, 124 // The chain endpoints should be retrievable 125 { 126 &getBlockHeadersData{Origin: hashOrNumber{Number: 0}, Amount: 1}, 127 []common.Hash{pm.blockchain.GetBlockByNumber(0).Hash()}, 128 }, { 129 &getBlockHeadersData{Origin: hashOrNumber{Number: pm.blockchain.CurrentBlock().NumberU64()}, Amount: 1}, 130 []common.Hash{pm.blockchain.CurrentBlock().Hash()}, 131 }, 132 // Ensure protocol limits are honored 133 { 134 &getBlockHeadersData{Origin: hashOrNumber{Number: pm.blockchain.CurrentBlock().NumberU64() - 1}, Amount: limit + 10, Reverse: true}, 135 pm.blockchain.GetBlockHashesFromHash(pm.blockchain.CurrentBlock().Hash(), limit), 136 }, 137 // Check that requesting more than available is handled gracefully 138 { 139 &getBlockHeadersData{Origin: hashOrNumber{Number: pm.blockchain.CurrentBlock().NumberU64() - 4}, Skip: 3, Amount: 3}, 140 []common.Hash{ 141 pm.blockchain.GetBlockByNumber(pm.blockchain.CurrentBlock().NumberU64() - 4).Hash(), 142 pm.blockchain.GetBlockByNumber(pm.blockchain.CurrentBlock().NumberU64()).Hash(), 143 }, 144 }, { 145 &getBlockHeadersData{Origin: hashOrNumber{Number: 4}, Skip: 3, Amount: 3, Reverse: true}, 146 []common.Hash{ 147 pm.blockchain.GetBlockByNumber(4).Hash(), 148 pm.blockchain.GetBlockByNumber(0).Hash(), 149 }, 150 }, 151 // Check that requesting more than available is handled gracefully, even if mid skip 152 { 153 &getBlockHeadersData{Origin: hashOrNumber{Number: pm.blockchain.CurrentBlock().NumberU64() - 4}, Skip: 2, Amount: 3}, 154 []common.Hash{ 155 pm.blockchain.GetBlockByNumber(pm.blockchain.CurrentBlock().NumberU64() - 4).Hash(), 156 pm.blockchain.GetBlockByNumber(pm.blockchain.CurrentBlock().NumberU64() - 1).Hash(), 157 }, 158 }, { 159 &getBlockHeadersData{Origin: hashOrNumber{Number: 4}, Skip: 2, Amount: 3, Reverse: true}, 160 []common.Hash{ 161 pm.blockchain.GetBlockByNumber(4).Hash(), 162 pm.blockchain.GetBlockByNumber(1).Hash(), 163 }, 164 }, 165 // Check a corner case where requesting more can iterate past the endpoints 166 { 167 &getBlockHeadersData{Origin: hashOrNumber{Number: 2}, Amount: 5, Reverse: true}, 168 []common.Hash{ 169 pm.blockchain.GetBlockByNumber(2).Hash(), 170 pm.blockchain.GetBlockByNumber(1).Hash(), 171 pm.blockchain.GetBlockByNumber(0).Hash(), 172 }, 173 }, 174 // Check a corner case where skipping overflow loops back into the chain start 175 { 176 &getBlockHeadersData{Origin: hashOrNumber{Hash: pm.blockchain.GetBlockByNumber(3).Hash()}, Amount: 2, Reverse: false, Skip: math.MaxUint64 - 1}, 177 []common.Hash{ 178 pm.blockchain.GetBlockByNumber(3).Hash(), 179 }, 180 }, 181 // Check a corner case where skipping overflow loops back to the same header 182 { 183 &getBlockHeadersData{Origin: hashOrNumber{Hash: pm.blockchain.GetBlockByNumber(1).Hash()}, Amount: 2, Reverse: false, Skip: math.MaxUint64}, 184 []common.Hash{ 185 pm.blockchain.GetBlockByNumber(1).Hash(), 186 }, 187 }, 188 // Check that non existing headers aren't returned 189 { 190 &getBlockHeadersData{Origin: hashOrNumber{Hash: unknown}, Amount: 1}, 191 []common.Hash{}, 192 }, { 193 &getBlockHeadersData{Origin: hashOrNumber{Number: pm.blockchain.CurrentBlock().NumberU64() + 1}, Amount: 1}, 194 []common.Hash{}, 195 }, 196 } 197 // Run each of the tests and verify the results against the chain 198 for i, tt := range tests { 199 // Collect the headers to expect in the response 200 headers := []*types.Header{} 201 for _, hash := range tt.expect { 202 headers = append(headers, pm.blockchain.GetBlockByHash(hash).Header()) 203 } 204 // Send the hash request and verify the response 205 p2p.Send(peer.app, 0x03, tt.query) 206 if err := p2p.ExpectMsg(peer.app, 0x04, headers); err != nil { 207 t.Errorf("test %d: headers mismatch: %v", i, err) 208 } 209 // If the test used number origins, repeat with hashes as the too 210 if tt.query.Origin.Hash == (common.Hash{}) { 211 if origin := pm.blockchain.GetBlockByNumber(tt.query.Origin.Number); origin != nil { 212 tt.query.Origin.Hash, tt.query.Origin.Number = origin.Hash(), 0 213 214 p2p.Send(peer.app, 0x03, tt.query) 215 if err := p2p.ExpectMsg(peer.app, 0x04, headers); err != nil { 216 t.Errorf("test %d: headers mismatch: %v", i, err) 217 } 218 } 219 } 220 } 221 } 222 223 // Tests that block contents can be retrieved from a remote chain based on their hashes. 224 func TestGetBlockBodies62(t *testing.T) { testGetBlockBodies(t, 62) } 225 func TestGetBlockBodies63(t *testing.T) { testGetBlockBodies(t, 63) } 226 227 func testGetBlockBodies(t *testing.T, protocol int) { 228 pm, _ := newTestProtocolManagerMust(t, downloader.FullSync, downloader.MaxBlockFetch+15, nil, nil) 229 peer, _ := newTestPeer("peer", protocol, pm, true) 230 defer peer.close() 231 232 // Create a batch of tests for various scenarios 233 limit := downloader.MaxBlockFetch 234 tests := []struct { 235 random int // Number of blocks to fetch randomly from the chain 236 explicit []common.Hash // Explicitly requested blocks 237 available []bool // Availability of explicitly requested blocks 238 expected int // Total number of existing blocks to expect 239 }{ 240 {1, nil, nil, 1}, // A single random block should be retrievable 241 {10, nil, nil, 10}, // Multiple random blocks should be retrievable 242 {limit, nil, nil, limit}, // The maximum possible blocks should be retrievable 243 {limit + 1, nil, nil, limit}, // No more than the possible block count should be returned 244 {0, []common.Hash{pm.blockchain.Genesis().Hash()}, []bool{true}, 1}, // The genesis block should be retrievable 245 {0, []common.Hash{pm.blockchain.CurrentBlock().Hash()}, []bool{true}, 1}, // The chains head block should be retrievable 246 {0, []common.Hash{{}}, []bool{false}, 0}, // A non existent block should not be returned 247 248 // Existing and non-existing blocks interleaved should not cause problems 249 {0, []common.Hash{ 250 {}, 251 pm.blockchain.GetBlockByNumber(1).Hash(), 252 {}, 253 pm.blockchain.GetBlockByNumber(10).Hash(), 254 {}, 255 pm.blockchain.GetBlockByNumber(100).Hash(), 256 {}, 257 }, []bool{false, true, false, true, false, true, false}, 3}, 258 } 259 // Run each of the tests and verify the results against the chain 260 for i, tt := range tests { 261 // Collect the hashes to request, and the response to expect 262 hashes, seen := []common.Hash{}, make(map[int64]bool) 263 bodies := []*blockBody{} 264 265 for j := 0; j < tt.random; j++ { 266 for { 267 num := rand.Int63n(int64(pm.blockchain.CurrentBlock().NumberU64())) 268 if !seen[num] { 269 seen[num] = true 270 271 block := pm.blockchain.GetBlockByNumber(uint64(num)) 272 hashes = append(hashes, block.Hash()) 273 if len(bodies) < tt.expected { 274 bodies = append(bodies, &blockBody{Transactions: block.Transactions(), Uncles: block.Uncles()}) 275 } 276 break 277 } 278 } 279 } 280 for j, hash := range tt.explicit { 281 hashes = append(hashes, hash) 282 if tt.available[j] && len(bodies) < tt.expected { 283 block := pm.blockchain.GetBlockByHash(hash) 284 bodies = append(bodies, &blockBody{Transactions: block.Transactions(), Uncles: block.Uncles()}) 285 } 286 } 287 // Send the hash request and verify the response 288 p2p.Send(peer.app, 0x05, hashes) 289 if err := p2p.ExpectMsg(peer.app, 0x06, bodies); err != nil { 290 t.Errorf("test %d: bodies mismatch: %v", i, err) 291 } 292 } 293 } 294 295 // Tests that the node state database can be retrieved based on hashes. 296 func TestGetNodeData63(t *testing.T) { testGetNodeData(t, 63) } 297 298 func testGetNodeData(t *testing.T, protocol int) { 299 // Define three accounts to simulate transactions with 300 acc1Key, _ := crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a") 301 acc2Key, _ := crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee") 302 acc1Addr := crypto.PubkeyToAddress(acc1Key.PublicKey) 303 acc2Addr := crypto.PubkeyToAddress(acc2Key.PublicKey) 304 305 signer := types.HomesteadSigner{} 306 // Create a chain generator with some simple transactions (blatantly stolen from @fjl/chain_markets_test) 307 generator := func(i int, block *core.BlockGen) { 308 switch i { 309 case 0: 310 // In block 1, the test bank sends account #1 some sbr. 311 tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBank), acc1Addr, big.NewInt(10000), params.TxGas, nil, nil), signer, testBankKey) 312 block.AddTx(tx) 313 case 1: 314 // In block 2, the test bank sends some more sbr to account #1. 315 // acc1Addr passes it on to account #2. 316 tx1, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBank), acc1Addr, big.NewInt(1000), params.TxGas, nil, nil), signer, testBankKey) 317 tx2, _ := types.SignTx(types.NewTransaction(block.TxNonce(acc1Addr), acc2Addr, big.NewInt(1000), params.TxGas, nil, nil), signer, acc1Key) 318 block.AddTx(tx1) 319 block.AddTx(tx2) 320 case 2: 321 // Block 3 is empty but was mined by account #2. 322 block.SetCoinbase(acc2Addr) 323 block.SetExtra([]byte("yeehaw")) 324 case 3: 325 // Block 4 includes blocks 2 and 3 as uncle headers (with modified extra data). 326 b2 := block.PrevBlock(1).Header() 327 b2.Extra = []byte("foo") 328 block.AddUncle(b2) 329 b3 := block.PrevBlock(2).Header() 330 b3.Extra = []byte("foo") 331 block.AddUncle(b3) 332 } 333 } 334 // Assemble the test environment 335 pm, db := newTestProtocolManagerMust(t, downloader.FullSync, 4, generator, nil) 336 peer, _ := newTestPeer("peer", protocol, pm, true) 337 defer peer.close() 338 339 // Fetch for now the entire chain db 340 hashes := []common.Hash{} 341 for _, key := range db.Keys() { 342 if len(key) == len(common.Hash{}) { 343 hashes = append(hashes, common.BytesToHash(key)) 344 } 345 } 346 p2p.Send(peer.app, 0x0d, hashes) 347 msg, err := peer.app.ReadMsg() 348 if err != nil { 349 t.Fatalf("failed to read node data response: %v", err) 350 } 351 if msg.Code != 0x0e { 352 t.Fatalf("response packet code mismatch: have %x, want %x", msg.Code, 0x0c) 353 } 354 var data [][]byte 355 if err := msg.Decode(&data); err != nil { 356 t.Fatalf("failed to decode response node data: %v", err) 357 } 358 // Verify that all hashes correspond to the requested data, and reconstruct a state tree 359 for i, want := range hashes { 360 if hash := crypto.Keccak256Hash(data[i]); hash != want { 361 t.Errorf("data hash mismatch: have %x, want %x", hash, want) 362 } 363 } 364 statedb, _ := ethdb.NewMemDatabase() 365 for i := 0; i < len(data); i++ { 366 statedb.Put(hashes[i].Bytes(), data[i]) 367 } 368 accounts := []common.Address{testBank, acc1Addr, acc2Addr} 369 for i := uint64(0); i <= pm.blockchain.CurrentBlock().NumberU64(); i++ { 370 trie, _ := state.New(pm.blockchain.GetBlockByNumber(i).Root(), state.NewDatabase(statedb)) 371 372 for j, acc := range accounts { 373 state, _ := pm.blockchain.State() 374 bw := state.GetBalance(acc) 375 bh := trie.GetBalance(acc) 376 377 if (bw != nil && bh == nil) || (bw == nil && bh != nil) { 378 t.Errorf("test %d, account %d: balance mismatch: have %v, want %v", i, j, bh, bw) 379 } 380 if bw != nil && bh != nil && bw.Cmp(bw) != 0 { 381 t.Errorf("test %d, account %d: balance mismatch: have %v, want %v", i, j, bh, bw) 382 } 383 } 384 } 385 } 386 387 // Tests that the transaction receipts can be retrieved based on hashes. 388 func TestGetReceipt63(t *testing.T) { testGetReceipt(t, 63) } 389 390 func testGetReceipt(t *testing.T, protocol int) { 391 // Define three accounts to simulate transactions with 392 acc1Key, _ := crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a") 393 acc2Key, _ := crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee") 394 acc1Addr := crypto.PubkeyToAddress(acc1Key.PublicKey) 395 acc2Addr := crypto.PubkeyToAddress(acc2Key.PublicKey) 396 397 signer := types.HomesteadSigner{} 398 // Create a chain generator with some simple transactions (blatantly stolen from @fjl/chain_markets_test) 399 generator := func(i int, block *core.BlockGen) { 400 switch i { 401 case 0: 402 // In block 1, the test bank sends account #1 some sbr. 403 tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBank), acc1Addr, big.NewInt(10000), params.TxGas, nil, nil), signer, testBankKey) 404 block.AddTx(tx) 405 case 1: 406 // In block 2, the test bank sends some more sbr to account #1. 407 // acc1Addr passes it on to account #2. 408 tx1, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBank), acc1Addr, big.NewInt(1000), params.TxGas, nil, nil), signer, testBankKey) 409 tx2, _ := types.SignTx(types.NewTransaction(block.TxNonce(acc1Addr), acc2Addr, big.NewInt(1000), params.TxGas, nil, nil), signer, acc1Key) 410 block.AddTx(tx1) 411 block.AddTx(tx2) 412 case 2: 413 // Block 3 is empty but was mined by account #2. 414 block.SetCoinbase(acc2Addr) 415 block.SetExtra([]byte("yeehaw")) 416 case 3: 417 // Block 4 includes blocks 2 and 3 as uncle headers (with modified extra data). 418 b2 := block.PrevBlock(1).Header() 419 b2.Extra = []byte("foo") 420 block.AddUncle(b2) 421 b3 := block.PrevBlock(2).Header() 422 b3.Extra = []byte("foo") 423 block.AddUncle(b3) 424 } 425 } 426 // Assemble the test environment 427 pm, _ := newTestProtocolManagerMust(t, downloader.FullSync, 4, generator, nil) 428 peer, _ := newTestPeer("peer", protocol, pm, true) 429 defer peer.close() 430 431 // Collect the hashes to request, and the response to expect 432 hashes, receipts := []common.Hash{}, []types.Receipts{} 433 for i := uint64(0); i <= pm.blockchain.CurrentBlock().NumberU64(); i++ { 434 block := pm.blockchain.GetBlockByNumber(i) 435 436 hashes = append(hashes, block.Hash()) 437 receipts = append(receipts, pm.blockchain.GetReceiptsByHash(block.Hash())) 438 } 439 // Send the hash request and verify the response 440 p2p.Send(peer.app, 0x0f, hashes) 441 if err := p2p.ExpectMsg(peer.app, 0x10, receipts); err != nil { 442 t.Errorf("receipts mismatch: %v", err) 443 } 444 } 445 446 // Tests that post eth protocol handshake, DAO fork-enabled clients also execute 447 // a DAO "challenge" verifying each others' DAO fork headers to ensure they're on 448 // compatible chains. 449 func TestDAOChallengeNoVsNo(t *testing.T) { testDAOChallenge(t, false, false, false) } 450 func TestDAOChallengeNoVsPro(t *testing.T) { testDAOChallenge(t, false, true, false) } 451 func TestDAOChallengeProVsNo(t *testing.T) { testDAOChallenge(t, true, false, false) } 452 func TestDAOChallengeProVsPro(t *testing.T) { testDAOChallenge(t, true, true, false) } 453 func TestDAOChallengeNoVsTimeout(t *testing.T) { testDAOChallenge(t, false, false, true) } 454 func TestDAOChallengeProVsTimeout(t *testing.T) { testDAOChallenge(t, true, true, true) } 455 456 func testDAOChallenge(t *testing.T, localForked, remoteForked bool, timeout bool) { 457 // Reduce the DAO handshake challenge timeout 458 if timeout { 459 defer func(old time.Duration) { daoChallengeTimeout = old }(daoChallengeTimeout) 460 daoChallengeTimeout = 500 * time.Millisecond 461 } 462 // Create a DAO aware protocol manager 463 var ( 464 evmux = new(event.TypeMux) 465 pow = ethash.NewFaker() 466 db, _ = ethdb.NewMemDatabase() 467 config = ¶ms.ChainConfig{DAOForkBlock: big.NewInt(1), DAOForkSupport: localForked} 468 gspec = &core.Genesis{Config: config} 469 genesis = gspec.MustCommit(db) 470 blockchain, _ = core.NewBlockChain(db, nil, config, pow, vm.Config{}) 471 ) 472 pm, err := NewProtocolManager(config, downloader.FullSync, DefaultConfig.NetworkId, evmux, new(testTxPool), pow, blockchain, db) 473 if err != nil { 474 t.Fatalf("failed to start test protocol manager: %v", err) 475 } 476 pm.Start(1000) 477 defer pm.Stop() 478 479 // Connect a new peer and check that we receive the DAO challenge 480 peer, _ := newTestPeer("peer", eth63, pm, true) 481 defer peer.close() 482 483 challenge := &getBlockHeadersData{ 484 Origin: hashOrNumber{Number: config.DAOForkBlock.Uint64()}, 485 Amount: 1, 486 Skip: 0, 487 Reverse: false, 488 } 489 if err := p2p.ExpectMsg(peer.app, GetBlockHeadersMsg, challenge); err != nil { 490 t.Fatalf("challenge mismatch: %v", err) 491 } 492 // Create a block to reply to the challenge if no timeout is simulated 493 if !timeout { 494 blocks, _ := core.GenerateChain(¶ms.ChainConfig{}, genesis, ethash.NewFaker(), db, 1, func(i int, block *core.BlockGen) { 495 if remoteForked { 496 block.SetExtra(params.DAOForkBlockExtra) 497 } 498 }) 499 if err := p2p.Send(peer.app, BlockHeadersMsg, []*types.Header{blocks[0].Header()}); err != nil { 500 t.Fatalf("failed to answer challenge: %v", err) 501 } 502 time.Sleep(100 * time.Millisecond) // Sleep to avoid the verification racing with the drops 503 } else { 504 // Otherwise wait until the test timeout passes 505 time.Sleep(daoChallengeTimeout + 500*time.Millisecond) 506 } 507 // Verify that depending on fork side, the remote peer is maintained or dropped 508 if localForked == remoteForked && !timeout { 509 if peers := pm.peers.Len(); peers != 1 { 510 t.Fatalf("peer count mismatch: have %d, want %d", peers, 1) 511 } 512 } else { 513 if peers := pm.peers.Len(); peers != 0 { 514 t.Fatalf("peer count mismatch: have %d, want %d", peers, 0) 515 } 516 } 517 }