github.com/theQRL/go-zond@v0.2.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/beacon"
    26  	"github.com/theQRL/go-zond/core"
    27  	"github.com/theQRL/go-zond/core/rawdb"
    28  	"github.com/theQRL/go-zond/core/txpool"
    29  	"github.com/theQRL/go-zond/core/types"
    30  	"github.com/theQRL/go-zond/core/vm"
    31  	"github.com/theQRL/go-zond/crypto/pqcrypto"
    32  	"github.com/theQRL/go-zond/event"
    33  	"github.com/theQRL/go-zond/params"
    34  	"github.com/theQRL/go-zond/zond/downloader"
    35  	"github.com/theQRL/go-zond/zonddb"
    36  )
    37  
    38  var (
    39  	// testKey is a private key to use for funding a tester account.
    40  	testKey, _ = pqcrypto.HexToDilithium("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
    41  
    42  	// testAddr is the Zond address of the tester account.
    43  	testAddr = testKey.GetAddress()
    44  )
    45  
    46  // testTxPool is a mock transaction pool that blindly accepts all transactions.
    47  // Its goal is to get around setting up a valid statedb for the balance and nonce
    48  // checks.
    49  type testTxPool struct {
    50  	pool map[common.Hash]*types.Transaction // Hash map of collected transactions
    51  
    52  	txFeed event.Feed   // Notification feed to allow waiting for inclusion
    53  	lock   sync.RWMutex // Protects the transaction pool
    54  }
    55  
    56  // newTestTxPool creates a mock transaction pool.
    57  func newTestTxPool() *testTxPool {
    58  	return &testTxPool{
    59  		pool: make(map[common.Hash]*types.Transaction),
    60  	}
    61  }
    62  
    63  // Has returns an indicator whether txpool has a transaction
    64  // cached with the given hash.
    65  func (p *testTxPool) Has(hash common.Hash) bool {
    66  	p.lock.Lock()
    67  	defer p.lock.Unlock()
    68  
    69  	return p.pool[hash] != nil
    70  }
    71  
    72  // Get retrieves the transaction from local txpool with given
    73  // tx hash.
    74  func (p *testTxPool) Get(hash common.Hash) *types.Transaction {
    75  	p.lock.Lock()
    76  	defer p.lock.Unlock()
    77  	return p.pool[hash]
    78  }
    79  
    80  // Add appends a batch of transactions to the pool, and notifies any
    81  // listeners if the addition channel is non nil
    82  func (p *testTxPool) Add(txs []*types.Transaction, local bool, sync bool) []error {
    83  	p.lock.Lock()
    84  	defer p.lock.Unlock()
    85  
    86  	for _, tx := range txs {
    87  		p.pool[tx.Hash()] = tx
    88  	}
    89  	p.txFeed.Send(core.NewTxsEvent{Txs: txs})
    90  	return make([]error, len(txs))
    91  }
    92  
    93  // Pending returns all the transactions known to the pool
    94  func (p *testTxPool) Pending(filter txpool.PendingFilter) map[common.Address][]*txpool.LazyTransaction {
    95  	p.lock.RLock()
    96  	defer p.lock.RUnlock()
    97  
    98  	batches := make(map[common.Address][]*types.Transaction)
    99  	for _, tx := range p.pool {
   100  		from, _ := types.Sender(types.ShanghaiSigner{ChainId: big.NewInt(0)}, tx)
   101  		batches[from] = append(batches[from], tx)
   102  	}
   103  	for _, batch := range batches {
   104  		sort.Sort(types.TxByNonce(batch))
   105  	}
   106  	pending := make(map[common.Address][]*txpool.LazyTransaction)
   107  	for addr, batch := range batches {
   108  		for _, tx := range batch {
   109  			pending[addr] = append(pending[addr], &txpool.LazyTransaction{
   110  				Hash:      tx.Hash(),
   111  				Tx:        tx,
   112  				Time:      tx.Time(),
   113  				GasFeeCap: tx.GasFeeCap(),
   114  				GasTipCap: tx.GasTipCap(),
   115  				Gas:       tx.Gas(),
   116  			})
   117  		}
   118  	}
   119  	return pending
   120  }
   121  
   122  // SubscribeTransactions should return an event subscription of NewTxsEvent and
   123  // send events to the given channel.
   124  func (p *testTxPool) SubscribeTransactions(ch chan<- core.NewTxsEvent) event.Subscription {
   125  	return p.txFeed.Subscribe(ch)
   126  }
   127  
   128  // testHandler is a live implementation of the Zond 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, beacon.NewFaker(), vm.Config{}, nil)
   153  
   154  	_, bs, _ := core.GenerateChainWithGenesis(gspec, beacon.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  		Network:    1,
   165  		Sync:       downloader.SnapSync,
   166  		BloomCache: 1,
   167  	})
   168  	handler.Start(1000)
   169  
   170  	return &testHandler{
   171  		db:      db,
   172  		chain:   chain,
   173  		txpool:  txpool,
   174  		handler: handler,
   175  	}
   176  }
   177  
   178  // close tears down the handler and all its internal constructs.
   179  func (b *testHandler) close() {
   180  	b.handler.Stop()
   181  	b.chain.Stop()
   182  }