github.com/reapchain/go-reapchain@v0.2.15-0.20210609012950-9735c110c705/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 "bytes" 21 "fmt" 22 "math/big" 23 "math/rand" 24 "time" 25 26 "github.com/ethereum/go-ethereum/common" 27 "github.com/ethereum/go-ethereum/core" 28 "github.com/ethereum/go-ethereum/log" 29 "github.com/ethereum/go-ethereum/params" 30 ) 31 32 // makeGenesis creates a new genesis struct based on some user input. 33 func (w *wizard) makeGenesis() { 34 // Construct a default genesis block 35 genesis := &core.Genesis{ 36 Timestamp: uint64(time.Now().Unix()), 37 GasLimit: 4700000, 38 Difficulty: big.NewInt(1048576), 39 Alloc: make(core.GenesisAlloc), 40 Config: ¶ms.ChainConfig{ 41 HomesteadBlock: big.NewInt(1), 42 EIP150Block: big.NewInt(2), 43 EIP155Block: big.NewInt(3), 44 EIP158Block: big.NewInt(3), 45 }, 46 } 47 // Figure out which consensus engine to choose 48 fmt.Println() 49 fmt.Println("Which consensus engine to use? (default = clique)") 50 fmt.Println(" 1. Ethash - proof-of-work") 51 fmt.Println(" 2. Clique - proof-of-authority") 52 53 choice := w.read() 54 switch { 55 case choice == "1": 56 // In case of ethash, we're pretty much done 57 genesis.Config.Ethash = new(params.EthashConfig) 58 genesis.ExtraData = make([]byte, 32) 59 60 case choice == "" || choice == "2": 61 // In the case of clique, configure the consensus parameters 62 genesis.Difficulty = big.NewInt(1) 63 genesis.Config.Clique = ¶ms.CliqueConfig{ 64 Period: 15, 65 Epoch: 30000, 66 } 67 fmt.Println() 68 fmt.Println("How many seconds should blocks take? (default = 15)") 69 genesis.Config.Clique.Period = uint64(w.readDefaultInt(15)) 70 71 // We also need the initial list of signers 72 fmt.Println() 73 fmt.Println("Which accounts are allowed to seal? (mandatory at least one)") 74 75 var signers []common.Address 76 for { 77 if address := w.readAddress(); address != nil { 78 signers = append(signers, *address) 79 continue 80 } 81 if len(signers) > 0 { 82 break 83 } 84 } 85 // Sort the signers and embed into the extra-data section 86 for i := 0; i < len(signers); i++ { 87 for j := i + 1; j < len(signers); j++ { 88 if bytes.Compare(signers[i][:], signers[j][:]) > 0 { 89 signers[i], signers[j] = signers[j], signers[i] 90 } 91 } 92 } 93 genesis.ExtraData = make([]byte, 32+len(signers)*common.AddressLength+65) 94 for i, signer := range signers { 95 copy(genesis.ExtraData[32+i*common.AddressLength:], signer[:]) 96 } 97 98 default: 99 log.Crit("Invalid consensus engine choice", "choice", choice) 100 } 101 // Consensus all set, just ask for initial funds and go 102 fmt.Println() 103 fmt.Println("Which accounts should be pre-funded? (advisable at least one)") 104 for { 105 // Read the address of the account to fund 106 if address := w.readAddress(); address != nil { 107 genesis.Alloc[*address] = core.GenesisAccount{ 108 Balance: new(big.Int).Lsh(big.NewInt(1), 256-7), // 2^256 / 128 (allow many pre-funds without balance overflows) 109 } 110 continue 111 } 112 break 113 } 114 // Add a batch of precompile balances to avoid them getting deleted 115 for i := int64(0); i < 256; i++ { 116 genesis.Alloc[common.BigToAddress(big.NewInt(i))] = core.GenesisAccount{Balance: big.NewInt(1)} 117 } 118 fmt.Println() 119 120 // Query the user for some custom extras 121 fmt.Println() 122 fmt.Println("Specify your chain/network ID if you want an explicit one (default = random)") 123 genesis.Config.ChainId = new(big.Int).SetUint64(uint64(w.readDefaultInt(rand.Intn(65536)))) 124 125 fmt.Println() 126 fmt.Println("Anything fun to embed into the genesis block? (max 32 bytes)") 127 128 extra := w.read() 129 if len(extra) > 32 { 130 extra = extra[:32] 131 } 132 genesis.ExtraData = append([]byte(extra), genesis.ExtraData[len(extra):]...) 133 134 // All done, store the genesis and flush to disk 135 w.conf.genesis = genesis 136 }