aboutsummaryrefslogtreecommitdiffstats
path: root/blockpool/blockpool_util_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'blockpool/blockpool_util_test.go')
-rw-r--r--blockpool/blockpool_util_test.go373
1 files changed, 0 insertions, 373 deletions
diff --git a/blockpool/blockpool_util_test.go b/blockpool/blockpool_util_test.go
deleted file mode 100644
index e52c0f753..000000000
--- a/blockpool/blockpool_util_test.go
+++ /dev/null
@@ -1,373 +0,0 @@
-package blockpool
-
-import (
- "fmt"
- "math/big"
- "sync"
- "testing"
- "time"
-
- "github.com/ethereum/go-ethereum/blockpool/test"
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/errs"
- "github.com/ethereum/go-ethereum/event"
- "github.com/ethereum/go-ethereum/pow"
-)
-
-var (
- waitTimeout = 60 * time.Second
- testBlockHashesRequestInterval = 10 * time.Millisecond
- testBlocksRequestInterval = 10 * time.Millisecond
- requestWatchInterval = 10 * time.Millisecond
-)
-
-// test blockChain is an integer trie
-type blockChain map[int][]int
-
-// blockPoolTester provides the interface between tests and a blockPool
-//
-// refBlockChain is used to guide which blocks will be accepted as valid
-// blockChain gives the current state of the blockchain and
-// accumulates inserts so that we can check the resulting chain
-type blockPoolTester struct {
- hashPool *test.TestHashPool
- lock sync.RWMutex
- reqlock sync.RWMutex
- blocksRequestsMap map[int]bool
- refBlockChain blockChain
- blockChain blockChain
- blockPool *BlockPool
- t *testing.T
- chainEvents *event.TypeMux
- tds map[int]int
-}
-
-func newTestBlockPool(t *testing.T) (hashPool *test.TestHashPool, blockPool *BlockPool, b *blockPoolTester) {
- hashPool = test.NewHashPool()
- b = &blockPoolTester{
- t: t,
- hashPool: hashPool,
- blockChain: make(blockChain),
- refBlockChain: make(blockChain),
- blocksRequestsMap: make(map[int]bool),
- chainEvents: &event.TypeMux{},
- }
- b.blockPool = New(b.hasBlock, b.insertChain, b.verifyPoW, b.chainEvents, common.Big0)
- blockPool = b.blockPool
- blockPool.Config.BlockHashesRequestInterval = testBlockHashesRequestInterval
- blockPool.Config.BlocksRequestInterval = testBlocksRequestInterval
- return
-}
-
-func (self *blockPoolTester) Errorf(format string, params ...interface{}) {
- // fmt.Printf(format+"\n", params...)
- self.t.Errorf(format, params...)
-}
-
-// blockPoolTester implements the 3 callbacks needed by the blockPool:
-// hasBlock, insetChain, verifyPoW as well as provides the eventer
-// to subscribe to head insertions
-func (self *blockPoolTester) hasBlock(block common.Hash) (ok bool) {
- self.lock.RLock()
- defer self.lock.RUnlock()
- indexes := self.hashPool.HashesToIndexes([]common.Hash{block})
- i := indexes[0]
- _, ok = self.blockChain[i]
- // fmt.Printf("has block %v (%x...): %v\n", i, block[0:4], ok)
- return
-}
-
-// mock insertChain relies on refBlockChain to determine block validity
-func (self *blockPoolTester) insertChain(blocks types.Blocks) error {
- self.lock.Lock()
- defer self.lock.Unlock()
- var parent, child int
- var children, refChildren []int
- var ok bool
- for _, block := range blocks {
- child = self.hashPool.HashesToIndexes([]common.Hash{block.Hash()})[0]
- td := child
- if self.tds != nil {
- td, ok = self.tds[child]
- }
- if !ok {
- td = child
- }
- block.Td = big.NewInt(int64(td))
- _, ok = self.blockChain[child]
- if ok {
- // fmt.Printf("block %v already in blockchain\n", child)
- continue // already in chain
- }
- parent = self.hashPool.HashesToIndexes([]common.Hash{block.ParentHeaderHash})[0]
- children, ok = self.blockChain[parent]
- if !ok {
- return fmt.Errorf("parent %v not in blockchain ", parent)
- }
- ok = false
- var found bool
- refChildren, found = self.refBlockChain[parent]
- if found {
- for _, c := range refChildren {
- if c == child {
- ok = true
- }
- }
- if !ok {
- return fmt.Errorf("invalid block %v", child)
- }
- } else {
- ok = true
- }
- if ok {
- // accept any blocks if parent not in refBlockChain
- self.blockChain[parent] = append(children, child)
- self.blockChain[child] = nil
- }
- }
- return nil
-}
-
-// mock soft block validation always succeeds
-func (self *blockPoolTester) verifyPoW(pblock pow.Block) bool {
- return true
-}
-
-// test helper that compares the resulting blockChain to the desired blockChain
-func (self *blockPoolTester) checkBlockChain(blockChain map[int][]int) {
- self.lock.RLock()
- defer self.lock.RUnlock()
- // for k, v := range self.blockChain {
- // fmt.Printf("got: %v -> %v\n", k, v)
- // }
- // for k, v := range blockChain {
- // fmt.Printf("expected: %v -> %v\n", k, v)
- // }
- if len(blockChain) != len(self.blockChain) {
- self.Errorf("blockchain incorrect (zlength differ)")
- }
- for k, v := range blockChain {
- vv, ok := self.blockChain[k]
- if !ok || !test.ArrayEq(v, vv) {
- self.Errorf("blockchain incorrect on %v -> %v (!= %v)", k, vv, v)
- }
- }
-}
-
-// peerTester provides the peer callbacks for the blockPool
-// it registers actual callbacks so that the result can be compared to desired behaviour
-// provides helper functions to mock the protocol calls to the blockPool
-type peerTester struct {
- // containers to record request and error callbacks
- blockHashesRequests []int
- blocksRequests [][]int
- blocksRequestsMap map[int]bool
- peerErrors []int
-
- blockPool *BlockPool
- hashPool *test.TestHashPool
- lock sync.RWMutex
- bt *blockPoolTester
- id string
- td int
- currentBlock int
- t *testing.T
-}
-
-// peerTester constructor takes hashPool and blockPool from the blockPoolTester
-func (self *blockPoolTester) newPeer(id string, td int, cb int) *peerTester {
- return &peerTester{
- id: id,
- td: td,
- currentBlock: cb,
- hashPool: self.hashPool,
- blockPool: self.blockPool,
- t: self.t,
- bt: self,
- blocksRequestsMap: self.blocksRequestsMap,
- }
-}
-
-func (self *peerTester) Errorf(format string, params ...interface{}) {
- // fmt.Printf(format+"\n", params...)
- self.t.Errorf(format, params...)
-}
-
-// helper to compare actual and expected block requests
-func (self *peerTester) checkBlocksRequests(blocksRequests ...[]int) {
- if len(blocksRequests) > len(self.blocksRequests) {
- self.Errorf("blocks requests incorrect (length differ)\ngot %v\nexpected %v", self.blocksRequests, blocksRequests)
- } else {
- for i, rr := range blocksRequests {
- r := self.blocksRequests[i]
- if !test.ArrayEq(r, rr) {
- self.Errorf("blocks requests incorrect\ngot %v\nexpected %v", self.blocksRequests, blocksRequests)
- }
- }
- }
-}
-
-// helper to compare actual and expected block hash requests
-func (self *peerTester) checkBlockHashesRequests(blocksHashesRequests ...int) {
- rr := blocksHashesRequests
- self.lock.RLock()
- r := self.blockHashesRequests
- self.lock.RUnlock()
- if len(r) != len(rr) {
- self.Errorf("block hashes requests incorrect (length differ)\ngot %v\nexpected %v", r, rr)
- } else {
- if !test.ArrayEq(r, rr) {
- self.Errorf("block hashes requests incorrect\ngot %v\nexpected %v", r, rr)
- }
- }
-}
-
-// waiter function used by peer.serveBlocks
-// blocking until requests appear
-// this mocks proper wire protocol behaviour
-// since block requests are sent to any random peers
-// block request map is shared between peers
-// times out after waitTimeout
-func (self *peerTester) waitBlocksRequests(blocksRequest ...int) {
- timeout := time.After(waitTimeout)
- rr := blocksRequest
- for {
- self.lock.RLock()
- r := self.blocksRequestsMap
- // fmt.Printf("[%s] blocks request check %v (%v)\n", self.id, rr, r)
- i := 0
- for i = 0; i < len(rr); i++ {
- _, ok := r[rr[i]]
- if !ok {
- break
- }
- }
- self.lock.RUnlock()
-
- if i == len(rr) {
- return
- }
- time.Sleep(requestWatchInterval)
- select {
- case <-timeout:
- default:
- }
- }
-}
-
-// waiter function used by peer.serveBlockHashes
-// blocking until requests appear
-// this mocks proper wire protocol behaviour
-// times out after a period
-func (self *peerTester) waitBlockHashesRequests(blocksHashesRequest int) {
- timeout := time.After(waitTimeout)
- rr := blocksHashesRequest
- for i := 0; ; {
- self.lock.RLock()
- r := self.blockHashesRequests
- self.lock.RUnlock()
- // fmt.Printf("[%s] block hash request check %v (%v)\n", self.id, rr, r)
- for ; i < len(r); i++ {
- if rr == r[i] {
- return
- }
- }
- time.Sleep(requestWatchInterval)
- select {
- case <-timeout:
- default:
- }
- }
-}
-
-// mocks a simple blockchain 0 (genesis) ... n (head)
-func (self *blockPoolTester) initRefBlockChain(n int) {
- for i := 0; i < n; i++ {
- self.refBlockChain[i] = []int{i + 1}
- }
-}
-
-// peerTester functions that mimic protocol calls to the blockpool
-// registers the peer with the blockPool
-func (self *peerTester) AddPeer() (best bool) {
- hash := self.hashPool.IndexesToHashes([]int{self.currentBlock})[0]
- best, _ = self.blockPool.AddPeer(big.NewInt(int64(self.td)), hash, self.id, self.requestBlockHashes, self.requestBlocks, self.peerError)
- return
-}
-
-// peer sends blockhashes if and when gets a request
-func (self *peerTester) serveBlockHashes(indexes ...int) {
- // fmt.Printf("ready to serve block hashes %v\n", indexes)
-
- self.waitBlockHashesRequests(indexes[0])
- self.sendBlockHashes(indexes...)
-}
-
-// peer sends blockhashes not waiting for request
-func (self *peerTester) sendBlockHashes(indexes ...int) {
- // fmt.Printf("adding block hashes %v\n", indexes)
- hashes := self.hashPool.IndexesToHashes(indexes)
- i := 1
- next := func() (hash common.Hash, ok bool) {
- if i < len(hashes) {
- hash = hashes[i]
- ok = true
- i++
- }
- return
- }
- self.blockPool.AddBlockHashes(next, self.id)
-}
-
-// peer sends blocks if and when there is a request
-// (in the shared request store, not necessarily to a specific peer)
-func (self *peerTester) serveBlocks(indexes ...int) {
- // fmt.Printf("ready to serve blocks %v\n", indexes[1:])
- self.waitBlocksRequests(indexes[1:]...)
- self.sendBlocks(indexes...)
-}
-
-// peer sends blocks not waiting for request
-func (self *peerTester) sendBlocks(indexes ...int) {
- // fmt.Printf("adding blocks %v \n", indexes)
- hashes := self.hashPool.IndexesToHashes(indexes)
- for i := 1; i < len(hashes); i++ {
- // fmt.Printf("adding block %v %x\n", indexes[i], hashes[i][:4])
- self.blockPool.AddBlock(&types.Block{HeaderHash: hashes[i], ParentHeaderHash: hashes[i-1]}, self.id)
- }
-}
-
-// the 3 mock peer callbacks
-
-// records block hashes requests by the blockPool
-// -1 is special: not found (a hash never seen)
-func (self *peerTester) requestBlockHashes(hash common.Hash) error {
- indexes := self.hashPool.HashesToIndexes([]common.Hash{hash})
- // fmt.Printf("[%s] block hash request %v %x\n", self.id, indexes[0], hash[:4])
- self.lock.Lock()
- defer self.lock.Unlock()
- self.blockHashesRequests = append(self.blockHashesRequests, indexes[0])
- return nil
-}
-
-// records block requests by the blockPool
-func (self *peerTester) requestBlocks(hashes []common.Hash) error {
- indexes := self.hashPool.HashesToIndexes(hashes)
- // fmt.Printf("blocks request %v %x...\n", indexes, hashes[0][:4])
- self.bt.reqlock.Lock()
- defer self.bt.reqlock.Unlock()
- self.blocksRequests = append(self.blocksRequests, indexes)
- for _, i := range indexes {
- self.blocksRequestsMap[i] = true
- }
- return nil
-}
-
-// records the error codes of all the peerErrors found the blockPool
-func (self *peerTester) peerError(err *errs.Error) {
- self.peerErrors = append(self.peerErrors, err.Code)
- if err.Fatal() {
- self.blockPool.RemovePeer(self.id)
- }
-}