github.com/aswedchain/aswed@v1.0.1/miner/miner_test.go (about) 1 // Copyright 2020 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 miner implements Ethereum block creation and mining. 18 package miner 19 20 import ( 21 "testing" 22 "time" 23 24 "github.com/aswedchain/aswed/common" 25 "github.com/aswedchain/aswed/consensus/ethash" 26 "github.com/aswedchain/aswed/core" 27 "github.com/aswedchain/aswed/core/rawdb" 28 "github.com/aswedchain/aswed/core/state" 29 "github.com/aswedchain/aswed/core/types" 30 "github.com/aswedchain/aswed/core/vm" 31 "github.com/aswedchain/aswed/eth/downloader" 32 "github.com/aswedchain/aswed/ethdb/memorydb" 33 "github.com/aswedchain/aswed/event" 34 "github.com/aswedchain/aswed/params" 35 "github.com/aswedchain/aswed/trie" 36 ) 37 38 type mockBackend struct { 39 bc *core.BlockChain 40 txPool *core.TxPool 41 } 42 43 func NewMockBackend(bc *core.BlockChain, txPool *core.TxPool) *mockBackend { 44 return &mockBackend{ 45 bc: bc, 46 txPool: txPool, 47 } 48 } 49 50 func (m *mockBackend) BlockChain() *core.BlockChain { 51 return m.bc 52 } 53 54 func (m *mockBackend) TxPool() *core.TxPool { 55 return m.txPool 56 } 57 58 type testBlockChain struct { 59 statedb *state.StateDB 60 gasLimit uint64 61 chainHeadFeed *event.Feed 62 } 63 64 func (bc *testBlockChain) CurrentBlock() *types.Block { 65 return types.NewBlock(&types.Header{ 66 GasLimit: bc.gasLimit, 67 }, nil, nil, nil, new(trie.Trie)) 68 } 69 70 func (bc *testBlockChain) GetBlock(hash common.Hash, number uint64) *types.Block { 71 return bc.CurrentBlock() 72 } 73 74 func (bc *testBlockChain) StateAt(common.Hash) (*state.StateDB, error) { 75 return bc.statedb, nil 76 } 77 78 func (bc *testBlockChain) SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription { 79 return bc.chainHeadFeed.Subscribe(ch) 80 } 81 82 func TestMiner(t *testing.T) { 83 miner, mux := createMiner(t) 84 miner.Start(common.HexToAddress("0x12345")) 85 waitForMiningState(t, miner, true) 86 // Start the downloader 87 mux.Post(downloader.StartEvent{}) 88 waitForMiningState(t, miner, false) 89 // Stop the downloader and wait for the update loop to run 90 mux.Post(downloader.DoneEvent{}) 91 waitForMiningState(t, miner, true) 92 93 // Subsequent downloader events after a successful DoneEvent should not cause the 94 // miner to start or stop. This prevents a security vulnerability 95 // that would allow entities to present fake high blocks that would 96 // stop mining operations by causing a downloader sync 97 // until it was discovered they were invalid, whereon mining would resume. 98 mux.Post(downloader.StartEvent{}) 99 waitForMiningState(t, miner, true) 100 101 mux.Post(downloader.FailedEvent{}) 102 waitForMiningState(t, miner, true) 103 } 104 105 // TestMinerDownloaderFirstFails tests that mining is only 106 // permitted to run indefinitely once the downloader sees a DoneEvent (success). 107 // An initial FailedEvent should allow mining to stop on a subsequent 108 // downloader StartEvent. 109 func TestMinerDownloaderFirstFails(t *testing.T) { 110 miner, mux := createMiner(t) 111 miner.Start(common.HexToAddress("0x12345")) 112 waitForMiningState(t, miner, true) 113 // Start the downloader 114 mux.Post(downloader.StartEvent{}) 115 waitForMiningState(t, miner, false) 116 117 // Stop the downloader and wait for the update loop to run 118 mux.Post(downloader.FailedEvent{}) 119 waitForMiningState(t, miner, true) 120 121 // Since the downloader hasn't yet emitted a successful DoneEvent, 122 // we expect the miner to stop on next StartEvent. 123 mux.Post(downloader.StartEvent{}) 124 waitForMiningState(t, miner, false) 125 126 // Downloader finally succeeds. 127 mux.Post(downloader.DoneEvent{}) 128 waitForMiningState(t, miner, true) 129 130 // Downloader starts again. 131 // Since it has achieved a DoneEvent once, we expect miner 132 // state to be unchanged. 133 mux.Post(downloader.StartEvent{}) 134 waitForMiningState(t, miner, true) 135 136 mux.Post(downloader.FailedEvent{}) 137 waitForMiningState(t, miner, true) 138 } 139 140 func TestMinerStartStopAfterDownloaderEvents(t *testing.T) { 141 miner, mux := createMiner(t) 142 143 miner.Start(common.HexToAddress("0x12345")) 144 waitForMiningState(t, miner, true) 145 // Start the downloader 146 mux.Post(downloader.StartEvent{}) 147 waitForMiningState(t, miner, false) 148 149 // Downloader finally succeeds. 150 mux.Post(downloader.DoneEvent{}) 151 waitForMiningState(t, miner, true) 152 153 miner.Stop() 154 waitForMiningState(t, miner, false) 155 156 miner.Start(common.HexToAddress("0x678910")) 157 waitForMiningState(t, miner, true) 158 159 miner.Stop() 160 waitForMiningState(t, miner, false) 161 } 162 163 func TestStartWhileDownload(t *testing.T) { 164 miner, mux := createMiner(t) 165 waitForMiningState(t, miner, false) 166 miner.Start(common.HexToAddress("0x12345")) 167 waitForMiningState(t, miner, true) 168 // Stop the downloader and wait for the update loop to run 169 mux.Post(downloader.StartEvent{}) 170 waitForMiningState(t, miner, false) 171 // Starting the miner after the downloader should not work 172 miner.Start(common.HexToAddress("0x12345")) 173 waitForMiningState(t, miner, false) 174 } 175 176 func TestStartStopMiner(t *testing.T) { 177 miner, _ := createMiner(t) 178 waitForMiningState(t, miner, false) 179 miner.Start(common.HexToAddress("0x12345")) 180 waitForMiningState(t, miner, true) 181 miner.Stop() 182 waitForMiningState(t, miner, false) 183 } 184 185 func TestCloseMiner(t *testing.T) { 186 miner, _ := createMiner(t) 187 waitForMiningState(t, miner, false) 188 miner.Start(common.HexToAddress("0x12345")) 189 waitForMiningState(t, miner, true) 190 // Terminate the miner and wait for the update loop to run 191 miner.Close() 192 waitForMiningState(t, miner, false) 193 } 194 195 // TestMinerSetEtherbase checks that etherbase becomes set even if mining isn't 196 // possible at the moment 197 func TestMinerSetEtherbase(t *testing.T) { 198 miner, mux := createMiner(t) 199 // Start with a 'bad' mining address 200 miner.Start(common.HexToAddress("0xdead")) 201 waitForMiningState(t, miner, true) 202 // Start the downloader 203 mux.Post(downloader.StartEvent{}) 204 waitForMiningState(t, miner, false) 205 // Now user tries to configure proper mining address 206 miner.Start(common.HexToAddress("0x1337")) 207 // Stop the downloader and wait for the update loop to run 208 mux.Post(downloader.DoneEvent{}) 209 210 waitForMiningState(t, miner, true) 211 // The miner should now be using the good address 212 if got, exp := miner.coinbase, common.HexToAddress("0x1337"); got != exp { 213 t.Fatalf("Wrong coinbase, got %x expected %x", got, exp) 214 } 215 } 216 217 // waitForMiningState waits until either 218 // * the desired mining state was reached 219 // * a timeout was reached which fails the test 220 func waitForMiningState(t *testing.T, m *Miner, mining bool) { 221 t.Helper() 222 223 var state bool 224 for i := 0; i < 100; i++ { 225 time.Sleep(10 * time.Millisecond) 226 if state = m.Mining(); state == mining { 227 return 228 } 229 } 230 t.Fatalf("Mining() == %t, want %t", state, mining) 231 } 232 233 func createMiner(t *testing.T) (*Miner, *event.TypeMux) { 234 // Create Ethash config 235 config := Config{ 236 Etherbase: common.HexToAddress("123456789"), 237 } 238 // Create chainConfig 239 memdb := memorydb.New() 240 chainDB := rawdb.NewDatabase(memdb) 241 genesis := core.DeveloperGenesisBlock(15, common.HexToAddress("12345")) 242 chainConfig, _, err := core.SetupGenesisBlock(chainDB, genesis) 243 if err != nil { 244 t.Fatalf("can't create new chain config: %v", err) 245 } 246 // Create event Mux 247 mux := new(event.TypeMux) 248 // Create consensus engine 249 engine := ethash.New(ethash.Config{}, []string{}, false) 250 engine.SetThreads(-1) 251 // Create isLocalBlock 252 isLocalBlock := func(block *types.Block) bool { 253 return true 254 } 255 // Create Ethereum backend 256 limit := uint64(1000) 257 bc, err := core.NewBlockChain(chainDB, new(core.CacheConfig), chainConfig, engine, vm.Config{}, isLocalBlock, &limit) 258 if err != nil { 259 t.Fatalf("can't create new chain %v", err) 260 } 261 statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil) 262 blockchain := &testBlockChain{statedb, 10000000, new(event.Feed)} 263 264 pool := core.NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain) 265 backend := NewMockBackend(bc, pool) 266 // Create Miner 267 return New(backend, &config, chainConfig, mux, engine, isLocalBlock), mux 268 }