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