github.com/codysnider/go-ethereum@v1.10.18-0.20220420071915-14f4ae99222a/miner/stress/ethash/main.go (about) 1 // Copyright 2018 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 // This file contains a miner stress test based on the Ethash consensus engine. 18 package main 19 20 import ( 21 "crypto/ecdsa" 22 "io/ioutil" 23 "math/big" 24 "math/rand" 25 "os" 26 "os/signal" 27 "time" 28 29 "github.com/ethereum/go-ethereum/common" 30 "github.com/ethereum/go-ethereum/common/fdlimit" 31 "github.com/ethereum/go-ethereum/consensus/ethash" 32 "github.com/ethereum/go-ethereum/core" 33 "github.com/ethereum/go-ethereum/core/types" 34 "github.com/ethereum/go-ethereum/crypto" 35 "github.com/ethereum/go-ethereum/eth" 36 "github.com/ethereum/go-ethereum/eth/downloader" 37 "github.com/ethereum/go-ethereum/eth/ethconfig" 38 "github.com/ethereum/go-ethereum/log" 39 "github.com/ethereum/go-ethereum/miner" 40 "github.com/ethereum/go-ethereum/node" 41 "github.com/ethereum/go-ethereum/p2p" 42 "github.com/ethereum/go-ethereum/p2p/enode" 43 "github.com/ethereum/go-ethereum/params" 44 ) 45 46 func main() { 47 log.Root().SetHandler(log.LvlFilterHandler(log.LvlInfo, log.StreamHandler(os.Stderr, log.TerminalFormat(true)))) 48 fdlimit.Raise(2048) 49 50 // Generate a batch of accounts to seal and fund with 51 faucets := make([]*ecdsa.PrivateKey, 128) 52 for i := 0; i < len(faucets); i++ { 53 faucets[i], _ = crypto.GenerateKey() 54 } 55 // Pre-generate the ethash mining DAG so we don't race 56 ethash.MakeDataset(1, ethconfig.Defaults.Ethash.DatasetDir) 57 58 // Create an Ethash network based off of the Ropsten config 59 genesis := makeGenesis(faucets) 60 61 // Handle interrupts. 62 interruptCh := make(chan os.Signal, 5) 63 signal.Notify(interruptCh, os.Interrupt) 64 65 var ( 66 stacks []*node.Node 67 nodes []*eth.Ethereum 68 enodes []*enode.Node 69 ) 70 for i := 0; i < 4; i++ { 71 // Start the node and wait until it's up 72 stack, ethBackend, err := makeMiner(genesis) 73 if err != nil { 74 panic(err) 75 } 76 defer stack.Close() 77 78 for stack.Server().NodeInfo().Ports.Listener == 0 { 79 time.Sleep(250 * time.Millisecond) 80 } 81 // Connect the node to all the previous ones 82 for _, n := range enodes { 83 stack.Server().AddPeer(n) 84 } 85 // Start tracking the node and its enode 86 stacks = append(stacks, stack) 87 nodes = append(nodes, ethBackend) 88 enodes = append(enodes, stack.Server().Self()) 89 } 90 91 // Iterate over all the nodes and start mining 92 time.Sleep(3 * time.Second) 93 for _, node := range nodes { 94 if err := node.StartMining(1); err != nil { 95 panic(err) 96 } 97 } 98 time.Sleep(3 * time.Second) 99 100 // Start injecting transactions from the faucets like crazy 101 nonces := make([]uint64, len(faucets)) 102 for { 103 // Stop when interrupted. 104 select { 105 case <-interruptCh: 106 for _, node := range stacks { 107 node.Close() 108 } 109 return 110 default: 111 } 112 113 // Pick a random mining node 114 index := rand.Intn(len(faucets)) 115 backend := nodes[index%len(nodes)] 116 117 // Create a self transaction and inject into the pool 118 tx, err := types.SignTx(types.NewTransaction(nonces[index], crypto.PubkeyToAddress(faucets[index].PublicKey), new(big.Int), 21000, big.NewInt(100000000000+rand.Int63n(65536)), nil), types.HomesteadSigner{}, faucets[index]) 119 if err != nil { 120 panic(err) 121 } 122 if err := backend.TxPool().AddLocal(tx); err != nil { 123 panic(err) 124 } 125 nonces[index]++ 126 127 // Wait if we're too saturated 128 if pend, _ := backend.TxPool().Stats(); pend > 2048 { 129 time.Sleep(100 * time.Millisecond) 130 } 131 } 132 } 133 134 // makeGenesis creates a custom Ethash genesis block based on some pre-defined 135 // faucet accounts. 136 func makeGenesis(faucets []*ecdsa.PrivateKey) *core.Genesis { 137 genesis := core.DefaultRopstenGenesisBlock() 138 genesis.Difficulty = params.MinimumDifficulty 139 genesis.GasLimit = 25000000 140 141 genesis.Config.ChainID = big.NewInt(18) 142 genesis.Config.EIP150Hash = common.Hash{} 143 144 genesis.Alloc = core.GenesisAlloc{} 145 for _, faucet := range faucets { 146 genesis.Alloc[crypto.PubkeyToAddress(faucet.PublicKey)] = core.GenesisAccount{ 147 Balance: new(big.Int).Exp(big.NewInt(2), big.NewInt(128), nil), 148 } 149 } 150 return genesis 151 } 152 153 func makeMiner(genesis *core.Genesis) (*node.Node, *eth.Ethereum, error) { 154 // Define the basic configurations for the Ethereum node 155 datadir, _ := ioutil.TempDir("", "") 156 157 config := &node.Config{ 158 Name: "geth", 159 Version: params.Version, 160 DataDir: datadir, 161 P2P: p2p.Config{ 162 ListenAddr: "0.0.0.0:0", 163 NoDiscovery: true, 164 MaxPeers: 25, 165 }, 166 UseLightweightKDF: true, 167 } 168 // Create the node and configure a full Ethereum node on it 169 stack, err := node.New(config) 170 if err != nil { 171 return nil, nil, err 172 } 173 ethBackend, err := eth.New(stack, ðconfig.Config{ 174 Genesis: genesis, 175 NetworkId: genesis.Config.ChainID.Uint64(), 176 SyncMode: downloader.FullSync, 177 DatabaseCache: 256, 178 DatabaseHandles: 256, 179 TxPool: core.DefaultTxPoolConfig, 180 GPO: ethconfig.Defaults.GPO, 181 Ethash: ethconfig.Defaults.Ethash, 182 Miner: miner.Config{ 183 Etherbase: common.Address{1}, 184 GasCeil: genesis.GasLimit * 11 / 10, 185 GasPrice: big.NewInt(1), 186 Recommit: time.Second, 187 }, 188 }) 189 if err != nil { 190 return nil, nil, err 191 } 192 193 err = stack.Start() 194 return stack, ethBackend, err 195 }