github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/miner/stress_ethash.go (about) 1 2 //<developer> 3 // <name>linapex 曹一峰</name> 4 // <email>linapex@163.com</email> 5 // <wx>superexc</wx> 6 // <qqgroup>128148617</qqgroup> 7 // <url>https://jsq.ink</url> 8 // <role>pku engineer</role> 9 // <date>2019-03-16 19:16:40</date> 10 //</624450100525010944> 11 12 13 //+不建 14 15 //此文件包含基于ethash共识引擎的矿工压力测试。 16 package main 17 18 import ( 19 "crypto/ecdsa" 20 "io/ioutil" 21 "math/big" 22 "math/rand" 23 "os" 24 "path/filepath" 25 "time" 26 27 "github.com/ethereum/go-ethereum/accounts/keystore" 28 "github.com/ethereum/go-ethereum/common" 29 "github.com/ethereum/go-ethereum/common/fdlimit" 30 "github.com/ethereum/go-ethereum/consensus/ethash" 31 "github.com/ethereum/go-ethereum/core" 32 "github.com/ethereum/go-ethereum/core/types" 33 "github.com/ethereum/go-ethereum/crypto" 34 "github.com/ethereum/go-ethereum/eth" 35 "github.com/ethereum/go-ethereum/eth/downloader" 36 "github.com/ethereum/go-ethereum/log" 37 "github.com/ethereum/go-ethereum/node" 38 "github.com/ethereum/go-ethereum/p2p" 39 "github.com/ethereum/go-ethereum/p2p/enode" 40 "github.com/ethereum/go-ethereum/params" 41 ) 42 43 func main() { 44 log.Root().SetHandler(log.LvlFilterHandler(log.LvlInfo, log.StreamHandler(os.Stderr, log.TerminalFormat(true)))) 45 fdlimit.Raise(2048) 46 47 //生成一批封存资金的账户 48 faucets := make([]*ecdsa.PrivateKey, 128) 49 for i := 0; i < len(faucets); i++ { 50 faucets[i], _ = crypto.GenerateKey() 51 } 52 //预先生成ethash挖掘数据,这样我们就不会比赛了 53 ethash.MakeDataset(1, filepath.Join(os.Getenv("HOME"), ".ethash")) 54 55 //基于Ropsten配置创建ethash网络 56 genesis := makeGenesis(faucets) 57 58 var ( 59 nodes []*node.Node 60 enodes []*enode.Node 61 ) 62 for i := 0; i < 4; i++ { 63 //启动节点并等待它启动 64 node, err := makeMiner(genesis) 65 if err != nil { 66 panic(err) 67 } 68 defer node.Stop() 69 70 for node.Server().NodeInfo().Ports.Listener == 0 { 71 time.Sleep(250 * time.Millisecond) 72 } 73 //将节点连接到前面的所有节点 74 for _, n := range enodes { 75 node.Server().AddPeer(n) 76 } 77 //开始跟踪节点,它是enode 78 nodes = append(nodes, node) 79 enodes = append(enodes, node.Server().Self()) 80 81 //注入签名者密钥并用它开始密封 82 store := node.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore) 83 if _, err := store.NewAccount(""); err != nil { 84 panic(err) 85 } 86 } 87 //遍历所有节点并开始使用它们进行签名 88 time.Sleep(3 * time.Second) 89 90 for _, node := range nodes { 91 var ethereum *eth.Ethereum 92 if err := node.Service(ðereum); err != nil { 93 panic(err) 94 } 95 if err := ethereum.StartMining(1); err != nil { 96 panic(err) 97 } 98 } 99 time.Sleep(3 * time.Second) 100 101 //开始疯狂地从水龙头注入交易 102 nonces := make([]uint64, len(faucets)) 103 for { 104 index := rand.Intn(len(faucets)) 105 106 //获取相关签名者的访问器 107 var ethereum *eth.Ethereum 108 if err := nodes[index%len(nodes)].Service(ðereum); err != nil { 109 panic(err) 110 } 111 //创建一个自事务并注入池 112 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]) 113 if err != nil { 114 panic(err) 115 } 116 if err := ethereum.TxPool().AddLocal(tx); err != nil { 117 panic(err) 118 } 119 nonces[index]++ 120 121 //等一下,如果我们太饱和了 122 if pend, _ := ethereum.TxPool().Stats(); pend > 2048 { 123 time.Sleep(100 * time.Millisecond) 124 } 125 } 126 } 127 128 //MakeGenesis基于一些预定义的 129 //水龙头账户。 130 func makeGenesis(faucets []*ecdsa.PrivateKey) *core.Genesis { 131 genesis := core.DefaultTestnetGenesisBlock() 132 genesis.Difficulty = params.MinimumDifficulty 133 genesis.GasLimit = 25000000 134 135 genesis.Config.ChainID = big.NewInt(18) 136 genesis.Config.EIP150Hash = common.Hash{} 137 138 genesis.Alloc = core.GenesisAlloc{} 139 for _, faucet := range faucets { 140 genesis.Alloc[crypto.PubkeyToAddress(faucet.PublicKey)] = core.GenesisAccount{ 141 Balance: new(big.Int).Exp(big.NewInt(2), big.NewInt(128), nil), 142 } 143 } 144 return genesis 145 } 146 147 func makeMiner(genesis *core.Genesis) (*node.Node, error) { 148 //定义以太坊节点的基本配置 149 datadir, _ := ioutil.TempDir("", "") 150 151 config := &node.Config{ 152 Name: "geth", 153 Version: params.Version, 154 DataDir: datadir, 155 P2P: p2p.Config{ 156 ListenAddr: "0.0.0.0:0", 157 NoDiscovery: true, 158 MaxPeers: 25, 159 }, 160 NoUSB: true, 161 UseLightweightKDF: true, 162 } 163 //启动节点并在其上配置完整的以太坊节点 164 stack, err := node.New(config) 165 if err != nil { 166 return nil, err 167 } 168 if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) { 169 return eth.New(ctx, ð.Config{ 170 Genesis: genesis, 171 NetworkId: genesis.Config.ChainID.Uint64(), 172 SyncMode: downloader.FullSync, 173 DatabaseCache: 256, 174 DatabaseHandles: 256, 175 TxPool: core.DefaultTxPoolConfig, 176 GPO: eth.DefaultConfig.GPO, 177 Ethash: eth.DefaultConfig.Ethash, 178 MinerGasFloor: genesis.GasLimit * 9 / 10, 179 MinerGasCeil: genesis.GasLimit * 11 / 10, 180 MinerGasPrice: big.NewInt(1), 181 MinerRecommit: time.Second, 182 }) 183 }); err != nil { 184 return nil, err 185 } 186 //启动节点,成功返回 187 return stack, stack.Start() 188 } 189