github.com/theQRL/go-zond@v0.1.1/miner/stress/clique/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 Clique consensus engine. 18 package main 19 20 import ( 21 "bytes" 22 "math/big" 23 "math/rand" 24 "os" 25 "os/signal" 26 "time" 27 28 "github.com/theQRL/go-qrllib/dilithium" 29 "github.com/theQRL/go-zond/accounts/keystore" 30 "github.com/theQRL/go-zond/common" 31 "github.com/theQRL/go-zond/common/fdlimit" 32 "github.com/theQRL/go-zond/core" 33 "github.com/theQRL/go-zond/core/txpool/legacypool" 34 "github.com/theQRL/go-zond/core/types" 35 "github.com/theQRL/go-zond/log" 36 "github.com/theQRL/go-zond/miner" 37 "github.com/theQRL/go-zond/node" 38 "github.com/theQRL/go-zond/p2p" 39 "github.com/theQRL/go-zond/p2p/enode" 40 "github.com/theQRL/go-zond/params" 41 "github.com/theQRL/go-zond/pqcrypto" 42 "github.com/theQRL/go-zond/zond" 43 "github.com/theQRL/go-zond/zond/downloader" 44 "github.com/theQRL/go-zond/zond/ethconfig" 45 ) 46 47 func main() { 48 log.Root().SetHandler(log.LvlFilterHandler(log.LvlInfo, log.StreamHandler(os.Stderr, log.TerminalFormat(true)))) 49 fdlimit.Raise(2048) 50 51 // Generate a batch of accounts to seal and fund with 52 faucets := make([]*dilithium.Dilithium, 128) 53 for i := 0; i < len(faucets); i++ { 54 faucets[i], _ = pqcrypto.GenerateDilithiumKey() 55 } 56 sealers := make([]*dilithium.Dilithium, 4) 57 for i := 0; i < len(sealers); i++ { 58 sealers[i], _ = pqcrypto.GenerateDilithiumKey() 59 } 60 // Create a Clique network based off of the Rinkeby config 61 genesis := makeGenesis(faucets, sealers) 62 63 // Handle interrupts. 64 interruptCh := make(chan os.Signal, 5) 65 signal.Notify(interruptCh, os.Interrupt) 66 67 var ( 68 stacks []*node.Node 69 nodes []*zond.Ethereum 70 enodes []*enode.Node 71 ) 72 for _, sealer := range sealers { 73 // Start the node and wait until it's up 74 stack, ethBackend, err := makeSealer(genesis) 75 if err != nil { 76 panic(err) 77 } 78 defer stack.Close() 79 80 for stack.Server().NodeInfo().Ports.Listener == 0 { 81 time.Sleep(250 * time.Millisecond) 82 } 83 // Connect the node to all the previous ones 84 for _, n := range enodes { 85 stack.Server().AddPeer(n) 86 } 87 // Start tracking the node and its enode 88 stacks = append(stacks, stack) 89 nodes = append(nodes, ethBackend) 90 enodes = append(enodes, stack.Server().Self()) 91 92 // Inject the signer key and start sealing with it 93 ks := keystore.NewKeyStore(stack.KeyStoreDir(), keystore.LightScryptN, keystore.LightScryptP) 94 signer, err := ks.ImportDilithium(sealer, "") 95 if err != nil { 96 panic(err) 97 } 98 if err := ks.Unlock(signer, ""); err != nil { 99 panic(err) 100 } 101 stack.AccountManager().AddBackend(ks) 102 } 103 104 // Iterate over all the nodes and start signing on them 105 time.Sleep(3 * time.Second) 106 for _, node := range nodes { 107 if err := node.StartMining(); err != nil { 108 panic(err) 109 } 110 } 111 time.Sleep(3 * time.Second) 112 113 // Start injecting transactions from the faucet like crazy 114 nonces := make([]uint64, len(faucets)) 115 for { 116 // Stop when interrupted. 117 select { 118 case <-interruptCh: 119 for _, node := range stacks { 120 node.Close() 121 } 122 return 123 default: 124 } 125 126 // Pick a random signer node 127 index := rand.Intn(len(faucets)) 128 backend := nodes[index%len(nodes)] 129 130 // Create a self transaction and inject into the pool 131 tx, err := types.SignTx(types.NewTransaction(nonces[index], faucets[index].GetAddress(), new(big.Int), 21000, big.NewInt(100000000000), nil), types.HomesteadSigner{}, faucets[index]) 132 if err != nil { 133 panic(err) 134 } 135 if err := backend.TxPool().Add([]*types.Transaction{tx}, true, false); err != nil { 136 panic(err) 137 } 138 nonces[index]++ 139 140 // Wait if we're too saturated 141 if pend, _ := backend.TxPool().Stats(); pend > 2048 { 142 time.Sleep(100 * time.Millisecond) 143 } 144 } 145 } 146 147 // makeGenesis creates a custom Clique genesis block based on some pre-defined 148 // signer and faucet accounts. 149 func makeGenesis(faucets []*dilithium.Dilithium, sealers []*dilithium.Dilithium) *core.Genesis { 150 // Create a Clique network based off of the Rinkeby config 151 genesis := core.DefaultRinkebyGenesisBlock() 152 genesis.GasLimit = 25000000 153 154 genesis.Config.ChainID = big.NewInt(18) 155 genesis.Config.Clique.Period = 1 156 157 genesis.Alloc = core.GenesisAlloc{} 158 for _, faucet := range faucets { 159 genesis.Alloc[faucet.GetAddress()] = core.GenesisAccount{ 160 Balance: new(big.Int).Exp(big.NewInt(2), big.NewInt(128), nil), 161 } 162 } 163 // Sort the signers and embed into the extra-data section 164 signers := make([]common.Address, len(sealers)) 165 for i, sealer := range sealers { 166 signers[i] = sealer.GetAddress() 167 } 168 for i := 0; i < len(signers); i++ { 169 for j := i + 1; j < len(signers); j++ { 170 if bytes.Compare(signers[i][:], signers[j][:]) > 0 { 171 signers[i], signers[j] = signers[j], signers[i] 172 } 173 } 174 } 175 genesis.ExtraData = make([]byte, 32+len(signers)*common.AddressLength+65) 176 for i, signer := range signers { 177 copy(genesis.ExtraData[32+i*common.AddressLength:], signer[:]) 178 } 179 // Return the genesis block for initialization 180 return genesis 181 } 182 183 func makeSealer(genesis *core.Genesis) (*node.Node, *zond.Ethereum, error) { 184 // Define the basic configurations for the Ethereum node 185 datadir, _ := os.MkdirTemp("", "") 186 187 config := &node.Config{ 188 Name: "gzond", 189 Version: params.Version, 190 DataDir: datadir, 191 P2P: p2p.Config{ 192 ListenAddr: "0.0.0.0:0", 193 NoDiscovery: true, 194 MaxPeers: 25, 195 }, 196 } 197 // Start the node and configure a full Ethereum node on it 198 stack, err := node.New(config) 199 if err != nil { 200 return nil, nil, err 201 } 202 // Create and register the backend 203 ethBackend, err := zond.New(stack, ðconfig.Config{ 204 Genesis: genesis, 205 NetworkId: genesis.Config.ChainID.Uint64(), 206 SyncMode: downloader.FullSync, 207 DatabaseCache: 256, 208 DatabaseHandles: 256, 209 TxPool: legacypool.DefaultConfig, 210 GPO: ethconfig.Defaults.GPO, 211 Miner: miner.Config{ 212 GasCeil: genesis.GasLimit * 11 / 10, 213 GasPrice: big.NewInt(1), 214 Recommit: time.Second, 215 }, 216 }) 217 if err != nil { 218 return nil, nil, err 219 } 220 221 err = stack.Start() 222 return stack, ethBackend, err 223 }