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