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