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: ¶ms.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 = ¶ms.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 }