github.com/platonnetwork/platon-go@v0.7.6/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 "encoding/binary" 21 "math" 22 "math/big" 23 "math/rand" 24 "testing" 25 26 "github.com/PlatONnetwork/PlatON-Go/common" 27 "github.com/PlatONnetwork/PlatON-Go/core" 28 "github.com/PlatONnetwork/PlatON-Go/core/snapshotdb" 29 "github.com/PlatONnetwork/PlatON-Go/core/state" 30 "github.com/PlatONnetwork/PlatON-Go/core/types" 31 "github.com/PlatONnetwork/PlatON-Go/crypto" 32 "github.com/PlatONnetwork/PlatON-Go/eth/downloader" 33 "github.com/PlatONnetwork/PlatON-Go/ethdb" 34 "github.com/PlatONnetwork/PlatON-Go/p2p" 35 "github.com/PlatONnetwork/PlatON-Go/params" 36 ) 37 38 // Tests that protocol versions and modes of operations are matched up properly. 39 func TestProtocolCompatibility(t *testing.T) { 40 // Define the compatibility chart 41 tests := []struct { 42 version uint 43 mode downloader.SyncMode 44 compatible bool 45 }{ 46 {61, downloader.FullSync, true}, {62, downloader.FullSync, true}, {63, downloader.FullSync, true}, 47 {61, downloader.FastSync, false}, {62, downloader.FastSync, false}, {63, downloader.FastSync, true}, 48 } 49 // Make sure anything we screw up is restored 50 backup := ProtocolVersions 51 defer func() { ProtocolVersions = backup }() 52 // Try all available compatibility configs and check for errors 53 for i, tt := range tests { 54 ProtocolVersions = []uint{tt.version} 55 //db := ethdb.NewMemDatabase() 56 pm, _, err := newTestProtocolManager(tt.mode, 0, nil, nil) 57 if pm != nil { 58 defer pm.Stop() 59 } 60 if (err == nil && !tt.compatible) || (err != nil && tt.compatible) { 61 t.Errorf("test %d: compatibility mismatch: have error %v, want compatibility %v", i, err, tt.compatible) 62 } 63 } 64 } 65 66 // Tests that block headers can be retrieved from a remote chain based on user queries. 67 func TestGetBlockHeaders62(t *testing.T) { testGetBlockHeaders(t, 62) } 68 69 func TestGetBlockHeaders63(t *testing.T) { testGetBlockHeaders(t, 63) } 70 71 func testGetBlockHeaders(t *testing.T, protocol int) { 72 //db := ethdb.NewMemDatabase() 73 pm, _ := newTestProtocolManagerMust(t, downloader.FullSync, downloader.MaxHashFetch+15, nil, nil) 74 peer, _ := newTestPeer("peer", protocol, pm, true) 75 defer peer.close() 76 77 // Create a "random" unknown hash for testing 78 var unknown common.Hash 79 for i := range unknown { 80 unknown[i] = byte(i) 81 } 82 // Create a batch of tests for various scenarios 83 limit := uint64(downloader.MaxHeaderFetch) 84 tests := []struct { 85 query *getBlockHeadersData // The query to execute for header retrieval 86 expect []common.Hash // The hashes of the block whose headers are expected 87 }{ 88 // A single random block should be retrievable by hash and number too 89 { 90 &getBlockHeadersData{Origin: hashOrNumber{Hash: pm.blockchain.GetBlockByNumber(limit / 2).Hash()}, Amount: 1}, 91 []common.Hash{pm.blockchain.GetBlockByNumber(limit / 2).Hash()}, 92 }, { 93 &getBlockHeadersData{Origin: hashOrNumber{Number: limit / 2}, Amount: 1}, 94 []common.Hash{pm.blockchain.GetBlockByNumber(limit / 2).Hash()}, 95 }, 96 // Multiple headers should be retrievable in both directions 97 { 98 &getBlockHeadersData{Origin: hashOrNumber{Number: limit / 2}, Amount: 3}, 99 []common.Hash{ 100 pm.blockchain.GetBlockByNumber(limit / 2).Hash(), 101 pm.blockchain.GetBlockByNumber(limit/2 + 1).Hash(), 102 pm.blockchain.GetBlockByNumber(limit/2 + 2).Hash(), 103 }, 104 }, { 105 &getBlockHeadersData{Origin: hashOrNumber{Number: limit / 2}, Amount: 3, Reverse: true}, 106 []common.Hash{ 107 pm.blockchain.GetBlockByNumber(limit / 2).Hash(), 108 pm.blockchain.GetBlockByNumber(limit/2 - 1).Hash(), 109 pm.blockchain.GetBlockByNumber(limit/2 - 2).Hash(), 110 }, 111 }, 112 // Multiple headers with skip lists should be retrievable 113 { 114 &getBlockHeadersData{Origin: hashOrNumber{Number: limit / 2}, Skip: 3, Amount: 3}, 115 []common.Hash{ 116 pm.blockchain.GetBlockByNumber(limit / 2).Hash(), 117 pm.blockchain.GetBlockByNumber(limit/2 + 4).Hash(), 118 pm.blockchain.GetBlockByNumber(limit/2 + 8).Hash(), 119 }, 120 }, { 121 &getBlockHeadersData{Origin: hashOrNumber{Number: limit / 2}, Skip: 3, Amount: 3, Reverse: true}, 122 []common.Hash{ 123 pm.blockchain.GetBlockByNumber(limit / 2).Hash(), 124 pm.blockchain.GetBlockByNumber(limit/2 - 4).Hash(), 125 pm.blockchain.GetBlockByNumber(limit/2 - 8).Hash(), 126 }, 127 }, 128 // The chain endpoints should be retrievable 129 { 130 &getBlockHeadersData{Origin: hashOrNumber{Number: 0}, Amount: 1}, 131 []common.Hash{pm.blockchain.GetBlockByNumber(0).Hash()}, 132 }, { 133 &getBlockHeadersData{Origin: hashOrNumber{Number: pm.blockchain.CurrentBlock().NumberU64()}, Amount: 1}, 134 []common.Hash{pm.blockchain.CurrentBlock().Hash()}, 135 }, 136 // Ensure protocol limits are honored 137 { 138 &getBlockHeadersData{Origin: hashOrNumber{Number: pm.blockchain.CurrentBlock().NumberU64() - 1}, Amount: limit + 10, Reverse: true}, 139 pm.blockchain.GetBlockHashesFromHash(pm.blockchain.CurrentBlock().Hash(), limit), 140 }, 141 // Check that requesting more than available is handled gracefully 142 { 143 &getBlockHeadersData{Origin: hashOrNumber{Number: pm.blockchain.CurrentBlock().NumberU64() - 4}, Skip: 3, Amount: 3}, 144 []common.Hash{ 145 pm.blockchain.GetBlockByNumber(pm.blockchain.CurrentBlock().NumberU64() - 4).Hash(), 146 pm.blockchain.GetBlockByNumber(pm.blockchain.CurrentBlock().NumberU64()).Hash(), 147 }, 148 }, { 149 &getBlockHeadersData{Origin: hashOrNumber{Number: 4}, Skip: 3, Amount: 3, Reverse: true}, 150 []common.Hash{ 151 pm.blockchain.GetBlockByNumber(4).Hash(), 152 pm.blockchain.GetBlockByNumber(0).Hash(), 153 }, 154 }, 155 // Check that requesting more than available is handled gracefully, even if mid skip 156 { 157 &getBlockHeadersData{Origin: hashOrNumber{Number: pm.blockchain.CurrentBlock().NumberU64() - 4}, Skip: 2, Amount: 3}, 158 []common.Hash{ 159 pm.blockchain.GetBlockByNumber(pm.blockchain.CurrentBlock().NumberU64() - 4).Hash(), 160 pm.blockchain.GetBlockByNumber(pm.blockchain.CurrentBlock().NumberU64() - 1).Hash(), 161 }, 162 }, { 163 &getBlockHeadersData{Origin: hashOrNumber{Number: 4}, Skip: 2, Amount: 3, Reverse: true}, 164 []common.Hash{ 165 pm.blockchain.GetBlockByNumber(4).Hash(), 166 pm.blockchain.GetBlockByNumber(1).Hash(), 167 }, 168 }, 169 // Check a corner case where requesting more can iterate past the endpoints 170 { 171 &getBlockHeadersData{Origin: hashOrNumber{Number: 2}, Amount: 5, Reverse: true}, 172 []common.Hash{ 173 pm.blockchain.GetBlockByNumber(2).Hash(), 174 pm.blockchain.GetBlockByNumber(1).Hash(), 175 pm.blockchain.GetBlockByNumber(0).Hash(), 176 }, 177 }, 178 // Check a corner case where skipping overflow loops back into the chain start 179 { 180 &getBlockHeadersData{Origin: hashOrNumber{Hash: pm.blockchain.GetBlockByNumber(3).Hash()}, Amount: 2, Reverse: false, Skip: math.MaxUint64 - 1}, 181 []common.Hash{ 182 pm.blockchain.GetBlockByNumber(3).Hash(), 183 }, 184 }, 185 // Check a corner case where skipping overflow loops back to the same header 186 { 187 &getBlockHeadersData{Origin: hashOrNumber{Hash: pm.blockchain.GetBlockByNumber(1).Hash()}, Amount: 2, Reverse: false, Skip: math.MaxUint64}, 188 []common.Hash{ 189 pm.blockchain.GetBlockByNumber(1).Hash(), 190 }, 191 }, 192 // Check that non existing headers aren't returned 193 { 194 &getBlockHeadersData{Origin: hashOrNumber{Hash: unknown}, Amount: 1}, 195 []common.Hash{}, 196 }, { 197 &getBlockHeadersData{Origin: hashOrNumber{Number: pm.blockchain.CurrentBlock().NumberU64() + 1}, Amount: 1}, 198 []common.Hash{}, 199 }, 200 } 201 // Run each of the tests and verify the results against the chain 202 for i, tt := range tests { 203 // Collect the headers to expect in the response 204 headers := []*types.Header{} 205 for _, hash := range tt.expect { 206 headers = append(headers, pm.blockchain.GetBlockByHash(hash).Header()) 207 } 208 // Send the hash request and verify the response 209 p2p.Send(peer.app, 0x03, tt.query) 210 if err := p2p.ExpectMsg(peer.app, 0x04, headers); err != nil { 211 t.Errorf("test %d: headers mismatch: %v", i, err) 212 } 213 // If the test used number origins, repeat with hashes as the too 214 if tt.query.Origin.Hash == (common.Hash{}) { 215 if origin := pm.blockchain.GetBlockByNumber(tt.query.Origin.Number); origin != nil { 216 tt.query.Origin.Hash, tt.query.Origin.Number = origin.Hash(), 0 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 } 224 } 225 } 226 227 // Tests that block contents can be retrieved from a remote chain based on their hashes. 228 func TestGetBlockBodies62(t *testing.T) { testGetBlockBodies(t, 62) } 229 230 func TestGetBlockBodies63(t *testing.T) { testGetBlockBodies(t, 63) } 231 232 func testGetBlockBodies(t *testing.T, protocol int) { 233 pm, _ := newTestProtocolManagerMust(t, downloader.FullSync, downloader.MaxBlockFetch+15, nil, nil) 234 peer, _ := newTestPeer("peer", protocol, pm, true) 235 defer peer.close() 236 237 // Create a batch of tests for various scenarios 238 limit := downloader.MaxBlockFetch 239 tests := []struct { 240 random int // Number of blocks to fetch randomly from the chain 241 explicit []common.Hash // Explicitly requested blocks 242 available []bool // Availability of explicitly requested blocks 243 expected int // Total number of existing blocks to expect 244 }{ 245 {1, nil, nil, 1}, // A single random block should be retrievable 246 {10, nil, nil, 10}, // Multiple random blocks should be retrievable 247 {limit, nil, nil, limit}, // The maximum possible blocks should be retrievable 248 {limit + 1, nil, nil, limit}, // No more than the possible block count should be returned 249 {0, []common.Hash{pm.blockchain.Genesis().Hash()}, []bool{true}, 1}, // The genesis block should be retrievable 250 {0, []common.Hash{pm.blockchain.CurrentBlock().Hash()}, []bool{true}, 1}, // The chains head block should be retrievable 251 {0, []common.Hash{{}}, []bool{false}, 0}, // A non existent block should not be returned 252 253 // Existing and non-existing blocks interleaved should not cause problems 254 {0, []common.Hash{ 255 {}, 256 pm.blockchain.GetBlockByNumber(1).Hash(), 257 {}, 258 pm.blockchain.GetBlockByNumber(10).Hash(), 259 {}, 260 pm.blockchain.GetBlockByNumber(100).Hash(), 261 {}, 262 }, []bool{false, true, false, true, false, true, false}, 3}, 263 } 264 // Run each of the tests and verify the results against the chain 265 for i, tt := range tests { 266 // Collect the hashes to request, and the response to expect 267 hashes, seen := []common.Hash{}, make(map[int64]bool) 268 bodies := []*blockBody{} 269 270 for j := 0; j < tt.random; j++ { 271 for { 272 num := rand.Int63n(int64(pm.blockchain.CurrentBlock().NumberU64())) 273 if !seen[num] { 274 seen[num] = true 275 276 block := pm.blockchain.GetBlockByNumber(uint64(num)) 277 hashes = append(hashes, block.Hash()) 278 if len(bodies) < tt.expected { 279 bodies = append(bodies, &blockBody{Transactions: block.Transactions()}) 280 } 281 break 282 } 283 } 284 } 285 for j, hash := range tt.explicit { 286 hashes = append(hashes, hash) 287 if tt.available[j] && len(bodies) < tt.expected { 288 block := pm.blockchain.GetBlockByHash(hash) 289 bodies = append(bodies, &blockBody{Transactions: block.Transactions()}) 290 } 291 } 292 // Send the hash request and verify the response 293 p2p.Send(peer.app, 0x05, hashes) 294 if err := p2p.ExpectMsg(peer.app, 0x06, bodies); err != nil { 295 t.Errorf("test %d: bodies mismatch: %v", i, err) 296 } 297 } 298 } 299 300 func newSnapshotdb() (snapshotdb.DB, error) { 301 db := snapshotdb.Instance() 302 highth := big.NewInt(100) 303 if err := db.SetCurrent(common.ZeroHash, *highth, *highth); err != nil { 304 return nil, err 305 } 306 var m [][2][]byte 307 for i := 0; i < 1028; i++ { 308 b := make([]byte, 8) 309 binary.LittleEndian.PutUint64(b, rand.Uint64()) 310 m = append(m, [2][]byte{b, b}) 311 } 312 if err := db.WriteBaseDB(m); err != nil { 313 return nil, err 314 } 315 return db, nil 316 } 317 318 func TestGetOriginAndPivotMsg(t *testing.T) { 319 // log.Root().SetHandler(log.CallerFileHandler(log.LvlFilterHandler(log.Lvl(3), log.StreamHandler(os.Stderr, log.TerminalFormat(true))))) 320 321 pm, _ := newTestProtocolManagerMust(t, downloader.FastSync, downloader.MaxBlockFetch+15, nil, nil) 322 peer, _ := newTestPeer("peer", 63, pm, true) 323 db, err := newSnapshotdb() 324 if err != nil { 325 t.Error(err) 326 return 327 } 328 defer func() { 329 peer.close() 330 db.Clear() 331 }() 332 333 if err := p2p.Send(peer.app, GetOriginAndPivotMsg, pm.blockchain.CurrentBlock().Header().Number.Uint64()); err != nil { 334 t.Error(err) 335 return 336 } 337 data := make([]*types.Header, 0) 338 339 oHead := pm.blockchain.GetHeaderByNumber(pm.blockchain.CurrentBlock().Header().Number.Uint64()) 340 pivot, err := db.BaseNum() 341 if err != nil { 342 t.Error(err) 343 return 344 } 345 pHead := pm.blockchain.GetHeaderByNumber(pivot.Uint64()) 346 data = append(data, oHead, pHead) 347 if err := p2p.ExpectMsg(peer.app, OriginAndPivotMsg, &data); err != nil { 348 t.Errorf("TestGetOriginAndPivotMsg : data mismatch: %v", err) 349 } 350 } 351 352 func TestGetPPOSStorageMsg(t *testing.T) { 353 // log.Root().SetHandler(log.CallerFileHandler(log.LvlFilterHandler(log.Lvl(4), log.StreamHandler(os.Stderr, log.TerminalFormat(true))))) 354 355 pm, _ := newTestProtocolManagerMust(t, downloader.FullSync, downloader.MaxBlockFetch+15, nil, nil) 356 peer, _ := newTestPeer("peer", 63, pm, true) 357 db, err := newSnapshotdb() 358 if err != nil { 359 t.Error(err) 360 return 361 } 362 defer func() { 363 peer.close() 364 db.Clear() 365 }() 366 if err := p2p.Send(peer.app, GetPPOSStorageMsg, []interface{}{}); err != nil { 367 t.Error(err) 368 return 369 } 370 var data PPOSInfo 371 msg, err := peer.app.ReadMsg() 372 if err != nil { 373 t.Error(err) 374 return 375 } 376 if err := msg.Decode(&data); err != nil { 377 t.Error(err) 378 return 379 } 380 if data.Pivot.Number.Int64() != 100 { 381 t.Error("Pivot num is wrong") 382 } 383 if data.Latest.Number.Int64() != int64(downloader.MaxBlockFetch+15) { 384 t.Error("latest num is wrong") 385 } 386 var data2 PPOSStorage 387 388 for { 389 msg, err := peer.app.ReadMsg() 390 if err != nil { 391 t.Error(err) 392 return 393 } 394 if err := msg.Decode(&data2); err != nil { 395 t.Error(err) 396 return 397 } 398 if data2.Last { 399 break 400 } 401 } 402 } 403 404 // Tests that the node state database can be retrieved based on hashes. 405 func TestGetNodeData63(t *testing.T) { testGetNodeData(t, 63) } 406 407 func testGetNodeData(t *testing.T, protocol int) { 408 // Define three accounts to simulate transactions with 409 acc1Key, _ := crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a") 410 acc2Key, _ := crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee") 411 acc1Addr := crypto.PubkeyToAddress(acc1Key.PublicKey) 412 acc2Addr := crypto.PubkeyToAddress(acc2Key.PublicKey) 413 //chanid := new(big.Int) 414 signer := types.NewEIP155Signer(big.NewInt(1)) 415 // Create a chain generator with some simple transactions (blatantly stolen from @fjl/chain_markets_test) 416 generator := func(i int, block *core.BlockGen) { 417 switch i { 418 case 0: 419 // In block 1, the test bank sends account #1 some ether. 420 tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBank), acc1Addr, big.NewInt(10000), params.TxGas, nil, nil), signer, testBankKey) 421 block.AddTx(tx) 422 case 1: 423 // In block 2, the test bank sends some more ether to account #1. 424 // acc1Addr passes it on to account #2. 425 tx1, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBank), acc1Addr, big.NewInt(1000), params.TxGas, nil, nil), signer, testBankKey) 426 tx2, _ := types.SignTx(types.NewTransaction(block.TxNonce(acc1Addr), acc2Addr, big.NewInt(1000), params.TxGas, nil, nil), signer, acc1Key) 427 block.AddTx(tx1) 428 block.AddTx(tx2) 429 case 2: 430 // Block 3 is empty but was mined by account #2. 431 block.SetCoinbase(acc2Addr) 432 block.SetExtra([]byte("yeehaw")) 433 case 3: 434 // Block 4 includes blocks 2 and 3 as uncle headers (with modified extra data). 435 b2 := block.PrevBlock(1).Header() 436 b2.Extra = []byte("foo") 437 b3 := block.PrevBlock(2).Header() 438 b3.Extra = []byte("foo") 439 } 440 } 441 // Assemble the test environment 442 pm, db := newTestProtocolManagerMust(t, downloader.FullSync, 4, generator, nil) 443 peer, _ := newTestPeer("peer", protocol, pm, true) 444 defer peer.close() 445 446 // Fetch for now the entire chain db 447 hashes := []common.Hash{} 448 for _, key := range db.Keys() { 449 if len(key) == len(common.Hash{}) { 450 hashes = append(hashes, common.BytesToHash(key)) 451 } 452 } 453 p2p.Send(peer.app, 0x0d, hashes) 454 msg, err := peer.app.ReadMsg() 455 if err != nil { 456 t.Fatalf("failed to read node data response: %v", err) 457 } 458 if msg.Code != 0x0e { 459 t.Fatalf("response packet code mismatch: have %x, want %x", msg.Code, 0x0c) 460 } 461 var data [][]byte 462 if err := msg.Decode(&data); err != nil { 463 t.Fatalf("failed to decode response node data: %v", err) 464 } 465 // Verify that all hashes correspond to the requested data, and reconstruct a state tree 466 for i, want := range hashes { 467 if hash := crypto.Keccak256Hash(data[i]); hash != want { 468 t.Errorf("data hash mismatch: have %x, want %x", hash, want) 469 } 470 } 471 statedb := ethdb.NewMemDatabase() 472 for i := 0; i < len(data); i++ { 473 statedb.Put(hashes[i].Bytes(), data[i]) 474 } 475 accounts := []common.Address{testBank, acc1Addr, acc2Addr} 476 for i := uint64(0); i <= pm.blockchain.CurrentBlock().NumberU64(); i++ { 477 trie, _ := state.New(pm.blockchain.GetBlockByNumber(i).Root(), state.NewDatabase(statedb)) 478 479 for j, acc := range accounts { 480 state, _ := pm.blockchain.State() 481 bw := state.GetBalance(acc) 482 bh := trie.GetBalance(acc) 483 484 if (bw != nil && bh == nil) || (bw == nil && bh != nil) { 485 t.Errorf("test %d, account %d: balance mismatch: have %v, want %v", i, j, bh, bw) 486 } 487 if bw != nil && bh != nil && bw.Cmp(bw) != 0 { 488 t.Errorf("test %d, account %d: balance mismatch: have %v, want %v", i, j, bh, bw) 489 } 490 } 491 } 492 } 493 494 // Tests that the transaction receipts can be retrieved based on hashes. 495 func TestGetReceipt63(t *testing.T) { testGetReceipt(t, 63) } 496 497 func testGetReceipt(t *testing.T, protocol int) { 498 // Define three accounts to simulate transactions with 499 acc1Key, _ := crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a") 500 acc2Key, _ := crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee") 501 acc1Addr := crypto.PubkeyToAddress(acc1Key.PublicKey) 502 acc2Addr := crypto.PubkeyToAddress(acc2Key.PublicKey) 503 504 signer := types.NewEIP155Signer(big.NewInt(1)) 505 // Create a chain generator with some simple transactions (blatantly stolen from @fjl/chain_markets_test) 506 generator := func(i int, block *core.BlockGen) { 507 switch i { 508 case 0: 509 // In block 1, the test bank sends account #1 some ether. 510 tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBank), acc1Addr, big.NewInt(10000), params.TxGas, nil, nil), signer, testBankKey) 511 block.AddTx(tx) 512 case 1: 513 // In block 2, the test bank sends some more ether to account #1. 514 // acc1Addr passes it on to account #2. 515 tx1, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBank), acc1Addr, big.NewInt(1000), params.TxGas, nil, nil), signer, testBankKey) 516 tx2, _ := types.SignTx(types.NewTransaction(block.TxNonce(acc1Addr), acc2Addr, big.NewInt(1000), params.TxGas, nil, nil), signer, acc1Key) 517 block.AddTx(tx1) 518 block.AddTx(tx2) 519 case 2: 520 // Block 3 is empty but was mined by account #2. 521 block.SetCoinbase(acc2Addr) 522 block.SetExtra([]byte("yeehaw")) 523 case 3: 524 // Block 4 includes blocks 2 and 3 as uncle headers (with modified extra data). 525 b2 := block.PrevBlock(1).Header() 526 b2.Extra = []byte("foo") 527 b3 := block.PrevBlock(2).Header() 528 b3.Extra = []byte("foo") 529 } 530 } 531 // Assemble the test environment 532 pm, _ := newTestProtocolManagerMust(t, downloader.FullSync, 4, generator, nil) 533 peer, _ := newTestPeer("peer", protocol, pm, true) 534 defer peer.close() 535 536 // Collect the hashes to request, and the response to expect 537 hashes, receipts := []common.Hash{}, []types.Receipts{} 538 for i := uint64(0); i <= pm.blockchain.CurrentBlock().NumberU64(); i++ { 539 block := pm.blockchain.GetBlockByNumber(i) 540 541 hashes = append(hashes, block.Hash()) 542 receipts = append(receipts, pm.blockchain.GetReceiptsByHash(block.Hash())) 543 } 544 // Send the hash request and verify the response 545 p2p.Send(peer.app, 0x0f, hashes) 546 if err := p2p.ExpectMsg(peer.app, 0x10, receipts); err != nil { 547 t.Errorf("receipts mismatch: %v", err) 548 } 549 }