github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/cmd/puppeth/wizard_genesis.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:33</date>
    10  //</624450069973700608>
    11  
    12  
    13  package main
    14  
    15  import (
    16  	"bytes"
    17  	"encoding/json"
    18  	"fmt"
    19  	"io"
    20  	"io/ioutil"
    21  	"math/big"
    22  	"math/rand"
    23  	"net/http"
    24  	"os"
    25  	"path/filepath"
    26  	"time"
    27  
    28  	"github.com/ethereum/go-ethereum/common"
    29  	"github.com/ethereum/go-ethereum/core"
    30  	"github.com/ethereum/go-ethereum/log"
    31  	"github.com/ethereum/go-ethereum/params"
    32  )
    33  
    34  //
    35  func (w *wizard) makeGenesis() {
    36  //
    37  	genesis := &core.Genesis{
    38  		Timestamp:  uint64(time.Now().Unix()),
    39  		GasLimit:   4700000,
    40  		Difficulty: big.NewInt(524288),
    41  		Alloc:      make(core.GenesisAlloc),
    42  		Config: &params.ChainConfig{
    43  			HomesteadBlock:      big.NewInt(1),
    44  			EIP150Block:         big.NewInt(2),
    45  			EIP155Block:         big.NewInt(3),
    46  			EIP158Block:         big.NewInt(3),
    47  			ByzantiumBlock:      big.NewInt(4),
    48  			ConstantinopleBlock: big.NewInt(5),
    49  		},
    50  	}
    51  //
    52  	fmt.Println()
    53  	fmt.Println("Which consensus engine to use? (default = clique)")
    54  	fmt.Println(" 1. Ethash - proof-of-work")
    55  	fmt.Println(" 2. Clique - proof-of-authority")
    56  
    57  	choice := w.read()
    58  	switch {
    59  	case choice == "1":
    60  //
    61  		genesis.Config.Ethash = new(params.EthashConfig)
    62  		genesis.ExtraData = make([]byte, 32)
    63  
    64  	case choice == "" || choice == "2":
    65  //
    66  		genesis.Difficulty = big.NewInt(1)
    67  		genesis.Config.Clique = &params.CliqueConfig{
    68  			Period: 15,
    69  			Epoch:  30000,
    70  		}
    71  		fmt.Println()
    72  		fmt.Println("How many seconds should blocks take? (default = 15)")
    73  		genesis.Config.Clique.Period = uint64(w.readDefaultInt(15))
    74  
    75  //我们还需要签名者的初始列表
    76  		fmt.Println()
    77  		fmt.Println("Which accounts are allowed to seal? (mandatory at least one)")
    78  
    79  		var signers []common.Address
    80  		for {
    81  			if address := w.readAddress(); address != nil {
    82  				signers = append(signers, *address)
    83  				continue
    84  			}
    85  			if len(signers) > 0 {
    86  				break
    87  			}
    88  		}
    89  //对签名者排序并嵌入到额外的数据部分
    90  		for i := 0; i < len(signers); i++ {
    91  			for j := i + 1; j < len(signers); j++ {
    92  				if bytes.Compare(signers[i][:], signers[j][:]) > 0 {
    93  					signers[i], signers[j] = signers[j], signers[i]
    94  				}
    95  			}
    96  		}
    97  		genesis.ExtraData = make([]byte, 32+len(signers)*common.AddressLength+65)
    98  		for i, signer := range signers {
    99  			copy(genesis.ExtraData[32+i*common.AddressLength:], signer[:])
   100  		}
   101  
   102  	default:
   103  		log.Crit("Invalid consensus engine choice", "choice", choice)
   104  	}
   105  //协商一致,只需申请初始资金就可以了。
   106  	fmt.Println()
   107  	fmt.Println("Which accounts should be pre-funded? (advisable at least one)")
   108  	for {
   109  //读取要资助的帐户的地址
   110  		if address := w.readAddress(); address != nil {
   111  			genesis.Alloc[*address] = core.GenesisAccount{
   112  Balance: new(big.Int).Lsh(big.NewInt(1), 256-7), //2^256/128(允许多个预付款没有余额溢出)
   113  			}
   114  			continue
   115  		}
   116  		break
   117  	}
   118  	fmt.Println()
   119  	fmt.Println("Should the precompile-addresses (0x1 .. 0xff) be pre-funded with 1 wei? (advisable yes)")
   120  	if w.readDefaultYesNo(true) {
   121  //添加一批预编译余额以避免删除它们
   122  		for i := int64(0); i < 256; i++ {
   123  			genesis.Alloc[common.BigToAddress(big.NewInt(i))] = core.GenesisAccount{Balance: big.NewInt(1)}
   124  		}
   125  	}
   126  //向用户查询一些自定义附加项
   127  	fmt.Println()
   128  	fmt.Println("Specify your chain/network ID if you want an explicit one (default = random)")
   129  	genesis.Config.ChainID = new(big.Int).SetUint64(uint64(w.readDefaultInt(rand.Intn(65536))))
   130  
   131  //全部完成,存储Genesis并刷新到磁盘
   132  	log.Info("Configured new genesis block")
   133  
   134  	w.conf.Genesis = genesis
   135  	w.conf.flush()
   136  }
   137  
   138  //
   139  func (w *wizard) importGenesis() {
   140  //
   141  	fmt.Println()
   142  	fmt.Println("Where's the genesis file? (local file or http/https url)")
   143  	url := w.readURL()
   144  
   145  //
   146  	var reader io.Reader
   147  
   148  	switch url.Scheme {
   149  	case "http", "https":
   150  //
   151  		res, err := http.Get(url.String())
   152  		if err != nil {
   153  			log.Error("Failed to retrieve remote genesis", "err", err)
   154  			return
   155  		}
   156  		defer res.Body.Close()
   157  		reader = res.Body
   158  
   159  	case "":
   160  //
   161  		file, err := os.Open(url.String())
   162  		if err != nil {
   163  			log.Error("Failed to open local genesis", "err", err)
   164  			return
   165  		}
   166  		defer file.Close()
   167  		reader = file
   168  
   169  	default:
   170  		log.Error("Unsupported genesis URL scheme", "scheme", url.Scheme)
   171  		return
   172  	}
   173  //
   174  	var genesis core.Genesis
   175  	if err := json.NewDecoder(reader).Decode(&genesis); err != nil {
   176  		log.Error("Invalid genesis spec: %v", err)
   177  		return
   178  	}
   179  	log.Info("Imported genesis block")
   180  
   181  	w.conf.Genesis = &genesis
   182  	w.conf.flush()
   183  }
   184  
   185  //ManageGenesis允许在
   186  //一个Genesis配置和整个Genesis规范的导出。
   187  func (w *wizard) manageGenesis() {
   188  //确定是修改还是导出Genesis
   189  	fmt.Println()
   190  	fmt.Println(" 1. Modify existing fork rules")
   191  	fmt.Println(" 2. Export genesis configurations")
   192  	fmt.Println(" 3. Remove genesis configuration")
   193  
   194  	choice := w.read()
   195  	switch choice {
   196  	case "1":
   197  //请求了fork规则更新,对每个fork进行迭代
   198  		fmt.Println()
   199  		fmt.Printf("Which block should Homestead come into effect? (default = %v)\n", w.conf.Genesis.Config.HomesteadBlock)
   200  		w.conf.Genesis.Config.HomesteadBlock = w.readDefaultBigInt(w.conf.Genesis.Config.HomesteadBlock)
   201  
   202  		fmt.Println()
   203  		fmt.Printf("Which block should EIP150 (Tangerine Whistle) come into effect? (default = %v)\n", w.conf.Genesis.Config.EIP150Block)
   204  		w.conf.Genesis.Config.EIP150Block = w.readDefaultBigInt(w.conf.Genesis.Config.EIP150Block)
   205  
   206  		fmt.Println()
   207  		fmt.Printf("Which block should EIP155 (Spurious Dragon) come into effect? (default = %v)\n", w.conf.Genesis.Config.EIP155Block)
   208  		w.conf.Genesis.Config.EIP155Block = w.readDefaultBigInt(w.conf.Genesis.Config.EIP155Block)
   209  
   210  		fmt.Println()
   211  		fmt.Printf("Which block should EIP158/161 (also Spurious Dragon) come into effect? (default = %v)\n", w.conf.Genesis.Config.EIP158Block)
   212  		w.conf.Genesis.Config.EIP158Block = w.readDefaultBigInt(w.conf.Genesis.Config.EIP158Block)
   213  
   214  		fmt.Println()
   215  		fmt.Printf("Which block should Byzantium come into effect? (default = %v)\n", w.conf.Genesis.Config.ByzantiumBlock)
   216  		w.conf.Genesis.Config.ByzantiumBlock = w.readDefaultBigInt(w.conf.Genesis.Config.ByzantiumBlock)
   217  
   218  		fmt.Println()
   219  		fmt.Printf("Which block should Constantinople come into effect? (default = %v)\n", w.conf.Genesis.Config.ConstantinopleBlock)
   220  		w.conf.Genesis.Config.ConstantinopleBlock = w.readDefaultBigInt(w.conf.Genesis.Config.ConstantinopleBlock)
   221  
   222  		out, _ := json.MarshalIndent(w.conf.Genesis.Config, "", "  ")
   223  		fmt.Printf("Chain configuration updated:\n\n%s\n", out)
   224  
   225  	case "2":
   226  //保存我们当前的Genesis配置
   227  		fmt.Println()
   228  		fmt.Printf("Which folder to save the genesis specs into? (default = current)\n")
   229  		fmt.Printf("  Will create %s.json, %s-aleth.json, %s-harmony.json, %s-parity.json\n", w.network, w.network, w.network, w.network)
   230  
   231  		folder := w.readDefaultString(".")
   232  		if err := os.MkdirAll(folder, 0755); err != nil {
   233  			log.Error("Failed to create spec folder", "folder", folder, "err", err)
   234  			return
   235  		}
   236  		out, _ := json.MarshalIndent(w.conf.Genesis, "", "  ")
   237  
   238  //
   239  		gethJson := filepath.Join(folder, fmt.Sprintf("%s.json", w.network))
   240  		if err := ioutil.WriteFile((gethJson), out, 0644); err != nil {
   241  			log.Error("Failed to save genesis file", "err", err)
   242  			return
   243  		}
   244  		log.Info("Saved native genesis chain spec", "path", gethJson)
   245  
   246  //
   247  		if spec, err := newAlethGenesisSpec(w.network, w.conf.Genesis); err != nil {
   248  			log.Error("Failed to create Aleth chain spec", "err", err)
   249  		} else {
   250  			saveGenesis(folder, w.network, "aleth", spec)
   251  		}
   252  //
   253  		if spec, err := newParityChainSpec(w.network, w.conf.Genesis, []string{}); err != nil {
   254  			log.Error("Failed to create Parity chain spec", "err", err)
   255  		} else {
   256  			saveGenesis(folder, w.network, "parity", spec)
   257  		}
   258  //
   259  		saveGenesis(folder, w.network, "harmony", w.conf.Genesis)
   260  
   261  	case "3":
   262  //
   263  		if len(w.conf.servers()) > 0 {
   264  			log.Error("Genesis reset requires all services and servers torn down")
   265  			return
   266  		}
   267  		log.Info("Genesis block destroyed")
   268  
   269  		w.conf.Genesis = nil
   270  		w.conf.flush()
   271  	default:
   272  		log.Error("That's not something I can do")
   273  		return
   274  	}
   275  }
   276  
   277  //
   278  func saveGenesis(folder, network, client string, spec interface{}) {
   279  	path := filepath.Join(folder, fmt.Sprintf("%s-%s.json", network, client))
   280  
   281  	out, _ := json.Marshal(spec)
   282  	if err := ioutil.WriteFile(path, out, 0644); err != nil {
   283  		log.Error("Failed to save genesis file", "client", client, "err", err)
   284  		return
   285  	}
   286  	log.Info("Saved genesis chain spec", "client", client, "path", path)
   287  }
   288