github.com/XinFinOrg/xdcchain@v1.1.0/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 "encoding/json" 22 "fmt" 23 "io" 24 "io/ioutil" 25 "math/rand" 26 "net/http" 27 "os" 28 "path/filepath" 29 "time" 30 31 "github.com/ethereum/go-ethereum/common" 32 "github.com/ethereum/go-ethereum/core" 33 "github.com/ethereum/go-ethereum/log" 34 "github.com/ethereum/go-ethereum/params" 35 36 "context" 37 "math/big" 38 39 "github.com/ethereum/go-ethereum/accounts/abi/bind" 40 "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" 41 blockSignerContract "github.com/ethereum/go-ethereum/contracts/blocksigner" 42 multiSignWalletContract "github.com/ethereum/go-ethereum/contracts/multisigwallet" 43 randomizeContract "github.com/ethereum/go-ethereum/contracts/randomize" 44 validatorContract "github.com/ethereum/go-ethereum/contracts/validator" 45 "github.com/ethereum/go-ethereum/crypto" 46 "github.com/ethereum/go-ethereum/rlp" 47 ) 48 49 // makeGenesis creates a new genesis struct based on some user input. 50 func (w *wizard) makeGenesis() { 51 // Construct a default genesis block 52 genesis := &core.Genesis{ 53 Timestamp: uint64(time.Now().Unix()), 54 GasLimit: 4700000, 55 Difficulty: big.NewInt(524288), 56 Alloc: make(core.GenesisAlloc), 57 Config: ¶ms.ChainConfig{ 58 HomesteadBlock: big.NewInt(1), 59 EIP150Block: big.NewInt(2), 60 EIP155Block: big.NewInt(3), 61 EIP158Block: big.NewInt(3), 62 ByzantiumBlock: big.NewInt(4), 63 ConstantinopleBlock: big.NewInt(5), 64 }, 65 } 66 // Figure out which consensus engine to choose 67 fmt.Println() 68 fmt.Println("Which consensus engine to use? (default = XDPoS)") 69 fmt.Println(" 1. Ethash - proof-of-work") 70 fmt.Println(" 2. Clique - proof-of-authority") 71 fmt.Println(" 3. XDPoS - delegated-proof-of-stake") 72 73 choice := w.read() 74 switch { 75 case choice == "1": 76 // In case of ethash, we're pretty much done 77 genesis.Config.Ethash = new(params.EthashConfig) 78 genesis.ExtraData = make([]byte, 32) 79 80 case choice == "2": 81 // In the case of clique, configure the consensus parameters 82 genesis.Difficulty = big.NewInt(1) 83 genesis.Config.Clique = ¶ms.CliqueConfig{ 84 Period: 15, 85 Epoch: 30000, 86 } 87 fmt.Println() 88 fmt.Println("How many seconds should blocks take? (default = 15)") 89 genesis.Config.Clique.Period = uint64(w.readDefaultInt(15)) 90 91 // We also need the initial list of signers 92 fmt.Println() 93 fmt.Println("Which accounts are allowed to seal? (mandatory at least one)") 94 95 var signers []common.Address 96 for { 97 if address := w.readAddress(); address != nil { 98 signers = append(signers, *address) 99 continue 100 } 101 if len(signers) > 0 { 102 break 103 } 104 } 105 // Sort the signers and embed into the extra-data section 106 for i := 0; i < len(signers); i++ { 107 for j := i + 1; j < len(signers); j++ { 108 if bytes.Compare(signers[i][:], signers[j][:]) > 0 { 109 signers[i], signers[j] = signers[j], signers[i] 110 } 111 } 112 } 113 genesis.ExtraData = make([]byte, 32+len(signers)*common.AddressLength+65) 114 for i, signer := range signers { 115 copy(genesis.ExtraData[32+i*common.AddressLength:], signer[:]) 116 } 117 118 case choice == "" || choice == "3": 119 genesis.Difficulty = big.NewInt(1) 120 genesis.Config.XDPoS = ¶ms.XDPoSConfig{ 121 Period: 15, 122 Epoch: 30000, 123 Reward: 0, 124 } 125 fmt.Println() 126 fmt.Println("How many seconds should blocks take? (default = 2)") 127 genesis.Config.XDPoS.Period = uint64(w.readDefaultInt(2)) 128 129 fmt.Println() 130 fmt.Println("How many XDC should be rewarded to masternode? (default = 5000)") 131 genesis.Config.XDPoS.Reward = uint64(w.readDefaultInt(5000)) 132 133 fmt.Println() 134 fmt.Println("Who own the first masternodes? (mandatory)") 135 owner := *w.readAddress() 136 137 // We also need the initial list of signers 138 fmt.Println() 139 fmt.Println("Which accounts are allowed to seal (signers)? (mandatory at least one)") 140 141 var signers []common.Address 142 for { 143 if address := w.readAddress(); address != nil { 144 signers = append(signers, *address) 145 continue 146 } 147 if len(signers) > 0 { 148 break 149 } 150 } 151 // Sort the signers and embed into the extra-data section 152 for i := 0; i < len(signers); i++ { 153 for j := i + 1; j < len(signers); j++ { 154 if bytes.Compare(signers[i][:], signers[j][:]) > 0 { 155 signers[i], signers[j] = signers[j], signers[i] 156 } 157 } 158 } 159 validatorCap := new(big.Int) 160 validatorCap.SetString("10000000000000000000000000", 10) 161 var validatorCaps []*big.Int 162 genesis.ExtraData = make([]byte, 32+len(signers)*common.AddressLength+65) 163 for i, signer := range signers { 164 validatorCaps = append(validatorCaps, validatorCap) 165 copy(genesis.ExtraData[32+i*common.AddressLength:], signer[:]) 166 } 167 168 fmt.Println() 169 fmt.Println("How many blocks per epoch? (default = 900)") 170 epochNumber := uint64(w.readDefaultInt(900)) 171 genesis.Config.XDPoS.Epoch = epochNumber 172 genesis.Config.XDPoS.RewardCheckpoint = epochNumber 173 174 fmt.Println() 175 fmt.Println("How many blocks before checkpoint need to prepare new set of masternodes? (default = 450)") 176 genesis.Config.XDPoS.Gap = uint64(w.readDefaultInt(450)) 177 178 fmt.Println() 179 fmt.Println("What is foundation wallet address? (default = xdc746249C61f5832C5eEd53172776b460491bDcd5C)") 180 genesis.Config.XDPoS.FoudationWalletAddr = w.readDefaultAddress(common.HexToAddress(common.FoudationAddr)) 181 182 // Validator Smart Contract Code 183 pKey, _ := crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 184 addr := crypto.PubkeyToAddress(pKey.PublicKey) 185 contractBackend := backends.NewSimulatedBackend(core.GenesisAlloc{addr: {Balance: big.NewInt(1000000000)}}, 10000000) 186 transactOpts := bind.NewKeyedTransactor(pKey) 187 188 validatorAddress, _, err := validatorContract.DeployValidator(transactOpts, contractBackend, signers, validatorCaps, owner) 189 if err != nil { 190 fmt.Println("Can't deploy root registry") 191 } 192 contractBackend.Commit() 193 194 d := time.Now().Add(1000 * time.Millisecond) 195 ctx, cancel := context.WithDeadline(context.Background(), d) 196 defer cancel() 197 code, _ := contractBackend.CodeAt(ctx, validatorAddress, nil) 198 storage := make(map[common.Hash]common.Hash) 199 f := func(key, val common.Hash) bool { 200 decode := []byte{} 201 trim := bytes.TrimLeft(val.Bytes(), "\x00") 202 rlp.DecodeBytes(trim, &decode) 203 storage[key] = common.BytesToHash(decode) 204 log.Info("DecodeBytes", "value", val.String(), "decode", storage[key].String()) 205 return true 206 } 207 contractBackend.ForEachStorageAt(ctx, validatorAddress, nil, f) 208 genesis.Alloc[common.HexToAddress(common.MasternodeVotingSMC)] = core.GenesisAccount{ 209 Balance: validatorCap.Mul(validatorCap, big.NewInt(int64(len(validatorCaps)))), 210 Code: code, 211 Storage: storage, 212 } 213 214 fmt.Println() 215 fmt.Println("Which accounts are allowed to confirm in Foudation MultiSignWallet?") 216 var owners []common.Address 217 for { 218 if address := w.readAddress(); address != nil { 219 owners = append(owners, *address) 220 continue 221 } 222 if len(owners) > 0 { 223 break 224 } 225 } 226 fmt.Println() 227 fmt.Println("How many require for confirm tx in Foudation MultiSignWallet? (default = 2)") 228 required := int64(w.readDefaultInt(2)) 229 230 // MultiSigWallet. 231 multiSignWalletAddr, _, err := multiSignWalletContract.DeployMultiSigWallet(transactOpts, contractBackend, owners, big.NewInt(required)) 232 if err != nil { 233 fmt.Println("Can't deploy MultiSignWallet SMC") 234 } 235 contractBackend.Commit() 236 code, _ = contractBackend.CodeAt(ctx, multiSignWalletAddr, nil) 237 storage = make(map[common.Hash]common.Hash) 238 contractBackend.ForEachStorageAt(ctx, multiSignWalletAddr, nil, f) 239 fBalance := big.NewInt(0) // 3 billion 240 fBalance.Add(fBalance, big.NewInt(0*1000*1000*1000)) 241 fBalance.Mul(fBalance, big.NewInt(1000000000000000000)) 242 genesis.Alloc[common.HexToAddress(common.FoudationAddr)] = core.GenesisAccount{ 243 Balance: fBalance, 244 Code: code, 245 Storage: storage, 246 } 247 248 // Block Signers Smart Contract 249 blockSignerAddress, _, err := blockSignerContract.DeployBlockSigner(transactOpts, contractBackend, big.NewInt(int64(epochNumber))) 250 if err != nil { 251 fmt.Println("Can't deploy root registry") 252 } 253 contractBackend.Commit() 254 255 code, _ = contractBackend.CodeAt(ctx, blockSignerAddress, nil) 256 storage = make(map[common.Hash]common.Hash) 257 contractBackend.ForEachStorageAt(ctx, blockSignerAddress, nil, f) 258 genesis.Alloc[common.HexToAddress(common.BlockSigners)] = core.GenesisAccount{ 259 Balance: big.NewInt(0), 260 Code: code, 261 Storage: storage, 262 } 263 264 // Randomize Smart Contract Code 265 randomizeAddress, _, err := randomizeContract.DeployRandomize(transactOpts, contractBackend) 266 if err != nil { 267 fmt.Println("Can't deploy root registry") 268 } 269 contractBackend.Commit() 270 271 code, _ = contractBackend.CodeAt(ctx, randomizeAddress, nil) 272 storage = make(map[common.Hash]common.Hash) 273 contractBackend.ForEachStorageAt(ctx, randomizeAddress, nil, f) 274 genesis.Alloc[common.HexToAddress(common.RandomizeSMC)] = core.GenesisAccount{ 275 Balance: big.NewInt(0), 276 Code: code, 277 Storage: storage, 278 } 279 280 fmt.Println() 281 fmt.Println("Which accounts are allowed to confirm in Team MultiSignWallet?") 282 var teams []common.Address 283 for { 284 if address := w.readAddress(); address != nil { 285 teams = append(teams, *address) 286 continue 287 } 288 if len(teams) > 0 { 289 break 290 } 291 } 292 fmt.Println() 293 fmt.Println("How many require for confirm tx in Team MultiSignWallet? (default = 2)") 294 required = int64(w.readDefaultInt(2)) 295 296 // MultiSigWallet. 297 multiSignWalletTeamAddr, _, err := multiSignWalletContract.DeployMultiSigWallet(transactOpts, contractBackend, teams, big.NewInt(required)) 298 if err != nil { 299 fmt.Println("Can't deploy MultiSignWallet SMC") 300 } 301 contractBackend.Commit() 302 code, _ = contractBackend.CodeAt(ctx, multiSignWalletTeamAddr, nil) 303 storage = make(map[common.Hash]common.Hash) 304 contractBackend.ForEachStorageAt(ctx, multiSignWalletTeamAddr, nil, f) 305 // Team balance. 306 balance := big.NewInt(0) // 20 billion 307 balance.Add(balance, big.NewInt(30*1000*1000)) 308 balance.Mul(balance, big.NewInt(1000000000000000000)) 309 subBalance := big.NewInt(0) // i * 50k 310 subBalance.Add(subBalance, big.NewInt(int64(len(signers))*10*1000*1000)) 311 subBalance.Mul(subBalance, big.NewInt(1000000000000000000)) 312 balance.Sub(balance, subBalance) // 12m - i * 50k 313 genesis.Alloc[common.HexToAddress(common.TeamAddr)] = core.GenesisAccount{ 314 Balance: balance, 315 Code: code, 316 Storage: storage, 317 } 318 319 fmt.Println() 320 fmt.Println("What is swap wallet address for fund 37.47Billion XDC?") 321 swapAddr := *w.readAddress() 322 baseBalance := big.NewInt(0) // 14.5Billion 323 baseBalance.Add(baseBalance, big.NewInt(3747*1000*1000*10)) 324 baseBalance.Mul(baseBalance, big.NewInt(1000000000000000000)) 325 genesis.Alloc[swapAddr] = core.GenesisAccount{ 326 Balance: baseBalance, 327 } 328 329 default: 330 log.Crit("Invalid consensus engine choice", "choice", choice) 331 } 332 // Consensus all set, just ask for initial funds and go 333 fmt.Println() 334 fmt.Println("Which accounts should be pre-funded? (advisable at least one)") 335 for { 336 // Read the address of the account to fund 337 if address := w.readAddress(); address != nil { 338 genesis.Alloc[*address] = core.GenesisAccount{ 339 Balance: new(big.Int).Lsh(big.NewInt(1), 256-7), // 2^256 / 128 (allow many pre-funds without balance overflows) 340 } 341 continue 342 } 343 break 344 } 345 // Add a batch of precompile balances to avoid them getting deleted 346 for i := int64(0); i < 2; i++ { 347 genesis.Alloc[common.BigToAddress(big.NewInt(i))] = core.GenesisAccount{Balance: big.NewInt(0)} 348 } 349 // Query the user for some custom extras 350 fmt.Println() 351 fmt.Println("Specify your chain/network ID if you want an explicit one (default = random)") 352 genesis.Config.ChainID = new(big.Int).SetUint64(uint64(w.readDefaultInt(rand.Intn(65536)))) 353 354 // All done, store the genesis and flush to disk 355 log.Info("Configured new genesis block") 356 357 w.conf.Genesis = genesis 358 w.conf.flush() 359 } 360 361 // importGenesis imports a Geth genesis spec into puppeth. 362 func (w *wizard) importGenesis() { 363 // Request the genesis JSON spec URL from the user 364 fmt.Println() 365 fmt.Println("Where's the genesis file? (local file or http/https url)") 366 url := w.readURL() 367 368 // Convert the various allowed URLs to a reader stream 369 var reader io.Reader 370 371 switch url.Scheme { 372 case "http", "https": 373 // Remote web URL, retrieve it via an HTTP client 374 res, err := http.Get(url.String()) 375 if err != nil { 376 log.Error("Failed to retrieve remote genesis", "err", err) 377 return 378 } 379 defer res.Body.Close() 380 reader = res.Body 381 382 case "": 383 // Schemaless URL, interpret as a local file 384 file, err := os.Open(url.String()) 385 if err != nil { 386 log.Error("Failed to open local genesis", "err", err) 387 return 388 } 389 defer file.Close() 390 reader = file 391 392 default: 393 log.Error("Unsupported genesis URL scheme", "scheme", url.Scheme) 394 return 395 } 396 // Parse the genesis file and inject it successful 397 var genesis core.Genesis 398 if err := json.NewDecoder(reader).Decode(&genesis); err != nil { 399 log.Error("Invalid genesis spec: %v", err) 400 return 401 } 402 log.Info("Imported genesis block") 403 404 w.conf.Genesis = &genesis 405 w.conf.flush() 406 } 407 408 // manageGenesis permits the modification of chain configuration parameters in 409 // a genesis config and the export of the entire genesis spec. 410 func (w *wizard) manageGenesis() { 411 // Figure out whether to modify or export the genesis 412 fmt.Println() 413 fmt.Println(" 1. Modify existing fork rules") 414 fmt.Println(" 2. Export genesis configurations") 415 fmt.Println(" 3. Remove genesis configuration") 416 417 choice := w.read() 418 switch choice { 419 case "1": 420 // Fork rule updating requested, iterate over each fork 421 fmt.Println() 422 fmt.Printf("Which block should Homestead come into effect? (default = %v)\n", w.conf.Genesis.Config.HomesteadBlock) 423 w.conf.Genesis.Config.HomesteadBlock = w.readDefaultBigInt(w.conf.Genesis.Config.HomesteadBlock) 424 425 fmt.Println() 426 fmt.Printf("Which block should EIP150 (Tangerine Whistle) come into effect? (default = %v)\n", w.conf.Genesis.Config.EIP150Block) 427 w.conf.Genesis.Config.EIP150Block = w.readDefaultBigInt(w.conf.Genesis.Config.EIP150Block) 428 429 fmt.Println() 430 fmt.Printf("Which block should EIP155 (Spurious Dragon) come into effect? (default = %v)\n", w.conf.Genesis.Config.EIP155Block) 431 w.conf.Genesis.Config.EIP155Block = w.readDefaultBigInt(w.conf.Genesis.Config.EIP155Block) 432 433 fmt.Println() 434 fmt.Printf("Which block should EIP158/161 (also Spurious Dragon) come into effect? (default = %v)\n", w.conf.Genesis.Config.EIP158Block) 435 w.conf.Genesis.Config.EIP158Block = w.readDefaultBigInt(w.conf.Genesis.Config.EIP158Block) 436 437 fmt.Println() 438 fmt.Printf("Which block should Byzantium come into effect? (default = %v)\n", w.conf.Genesis.Config.ByzantiumBlock) 439 w.conf.Genesis.Config.ByzantiumBlock = w.readDefaultBigInt(w.conf.Genesis.Config.ByzantiumBlock) 440 441 fmt.Println() 442 fmt.Printf("Which block should Constantinople come into effect? (default = %v)\n", w.conf.Genesis.Config.ConstantinopleBlock) 443 w.conf.Genesis.Config.ConstantinopleBlock = w.readDefaultBigInt(w.conf.Genesis.Config.ConstantinopleBlock) 444 if w.conf.Genesis.Config.PetersburgBlock == nil { 445 w.conf.Genesis.Config.PetersburgBlock = w.conf.Genesis.Config.ConstantinopleBlock 446 } 447 fmt.Println() 448 fmt.Printf("Which block should Constantinople-Fix (remove EIP-1283) come into effect? (default = %v)\n", w.conf.Genesis.Config.PetersburgBlock) 449 w.conf.Genesis.Config.PetersburgBlock = w.readDefaultBigInt(w.conf.Genesis.Config.PetersburgBlock) 450 451 out, _ := json.MarshalIndent(w.conf.Genesis.Config, "", " ") 452 fmt.Printf("Chain configuration updated:\n\n%s\n", out) 453 454 w.conf.flush() 455 456 case "2": 457 // Save whatever genesis configuration we currently have 458 fmt.Println() 459 fmt.Printf("Which folder to save the genesis specs into? (default = current)\n") 460 fmt.Printf(" Will create %s.json, %s-aleth.json, %s-harmony.json, %s-parity.json\n", w.network, w.network, w.network, w.network) 461 462 folder := w.readDefaultString(".") 463 if err := os.MkdirAll(folder, 0755); err != nil { 464 log.Error("Failed to create spec folder", "folder", folder, "err", err) 465 return 466 } 467 out, _ := json.MarshalIndent(w.conf.Genesis, "", " ") 468 469 // Export the native genesis spec used by puppeth and Geth 470 gethJson := filepath.Join(folder, fmt.Sprintf("%s.json", w.network)) 471 if err := ioutil.WriteFile((gethJson), out, 0644); err != nil { 472 log.Error("Failed to save genesis file", "err", err) 473 return 474 } 475 log.Info("Saved native genesis chain spec", "path", gethJson) 476 477 // Export the genesis spec used by Aleth (formerly C++ Ethereum) 478 if spec, err := newAlethGenesisSpec(w.network, w.conf.Genesis); err != nil { 479 log.Error("Failed to create Aleth chain spec", "err", err) 480 } else { 481 saveGenesis(folder, w.network, "aleth", spec) 482 } 483 // Export the genesis spec used by Parity 484 if spec, err := newParityChainSpec(w.network, w.conf.Genesis, []string{}); err != nil { 485 log.Error("Failed to create Parity chain spec", "err", err) 486 } else { 487 saveGenesis(folder, w.network, "parity", spec) 488 } 489 // Export the genesis spec used by Harmony (formerly EthereumJ 490 saveGenesis(folder, w.network, "harmony", w.conf.Genesis) 491 492 case "3": 493 // Make sure we don't have any services running 494 if len(w.conf.servers()) > 0 { 495 log.Error("Genesis reset requires all services and servers torn down") 496 return 497 } 498 log.Info("Genesis block destroyed") 499 500 w.conf.Genesis = nil 501 w.conf.flush() 502 default: 503 log.Error("That's not something I can do") 504 return 505 } 506 } 507 508 // saveGenesis JSON encodes an arbitrary genesis spec into a pre-defined file. 509 func saveGenesis(folder, network, client string, spec interface{}) { 510 path := filepath.Join(folder, fmt.Sprintf("%s-%s.json", network, client)) 511 512 out, _ := json.Marshal(spec) 513 if err := ioutil.WriteFile(path, out, 0644); err != nil { 514 log.Error("Failed to save genesis file", "client", client, "err", err) 515 return 516 } 517 log.Info("Saved genesis chain spec", "client", client, "path", path) 518 }