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  }