github.com/karalabe/go-ethereum@v0.8.5/eth/block_pool_test.go (about) 1 package eth 2 3 import ( 4 "fmt" 5 "log" 6 "math/big" 7 "os" 8 "sync" 9 "testing" 10 "time" 11 12 "github.com/ethereum/go-ethereum/core/types" 13 "github.com/ethereum/go-ethereum/crypto" 14 "github.com/ethereum/go-ethereum/ethutil" 15 ethlogger "github.com/ethereum/go-ethereum/logger" 16 "github.com/ethereum/go-ethereum/pow" 17 ) 18 19 const waitTimeout = 60 // seconds 20 21 var logsys = ethlogger.NewStdLogSystem(os.Stdout, log.LstdFlags, ethlogger.LogLevel(ethlogger.DebugDetailLevel)) 22 23 var ini = false 24 25 func logInit() { 26 if !ini { 27 ethlogger.AddLogSystem(logsys) 28 ini = true 29 } 30 } 31 32 // test helpers 33 func arrayEq(a, b []int) bool { 34 if len(a) != len(b) { 35 return false 36 } 37 for i := range a { 38 if a[i] != b[i] { 39 return false 40 } 41 } 42 return true 43 } 44 45 type intToHash map[int][]byte 46 47 type hashToInt map[string]int 48 49 // hashPool is a test helper, that allows random hashes to be referred to by integers 50 type testHashPool struct { 51 intToHash 52 hashToInt 53 lock sync.Mutex 54 } 55 56 func newHash(i int) []byte { 57 return crypto.Sha3([]byte(string(i))) 58 } 59 60 func (self *testHashPool) indexesToHashes(indexes []int) (hashes [][]byte) { 61 self.lock.Lock() 62 defer self.lock.Unlock() 63 for _, i := range indexes { 64 hash, found := self.intToHash[i] 65 if !found { 66 hash = newHash(i) 67 self.intToHash[i] = hash 68 self.hashToInt[string(hash)] = i 69 } 70 hashes = append(hashes, hash) 71 } 72 return 73 } 74 75 func (self *testHashPool) hashesToIndexes(hashes [][]byte) (indexes []int) { 76 self.lock.Lock() 77 defer self.lock.Unlock() 78 for _, hash := range hashes { 79 i, found := self.hashToInt[string(hash)] 80 if !found { 81 i = -1 82 } 83 indexes = append(indexes, i) 84 } 85 return 86 } 87 88 // test blockChain is an integer trie 89 type blockChain map[int][]int 90 91 // blockPoolTester provides the interface between tests and a blockPool 92 // 93 // refBlockChain is used to guide which blocks will be accepted as valid 94 // blockChain gives the current state of the blockchain and 95 // accumulates inserts so that we can check the resulting chain 96 type blockPoolTester struct { 97 hashPool *testHashPool 98 lock sync.RWMutex 99 refBlockChain blockChain 100 blockChain blockChain 101 blockPool *BlockPool 102 t *testing.T 103 } 104 105 func newTestBlockPool(t *testing.T) (hashPool *testHashPool, blockPool *BlockPool, b *blockPoolTester) { 106 hashPool = &testHashPool{intToHash: make(intToHash), hashToInt: make(hashToInt)} 107 b = &blockPoolTester{ 108 t: t, 109 hashPool: hashPool, 110 blockChain: make(blockChain), 111 refBlockChain: make(blockChain), 112 } 113 b.blockPool = NewBlockPool(b.hasBlock, b.insertChain, b.verifyPoW) 114 blockPool = b.blockPool 115 return 116 } 117 118 func (self *blockPoolTester) Errorf(format string, params ...interface{}) { 119 fmt.Printf(format+"\n", params...) 120 self.t.Errorf(format, params...) 121 } 122 123 // blockPoolTester implements the 3 callbacks needed by the blockPool: 124 // hasBlock, insetChain, verifyPoW 125 func (self *blockPoolTester) hasBlock(block []byte) (ok bool) { 126 self.lock.RLock() 127 defer self.lock.RUnlock() 128 indexes := self.hashPool.hashesToIndexes([][]byte{block}) 129 i := indexes[0] 130 _, ok = self.blockChain[i] 131 fmt.Printf("has block %v (%x...): %v\n", i, block[0:4], ok) 132 return 133 } 134 135 func (self *blockPoolTester) insertChain(blocks types.Blocks) error { 136 self.lock.RLock() 137 defer self.lock.RUnlock() 138 var parent, child int 139 var children, refChildren []int 140 var ok bool 141 for _, block := range blocks { 142 child = self.hashPool.hashesToIndexes([][]byte{block.Hash()})[0] 143 _, ok = self.blockChain[child] 144 if ok { 145 fmt.Printf("block %v already in blockchain\n", child) 146 continue // already in chain 147 } 148 parent = self.hashPool.hashesToIndexes([][]byte{block.ParentHeaderHash})[0] 149 children, ok = self.blockChain[parent] 150 if !ok { 151 return fmt.Errorf("parent %v not in blockchain ", parent) 152 } 153 ok = false 154 var found bool 155 refChildren, found = self.refBlockChain[parent] 156 if found { 157 for _, c := range refChildren { 158 if c == child { 159 ok = true 160 } 161 } 162 if !ok { 163 return fmt.Errorf("invalid block %v", child) 164 } 165 } else { 166 ok = true 167 } 168 if ok { 169 // accept any blocks if parent not in refBlockChain 170 fmt.Errorf("blockchain insert %v -> %v\n", parent, child) 171 self.blockChain[parent] = append(children, child) 172 self.blockChain[child] = nil 173 } 174 } 175 return nil 176 } 177 178 func (self *blockPoolTester) verifyPoW(pblock pow.Block) bool { 179 return true 180 } 181 182 // test helper that compares the resulting blockChain to the desired blockChain 183 func (self *blockPoolTester) checkBlockChain(blockChain map[int][]int) { 184 for k, v := range self.blockChain { 185 fmt.Printf("got: %v -> %v\n", k, v) 186 } 187 for k, v := range blockChain { 188 fmt.Printf("expected: %v -> %v\n", k, v) 189 } 190 if len(blockChain) != len(self.blockChain) { 191 self.Errorf("blockchain incorrect (zlength differ)") 192 } 193 for k, v := range blockChain { 194 vv, ok := self.blockChain[k] 195 if !ok || !arrayEq(v, vv) { 196 self.Errorf("blockchain incorrect on %v -> %v (!= %v)", k, vv, v) 197 } 198 } 199 } 200 201 // 202 203 // peerTester provides the peer callbacks for the blockPool 204 // it registers actual callbacks so that result can be compared to desired behaviour 205 // provides helper functions to mock the protocol calls to the blockPool 206 type peerTester struct { 207 blockHashesRequests []int 208 blocksRequests [][]int 209 blocksRequestsMap map[int]bool 210 peerErrors []int 211 blockPool *BlockPool 212 hashPool *testHashPool 213 lock sync.RWMutex 214 id string 215 td int 216 currentBlock int 217 t *testing.T 218 } 219 220 // peerTester constructor takes hashPool and blockPool from the blockPoolTester 221 func (self *blockPoolTester) newPeer(id string, td int, cb int) *peerTester { 222 return &peerTester{ 223 id: id, 224 td: td, 225 currentBlock: cb, 226 hashPool: self.hashPool, 227 blockPool: self.blockPool, 228 t: self.t, 229 blocksRequestsMap: make(map[int]bool), 230 } 231 } 232 233 func (self *peerTester) Errorf(format string, params ...interface{}) { 234 fmt.Printf(format+"\n", params...) 235 self.t.Errorf(format, params...) 236 } 237 238 // helper to compare actual and expected block requests 239 func (self *peerTester) checkBlocksRequests(blocksRequests ...[]int) { 240 if len(blocksRequests) > len(self.blocksRequests) { 241 self.Errorf("blocks requests incorrect (length differ)\ngot %v\nexpected %v", self.blocksRequests, blocksRequests) 242 } else { 243 for i, rr := range blocksRequests { 244 r := self.blocksRequests[i] 245 if !arrayEq(r, rr) { 246 self.Errorf("blocks requests incorrect\ngot %v\nexpected %v", self.blocksRequests, blocksRequests) 247 } 248 } 249 } 250 } 251 252 // helper to compare actual and expected block hash requests 253 func (self *peerTester) checkBlockHashesRequests(blocksHashesRequests ...int) { 254 rr := blocksHashesRequests 255 self.lock.RLock() 256 r := self.blockHashesRequests 257 self.lock.RUnlock() 258 if len(r) != len(rr) { 259 self.Errorf("block hashes requests incorrect (length differ)\ngot %v\nexpected %v", r, rr) 260 } else { 261 if !arrayEq(r, rr) { 262 self.Errorf("block hashes requests incorrect\ngot %v\nexpected %v", r, rr) 263 } 264 } 265 } 266 267 // waiter function used by peer.AddBlocks 268 // blocking until requests appear 269 // since block requests are sent to any random peers 270 // block request map is shared between peers 271 // times out after a period 272 func (self *peerTester) waitBlocksRequests(blocksRequest ...int) { 273 timeout := time.After(waitTimeout * time.Second) 274 rr := blocksRequest 275 for { 276 self.lock.RLock() 277 r := self.blocksRequestsMap 278 fmt.Printf("[%s] blocks request check %v (%v)\n", self.id, rr, r) 279 i := 0 280 for i = 0; i < len(rr); i++ { 281 _, ok := r[rr[i]] 282 if !ok { 283 break 284 } 285 } 286 self.lock.RUnlock() 287 288 if i == len(rr) { 289 return 290 } 291 time.Sleep(100 * time.Millisecond) 292 select { 293 case <-timeout: 294 default: 295 } 296 } 297 } 298 299 // waiter function used by peer.AddBlockHashes 300 // blocking until requests appear 301 // times out after a period 302 func (self *peerTester) waitBlockHashesRequests(blocksHashesRequest int) { 303 timeout := time.After(waitTimeout * time.Second) 304 rr := blocksHashesRequest 305 for i := 0; ; { 306 self.lock.RLock() 307 r := self.blockHashesRequests 308 self.lock.RUnlock() 309 fmt.Printf("[%s] block hash request check %v (%v)\n", self.id, rr, r) 310 for ; i < len(r); i++ { 311 if rr == r[i] { 312 return 313 } 314 } 315 time.Sleep(100 * time.Millisecond) 316 select { 317 case <-timeout: 318 default: 319 } 320 } 321 } 322 323 // mocks a simple blockchain 0 (genesis) ... n (head) 324 func (self *blockPoolTester) initRefBlockChain(n int) { 325 for i := 0; i < n; i++ { 326 self.refBlockChain[i] = []int{i + 1} 327 } 328 } 329 330 // peerTester functions that mimic protocol calls to the blockpool 331 // registers the peer with the blockPool 332 func (self *peerTester) AddPeer() bool { 333 hash := self.hashPool.indexesToHashes([]int{self.currentBlock})[0] 334 return self.blockPool.AddPeer(big.NewInt(int64(self.td)), hash, self.id, self.requestBlockHashes, self.requestBlocks, self.peerError) 335 } 336 337 // peer sends blockhashes if and when gets a request 338 func (self *peerTester) AddBlockHashes(indexes ...int) { 339 fmt.Printf("ready to add block hashes %v\n", indexes) 340 341 self.waitBlockHashesRequests(indexes[0]) 342 fmt.Printf("adding block hashes %v\n", indexes) 343 hashes := self.hashPool.indexesToHashes(indexes) 344 i := 1 345 next := func() (hash []byte, ok bool) { 346 if i < len(hashes) { 347 hash = hashes[i] 348 ok = true 349 i++ 350 } 351 return 352 } 353 self.blockPool.AddBlockHashes(next, self.id) 354 } 355 356 // peer sends blocks if and when there is a request 357 // (in the shared request store, not necessarily to a person) 358 func (self *peerTester) AddBlocks(indexes ...int) { 359 hashes := self.hashPool.indexesToHashes(indexes) 360 fmt.Printf("ready to add blocks %v\n", indexes[1:]) 361 self.waitBlocksRequests(indexes[1:]...) 362 fmt.Printf("adding blocks %v \n", indexes[1:]) 363 for i := 1; i < len(hashes); i++ { 364 fmt.Printf("adding block %v %x\n", indexes[i], hashes[i][:4]) 365 self.blockPool.AddBlock(&types.Block{HeaderHash: ethutil.Bytes(hashes[i]), ParentHeaderHash: ethutil.Bytes(hashes[i-1])}, self.id) 366 } 367 } 368 369 // peer callbacks 370 // -1 is special: not found (a hash never seen) 371 // records block hashes requests by the blockPool 372 func (self *peerTester) requestBlockHashes(hash []byte) error { 373 indexes := self.hashPool.hashesToIndexes([][]byte{hash}) 374 fmt.Printf("[%s] blocks hash request %v %x\n", self.id, indexes[0], hash[:4]) 375 self.lock.Lock() 376 defer self.lock.Unlock() 377 self.blockHashesRequests = append(self.blockHashesRequests, indexes[0]) 378 return nil 379 } 380 381 // records block requests by the blockPool 382 func (self *peerTester) requestBlocks(hashes [][]byte) error { 383 indexes := self.hashPool.hashesToIndexes(hashes) 384 fmt.Printf("blocks request %v %x...\n", indexes, hashes[0][:4]) 385 self.lock.Lock() 386 defer self.lock.Unlock() 387 self.blocksRequests = append(self.blocksRequests, indexes) 388 for _, i := range indexes { 389 self.blocksRequestsMap[i] = true 390 } 391 return nil 392 } 393 394 // records the error codes of all the peerErrors found the blockPool 395 func (self *peerTester) peerError(code int, format string, params ...interface{}) { 396 self.peerErrors = append(self.peerErrors, code) 397 } 398 399 // the actual tests 400 func TestAddPeer(t *testing.T) { 401 logInit() 402 _, blockPool, blockPoolTester := newTestBlockPool(t) 403 peer0 := blockPoolTester.newPeer("peer0", 1, 0) 404 peer1 := blockPoolTester.newPeer("peer1", 2, 1) 405 peer2 := blockPoolTester.newPeer("peer2", 3, 2) 406 var peer *peerInfo 407 408 blockPool.Start() 409 410 // pool 411 best := peer0.AddPeer() 412 if !best { 413 t.Errorf("peer0 (TD=1) not accepted as best") 414 } 415 if blockPool.peer.id != "peer0" { 416 t.Errorf("peer0 (TD=1) not set as best") 417 } 418 // peer0.checkBlockHashesRequests(0) 419 420 best = peer2.AddPeer() 421 if !best { 422 t.Errorf("peer2 (TD=3) not accepted as best") 423 } 424 if blockPool.peer.id != "peer2" { 425 t.Errorf("peer2 (TD=3) not set as best") 426 } 427 peer2.waitBlocksRequests(2) 428 429 best = peer1.AddPeer() 430 if best { 431 t.Errorf("peer1 (TD=2) accepted as best") 432 } 433 if blockPool.peer.id != "peer2" { 434 t.Errorf("peer2 (TD=3) not set any more as best") 435 } 436 if blockPool.peer.td.Cmp(big.NewInt(int64(3))) != 0 { 437 t.Errorf("peer1 TD not set") 438 } 439 440 peer2.td = 4 441 peer2.currentBlock = 3 442 best = peer2.AddPeer() 443 if !best { 444 t.Errorf("peer2 (TD=4) not accepted as best") 445 } 446 if blockPool.peer.id != "peer2" { 447 t.Errorf("peer2 (TD=4) not set as best") 448 } 449 if blockPool.peer.td.Cmp(big.NewInt(int64(4))) != 0 { 450 t.Errorf("peer2 TD not updated") 451 } 452 peer2.waitBlocksRequests(3) 453 454 peer1.td = 3 455 peer1.currentBlock = 2 456 best = peer1.AddPeer() 457 if best { 458 t.Errorf("peer1 (TD=3) should not be set as best") 459 } 460 if blockPool.peer.id == "peer1" { 461 t.Errorf("peer1 (TD=3) should not be set as best") 462 } 463 peer, best = blockPool.getPeer("peer1") 464 if peer.td.Cmp(big.NewInt(int64(3))) != 0 { 465 t.Errorf("peer1 TD should be updated") 466 } 467 468 blockPool.RemovePeer("peer2") 469 peer, best = blockPool.getPeer("peer2") 470 if peer != nil { 471 t.Errorf("peer2 not removed") 472 } 473 474 if blockPool.peer.id != "peer1" { 475 t.Errorf("existing peer1 (TD=3) should be set as best peer") 476 } 477 peer1.waitBlocksRequests(2) 478 479 blockPool.RemovePeer("peer1") 480 peer, best = blockPool.getPeer("peer1") 481 if peer != nil { 482 t.Errorf("peer1 not removed") 483 } 484 485 if blockPool.peer.id != "peer0" { 486 t.Errorf("existing peer0 (TD=1) should be set as best peer") 487 } 488 peer0.waitBlocksRequests(0) 489 490 blockPool.RemovePeer("peer0") 491 peer, best = blockPool.getPeer("peer0") 492 if peer != nil { 493 t.Errorf("peer1 not removed") 494 } 495 496 // adding back earlier peer ok 497 peer0.currentBlock = 3 498 best = peer0.AddPeer() 499 if !best { 500 t.Errorf("peer0 (TD=1) should be set as best") 501 } 502 503 if blockPool.peer.id != "peer0" { 504 t.Errorf("peer0 (TD=1) should be set as best") 505 } 506 peer0.waitBlocksRequests(3) 507 508 blockPool.Stop() 509 510 } 511 512 func TestPeerWithKnownBlock(t *testing.T) { 513 logInit() 514 _, blockPool, blockPoolTester := newTestBlockPool(t) 515 blockPoolTester.refBlockChain[0] = nil 516 blockPoolTester.blockChain[0] = nil 517 blockPool.Start() 518 519 peer0 := blockPoolTester.newPeer("0", 1, 0) 520 peer0.AddPeer() 521 522 blockPool.Wait(waitTimeout * time.Second) 523 blockPool.Stop() 524 // no request on known block 525 peer0.checkBlockHashesRequests() 526 } 527 528 func TestPeerWithKnownParentBlock(t *testing.T) { 529 logInit() 530 _, blockPool, blockPoolTester := newTestBlockPool(t) 531 blockPoolTester.initRefBlockChain(1) 532 blockPoolTester.blockChain[0] = nil 533 blockPool.Start() 534 535 peer0 := blockPoolTester.newPeer("0", 1, 1) 536 peer0.AddPeer() 537 peer0.AddBlocks(0, 1) 538 539 blockPool.Wait(waitTimeout * time.Second) 540 blockPool.Stop() 541 peer0.checkBlocksRequests([]int{1}) 542 peer0.checkBlockHashesRequests() 543 blockPoolTester.refBlockChain[1] = []int{} 544 blockPoolTester.checkBlockChain(blockPoolTester.refBlockChain) 545 } 546 547 func TestSimpleChain(t *testing.T) { 548 logInit() 549 _, blockPool, blockPoolTester := newTestBlockPool(t) 550 blockPoolTester.blockChain[0] = nil 551 blockPoolTester.initRefBlockChain(2) 552 553 blockPool.Start() 554 555 peer1 := blockPoolTester.newPeer("peer1", 1, 2) 556 peer1.AddPeer() 557 peer1.AddBlocks(1, 2) 558 go peer1.AddBlockHashes(2, 1, 0) 559 peer1.AddBlocks(0, 1) 560 561 blockPool.Wait(waitTimeout * time.Second) 562 blockPool.Stop() 563 blockPoolTester.refBlockChain[2] = []int{} 564 blockPoolTester.checkBlockChain(blockPoolTester.refBlockChain) 565 } 566 567 func TestChainConnectingWithParentHash(t *testing.T) { 568 logInit() 569 _, blockPool, blockPoolTester := newTestBlockPool(t) 570 blockPoolTester.blockChain[0] = nil 571 blockPoolTester.initRefBlockChain(3) 572 573 blockPool.Start() 574 575 peer1 := blockPoolTester.newPeer("peer1", 1, 3) 576 peer1.AddPeer() 577 go peer1.AddBlocks(2, 3) 578 go peer1.AddBlockHashes(3, 2, 1) 579 peer1.AddBlocks(0, 1, 2) 580 581 blockPool.Wait(waitTimeout * time.Second) 582 blockPool.Stop() 583 blockPoolTester.refBlockChain[3] = []int{} 584 blockPoolTester.checkBlockChain(blockPoolTester.refBlockChain) 585 } 586 587 func TestInvalidBlock(t *testing.T) { 588 logInit() 589 _, blockPool, blockPoolTester := newTestBlockPool(t) 590 blockPoolTester.blockChain[0] = nil 591 blockPoolTester.initRefBlockChain(2) 592 blockPoolTester.refBlockChain[2] = []int{} 593 594 blockPool.Start() 595 596 peer1 := blockPoolTester.newPeer("peer1", 1, 3) 597 peer1.AddPeer() 598 go peer1.AddBlocks(2, 3) 599 go peer1.AddBlockHashes(3, 2, 1, 0) 600 peer1.AddBlocks(0, 1, 2) 601 602 blockPool.Wait(waitTimeout * time.Second) 603 blockPool.Stop() 604 blockPoolTester.refBlockChain[2] = []int{} 605 blockPoolTester.checkBlockChain(blockPoolTester.refBlockChain) 606 if len(peer1.peerErrors) == 1 { 607 if peer1.peerErrors[0] != ErrInvalidBlock { 608 t.Errorf("wrong error, got %v, expected %v", peer1.peerErrors[0], ErrInvalidBlock) 609 } 610 } else { 611 t.Errorf("expected invalid block error, got nothing %v", peer1.peerErrors) 612 } 613 } 614 615 func TestVerifyPoW(t *testing.T) { 616 t.Skip("***FIX*** This test is broken") 617 logInit() 618 _, blockPool, blockPoolTester := newTestBlockPool(t) 619 blockPoolTester.blockChain[0] = nil 620 blockPoolTester.initRefBlockChain(3) 621 first := false 622 blockPoolTester.blockPool.verifyPoW = func(b pow.Block) bool { 623 bb, _ := b.(*types.Block) 624 indexes := blockPoolTester.hashPool.hashesToIndexes([][]byte{bb.Hash()}) 625 if indexes[0] == 2 && !first { 626 first = true 627 return false 628 } else { 629 return true 630 } 631 632 } 633 634 blockPool.Start() 635 636 peer1 := blockPoolTester.newPeer("peer1", 1, 3) 637 peer1.AddPeer() 638 go peer1.AddBlocks(2, 3) 639 go peer1.AddBlockHashes(3, 2, 1, 0) 640 peer1.AddBlocks(0, 1, 2) 641 642 // blockPool.Wait(waitTimeout * time.Second) 643 time.Sleep(1 * time.Second) 644 blockPool.Stop() 645 blockPoolTester.refBlockChain[1] = []int{} 646 delete(blockPoolTester.refBlockChain, 2) 647 blockPoolTester.checkBlockChain(blockPoolTester.refBlockChain) 648 if len(peer1.peerErrors) == 1 { 649 if peer1.peerErrors[0] != ErrInvalidPoW { 650 t.Errorf("wrong error, got %v, expected %v", peer1.peerErrors[0], ErrInvalidPoW) 651 } 652 } else { 653 t.Errorf("expected invalid pow error, got nothing") 654 } 655 } 656 657 func TestMultiSectionChain(t *testing.T) { 658 logInit() 659 _, blockPool, blockPoolTester := newTestBlockPool(t) 660 blockPoolTester.blockChain[0] = nil 661 blockPoolTester.initRefBlockChain(5) 662 663 blockPool.Start() 664 665 peer1 := blockPoolTester.newPeer("peer1", 1, 5) 666 667 peer1.AddPeer() 668 go peer1.AddBlocks(4, 5) 669 go peer1.AddBlockHashes(5, 4, 3) 670 go peer1.AddBlocks(2, 3, 4) 671 go peer1.AddBlockHashes(3, 2, 1, 0) 672 peer1.AddBlocks(0, 1, 2) 673 674 blockPool.Wait(waitTimeout * time.Second) 675 blockPool.Stop() 676 blockPoolTester.refBlockChain[5] = []int{} 677 blockPoolTester.checkBlockChain(blockPoolTester.refBlockChain) 678 } 679 680 func TestNewBlocksOnPartialChain(t *testing.T) { 681 logInit() 682 _, blockPool, blockPoolTester := newTestBlockPool(t) 683 blockPoolTester.blockChain[0] = nil 684 blockPoolTester.initRefBlockChain(7) 685 blockPool.Start() 686 687 peer1 := blockPoolTester.newPeer("peer1", 1, 5) 688 689 peer1.AddPeer() 690 go peer1.AddBlocks(4, 5) // partially complete section 691 go peer1.AddBlockHashes(5, 4, 3) 692 peer1.AddBlocks(3, 4) // partially complete section 693 // peer1 found new blocks 694 peer1.td = 2 695 peer1.currentBlock = 7 696 peer1.AddPeer() 697 go peer1.AddBlocks(6, 7) 698 go peer1.AddBlockHashes(7, 6, 5) 699 go peer1.AddBlocks(2, 3) 700 go peer1.AddBlocks(5, 6) 701 go peer1.AddBlockHashes(3, 2, 1, 0) // tests that hash request from known chain root is remembered 702 peer1.AddBlocks(0, 1, 2) 703 704 blockPool.Wait(waitTimeout * time.Second) 705 blockPool.Stop() 706 blockPoolTester.refBlockChain[7] = []int{} 707 blockPoolTester.checkBlockChain(blockPoolTester.refBlockChain) 708 } 709 710 func TestPeerSwitchUp(t *testing.T) { 711 logInit() 712 _, blockPool, blockPoolTester := newTestBlockPool(t) 713 blockPoolTester.blockChain[0] = nil 714 blockPoolTester.initRefBlockChain(7) 715 716 blockPool.Start() 717 718 peer1 := blockPoolTester.newPeer("peer1", 1, 6) 719 peer2 := blockPoolTester.newPeer("peer2", 2, 7) 720 peer2.blocksRequestsMap = peer1.blocksRequestsMap 721 722 peer1.AddPeer() 723 go peer1.AddBlocks(5, 6) 724 go peer1.AddBlockHashes(6, 5, 4, 3) // 725 peer1.AddBlocks(2, 3) // section partially complete, block 3 will be preserved after peer demoted 726 peer2.AddPeer() // peer2 is promoted as best peer, peer1 is demoted 727 go peer2.AddBlocks(6, 7) 728 go peer2.AddBlockHashes(7, 6) // 729 go peer2.AddBlocks(4, 5) // tests that block request for earlier section is remembered 730 go peer1.AddBlocks(3, 4) // tests that connecting section by demoted peer is remembered and blocks are accepted from demoted peer 731 go peer2.AddBlockHashes(3, 2, 1, 0) // tests that known chain section is activated, hash requests from 3 is remembered 732 peer2.AddBlocks(0, 1, 2) // final blocks linking to blockchain sent 733 734 blockPool.Wait(waitTimeout * time.Second) 735 blockPool.Stop() 736 blockPoolTester.refBlockChain[7] = []int{} 737 blockPoolTester.checkBlockChain(blockPoolTester.refBlockChain) 738 } 739 740 func TestPeerSwitchDown(t *testing.T) { 741 logInit() 742 _, blockPool, blockPoolTester := newTestBlockPool(t) 743 blockPoolTester.blockChain[0] = nil 744 blockPoolTester.initRefBlockChain(6) 745 blockPool.Start() 746 747 peer1 := blockPoolTester.newPeer("peer1", 1, 4) 748 peer2 := blockPoolTester.newPeer("peer2", 2, 6) 749 peer2.blocksRequestsMap = peer1.blocksRequestsMap 750 751 peer2.AddPeer() 752 peer2.AddBlocks(5, 6) // partially complete, section will be preserved 753 go peer2.AddBlockHashes(6, 5, 4) // 754 peer2.AddBlocks(4, 5) // 755 blockPool.RemovePeer("peer2") // peer2 disconnects 756 peer1.AddPeer() // inferior peer1 is promoted as best peer 757 go peer1.AddBlockHashes(4, 3, 2, 1, 0) // 758 go peer1.AddBlocks(3, 4) // tests that section set by demoted peer is remembered and blocks are accepted , this connects the chain sections together 759 peer1.AddBlocks(0, 1, 2, 3) 760 761 blockPool.Wait(waitTimeout * time.Second) 762 blockPool.Stop() 763 blockPoolTester.refBlockChain[6] = []int{} 764 blockPoolTester.checkBlockChain(blockPoolTester.refBlockChain) 765 } 766 767 func TestPeerCompleteSectionSwitchDown(t *testing.T) { 768 logInit() 769 _, blockPool, blockPoolTester := newTestBlockPool(t) 770 blockPoolTester.blockChain[0] = nil 771 blockPoolTester.initRefBlockChain(6) 772 blockPool.Start() 773 774 peer1 := blockPoolTester.newPeer("peer1", 1, 4) 775 peer2 := blockPoolTester.newPeer("peer2", 2, 6) 776 peer2.blocksRequestsMap = peer1.blocksRequestsMap 777 778 peer2.AddPeer() 779 peer2.AddBlocks(5, 6) // partially complete, section will be preserved 780 go peer2.AddBlockHashes(6, 5, 4) // 781 peer2.AddBlocks(3, 4, 5) // complete section 782 blockPool.RemovePeer("peer2") // peer2 disconnects 783 peer1.AddPeer() // inferior peer1 is promoted as best peer 784 peer1.AddBlockHashes(4, 3, 2, 1, 0) // tests that hash request are directly connecting if the head block exists 785 peer1.AddBlocks(0, 1, 2, 3) 786 787 blockPool.Wait(waitTimeout * time.Second) 788 blockPool.Stop() 789 blockPoolTester.refBlockChain[6] = []int{} 790 blockPoolTester.checkBlockChain(blockPoolTester.refBlockChain) 791 } 792 793 func TestPeerSwitchBack(t *testing.T) { 794 logInit() 795 _, blockPool, blockPoolTester := newTestBlockPool(t) 796 blockPoolTester.blockChain[0] = nil 797 blockPoolTester.initRefBlockChain(8) 798 799 blockPool.Start() 800 801 peer1 := blockPoolTester.newPeer("peer1", 2, 11) 802 peer2 := blockPoolTester.newPeer("peer2", 1, 8) 803 peer2.blocksRequestsMap = peer1.blocksRequestsMap 804 805 peer2.AddPeer() 806 go peer2.AddBlocks(7, 8) 807 go peer2.AddBlockHashes(8, 7, 6) 808 go peer2.AddBlockHashes(6, 5, 4) 809 peer2.AddBlocks(4, 5) // section partially complete 810 peer1.AddPeer() // peer1 is promoted as best peer 811 go peer1.AddBlocks(10, 11) // 812 peer1.AddBlockHashes(11, 10) // only gives useless results 813 blockPool.RemovePeer("peer1") // peer1 disconnects 814 go peer2.AddBlockHashes(4, 3, 2, 1, 0) // tests that asking for hashes from 4 is remembered 815 go peer2.AddBlocks(3, 4, 5, 6, 7, 8) // tests that section 4, 5, 6 and 7, 8 are remembered for missing blocks 816 peer2.AddBlocks(0, 1, 2, 3) 817 818 blockPool.Wait(waitTimeout * time.Second) 819 blockPool.Stop() 820 blockPoolTester.refBlockChain[8] = []int{} 821 blockPoolTester.checkBlockChain(blockPoolTester.refBlockChain) 822 } 823 824 func TestForkSimple(t *testing.T) { 825 logInit() 826 _, blockPool, blockPoolTester := newTestBlockPool(t) 827 blockPoolTester.blockChain[0] = nil 828 blockPoolTester.initRefBlockChain(9) 829 blockPoolTester.refBlockChain[3] = []int{4, 7} 830 delete(blockPoolTester.refBlockChain, 6) 831 832 blockPool.Start() 833 834 peer1 := blockPoolTester.newPeer("peer1", 1, 9) 835 peer2 := blockPoolTester.newPeer("peer2", 2, 6) 836 peer2.blocksRequestsMap = peer1.blocksRequestsMap 837 838 peer1.AddPeer() 839 go peer1.AddBlocks(8, 9) 840 go peer1.AddBlockHashes(9, 8, 7, 3, 2) 841 peer1.AddBlocks(1, 2, 3, 7, 8) 842 peer2.AddPeer() // peer2 is promoted as best peer 843 go peer2.AddBlocks(5, 6) // 844 go peer2.AddBlockHashes(6, 5, 4, 3, 2) // fork on 3 -> 4 (earlier child: 7) 845 go peer2.AddBlocks(1, 2, 3, 4, 5) 846 go peer2.AddBlockHashes(2, 1, 0) 847 peer2.AddBlocks(0, 1, 2) 848 849 blockPool.Wait(waitTimeout * time.Second) 850 blockPool.Stop() 851 blockPoolTester.refBlockChain[6] = []int{} 852 blockPoolTester.refBlockChain[3] = []int{4} 853 delete(blockPoolTester.refBlockChain, 7) 854 delete(blockPoolTester.refBlockChain, 8) 855 delete(blockPoolTester.refBlockChain, 9) 856 blockPoolTester.checkBlockChain(blockPoolTester.refBlockChain) 857 858 } 859 860 func TestForkSwitchBackByNewBlocks(t *testing.T) { 861 logInit() 862 _, blockPool, blockPoolTester := newTestBlockPool(t) 863 blockPoolTester.blockChain[0] = nil 864 blockPoolTester.initRefBlockChain(11) 865 blockPoolTester.refBlockChain[3] = []int{4, 7} 866 delete(blockPoolTester.refBlockChain, 6) 867 868 blockPool.Start() 869 870 peer1 := blockPoolTester.newPeer("peer1", 1, 9) 871 peer2 := blockPoolTester.newPeer("peer2", 2, 6) 872 peer2.blocksRequestsMap = peer1.blocksRequestsMap 873 874 peer1.AddPeer() 875 peer1.AddBlocks(8, 9) // 876 go peer1.AddBlockHashes(9, 8, 7, 3, 2) // 877 peer1.AddBlocks(7, 8) // partial section 878 peer2.AddPeer() // 879 peer2.AddBlocks(5, 6) // 880 go peer2.AddBlockHashes(6, 5, 4, 3, 2) // peer2 forks on block 3 881 peer2.AddBlocks(1, 2, 3, 4, 5) // 882 883 // peer1 finds new blocks 884 peer1.td = 3 885 peer1.currentBlock = 11 886 peer1.AddPeer() 887 go peer1.AddBlocks(10, 11) 888 go peer1.AddBlockHashes(11, 10, 9) 889 peer1.AddBlocks(9, 10) 890 go peer1.AddBlocks(3, 7) // tests that block requests on earlier fork are remembered 891 go peer1.AddBlockHashes(2, 1, 0) // tests that hash request from root of connecting chain section (added by demoted peer) is remembered 892 peer1.AddBlocks(0, 1) 893 894 blockPool.Wait(waitTimeout * time.Second) 895 blockPool.Stop() 896 blockPoolTester.refBlockChain[11] = []int{} 897 blockPoolTester.refBlockChain[3] = []int{7} 898 delete(blockPoolTester.refBlockChain, 6) 899 delete(blockPoolTester.refBlockChain, 5) 900 delete(blockPoolTester.refBlockChain, 4) 901 blockPoolTester.checkBlockChain(blockPoolTester.refBlockChain) 902 903 } 904 905 func TestForkSwitchBackByPeerSwitchBack(t *testing.T) { 906 logInit() 907 _, blockPool, blockPoolTester := newTestBlockPool(t) 908 blockPoolTester.blockChain[0] = nil 909 blockPoolTester.initRefBlockChain(9) 910 blockPoolTester.refBlockChain[3] = []int{4, 7} 911 delete(blockPoolTester.refBlockChain, 6) 912 913 blockPool.Start() 914 915 peer1 := blockPoolTester.newPeer("peer1", 1, 9) 916 peer2 := blockPoolTester.newPeer("peer2", 2, 6) 917 peer2.blocksRequestsMap = peer1.blocksRequestsMap 918 919 peer1.AddPeer() 920 go peer1.AddBlocks(8, 9) 921 go peer1.AddBlockHashes(9, 8, 7, 3, 2) 922 peer1.AddBlocks(7, 8) 923 peer2.AddPeer() 924 go peer2.AddBlocks(5, 6) // 925 go peer2.AddBlockHashes(6, 5, 4, 3, 2) // peer2 forks on block 3 926 peer2.AddBlocks(2, 3, 4, 5) // 927 blockPool.RemovePeer("peer2") // peer2 disconnects, peer1 is promoted again as best peer 928 go peer1.AddBlocks(3, 7) // tests that block requests on earlier fork are remembered and orphan section relinks to existing parent block 929 go peer1.AddBlocks(1, 2) // 930 go peer1.AddBlockHashes(2, 1, 0) // 931 peer1.AddBlocks(0, 1) 932 933 blockPool.Wait(waitTimeout * time.Second) 934 blockPool.Stop() 935 blockPoolTester.refBlockChain[9] = []int{} 936 blockPoolTester.refBlockChain[3] = []int{7} 937 delete(blockPoolTester.refBlockChain, 6) 938 delete(blockPoolTester.refBlockChain, 5) 939 delete(blockPoolTester.refBlockChain, 4) 940 blockPoolTester.checkBlockChain(blockPoolTester.refBlockChain) 941 942 } 943 944 func TestForkCompleteSectionSwitchBackByPeerSwitchBack(t *testing.T) { 945 logInit() 946 _, blockPool, blockPoolTester := newTestBlockPool(t) 947 blockPoolTester.blockChain[0] = nil 948 blockPoolTester.initRefBlockChain(9) 949 blockPoolTester.refBlockChain[3] = []int{4, 7} 950 delete(blockPoolTester.refBlockChain, 6) 951 952 blockPool.Start() 953 954 peer1 := blockPoolTester.newPeer("peer1", 1, 9) 955 peer2 := blockPoolTester.newPeer("peer2", 2, 6) 956 peer2.blocksRequestsMap = peer1.blocksRequestsMap 957 958 peer1.AddPeer() 959 go peer1.AddBlocks(8, 9) 960 go peer1.AddBlockHashes(9, 8, 7) 961 peer1.AddBlocks(3, 7, 8) // make sure this section is complete 962 time.Sleep(1 * time.Second) 963 go peer1.AddBlockHashes(7, 3, 2) // block 3/7 is section boundary 964 peer1.AddBlocks(2, 3) // partially complete sections block 2 missing 965 peer2.AddPeer() // 966 go peer2.AddBlocks(5, 6) // 967 go peer2.AddBlockHashes(6, 5, 4, 3, 2) // peer2 forks on block 3 968 peer2.AddBlocks(2, 3, 4, 5) // block 2 still missing. 969 blockPool.RemovePeer("peer2") // peer2 disconnects, peer1 is promoted again as best peer 970 // peer1.AddBlockHashes(7, 3) // tests that hash request from fork root is remembered even though section process completed 971 go peer1.AddBlockHashes(2, 1, 0) // 972 peer1.AddBlocks(0, 1, 2) 973 974 blockPool.Wait(waitTimeout * time.Second) 975 blockPool.Stop() 976 blockPoolTester.refBlockChain[9] = []int{} 977 blockPoolTester.refBlockChain[3] = []int{7} 978 delete(blockPoolTester.refBlockChain, 6) 979 delete(blockPoolTester.refBlockChain, 5) 980 delete(blockPoolTester.refBlockChain, 4) 981 blockPoolTester.checkBlockChain(blockPoolTester.refBlockChain) 982 983 }