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