// Copyright 2017 AMIS Technologies // This file is part of the go-ethereum library. // // The go-ethereum library is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // The go-ethereum library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . package setup import ( "encoding/json" "fmt" "io/ioutil" "math/big" "net" "os" "path" "strconv" "strings" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/p2p/discv5" istcommon "github.com/jpmorganchase/istanbul-tools/common" "github.com/jpmorganchase/istanbul-tools/docker/compose" "github.com/jpmorganchase/istanbul-tools/genesis" "github.com/urfave/cli" ) type validatorInfo struct { Address common.Address Nodekey string NodeInfo string } var ( SetupCommand = cli.Command{ Name: "setup", Usage: "Setup your Istanbul network in seconds", Description: `This tool helps generate: * Genesis block * Static nodes for all validators * Validator details for Istanbul consensus. `, Action: gen, Flags: []cli.Flag{ numOfValidatorsFlag, staticNodesFlag, verboseFlag, quorumFlag, dockerComposeFlag, saveFlag, }, } ) func gen(ctx *cli.Context) error { num := ctx.Int(numOfValidatorsFlag.Name) keys, nodekeys, addrs := istcommon.GenerateKeys(num) var nodes []string if ctx.Bool(verboseFlag.Name) { fmt.Println("validators") } for i := 0; i < num; i++ { v := &validatorInfo{ Address: addrs[i], Nodekey: nodekeys[i], NodeInfo: discv5.NewNode( discv5.PubkeyID(&keys[i].PublicKey), net.ParseIP("0.0.0.0"), 0, uint16(30303)).String(), } nodes = append(nodes, string(v.NodeInfo)) if ctx.Bool(verboseFlag.Name) { str, _ := json.MarshalIndent(v, "", "\t") fmt.Println(string(str)) if ctx.Bool(saveFlag.Name) { folderName := strconv.Itoa(i) os.MkdirAll(folderName, os.ModePerm) ioutil.WriteFile(path.Join(folderName, "nodekey"), []byte(nodekeys[i]), os.ModePerm) } } } if ctx.Bool(verboseFlag.Name) { fmt.Print("\n\n\n") } staticNodes, _ := json.MarshalIndent(nodes, "", "\t") if ctx.Bool(staticNodesFlag.Name) { name := "static-nodes.json" fmt.Println(name) fmt.Println(string(staticNodes)) fmt.Print("\n\n\n") if ctx.Bool(saveFlag.Name) { ioutil.WriteFile(name, staticNodes, os.ModePerm) } } var jsonBytes []byte isQuorum := ctx.Bool(quorumFlag.Name) g := genesis.New( genesis.Validators(addrs...), genesis.Alloc(addrs, new(big.Int).Exp(big.NewInt(10), big.NewInt(50), nil)), ) if isQuorum { jsonBytes, _ = json.MarshalIndent(genesis.ToQuorum(g, true), "", " ") } else { jsonBytes, _ = json.MarshalIndent(g, "", " ") } fmt.Println("genesis.json") fmt.Println(string(jsonBytes)) if ctx.Bool(saveFlag.Name) { ioutil.WriteFile("genesis.json", jsonBytes, os.ModePerm) } if ctx.Bool(dockerComposeFlag.Name) { fmt.Print("\n\n\n") compose := compose.New( "172.16.239", num, "bb98a0b6442386d0cdf8a31b267892c1", nodekeys, removeSpacesAndLines(jsonBytes), removeSpacesAndLines(staticNodes), isQuorum) fmt.Println("docker-compose.yml") fmt.Println(compose.String()) if ctx.Bool(saveFlag.Name) { ioutil.WriteFile("docker-compose.yml", []byte(compose.String()), os.ModePerm) } } return nil } func removeSpacesAndLines(b []byte) string { out := string(b) out = strings.Replace(out, " ", "", -1) out = strings.Replace(out, "\t", "", -1) out = strings.Replace(out, "\n", "", -1) return out }