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