github.com/theQRL/go-zond@v0.1.1/zond/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 zond
    18  
    19  import (
    20  	"math/big"
    21  	"sort"
    22  	"sync"
    23  
    24  	"github.com/theQRL/go-zond/common"
    25  	"github.com/theQRL/go-zond/consensus"
    26  	"github.com/theQRL/go-zond/consensus/ethash"
    27  	"github.com/theQRL/go-zond/core"
    28  	"github.com/theQRL/go-zond/core/rawdb"
    29  	"github.com/theQRL/go-zond/core/txpool"
    30  	"github.com/theQRL/go-zond/core/types"
    31  	"github.com/theQRL/go-zond/core/vm"
    32  	"github.com/theQRL/go-zond/crypto"
    33  	"github.com/theQRL/go-zond/event"
    34  	"github.com/theQRL/go-zond/params"
    35  	"github.com/theQRL/go-zond/zond/downloader"
    36  	"github.com/theQRL/go-zond/zonddb"
    37  )
    38  
    39  var (
    40  	// testKey is a private key to use for funding a tester account.
    41  	testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
    42  
    43  	// testAddr is the Ethereum address of the tester account.
    44  	testAddr = crypto.PubkeyToAddress(testKey.PublicKey)
    45  )
    46  
    47  // testTxPool is a mock transaction pool that blindly accepts all transactions.
    48  // Its goal is to get around setting up a valid statedb for the balance and nonce
    49  // checks.
    50  type testTxPool struct {
    51  	pool map[common.Hash]*types.Transaction // Hash map of collected transactions
    52  
    53  	txFeed event.Feed   // Notification feed to allow waiting for inclusion
    54  	lock   sync.RWMutex // Protects the transaction pool
    55  }
    56  
    57  // newTestTxPool creates a mock transaction pool.
    58  func newTestTxPool() *testTxPool {
    59  	return &testTxPool{
    60  		pool: make(map[common.Hash]*types.Transaction),
    61  	}
    62  }
    63  
    64  // Has returns an indicator whether txpool has a transaction
    65  // cached with the given hash.
    66  func (p *testTxPool) Has(hash common.Hash) bool {
    67  	p.lock.Lock()
    68  	defer p.lock.Unlock()
    69  
    70  	return p.pool[hash] != nil
    71  }
    72  
    73  // Get retrieves the transaction from local txpool with given
    74  // tx hash.
    75  func (p *testTxPool) Get(hash common.Hash) *types.Transaction {
    76  	p.lock.Lock()
    77  	defer p.lock.Unlock()
    78  	return p.pool[hash]
    79  }
    80  
    81  // Add appends a batch of transactions to the pool, and notifies any
    82  // listeners if the addition channel is non nil
    83  func (p *testTxPool) Add(txs []*types.Transaction, local bool, sync bool) []error {
    84  	p.lock.Lock()
    85  	defer p.lock.Unlock()
    86  
    87  	for _, tx := range txs {
    88  		p.pool[tx.Hash()] = tx
    89  	}
    90  	p.txFeed.Send(core.NewTxsEvent{Txs: txs})
    91  	return make([]error, len(txs))
    92  }
    93  
    94  // Pending returns all the transactions known to the pool
    95  func (p *testTxPool) Pending(enforceTips bool) map[common.Address][]*txpool.LazyTransaction {
    96  	p.lock.RLock()
    97  	defer p.lock.RUnlock()
    98  
    99  	batches := make(map[common.Address][]*types.Transaction)
   100  	for _, tx := range p.pool {
   101  		from, _ := types.Sender(types.HomesteadSigner{}, tx)
   102  		batches[from] = append(batches[from], tx)
   103  	}
   104  	for _, batch := range batches {
   105  		sort.Sort(types.TxByNonce(batch))
   106  	}
   107  	pending := make(map[common.Address][]*txpool.LazyTransaction)
   108  	for addr, batch := range batches {
   109  		for _, tx := range batch {
   110  			pending[addr] = append(pending[addr], &txpool.LazyTransaction{
   111  				Hash:      tx.Hash(),
   112  				Tx:        tx,
   113  				Time:      tx.Time(),
   114  				GasFeeCap: tx.GasFeeCap(),
   115  				GasTipCap: tx.GasTipCap(),
   116  			})
   117  		}
   118  	}
   119  	return pending
   120  }
   121  
   122  // SubscribeNewTxsEvent should return an event subscription of NewTxsEvent and
   123  // send events to the given channel.
   124  func (p *testTxPool) SubscribeNewTxsEvent(ch chan<- core.NewTxsEvent) event.Subscription {
   125  	return p.txFeed.Subscribe(ch)
   126  }
   127  
   128  // testHandler is a live implementation of the Ethereum protocol handler, just
   129  // preinitialized with some sane testing defaults and the transaction pool mocked
   130  // out.
   131  type testHandler struct {
   132  	db      zonddb.Database
   133  	chain   *core.BlockChain
   134  	txpool  *testTxPool
   135  	handler *handler
   136  }
   137  
   138  // newTestHandler creates a new handler for testing purposes with no blocks.
   139  func newTestHandler() *testHandler {
   140  	return newTestHandlerWithBlocks(0)
   141  }
   142  
   143  // newTestHandlerWithBlocks creates a new handler for testing purposes, with a
   144  // given number of initial blocks.
   145  func newTestHandlerWithBlocks(blocks int) *testHandler {
   146  	// Create a database pre-initialize with a genesis block
   147  	db := rawdb.NewMemoryDatabase()
   148  	gspec := &core.Genesis{
   149  		Config: params.TestChainConfig,
   150  		Alloc:  core.GenesisAlloc{testAddr: {Balance: big.NewInt(1000000)}},
   151  	}
   152  	chain, _ := core.NewBlockChain(db, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
   153  
   154  	_, bs, _ := core.GenerateChainWithGenesis(gspec, ethash.NewFaker(), blocks, nil)
   155  	if _, err := chain.InsertChain(bs); err != nil {
   156  		panic(err)
   157  	}
   158  	txpool := newTestTxPool()
   159  
   160  	handler, _ := newHandler(&handlerConfig{
   161  		Database:   db,
   162  		Chain:      chain,
   163  		TxPool:     txpool,
   164  		Merger:     consensus.NewMerger(rawdb.NewMemoryDatabase()),
   165  		Network:    1,
   166  		Sync:       downloader.SnapSync,
   167  		BloomCache: 1,
   168  	})
   169  	handler.Start(1000)
   170  
   171  	return &testHandler{
   172  		db:      db,
   173  		chain:   chain,
   174  		txpool:  txpool,
   175  		handler: handler,
   176  	}
   177  }
   178  
   179  // close tears down the handler and all its internal constructs.
   180  func (b *testHandler) close() {
   181  	b.handler.Stop()
   182  	b.chain.Stop()
   183  }