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(&ethereum); 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(&ethereum); 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, &eth.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