github.com/cheng762/platon-go@v1.8.17-0.20190529111256-7deff2d7be26/cmd/puppeth/wizard_genesis.go (about)

     1  // Copyright 2017 The go-ethereum Authors
     2  // This file is part of go-ethereum.
     3  //
     4  // go-ethereum is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU 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  // go-ethereum 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 General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU General Public License
    15  // along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package main
    18  
    19  import (
    20  	"github.com/PlatONnetwork/PlatON-Go/crypto"
    21  	"github.com/PlatONnetwork/PlatON-Go/p2p/discover"
    22  	"bytes"
    23  	"encoding/json"
    24  	"fmt"
    25  	"io/ioutil"
    26  	"math/big"
    27  	"math/rand"
    28  	"time"
    29  
    30  	"github.com/PlatONnetwork/PlatON-Go/common"
    31  	"github.com/PlatONnetwork/PlatON-Go/core"
    32  	"github.com/PlatONnetwork/PlatON-Go/log"
    33  	"github.com/PlatONnetwork/PlatON-Go/params"
    34  )
    35  
    36  // makeGenesis creates a new genesis struct based on some user input.
    37  func (w *wizard) makeGenesis() {
    38  	// Construct a default genesis block
    39  	genesis := &core.Genesis{
    40  		Timestamp:  uint64(time.Now().Unix()),
    41  		GasLimit:   3150000000,
    42  		Alloc:      make(core.GenesisAlloc),
    43  		Config: &params.ChainConfig{
    44  			HomesteadBlock: big.NewInt(1),
    45  			EIP150Block:    big.NewInt(2),
    46  			EIP155Block:    big.NewInt(3),
    47  			EIP158Block:    big.NewInt(3),
    48  			ByzantiumBlock: big.NewInt(4),
    49  		},
    50  	}
    51  	// Figure out which consensus engine to choose
    52  	fmt.Println()
    53  	fmt.Println("Which consensus engine to use? (default = CBFT)")
    54  	fmt.Println(" 1. Ethash - proof-of-work")
    55  	fmt.Println(" 2. Clique - proof-of-authority")
    56  	fmt.Println(" 3. CBFT -   Concurrent Byzantine Fault Tolerance")
    57  
    58  	choice := w.read()
    59  	switch {
    60  	case choice == "1":
    61  		// In case of ethash, we're pretty much done
    62  		genesis.Config.Ethash = new(params.EthashConfig)
    63  		genesis.ExtraData = make([]byte, 32)
    64  
    65  	case choice == "2":
    66  		// In the case of clique, configure the consensus parameters
    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  		// We also need the initial list of signers
    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  		// Sort the signers and embed into the extra-data section
    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  	case choice == "" || choice == "3":
   103  		// In the case of cbft, configure the consensus parameters
   104  		genesis.Config.Cbft = &params.CbftConfig{}
   105  		// We also need the initial list of signers
   106  		fmt.Println()
   107  		fmt.Println("Which nodes are allowed to seal? (mandatory at least four)")
   108  
   109  		var nodes []discover.Node
   110  		for {
   111  			if node := w.readNodeURL(); node != nil {
   112  				nodes = append(nodes, *node)
   113  				continue
   114  			}
   115  			if len(nodes) >= 4 {
   116  				break
   117  			}
   118  		}
   119  		// Sort the signers and embed into the extra-data section
   120  		for i := 0; i < len(nodes); i++ {
   121  			for j := i + 1; j < len(nodes); j++ {
   122  				if bytes.Compare(nodes[i].ID[:], nodes[j].ID[:]) > 0 {
   123  					nodes[i], nodes[j] = nodes[j], nodes[i]
   124  				}
   125  			}
   126  		}
   127  		genesis.ExtraData = make([]byte, 32+len(nodes)*common.AddressLength+65)
   128  		for i, node := range nodes {
   129  			copy(genesis.ExtraData[32+i*common.AddressLength:], crypto.Keccak256(node.ID[:])[12:])
   130  		}
   131  		genesis.Config.Cbft.InitialNodes = nodes
   132  	default:
   133  		log.Crit("Invalid consensus engine choice", "choice", choice)
   134  	}
   135  	// Consensus all set, just ask for initial funds and go
   136  	fmt.Println()
   137  	fmt.Println("Which accounts should be pre-funded? (advisable at least one)")
   138  	for {
   139  		// Read the address of the account to fund
   140  		if address := w.readAddress(); address != nil {
   141  			genesis.Alloc[*address] = core.GenesisAccount{
   142  				Balance: new(big.Int).Lsh(big.NewInt(1), 256-7), // 2^256 / 128 (allow many pre-funds without balance overflows)
   143  			}
   144  			continue
   145  		}
   146  		break
   147  	}
   148  	// Add a batch of precompile balances to avoid them getting deleted
   149  	for i := int64(0); i < 256; i++ {
   150  		genesis.Alloc[common.BigToAddress(big.NewInt(i))] = core.GenesisAccount{Balance: big.NewInt(1)}
   151  	}
   152  	// Query the user for some custom extras
   153  	fmt.Println()
   154  	fmt.Println("Specify your chain/network ID if you want an explicit one (default = random)")
   155  	genesis.Config.ChainID = new(big.Int).SetUint64(uint64(w.readDefaultInt(rand.Intn(65536))))
   156  
   157  	// All done, store the genesis and flush to disk
   158  	log.Info("Configured new genesis block")
   159  
   160  	w.conf.Genesis = genesis
   161  	w.conf.flush()
   162  }
   163  
   164  // manageGenesis permits the modification of chain configuration parameters in
   165  // a genesis config and the export of the entire genesis spec.
   166  func (w *wizard) manageGenesis() {
   167  	// Figure out whether to modify or export the genesis
   168  	fmt.Println()
   169  	fmt.Println(" 1. Modify existing fork rules")
   170  	fmt.Println(" 2. Export genesis configuration")
   171  	fmt.Println(" 3. Remove genesis configuration")
   172  
   173  	choice := w.read()
   174  	switch {
   175  	case choice == "1":
   176  		// Fork rule updating requested, iterate over each fork
   177  		fmt.Println()
   178  		fmt.Printf("Which block should Homestead come into effect? (default = %v)\n", w.conf.Genesis.Config.HomesteadBlock)
   179  		w.conf.Genesis.Config.HomesteadBlock = w.readDefaultBigInt(w.conf.Genesis.Config.HomesteadBlock)
   180  
   181  		fmt.Println()
   182  		fmt.Printf("Which block should EIP150 come into effect? (default = %v)\n", w.conf.Genesis.Config.EIP150Block)
   183  		w.conf.Genesis.Config.EIP150Block = w.readDefaultBigInt(w.conf.Genesis.Config.EIP150Block)
   184  
   185  		fmt.Println()
   186  		fmt.Printf("Which block should EIP155 come into effect? (default = %v)\n", w.conf.Genesis.Config.EIP155Block)
   187  		w.conf.Genesis.Config.EIP155Block = w.readDefaultBigInt(w.conf.Genesis.Config.EIP155Block)
   188  
   189  		fmt.Println()
   190  		fmt.Printf("Which block should EIP158 come into effect? (default = %v)\n", w.conf.Genesis.Config.EIP158Block)
   191  		w.conf.Genesis.Config.EIP158Block = w.readDefaultBigInt(w.conf.Genesis.Config.EIP158Block)
   192  
   193  		fmt.Println()
   194  		fmt.Printf("Which block should Byzantium come into effect? (default = %v)\n", w.conf.Genesis.Config.ByzantiumBlock)
   195  		w.conf.Genesis.Config.ByzantiumBlock = w.readDefaultBigInt(w.conf.Genesis.Config.ByzantiumBlock)
   196  
   197  		out, _ := json.MarshalIndent(w.conf.Genesis.Config, "", "  ")
   198  		fmt.Printf("Chain configuration updated:\n\n%s\n", out)
   199  
   200  	case choice == "2":
   201  		// Save whatever genesis configuration we currently have
   202  		fmt.Println()
   203  		fmt.Printf("Which file to save the genesis into? (default = %s.json)\n", w.network)
   204  		out, _ := json.MarshalIndent(w.conf.Genesis, "", "  ")
   205  		if err := ioutil.WriteFile(w.readDefaultString(fmt.Sprintf("%s.json", w.network)), out, 0644); err != nil {
   206  			log.Error("Failed to save genesis file", "err", err)
   207  		}
   208  		log.Info("Exported existing genesis block")
   209  
   210  	case choice == "3":
   211  		// Make sure we don't have any services running
   212  		if len(w.conf.servers()) > 0 {
   213  			log.Error("Genesis reset requires all services and servers torn down")
   214  			return
   215  		}
   216  		log.Info("Genesis block destroyed")
   217  
   218  		w.conf.Genesis = nil
   219  		w.conf.flush()
   220  
   221  	default:
   222  		log.Error("That's not something I can do")
   223  	}
   224  }