github.com/SmartMeshFoundation/Spectrum@v0.0.0-20220621030607-452a266fee1e/cmd/puppeth/wizard_genesis.go (about)

     1  // Copyright 2017 The Spectrum Authors
     2  // This file is part of Spectrum.
     3  //
     4  // Spectrum 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  // Spectrum 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 Spectrum. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package main
    18  
    19  import (
    20  	"bytes"
    21  	"encoding/json"
    22  	"fmt"
    23  	"io/ioutil"
    24  	"math/big"
    25  	"math/rand"
    26  	"time"
    27  
    28  	"github.com/SmartMeshFoundation/Spectrum/common"
    29  	"github.com/SmartMeshFoundation/Spectrum/core"
    30  	"github.com/SmartMeshFoundation/Spectrum/log"
    31  	"github.com/SmartMeshFoundation/Spectrum/params"
    32  )
    33  
    34  // makeGenesis creates a new genesis struct based on some user input.
    35  func (w *wizard) makeGenesis() {
    36  	// Construct a default genesis block
    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  		},
    49  	}
    50  	// Figure out which consensus engine to choose
    51  	fmt.Println()
    52  	fmt.Println("Which consensus engine to use? (default = clique)")
    53  	fmt.Println(" 1. Ethash - proof-of-work")
    54  	fmt.Println(" 2. Clique - proof-of-authority")
    55  
    56  	choice := w.read()
    57  	switch {
    58  	case choice == "1":
    59  		// In case of ethash, we're pretty much done
    60  		genesis.Config.Ethash = new(params.EthashConfig)
    61  		genesis.ExtraData = make([]byte, 32)
    62  
    63  	case choice == "" || choice == "2":
    64  		// In the case of clique, configure the consensus parameters
    65  		genesis.Difficulty = big.NewInt(1)
    66  		genesis.Config.Clique = &params.CliqueConfig{
    67  			Period: 15,
    68  			Epoch:  30000,
    69  		}
    70  		fmt.Println()
    71  		fmt.Println("How many seconds should blocks take? (default = 15)")
    72  		genesis.Config.Clique.Period = uint64(w.readDefaultInt(15))
    73  
    74  		// We also need the initial list of signers
    75  		fmt.Println()
    76  		fmt.Println("Which accounts are allowed to seal? (mandatory at least one)")
    77  
    78  		var signers []common.Address
    79  		for {
    80  			if address := w.readAddress(); address != nil {
    81  				signers = append(signers, *address)
    82  				continue
    83  			}
    84  			if len(signers) > 0 {
    85  				break
    86  			}
    87  		}
    88  		// Sort the signers and embed into the extra-data section
    89  		for i := 0; i < len(signers); i++ {
    90  			for j := i + 1; j < len(signers); j++ {
    91  				if bytes.Compare(signers[i][:], signers[j][:]) > 0 {
    92  					signers[i], signers[j] = signers[j], signers[i]
    93  				}
    94  			}
    95  		}
    96  		genesis.ExtraData = make([]byte, 32+len(signers)*common.AddressLength+65)
    97  		for i, signer := range signers {
    98  			copy(genesis.ExtraData[32+i*common.AddressLength:], signer[:])
    99  		}
   100  
   101  	default:
   102  		log.Crit("Invalid consensus engine choice", "choice", choice)
   103  	}
   104  	// Consensus all set, just ask for initial funds and go
   105  	fmt.Println()
   106  	fmt.Println("Which accounts should be pre-funded? (advisable at least one)")
   107  	for {
   108  		// Read the address of the account to fund
   109  		if address := w.readAddress(); address != nil {
   110  			genesis.Alloc[*address] = core.GenesisAccount{
   111  				Balance: new(big.Int).Lsh(big.NewInt(1), 256-7), // 2^256 / 128 (allow many pre-funds without balance overflows)
   112  			}
   113  			continue
   114  		}
   115  		break
   116  	}
   117  	// Add a batch of precompile balances to avoid them getting deleted
   118  	for i := int64(0); i < 256; i++ {
   119  		genesis.Alloc[common.BigToAddress(big.NewInt(i))] = core.GenesisAccount{Balance: big.NewInt(1)}
   120  	}
   121  	// Query the user for some custom extras
   122  	fmt.Println()
   123  	fmt.Println("Specify your chain/network ID if you want an explicit one (default = random)")
   124  	genesis.Config.ChainId = new(big.Int).SetUint64(uint64(w.readDefaultInt(rand.Intn(65536))))
   125  
   126  	// All done, store the genesis and flush to disk
   127  	log.Info("Configured new genesis block")
   128  
   129  	w.conf.Genesis = genesis
   130  	w.conf.flush()
   131  }
   132  
   133  // manageGenesis permits the modification of chain configuration parameters in
   134  // a genesis config and the export of the entire genesis spec.
   135  func (w *wizard) manageGenesis() {
   136  	// Figure out whether to modify or export the genesis
   137  	fmt.Println()
   138  	fmt.Println(" 1. Modify existing fork rules")
   139  	fmt.Println(" 2. Export genesis configuration")
   140  	fmt.Println(" 3. Remove genesis configuration")
   141  
   142  	choice := w.read()
   143  	switch {
   144  	case choice == "1":
   145  		// Fork rule updating requested, iterate over each fork
   146  		fmt.Println()
   147  		fmt.Printf("Which block should Homestead come into effect? (default = %v)\n", w.conf.Genesis.Config.HomesteadBlock)
   148  		w.conf.Genesis.Config.HomesteadBlock = w.readDefaultBigInt(w.conf.Genesis.Config.HomesteadBlock)
   149  
   150  		fmt.Println()
   151  		fmt.Printf("Which block should EIP150 come into effect? (default = %v)\n", w.conf.Genesis.Config.EIP150Block)
   152  		w.conf.Genesis.Config.EIP150Block = w.readDefaultBigInt(w.conf.Genesis.Config.EIP150Block)
   153  
   154  		fmt.Println()
   155  		fmt.Printf("Which block should EIP155 come into effect? (default = %v)\n", w.conf.Genesis.Config.EIP155Block)
   156  		w.conf.Genesis.Config.EIP155Block = w.readDefaultBigInt(w.conf.Genesis.Config.EIP155Block)
   157  
   158  		fmt.Println()
   159  		fmt.Printf("Which block should EIP158 come into effect? (default = %v)\n", w.conf.Genesis.Config.EIP158Block)
   160  		w.conf.Genesis.Config.EIP158Block = w.readDefaultBigInt(w.conf.Genesis.Config.EIP158Block)
   161  
   162  		fmt.Println()
   163  		fmt.Printf("Which block should Byzantium come into effect? (default = %v)\n", w.conf.Genesis.Config.ByzantiumBlock)
   164  		w.conf.Genesis.Config.ByzantiumBlock = w.readDefaultBigInt(w.conf.Genesis.Config.ByzantiumBlock)
   165  
   166  		out, _ := json.MarshalIndent(w.conf.Genesis.Config, "", "  ")
   167  		fmt.Printf("Chain configuration updated:\n\n%s\n", out)
   168  
   169  	case choice == "2":
   170  		// Save whatever genesis configuration we currently have
   171  		fmt.Println()
   172  		fmt.Printf("Which file to save the genesis into? (default = %s.json)\n", w.network)
   173  		out, _ := json.MarshalIndent(w.conf.Genesis, "", "  ")
   174  		if err := ioutil.WriteFile(w.readDefaultString(fmt.Sprintf("%s.json", w.network)), out, 0644); err != nil {
   175  			log.Error("Failed to save genesis file", "err", err)
   176  		}
   177  		log.Info("Exported existing genesis block")
   178  
   179  	case choice == "3":
   180  		// Make sure we don't have any services running
   181  		if len(w.conf.servers()) > 0 {
   182  			log.Error("Genesis reset requires all services and servers torn down")
   183  			return
   184  		}
   185  		log.Info("Genesis block destroyed")
   186  
   187  		w.conf.Genesis = nil
   188  		w.conf.flush()
   189  
   190  	default:
   191  		log.Error("That's not something I can do")
   192  	}
   193  }