github.com/klaytn/klaytn@v1.10.2/cmd/homi/setup/cmd.go (about)

     1  // Copyright 2018 The klaytn Authors
     2  // Copyright 2017 AMIS Technologies
     3  // This file is part of the go-ethereum library.
     4  //
     5  // The go-ethereum library is free software: you can redistribute it and/or modify
     6  // it under the terms of the GNU Lesser General Public License as published by
     7  // the Free Software Foundation, either version 3 of the License, or
     8  // (at your option) any later version.
     9  //
    10  // The go-ethereum library is distributed in the hope that it will be useful,
    11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    13  // GNU Lesser General Public License for more details.
    14  //
    15  // You should have received a copy of the GNU Lesser General Public License
    16  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    17  
    18  package setup
    19  
    20  import (
    21  	"crypto/ecdsa"
    22  	"encoding/json"
    23  	"fmt"
    24  	"io/ioutil"
    25  	"math/big"
    26  	"math/rand"
    27  	"net"
    28  	"net/http"
    29  	"os"
    30  	"path"
    31  	"strconv"
    32  	"strings"
    33  	"time"
    34  
    35  	"github.com/klaytn/klaytn/accounts"
    36  	"github.com/klaytn/klaytn/accounts/keystore"
    37  	"github.com/klaytn/klaytn/blockchain"
    38  	istcommon "github.com/klaytn/klaytn/cmd/homi/common"
    39  	"github.com/klaytn/klaytn/cmd/homi/docker/compose"
    40  	"github.com/klaytn/klaytn/cmd/homi/docker/service"
    41  	"github.com/klaytn/klaytn/cmd/homi/genesis"
    42  	"github.com/klaytn/klaytn/common"
    43  	"github.com/klaytn/klaytn/crypto"
    44  	"github.com/klaytn/klaytn/log"
    45  	"github.com/klaytn/klaytn/networks/p2p/discover"
    46  	"github.com/klaytn/klaytn/params"
    47  	"github.com/urfave/cli/altsrc"
    48  	"gopkg.in/urfave/cli.v1"
    49  )
    50  
    51  type ValidatorInfo struct {
    52  	Address  common.Address
    53  	Nodekey  string
    54  	NodeInfo string
    55  }
    56  
    57  type GrafanaFile struct {
    58  	url  string
    59  	name string
    60  }
    61  
    62  var HomiFlags = []cli.Flag{
    63  	homiYamlFlag,
    64  	altsrc.NewStringFlag(genTypeFlag),
    65  	altsrc.NewBoolFlag(cypressTestFlag),
    66  	altsrc.NewBoolFlag(cypressFlag),
    67  	altsrc.NewBoolFlag(baobabTestFlag),
    68  	altsrc.NewBoolFlag(baobabFlag),
    69  	altsrc.NewBoolFlag(serviceChainFlag),
    70  	altsrc.NewBoolFlag(serviceChainTestFlag),
    71  	altsrc.NewBoolFlag(cliqueFlag),
    72  	altsrc.NewIntFlag(numOfCNsFlag),
    73  	altsrc.NewIntFlag(numOfValidatorsFlag),
    74  	altsrc.NewIntFlag(numOfPNsFlag),
    75  	altsrc.NewIntFlag(numOfENsFlag),
    76  	altsrc.NewIntFlag(numOfSCNsFlag),
    77  	altsrc.NewIntFlag(numOfSPNsFlag),
    78  	altsrc.NewIntFlag(numOfSENsFlag),
    79  	altsrc.NewIntFlag(numOfTestKeyFlag),
    80  	altsrc.NewUint64Flag(chainIDFlag),
    81  	altsrc.NewUint64Flag(serviceChainIDFlag),
    82  	altsrc.NewUint64Flag(unitPriceFlag),
    83  	altsrc.NewIntFlag(deriveShaImplFlag),
    84  	altsrc.NewStringFlag(fundingAddrFlag),
    85  	altsrc.NewBoolFlag(patchAddressBookFlag),
    86  	altsrc.NewStringFlag(patchAddressBookAddrFlag),
    87  	altsrc.NewStringFlag(outputPathFlag),
    88  	altsrc.NewBoolFlag(addressBookMockFlag),
    89  	altsrc.NewStringFlag(dockerImageIdFlag),
    90  	altsrc.NewBoolFlag(fasthttpFlag),
    91  	altsrc.NewIntFlag(networkIdFlag),
    92  	altsrc.NewBoolFlag(nografanaFlag),
    93  	altsrc.NewBoolFlag(useTxGenFlag),
    94  	altsrc.NewIntFlag(txGenRateFlag),
    95  	altsrc.NewIntFlag(txGenThFlag),
    96  	altsrc.NewIntFlag(txGenConnFlag),
    97  	altsrc.NewStringFlag(txGenDurFlag),
    98  	altsrc.NewIntFlag(rpcPortFlag),
    99  	altsrc.NewIntFlag(wsPortFlag),
   100  	altsrc.NewIntFlag(p2pPortFlag),
   101  	altsrc.NewStringFlag(dataDirFlag),
   102  	altsrc.NewStringFlag(logDirFlag),
   103  	altsrc.NewBoolFlag(governanceFlag),
   104  	altsrc.NewStringFlag(govModeFlag),
   105  	altsrc.NewStringFlag(governingNodeFlag),
   106  	altsrc.NewStringFlag(govParamContractFlag),
   107  	altsrc.NewStringFlag(rewardMintAmountFlag),
   108  	altsrc.NewStringFlag(rewardRatioFlag),
   109  	altsrc.NewStringFlag(rewardKip82RatioFlag),
   110  	altsrc.NewBoolFlag(rewardGiniCoeffFlag),
   111  	altsrc.NewUint64Flag(rewardStakingFlag),
   112  	altsrc.NewUint64Flag(rewardProposerFlag),
   113  	altsrc.NewStringFlag(rewardMinimumStakeFlag),
   114  	altsrc.NewBoolFlag(rewardDeferredTxFeeFlag),
   115  	altsrc.NewUint64Flag(istEpochFlag),
   116  	altsrc.NewUint64Flag(istProposerPolicyFlag),
   117  	altsrc.NewUint64Flag(istSubGroupFlag),
   118  	altsrc.NewUint64Flag(cliqueEpochFlag),
   119  	altsrc.NewUint64Flag(cliquePeriodFlag),
   120  	altsrc.NewInt64Flag(istanbulCompatibleBlockNumberFlag),
   121  	altsrc.NewInt64Flag(londonCompatibleBlockNumberFlag),
   122  	altsrc.NewInt64Flag(ethTxTypeCompatibleBlockNumberFlag),
   123  	altsrc.NewInt64Flag(magmaCompatibleBlockNumberFlag),
   124  	altsrc.NewInt64Flag(koreCompatibleBlockNumberFlag),
   125  	altsrc.NewInt64Flag(kip103CompatibleBlockNumberFlag),
   126  	altsrc.NewStringFlag(kip103ContractAddressFlag),
   127  }
   128  
   129  var SetupCommand = cli.Command{
   130  	Name:  "setup",
   131  	Usage: "Generate klaytn CN's init files",
   132  	Description: `This tool helps generate:
   133  		* Genesis Block (genesis.json)
   134  		* Static nodes for all CNs(Consensus Node)
   135  		* CN details
   136  		* Docker-compose
   137  
   138  		for Klaytn Consensus Node.
   139  
   140  Args :
   141  		type : [local | remote | deploy | docker (default)]
   142  `,
   143  	Action:    Gen,
   144  	Flags:     HomiFlags,
   145  	ArgsUsage: "type",
   146  }
   147  
   148  const (
   149  	baobabOperatorAddress = "0x79deccfacd0599d3166eb76972be7bb20f51b46f"
   150  	baobabOperatorKey     = "199fd187fdb2ce5f577797e1abaf4dd50e62275949c021f0112be40c9721e1a2"
   151  )
   152  
   153  const (
   154  	DefaultTcpPort uint16 = 32323
   155  	TypeNotDefined        = -1
   156  	TypeDocker            = 0
   157  	TypeLocal             = 1
   158  	TypeRemote            = 2
   159  	TypeDeploy            = 3
   160  	DirScript             = "scripts"
   161  	DirKeys               = "keys"
   162  	DirPnScript           = "scripts_pn"
   163  	DirPnKeys             = "keys_pn"
   164  	DirTestKeys           = "keys_test"
   165  	CNIpNetwork           = "10.11.2"
   166  	PNIpNetwork1          = "10.11.10"
   167  	PNIpNetwork2          = "10.11.11"
   168  )
   169  
   170  var Types = [4]string{"docker", "local", "remote", "deploy"}
   171  
   172  var GrafanaFiles = [...]GrafanaFile{
   173  	{
   174  		url:  "https://s3.ap-northeast-2.amazonaws.com/klaytn-tools/Klaytn.json",
   175  		name: "Klaytn.json",
   176  	},
   177  	{
   178  		url:  "https://s3.ap-northeast-2.amazonaws.com/klaytn-tools/klaytn_txpool.json",
   179  		name: "Klaytn_txpool.json",
   180  	},
   181  }
   182  
   183  var lastIssuedPortNum = DefaultTcpPort
   184  
   185  func genRewardConfig(ctx *cli.Context) *params.RewardConfig {
   186  	mintingAmount := new(big.Int)
   187  	mintingAmountString := ctx.String(rewardMintAmountFlag.Name)
   188  	if _, ok := mintingAmount.SetString(mintingAmountString, 10); !ok {
   189  		log.Fatalf("Minting amount must be a number", "value", mintingAmountString)
   190  	}
   191  	ratio := ctx.String(rewardRatioFlag.Name)
   192  	kip82Ratio := ctx.String(rewardKip82RatioFlag.Name)
   193  	giniCoeff := ctx.Bool(rewardGiniCoeffFlag.Name)
   194  	deferredTxFee := ctx.Bool(rewardDeferredTxFeeFlag.Name)
   195  	stakingInterval := ctx.Uint64(rewardStakingFlag.Name)
   196  	proposalInterval := ctx.Uint64(rewardProposerFlag.Name)
   197  	minimumStake := new(big.Int)
   198  	minimumStakeString := ctx.String(rewardMinimumStakeFlag.Name)
   199  	if _, ok := minimumStake.SetString(minimumStakeString, 10); !ok {
   200  		log.Fatalf("Minimum stake must be a number", "value", minimumStakeString)
   201  	}
   202  
   203  	return &params.RewardConfig{
   204  		MintingAmount:          mintingAmount,
   205  		Ratio:                  ratio,
   206  		Kip82Ratio:             kip82Ratio,
   207  		UseGiniCoeff:           giniCoeff,
   208  		DeferredTxFee:          deferredTxFee,
   209  		StakingUpdateInterval:  stakingInterval,
   210  		ProposerUpdateInterval: proposalInterval,
   211  		MinimumStake:           minimumStake,
   212  	}
   213  }
   214  
   215  func genKIP71Config(ctx *cli.Context) *params.KIP71Config {
   216  	lowerBoundBaseFee := ctx.Uint64(magmaLowerBoundBaseFeeFlag.Name)
   217  	upperBoundBaseFee := ctx.Uint64(magmaUpperBoundBaseFeeFlag.Name)
   218  	gasTarget := ctx.Uint64(magmaGasTarget.Name)
   219  	maxBlockGasUsedForBaseFee := ctx.Uint64(magmaMaxBlockGasUsedForBaseFee.Name)
   220  	baseFeeDenominator := ctx.Uint64(magmaBaseFeeDenominator.Name)
   221  
   222  	return &params.KIP71Config{
   223  		LowerBoundBaseFee:         lowerBoundBaseFee,         // lower bound of the base fee
   224  		UpperBoundBaseFee:         upperBoundBaseFee,         // upper bound of the base fee
   225  		GasTarget:                 gasTarget,                 // standard gas usage for whether to raise or lower the base fee
   226  		MaxBlockGasUsedForBaseFee: maxBlockGasUsedForBaseFee, // maximum gas that can be used to calculate the base fee
   227  		BaseFeeDenominator:        baseFeeDenominator,        // scaling factor to adjust the gap between used and target gas
   228  	}
   229  }
   230  
   231  func genIstanbulConfig(ctx *cli.Context) *params.IstanbulConfig {
   232  	epoch := ctx.Uint64(istEpochFlag.Name)
   233  	policy := ctx.Uint64(istProposerPolicyFlag.Name)
   234  	subGroup := ctx.Uint64(istSubGroupFlag.Name)
   235  
   236  	return &params.IstanbulConfig{
   237  		Epoch:          epoch,
   238  		ProposerPolicy: policy,
   239  		SubGroupSize:   subGroup,
   240  	}
   241  }
   242  
   243  func genGovernanceConfig(ctx *cli.Context) *params.GovernanceConfig {
   244  	govMode := ctx.String(govModeFlag.Name)
   245  	governingNode := ctx.String(governingNodeFlag.Name)
   246  	if !common.IsHexAddress(governingNode) {
   247  		log.Fatalf("Governing Node is not a valid hex address", "value", governingNode)
   248  	}
   249  	govParamContract := ctx.String(govParamContractFlag.Name)
   250  	if !common.IsHexAddress(govParamContract) {
   251  		log.Fatalf("GovParam Contract is not a valid hex address", "value", govParamContract)
   252  	}
   253  	return &params.GovernanceConfig{
   254  		GoverningNode:    common.HexToAddress(governingNode),
   255  		GovernanceMode:   govMode,
   256  		GovParamContract: common.HexToAddress(govParamContract),
   257  		Reward:           genRewardConfig(ctx),
   258  		KIP71:            genKIP71Config(ctx),
   259  	}
   260  }
   261  
   262  func genCliqueConfig(ctx *cli.Context) *params.CliqueConfig {
   263  	epoch := ctx.Uint64(cliqueEpochFlag.Name)
   264  	period := ctx.Uint64(cliquePeriodFlag.Name)
   265  
   266  	return &params.CliqueConfig{
   267  		Period: period,
   268  		Epoch:  epoch,
   269  	}
   270  }
   271  
   272  func genIstanbulGenesis(ctx *cli.Context, nodeAddrs, testAddrs []common.Address, chainId uint64) *blockchain.Genesis {
   273  	unitPrice := ctx.Uint64(unitPriceFlag.Name)
   274  	chainID := new(big.Int).SetUint64(chainId)
   275  	deriveShaImpl := ctx.Int(deriveShaImplFlag.Name)
   276  
   277  	config := genGovernanceConfig(ctx)
   278  	if len(nodeAddrs) > 0 && config.GoverningNode.String() == params.DefaultGoverningNode {
   279  		config.GoverningNode = nodeAddrs[0]
   280  	}
   281  
   282  	options := []genesis.Option{
   283  		genesis.Validators(nodeAddrs...),
   284  		genesis.Alloc(append(nodeAddrs, testAddrs...), new(big.Int).Exp(big.NewInt(10), big.NewInt(50), nil)),
   285  		genesis.DeriveShaImpl(deriveShaImpl),
   286  		genesis.UnitPrice(unitPrice),
   287  		genesis.ChainID(chainID),
   288  	}
   289  
   290  	if ok := ctx.Bool(governanceFlag.Name); ok {
   291  		options = append(options, genesis.Governance(config))
   292  	}
   293  	options = append(options, genesis.Istanbul(genIstanbulConfig(ctx)))
   294  
   295  	return genesis.New(options...)
   296  }
   297  
   298  func genCliqueGenesis(ctx *cli.Context, nodeAddrs, testAddrs []common.Address, chainId uint64) *blockchain.Genesis {
   299  	config := genCliqueConfig(ctx)
   300  	unitPrice := ctx.Uint64(unitPriceFlag.Name)
   301  	chainID := new(big.Int).SetUint64(chainId)
   302  
   303  	if ok := ctx.Bool(governanceFlag.Name); ok {
   304  		log.Fatalf("Currently, governance is not supported for clique consensus", "--governance", ok)
   305  	}
   306  
   307  	genesisJson := genesis.NewClique(
   308  		genesis.ValidatorsOfClique(nodeAddrs...),
   309  		genesis.Alloc(append(nodeAddrs, testAddrs...), new(big.Int).Exp(big.NewInt(10), big.NewInt(50), nil)),
   310  		genesis.UnitPrice(unitPrice),
   311  		genesis.ChainID(chainID),
   312  		genesis.Clique(config),
   313  	)
   314  	return genesisJson
   315  }
   316  
   317  func genValidatorKeystore(privKeys []*ecdsa.PrivateKey) {
   318  	path := path.Join(outputPath, DirKeys)
   319  	ks := keystore.NewKeyStore(path, keystore.StandardScryptN, keystore.StandardScryptP)
   320  
   321  	for i, pk := range privKeys {
   322  		pwdStr := RandStringRunes(params.PasswordLength)
   323  		account, _ := ks.ImportECDSA(pk, pwdStr)
   324  		genRewardKeystore(account, i)
   325  		WriteFile([]byte(pwdStr), DirKeys, "passwd"+strconv.Itoa(i+1))
   326  	}
   327  }
   328  
   329  func genRewardKeystore(account accounts.Account, i int) {
   330  	file, err := os.Open(account.URL.Path)
   331  	if err != nil {
   332  		log.Fatalf("Failed to open file: %s", err)
   333  	}
   334  	defer file.Close()
   335  
   336  	data, err := ioutil.ReadAll(file)
   337  	if err != nil {
   338  		log.Fatalf("Failed to read file: %s", err)
   339  	}
   340  
   341  	v := make(map[string]interface{})
   342  	if err := json.Unmarshal(data, &v); err != nil {
   343  		log.Fatalf("Failed to unmarshal keystore file: %s", err)
   344  	}
   345  
   346  	WriteFile([]byte(v["address"].(string)), DirKeys, "reward"+strconv.Itoa(i+1))
   347  	WriteFile(data, DirKeys, "keystore"+strconv.Itoa(i+1))
   348  
   349  	// Remove UTC-XXX file created by keystore package
   350  	os.Remove(account.URL.Path)
   351  }
   352  
   353  func genCypressCommonGenesis(nodeAddrs, testAddrs []common.Address) *blockchain.Genesis {
   354  	mintingAmount, _ := new(big.Int).SetString("9600000000000000000", 10)
   355  	genesisJson := &blockchain.Genesis{
   356  		Timestamp:  uint64(time.Now().Unix()),
   357  		BlockScore: big.NewInt(genesis.InitBlockScore),
   358  		Alloc:      make(blockchain.GenesisAlloc),
   359  		Config: &params.ChainConfig{
   360  			ChainID:       big.NewInt(10000),
   361  			DeriveShaImpl: 2,
   362  			Governance: &params.GovernanceConfig{
   363  				GoverningNode:  nodeAddrs[0],
   364  				GovernanceMode: "single",
   365  				Reward: &params.RewardConfig{
   366  					MintingAmount: mintingAmount,
   367  					Ratio:         "34/54/12",
   368  					UseGiniCoeff:  true,
   369  					DeferredTxFee: true,
   370  				},
   371  			},
   372  			Istanbul: &params.IstanbulConfig{
   373  				ProposerPolicy: 2,
   374  				SubGroupSize:   22,
   375  			},
   376  			UnitPrice: 25000000000,
   377  		},
   378  	}
   379  	assignExtraData := genesis.Validators(nodeAddrs...)
   380  	assignExtraData(genesisJson)
   381  
   382  	return genesisJson
   383  }
   384  
   385  func genCypressGenesis(nodeAddrs, testAddrs []common.Address) *blockchain.Genesis {
   386  	genesisJson := genCypressCommonGenesis(nodeAddrs, testAddrs)
   387  	genesisJson.Config.Istanbul.Epoch = 604800
   388  	genesisJson.Config.Governance.Reward.StakingUpdateInterval = 86400
   389  	genesisJson.Config.Governance.Reward.ProposerUpdateInterval = 3600
   390  	genesisJson.Config.Governance.Reward.MinimumStake = new(big.Int).SetUint64(5000000)
   391  	allocationFunction := genesis.AllocWithCypressContract(append(nodeAddrs, testAddrs...), new(big.Int).Exp(big.NewInt(10), big.NewInt(50), nil))
   392  	allocationFunction(genesisJson)
   393  	return genesisJson
   394  }
   395  
   396  func genServiceChainCommonGenesis(nodeAddrs, testAddrs []common.Address) *blockchain.Genesis {
   397  	genesisJson := &blockchain.Genesis{
   398  		Timestamp:  uint64(time.Now().Unix()),
   399  		BlockScore: big.NewInt(genesis.InitBlockScore),
   400  		Alloc:      make(blockchain.GenesisAlloc),
   401  		Config: &params.ChainConfig{
   402  			ChainID:       big.NewInt(1000),
   403  			DeriveShaImpl: 2,
   404  			Istanbul: &params.IstanbulConfig{
   405  				ProposerPolicy: 0,
   406  				SubGroupSize:   22,
   407  			},
   408  			UnitPrice: 0,
   409  		},
   410  	}
   411  	assignExtraData := genesis.Validators(nodeAddrs...)
   412  	assignExtraData(genesisJson)
   413  
   414  	return genesisJson
   415  }
   416  
   417  func genServiceChainGenesis(nodeAddrs, testAddrs []common.Address) *blockchain.Genesis {
   418  	genesisJson := genServiceChainCommonGenesis(nodeAddrs, testAddrs)
   419  	genesisJson.Config.Istanbul.Epoch = 3600
   420  	allocationFunction := genesis.Alloc(append(nodeAddrs, testAddrs...), new(big.Int).Exp(big.NewInt(10), big.NewInt(50), nil))
   421  	allocationFunction(genesisJson)
   422  	return genesisJson
   423  }
   424  
   425  func genServiceChainTestGenesis(nodeAddrs, testAddrs []common.Address) *blockchain.Genesis {
   426  	genesisJson := genServiceChainCommonGenesis(nodeAddrs, testAddrs)
   427  	genesisJson.Config.Istanbul.Epoch = 30
   428  	allocationFunction := genesis.Alloc(append(nodeAddrs, testAddrs...), new(big.Int).Exp(big.NewInt(10), big.NewInt(50), nil))
   429  	allocationFunction(genesisJson)
   430  	return genesisJson
   431  }
   432  
   433  func genCypressTestGenesis(nodeAddrs, testAddrs []common.Address) *blockchain.Genesis {
   434  	testGenesis := genCypressCommonGenesis(nodeAddrs, testAddrs)
   435  	testGenesis.Config.Istanbul.Epoch = 30
   436  	testGenesis.Config.Governance.Reward.StakingUpdateInterval = 60
   437  	testGenesis.Config.Governance.Reward.ProposerUpdateInterval = 30
   438  	testGenesis.Config.Governance.Reward.MinimumStake = new(big.Int).SetUint64(5000000)
   439  	allocationFunction := genesis.AllocWithPrecypressContract(append(nodeAddrs, testAddrs...), new(big.Int).Exp(big.NewInt(10), big.NewInt(50), nil))
   440  	allocationFunction(testGenesis)
   441  	return testGenesis
   442  }
   443  
   444  func genBaobabCommonGenesis(nodeAddrs, testAddrs []common.Address) *blockchain.Genesis {
   445  	mintingAmount, _ := new(big.Int).SetString("9600000000000000000", 10)
   446  	genesisJson := &blockchain.Genesis{
   447  		Timestamp:  uint64(time.Now().Unix()),
   448  		BlockScore: big.NewInt(genesis.InitBlockScore),
   449  		Alloc:      make(blockchain.GenesisAlloc),
   450  		Config: &params.ChainConfig{
   451  			ChainID:       big.NewInt(2019),
   452  			DeriveShaImpl: 2,
   453  			Governance: &params.GovernanceConfig{
   454  				GoverningNode:  nodeAddrs[0],
   455  				GovernanceMode: "single",
   456  				Reward: &params.RewardConfig{
   457  					MintingAmount: mintingAmount,
   458  					Ratio:         "34/54/12",
   459  					UseGiniCoeff:  false,
   460  					DeferredTxFee: true,
   461  				},
   462  			},
   463  			Istanbul: &params.IstanbulConfig{
   464  				ProposerPolicy: 2,
   465  				SubGroupSize:   13,
   466  			},
   467  			UnitPrice: 25000000000,
   468  		},
   469  	}
   470  	assignExtraData := genesis.Validators(nodeAddrs...)
   471  	assignExtraData(genesisJson)
   472  
   473  	return genesisJson
   474  }
   475  
   476  func genBaobabGenesis(nodeAddrs, testAddrs []common.Address) *blockchain.Genesis {
   477  	genesisJson := genBaobabCommonGenesis(nodeAddrs, testAddrs)
   478  	genesisJson.Config.Istanbul.Epoch = 604800
   479  	genesisJson.Config.Governance.Reward.StakingUpdateInterval = 86400
   480  	genesisJson.Config.Governance.Reward.ProposerUpdateInterval = 3600
   481  	genesisJson.Config.Governance.Reward.MinimumStake = new(big.Int).SetUint64(5000000)
   482  	allocationFunction := genesis.AllocWithBaobabContract(append(nodeAddrs, testAddrs...), new(big.Int).Exp(big.NewInt(10), big.NewInt(50), nil))
   483  	allocationFunction(genesisJson)
   484  	return genesisJson
   485  }
   486  
   487  func genBaobabTestGenesis(nodeAddrs, testAddrs []common.Address) *blockchain.Genesis {
   488  	testGenesis := genBaobabCommonGenesis(nodeAddrs, testAddrs)
   489  	testGenesis.Config.Istanbul.Epoch = 30
   490  	testGenesis.Config.Governance.Reward.StakingUpdateInterval = 60
   491  	testGenesis.Config.Governance.Reward.ProposerUpdateInterval = 30
   492  	testGenesis.Config.Governance.Reward.MinimumStake = new(big.Int).SetUint64(5000000)
   493  	allocationFunction := genesis.AllocWithPrebaobabContract(append(nodeAddrs, testAddrs...), new(big.Int).Exp(big.NewInt(10), big.NewInt(50), nil))
   494  	allocationFunction(testGenesis)
   495  	WriteFile([]byte(baobabOperatorAddress), "baobab_operator", "address")
   496  	WriteFile([]byte(baobabOperatorKey), "baobab_operator", "private")
   497  	return testGenesis
   498  }
   499  
   500  func allocGenesisFund(ctx *cli.Context, genesisJson *blockchain.Genesis) {
   501  	fundingAddr := ctx.String(fundingAddrFlag.Name)
   502  	if len(fundingAddr) == 0 {
   503  		return
   504  	}
   505  
   506  	if !common.IsHexAddress(fundingAddr) {
   507  		log.Fatalf("'%s' is not a valid hex address", fundingAddr)
   508  	}
   509  	addr := common.HexToAddress(fundingAddr)
   510  	balance := new(big.Int).Exp(big.NewInt(10), big.NewInt(50), nil)
   511  	genesisJson.Alloc[addr] = blockchain.GenesisAccount{Balance: balance}
   512  }
   513  
   514  func patchGenesisAddressBook(ctx *cli.Context, genesisJson *blockchain.Genesis, nodeAddrs []common.Address) {
   515  	if patchAddressBook := ctx.Bool(patchAddressBookFlag.Name); !patchAddressBook {
   516  		return
   517  	}
   518  
   519  	var targetAddr common.Address
   520  
   521  	patchAddressBookAddr := ctx.String(patchAddressBookAddrFlag.Name)
   522  	if len(patchAddressBookAddr) == 0 {
   523  		if len(nodeAddrs) == 0 {
   524  			log.Fatalf("Need at least one consensus node (--cn-num 1) to patch AddressBook with the first CN")
   525  		}
   526  		targetAddr = nodeAddrs[0]
   527  	} else {
   528  		if !common.IsHexAddress(patchAddressBookAddr) {
   529  			log.Fatalf("'%s' is not a valid hex address", patchAddressBookAddr)
   530  		}
   531  		targetAddr = common.HexToAddress(patchAddressBookAddr)
   532  	}
   533  
   534  	allocationFunction := genesis.PatchAddressBook(targetAddr)
   535  	allocationFunction(genesisJson)
   536  }
   537  
   538  func useAddressBookMock(ctx *cli.Context, genesisJson *blockchain.Genesis) {
   539  	if useMock := ctx.Bool(addressBookMockFlag.Name); !useMock {
   540  		return
   541  	}
   542  
   543  	allocationFunction := genesis.AddressBookMock()
   544  	allocationFunction(genesisJson)
   545  }
   546  
   547  func RandStringRunes(n int) string {
   548  	letterRunes := []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789~!@#$%^&*()_+{}|[]")
   549  
   550  	rand.Seed(time.Now().UnixNano())
   551  
   552  	b := make([]rune, n)
   553  	for i := range b {
   554  		b[i] = letterRunes[rand.Intn(len(letterRunes))]
   555  	}
   556  	return string(b)
   557  }
   558  
   559  func Gen(ctx *cli.Context) error {
   560  	genType := findGenType(ctx)
   561  
   562  	cnNum := ctx.Int(numOfCNsFlag.Name)
   563  	numValidators := ctx.Int(numOfValidatorsFlag.Name)
   564  	pnNum := ctx.Int(numOfPNsFlag.Name)
   565  	enNum := ctx.Int(numOfENsFlag.Name)
   566  	scnNum := ctx.Int(numOfSCNsFlag.Name)
   567  	spnNum := ctx.Int(numOfSPNsFlag.Name)
   568  	senNum := ctx.Int(numOfSENsFlag.Name)
   569  	numTestAccs := ctx.Int(numOfTestKeyFlag.Name)
   570  	baobab := ctx.Bool(baobabFlag.Name)
   571  	baobabTest := ctx.Bool(baobabTestFlag.Name)
   572  	cypress := ctx.Bool(cypressFlag.Name)
   573  	cypressTest := ctx.Bool(cypressTestFlag.Name)
   574  	clique := ctx.Bool(cliqueFlag.Name)
   575  	serviceChain := ctx.Bool(serviceChainFlag.Name)
   576  	serviceChainTest := ctx.Bool(serviceChainTestFlag.Name)
   577  	chainid := ctx.Uint64(chainIDFlag.Name)
   578  	serviceChainId := ctx.Uint64(serviceChainIDFlag.Name)
   579  
   580  	// Note-klaytn : the following code that seems unnecessary is for the priority to flags, not yaml
   581  	if !baobab && !baobabTest && !cypress && !cypressTest && !serviceChain && !serviceChainTest && !clique {
   582  		switch genesisType := ctx.String(genesisTypeFlag.Name); genesisType {
   583  		case "baobab":
   584  			baobab = true
   585  		case "baobab-test":
   586  			baobabTest = true
   587  		case "cypress":
   588  			cypress = true
   589  		case "cypress-test":
   590  			cypressTest = true
   591  		case "servicechain":
   592  			serviceChain = true
   593  		case "servicechain-test":
   594  			serviceChainTest = true
   595  		case "clique":
   596  			clique = true
   597  		default:
   598  			fmt.Printf("Unknown genesis type is %s.\n", genesisType)
   599  		}
   600  	}
   601  
   602  	if cnNum == 0 && scnNum == 0 {
   603  		return fmt.Errorf("needed at least one consensus node (--cn-num 1) or one service chain consensus node (--scn-num 1) ")
   604  	}
   605  
   606  	if numValidators == 0 {
   607  		numValidators = cnNum
   608  	}
   609  	if numValidators > cnNum {
   610  		return fmt.Errorf("validators-num(%d) cannot be greater than num(%d)", numValidators, cnNum)
   611  	}
   612  
   613  	privKeys, nodeKeys, nodeAddrs := istcommon.GenerateKeys(cnNum)
   614  	testPrivKeys, testKeys, testAddrs := istcommon.GenerateKeys(numTestAccs)
   615  
   616  	var (
   617  		genesisJson      *blockchain.Genesis
   618  		genesisJsonBytes []byte
   619  	)
   620  
   621  	validatorNodeAddrs := make([]common.Address, numValidators)
   622  	copy(validatorNodeAddrs, nodeAddrs[:numValidators])
   623  
   624  	if cypressTest {
   625  		genesisJson = genCypressTestGenesis(validatorNodeAddrs, testAddrs)
   626  	} else if cypress {
   627  		genesisJson = genCypressGenesis(validatorNodeAddrs, testAddrs)
   628  	} else if baobabTest {
   629  		genesisJson = genBaobabTestGenesis(validatorNodeAddrs, testAddrs)
   630  	} else if baobab {
   631  		genesisJson = genBaobabGenesis(validatorNodeAddrs, testAddrs)
   632  	} else if clique {
   633  		genesisJson = genCliqueGenesis(ctx, validatorNodeAddrs, testAddrs, chainid)
   634  	} else if serviceChain {
   635  		genesisJson = genServiceChainGenesis(validatorNodeAddrs, testAddrs)
   636  	} else if serviceChainTest {
   637  		genesisJson = genServiceChainTestGenesis(validatorNodeAddrs, testAddrs)
   638  	} else {
   639  		genesisJson = genIstanbulGenesis(ctx, validatorNodeAddrs, testAddrs, chainid)
   640  	}
   641  
   642  	allocGenesisFund(ctx, genesisJson)
   643  	patchGenesisAddressBook(ctx, genesisJson, validatorNodeAddrs)
   644  	useAddressBookMock(ctx, genesisJson)
   645  
   646  	genesisJson.Config.IstanbulCompatibleBlock = big.NewInt(ctx.Int64(istanbulCompatibleBlockNumberFlag.Name))
   647  	genesisJson.Config.LondonCompatibleBlock = big.NewInt(ctx.Int64(londonCompatibleBlockNumberFlag.Name))
   648  	genesisJson.Config.EthTxTypeCompatibleBlock = big.NewInt(ctx.Int64(ethTxTypeCompatibleBlockNumberFlag.Name))
   649  	genesisJson.Config.MagmaCompatibleBlock = big.NewInt(ctx.Int64(magmaCompatibleBlockNumberFlag.Name))
   650  	genesisJson.Config.KoreCompatibleBlock = big.NewInt(ctx.Int64(koreCompatibleBlockNumberFlag.Name))
   651  	genesisJson.Config.Kip103CompatibleBlock = big.NewInt(ctx.Int64(kip103CompatibleBlockNumberFlag.Name))
   652  	genesisJson.Config.Kip103ContractAddress = common.HexToAddress(ctx.String(kip103ContractAddressFlag.Name))
   653  
   654  	genesisJsonBytes, _ = json.MarshalIndent(genesisJson, "", "    ")
   655  	genValidatorKeystore(privKeys)
   656  	lastIssuedPortNum = uint16(ctx.Int(p2pPortFlag.Name))
   657  
   658  	switch genType {
   659  	case TypeDocker:
   660  		validators := makeValidators(cnNum, false, nodeAddrs, nodeKeys, privKeys)
   661  		pnValidators, proxyNodeKeys := makeProxys(pnNum, false)
   662  		nodeInfos := filterNodeInfo(validators)
   663  		staticNodesJsonBytes, _ := json.MarshalIndent(nodeInfos, "", "\t")
   664  		address := filterAddressesString(validators)
   665  		pnInfos := filterNodeInfo(pnValidators)
   666  		enValidators, enKeys := makeEndpoints(enNum, false)
   667  		enInfos := filterNodeInfo(enValidators)
   668  
   669  		scnValidators, scnKeys := makeSCNs(scnNum, false)
   670  		scnInfos := filterNodeInfo(scnValidators)
   671  		scnAddress := filterAddresses(scnValidators)
   672  
   673  		spnValidators, spnKeys := makeSPNs(spnNum, false)
   674  		spnInfos := filterNodeInfo(spnValidators)
   675  
   676  		senValidators, senKeys := makeSENs(senNum, false)
   677  		senInfos := filterNodeInfo(senValidators)
   678  
   679  		staticPNJsonBytes, _ := json.MarshalIndent(pnInfos, "", "\t")
   680  		staticENJsonBytes, _ := json.MarshalIndent(enInfos, "", "\t")
   681  		staticSCNJsonBytes, _ := json.MarshalIndent(scnInfos, "", "\t")
   682  		staticSPNJsonBytes, _ := json.MarshalIndent(spnInfos, "", "\t")
   683  		staticSENJsonBytes, _ := json.MarshalIndent(senInfos, "", "\t")
   684  		var bridgeNodesJsonBytes []byte
   685  		if len(enInfos) != 0 {
   686  			bridgeNodesJsonBytes, _ = json.MarshalIndent(enInfos[:1], "", "\t")
   687  		}
   688  		scnGenesisJsonBytes, _ := json.MarshalIndent(genIstanbulGenesis(ctx, scnAddress, nil, serviceChainId), "", "\t")
   689  
   690  		dockerImageId := ctx.String(dockerImageIdFlag.Name)
   691  
   692  		compose := compose.New(
   693  			"172.16.239",
   694  			cnNum,
   695  			"bb98a0b6442386d0cdf8a31b267892c1",
   696  			address,
   697  			nodeKeys,
   698  			removeSpacesAndLines(genesisJsonBytes),
   699  			removeSpacesAndLines(scnGenesisJsonBytes),
   700  			removeSpacesAndLines(staticNodesJsonBytes),
   701  			removeSpacesAndLines(staticPNJsonBytes),
   702  			removeSpacesAndLines(staticENJsonBytes),
   703  			removeSpacesAndLines(staticSCNJsonBytes),
   704  			removeSpacesAndLines(staticSPNJsonBytes),
   705  			removeSpacesAndLines(staticSENJsonBytes),
   706  			removeSpacesAndLines(bridgeNodesJsonBytes),
   707  			dockerImageId,
   708  			ctx.Bool(fasthttpFlag.Name),
   709  			ctx.Int(networkIdFlag.Name),
   710  			int(chainid),
   711  			!ctx.BoolT(nografanaFlag.Name),
   712  			proxyNodeKeys,
   713  			enKeys,
   714  			scnKeys,
   715  			spnKeys,
   716  			senKeys,
   717  			ctx.Bool(useTxGenFlag.Name),
   718  			service.TxGenOption{
   719  				TxGenRate:       ctx.Int(txGenRateFlag.Name),
   720  				TxGenThreadSize: ctx.Int(txGenThFlag.Name),
   721  				TxGenConnSize:   ctx.Int(txGenConnFlag.Name),
   722  				TxGenDuration:   ctx.String(txGenDurFlag.Name),
   723  			})
   724  		os.MkdirAll(outputPath, os.ModePerm)
   725  		ioutil.WriteFile(path.Join(outputPath, "docker-compose.yml"), []byte(compose.String()), os.ModePerm)
   726  		fmt.Println("Created : ", path.Join(outputPath, "docker-compose.yml"))
   727  		ioutil.WriteFile(path.Join(outputPath, "prometheus.yml"), []byte(compose.PrometheusService.Config.String()), os.ModePerm)
   728  		fmt.Println("Created : ", path.Join(outputPath, "prometheus.yml"))
   729  		downLoadGrafanaJson()
   730  	case TypeLocal:
   731  		writeNodeFiles(true, cnNum, pnNum, nodeAddrs, nodeKeys, privKeys, genesisJsonBytes)
   732  		writeTestKeys(DirTestKeys, testPrivKeys, testKeys)
   733  		downLoadGrafanaJson()
   734  	case TypeRemote:
   735  		writeNodeFiles(false, cnNum, pnNum, nodeAddrs, nodeKeys, privKeys, genesisJsonBytes)
   736  		writeTestKeys(DirTestKeys, testPrivKeys, testKeys)
   737  		downLoadGrafanaJson()
   738  	case TypeDeploy:
   739  		writeCNInfoKey(cnNum, nodeAddrs, nodeKeys, privKeys, genesisJsonBytes)
   740  		writeKlayConfig(ctx.Int(networkIdFlag.Name), ctx.Int(rpcPortFlag.Name), ctx.Int(wsPortFlag.Name), ctx.Int(p2pPortFlag.Name),
   741  			ctx.String(dataDirFlag.Name), ctx.String(logDirFlag.Name), "CN")
   742  		writeKlayConfig(ctx.Int(networkIdFlag.Name), ctx.Int(rpcPortFlag.Name), ctx.Int(wsPortFlag.Name), ctx.Int(p2pPortFlag.Name),
   743  			ctx.String(dataDirFlag.Name), ctx.String(logDirFlag.Name), "PN")
   744  		writePNInfoKey(ctx.Int(numOfPNsFlag.Name))
   745  		writePrometheusConfig(cnNum, ctx.Int(numOfPNsFlag.Name))
   746  	}
   747  
   748  	return nil
   749  }
   750  
   751  func downLoadGrafanaJson() {
   752  	for _, file := range GrafanaFiles {
   753  		resp, err := http.Get(file.url)
   754  		if err != nil {
   755  			fmt.Printf("Failed to download the imgs dashboard file(%s) - %v\n", file.url, err)
   756  		} else if resp.StatusCode != 200 {
   757  			fmt.Printf("Failed to download the imgs dashboard file(%s) [%s] - %v\n", file.url, resp.Status, err)
   758  		} else {
   759  			bytes, e := ioutil.ReadAll(resp.Body)
   760  			if e != nil {
   761  				fmt.Println("Failed to read http response", e)
   762  			} else {
   763  				fileName := file.name
   764  				ioutil.WriteFile(path.Join(outputPath, fileName), bytes, os.ModePerm)
   765  				fmt.Println("Created : ", path.Join(outputPath, fileName))
   766  			}
   767  			resp.Body.Close()
   768  		}
   769  	}
   770  }
   771  
   772  func writeCNInfoKey(num int, nodeAddrs []common.Address, nodeKeys []string, privKeys []*ecdsa.PrivateKey,
   773  	genesisJsonBytes []byte,
   774  ) {
   775  	const DirCommon = "common"
   776  	WriteFile(genesisJsonBytes, DirCommon, "genesis.json")
   777  
   778  	validators := makeValidatorsWithIp(num, false, nodeAddrs, nodeKeys, privKeys, []string{CNIpNetwork})
   779  	staticNodesJsonBytes, _ := json.MarshalIndent(filterNodeInfo(validators), "", "\t")
   780  	WriteFile(staticNodesJsonBytes, DirCommon, "static-nodes.json")
   781  
   782  	for i, v := range validators {
   783  		parentDir := fmt.Sprintf("cn%02d", i+1)
   784  		WriteFile([]byte(nodeKeys[i]), parentDir, "nodekey")
   785  		str, _ := json.MarshalIndent(v, "", "\t")
   786  		WriteFile([]byte(str), parentDir, "validator")
   787  	}
   788  }
   789  
   790  func writePNInfoKey(num int) {
   791  	privKeys, nodeKeys, nodeAddrs := istcommon.GenerateKeys(num)
   792  	validators := makeValidatorsWithIp(num, false, nodeAddrs, nodeKeys, privKeys, []string{PNIpNetwork1, PNIpNetwork2})
   793  	for i, v := range validators {
   794  		parentDir := fmt.Sprintf("pn%02d", i+1)
   795  		WriteFile([]byte(nodeKeys[i]), parentDir, "nodekey")
   796  		str, _ := json.MarshalIndent(v, "", "\t")
   797  		WriteFile([]byte(str), parentDir, "validator")
   798  	}
   799  }
   800  
   801  func writeKlayConfig(networkId int, rpcPort int, wsPort int, p2pPort int, dataDir string, logDir string, nodeType string) {
   802  	kConfig := NewKlaytnConfig(networkId, rpcPort, wsPort, p2pPort, dataDir, logDir, "/var/run/klay", nodeType)
   803  	WriteFile([]byte(kConfig.String()), strings.ToLower(nodeType), "klay.conf")
   804  }
   805  
   806  func writePrometheusConfig(cnNum int, pnNum int) {
   807  	pConf := NewPrometheusConfig(cnNum, CNIpNetwork, pnNum, PNIpNetwork1, PNIpNetwork2)
   808  	WriteFile([]byte(pConf.String()), "monitoring", "prometheus.yml")
   809  }
   810  
   811  func writeNodeFiles(isWorkOnSingleHost bool, num int, pnum int, nodeAddrs []common.Address, nodeKeys []string,
   812  	privKeys []*ecdsa.PrivateKey, genesisJsonBytes []byte,
   813  ) {
   814  	WriteFile(genesisJsonBytes, DirScript, "genesis.json")
   815  
   816  	validators := makeValidators(num, isWorkOnSingleHost, nodeAddrs, nodeKeys, privKeys)
   817  	nodeInfos := filterNodeInfo(validators)
   818  	staticNodesJsonBytes, _ := json.MarshalIndent(nodeInfos, "", "\t")
   819  	writeValidatorsAndNodesToFile(validators, DirKeys, nodeKeys)
   820  	WriteFile(staticNodesJsonBytes, DirScript, "static-nodes.json")
   821  
   822  	if pnum > 0 {
   823  		proxys, proxyNodeKeys := makeProxys(pnum, isWorkOnSingleHost)
   824  		pNodeInfos := filterNodeInfo(proxys)
   825  		staticPNodesJsonBytes, _ := json.MarshalIndent(pNodeInfos, "", "\t")
   826  		writeValidatorsAndNodesToFile(proxys, DirPnKeys, proxyNodeKeys)
   827  		WriteFile(staticPNodesJsonBytes, DirPnScript, "static-nodes.json")
   828  	}
   829  }
   830  
   831  func filterAddresses(validatorInfos []*ValidatorInfo) []common.Address {
   832  	var addresses []common.Address
   833  	for _, v := range validatorInfos {
   834  		addresses = append(addresses, v.Address)
   835  	}
   836  	return addresses
   837  }
   838  
   839  func filterAddressesString(validatorInfos []*ValidatorInfo) []string {
   840  	var address []string
   841  	for _, v := range validatorInfos {
   842  		address = append(address, v.Address.String())
   843  	}
   844  	return address
   845  }
   846  
   847  func filterNodeInfo(validatorInfos []*ValidatorInfo) []string {
   848  	var nodes []string
   849  	for _, v := range validatorInfos {
   850  		nodes = append(nodes, string(v.NodeInfo))
   851  	}
   852  	return nodes
   853  }
   854  
   855  func makeValidators(num int, isWorkOnSingleHost bool, nodeAddrs []common.Address, nodeKeys []string,
   856  	keys []*ecdsa.PrivateKey,
   857  ) []*ValidatorInfo {
   858  	var validatorPort uint16
   859  	var validators []*ValidatorInfo
   860  	for i := 0; i < num; i++ {
   861  		if isWorkOnSingleHost {
   862  			validatorPort = lastIssuedPortNum
   863  			lastIssuedPortNum++
   864  		} else {
   865  			validatorPort = DefaultTcpPort
   866  		}
   867  
   868  		v := &ValidatorInfo{
   869  			Address: nodeAddrs[i],
   870  			Nodekey: nodeKeys[i],
   871  			NodeInfo: discover.NewNode(
   872  				discover.PubkeyID(&keys[i].PublicKey),
   873  				net.ParseIP("0.0.0.0"),
   874  				0,
   875  				validatorPort,
   876  				nil,
   877  				discover.NodeTypeCN).String(),
   878  		}
   879  		validators = append(validators, v)
   880  	}
   881  	return validators
   882  }
   883  
   884  func makeValidatorsWithIp(num int, isWorkOnSingleHost bool, nodeAddrs []common.Address, nodeKeys []string,
   885  	keys []*ecdsa.PrivateKey, networkIds []string,
   886  ) []*ValidatorInfo {
   887  	var validatorPort uint16
   888  	var validators []*ValidatorInfo
   889  	for i := 0; i < num; i++ {
   890  		if isWorkOnSingleHost {
   891  			validatorPort = lastIssuedPortNum
   892  			lastIssuedPortNum++
   893  		} else {
   894  			validatorPort = DefaultTcpPort
   895  		}
   896  
   897  		nn := len(networkIds)
   898  		idx := (i + 1) % nn
   899  		if nn > 1 {
   900  			if idx == 0 {
   901  				idx = nn - 1
   902  			} else { // idx > 0
   903  				idx = idx - 1
   904  			}
   905  		}
   906  		v := &ValidatorInfo{
   907  			Address: nodeAddrs[i],
   908  			Nodekey: nodeKeys[i],
   909  			NodeInfo: discover.NewNode(
   910  				discover.PubkeyID(&keys[i].PublicKey),
   911  				net.ParseIP(fmt.Sprintf("%s.%d", networkIds[idx], 100+(i/nn)+1)),
   912  				0,
   913  				validatorPort,
   914  				nil,
   915  				discover.NodeTypeCN).String(),
   916  		}
   917  		validators = append(validators, v)
   918  	}
   919  	return validators
   920  }
   921  
   922  func makeProxys(num int, isWorkOnSingleHost bool) ([]*ValidatorInfo, []string) {
   923  	privKeys, nodeKeys, nodeAddrs := istcommon.GenerateKeys(num)
   924  
   925  	var p2pPort uint16
   926  	var proxies []*ValidatorInfo
   927  	var proxyNodeKeys []string
   928  	for i := 0; i < num; i++ {
   929  		if isWorkOnSingleHost {
   930  			p2pPort = lastIssuedPortNum
   931  			lastIssuedPortNum++
   932  		} else {
   933  			p2pPort = DefaultTcpPort
   934  		}
   935  
   936  		v := &ValidatorInfo{
   937  			Address: nodeAddrs[i],
   938  			Nodekey: nodeKeys[i],
   939  			NodeInfo: discover.NewNode(
   940  				discover.PubkeyID(&privKeys[i].PublicKey),
   941  				net.ParseIP("0.0.0.0"),
   942  				0,
   943  				p2pPort,
   944  				nil,
   945  				discover.NodeTypePN).String(),
   946  		}
   947  		proxies = append(proxies, v)
   948  		proxyNodeKeys = append(proxyNodeKeys, v.Nodekey)
   949  	}
   950  	return proxies, proxyNodeKeys
   951  }
   952  
   953  func makeEndpoints(num int, isWorkOnSingleHost bool) ([]*ValidatorInfo, []string) {
   954  	privKeys, nodeKeys, nodeAddrs := istcommon.GenerateKeys(num)
   955  
   956  	var p2pPort uint16
   957  	var endpoints []*ValidatorInfo
   958  	var endpointsNodeKeys []string
   959  	for i := 0; i < num; i++ {
   960  		if isWorkOnSingleHost {
   961  			p2pPort = lastIssuedPortNum
   962  			lastIssuedPortNum++
   963  		} else {
   964  			p2pPort = DefaultTcpPort
   965  		}
   966  
   967  		v := &ValidatorInfo{
   968  			Address: nodeAddrs[i],
   969  			Nodekey: nodeKeys[i],
   970  			NodeInfo: discover.NewNode(
   971  				discover.PubkeyID(&privKeys[i].PublicKey),
   972  				net.ParseIP("0.0.0.0"),
   973  				0,
   974  				p2pPort,
   975  				nil,
   976  				discover.NodeTypeEN).String(),
   977  		}
   978  		endpoints = append(endpoints, v)
   979  		endpointsNodeKeys = append(endpointsNodeKeys, v.Nodekey)
   980  	}
   981  	return endpoints, endpointsNodeKeys
   982  }
   983  
   984  func makeSCNs(num int, isWorkOnSingleHost bool) ([]*ValidatorInfo, []string) {
   985  	privKeys, nodeKeys, nodeAddrs := istcommon.GenerateKeys(num)
   986  
   987  	var p2pPort uint16
   988  	var scn []*ValidatorInfo
   989  	var scnKeys []string
   990  	for i := 0; i < num; i++ {
   991  		if isWorkOnSingleHost {
   992  			p2pPort = lastIssuedPortNum
   993  			lastIssuedPortNum++
   994  		} else {
   995  			p2pPort = DefaultTcpPort
   996  		}
   997  
   998  		v := &ValidatorInfo{
   999  			Address: nodeAddrs[i],
  1000  			Nodekey: nodeKeys[i],
  1001  			NodeInfo: discover.NewNode(
  1002  				discover.PubkeyID(&privKeys[i].PublicKey),
  1003  				net.ParseIP("0.0.0.0"),
  1004  				0,
  1005  				p2pPort,
  1006  				nil,
  1007  				discover.NodeTypeUnknown).String(),
  1008  		}
  1009  		scn = append(scn, v)
  1010  		scnKeys = append(scnKeys, v.Nodekey)
  1011  	}
  1012  	return scn, scnKeys
  1013  }
  1014  
  1015  func makeSPNs(num int, isWorkOnSingleHost bool) ([]*ValidatorInfo, []string) {
  1016  	privKeys, nodeKeys, nodeAddrs := istcommon.GenerateKeys(num)
  1017  
  1018  	var p2pPort uint16
  1019  	var proxies []*ValidatorInfo
  1020  	var proxyNodeKeys []string
  1021  	for i := 0; i < num; i++ {
  1022  		if isWorkOnSingleHost {
  1023  			p2pPort = lastIssuedPortNum
  1024  			lastIssuedPortNum++
  1025  		} else {
  1026  			p2pPort = DefaultTcpPort
  1027  		}
  1028  
  1029  		v := &ValidatorInfo{
  1030  			Address: nodeAddrs[i],
  1031  			Nodekey: nodeKeys[i],
  1032  			NodeInfo: discover.NewNode(
  1033  				discover.PubkeyID(&privKeys[i].PublicKey),
  1034  				net.ParseIP("0.0.0.0"),
  1035  				0,
  1036  				p2pPort,
  1037  				nil,
  1038  				discover.NodeTypeUnknown).String(),
  1039  		}
  1040  		proxies = append(proxies, v)
  1041  		proxyNodeKeys = append(proxyNodeKeys, v.Nodekey)
  1042  	}
  1043  	return proxies, proxyNodeKeys
  1044  }
  1045  
  1046  func makeSENs(num int, isWorkOnSingleHost bool) ([]*ValidatorInfo, []string) {
  1047  	privKeys, nodeKeys, nodeAddrs := istcommon.GenerateKeys(num)
  1048  
  1049  	var p2pPort uint16
  1050  	var endpoints []*ValidatorInfo
  1051  	var endpointsNodeKeys []string
  1052  	for i := 0; i < num; i++ {
  1053  		if isWorkOnSingleHost {
  1054  			p2pPort = lastIssuedPortNum
  1055  			lastIssuedPortNum++
  1056  		} else {
  1057  			p2pPort = DefaultTcpPort
  1058  		}
  1059  
  1060  		v := &ValidatorInfo{
  1061  			Address: nodeAddrs[i],
  1062  			Nodekey: nodeKeys[i],
  1063  			NodeInfo: discover.NewNode(
  1064  				discover.PubkeyID(&privKeys[i].PublicKey),
  1065  				net.ParseIP("0.0.0.0"),
  1066  				0,
  1067  				p2pPort,
  1068  				nil,
  1069  				discover.NodeTypeUnknown).String(),
  1070  		}
  1071  		endpoints = append(endpoints, v)
  1072  		endpointsNodeKeys = append(endpointsNodeKeys, v.Nodekey)
  1073  	}
  1074  	return endpoints, endpointsNodeKeys
  1075  }
  1076  
  1077  func writeValidatorsAndNodesToFile(validators []*ValidatorInfo, parentDir string, nodekeys []string) {
  1078  	parentPath := path.Join(outputPath, parentDir)
  1079  	os.MkdirAll(parentPath, os.ModePerm)
  1080  
  1081  	for i, v := range validators {
  1082  		nodeKeyFilePath := path.Join(parentPath, "nodekey"+strconv.Itoa(i+1))
  1083  		ioutil.WriteFile(nodeKeyFilePath, []byte(nodekeys[i]), os.ModePerm)
  1084  		fmt.Println("Created : ", nodeKeyFilePath)
  1085  
  1086  		str, _ := json.MarshalIndent(v, "", "\t")
  1087  		validatorInfoFilePath := path.Join(parentPath, "validator"+strconv.Itoa(i+1))
  1088  		ioutil.WriteFile(validatorInfoFilePath, []byte(str), os.ModePerm)
  1089  		fmt.Println("Created : ", validatorInfoFilePath)
  1090  	}
  1091  }
  1092  
  1093  func writeTestKeys(parentDir string, privKeys []*ecdsa.PrivateKey, keys []string) {
  1094  	parentPath := path.Join(outputPath, parentDir)
  1095  	os.MkdirAll(parentPath, os.ModePerm)
  1096  
  1097  	for i, key := range keys {
  1098  		testKeyFilePath := path.Join(parentPath, "testkey"+strconv.Itoa(i+1))
  1099  		ioutil.WriteFile(testKeyFilePath, []byte(key), os.ModePerm)
  1100  		fmt.Println("Created : ", testKeyFilePath)
  1101  
  1102  		pk := privKeys[i]
  1103  		ksPath := path.Join(parentPath, "keystore"+strconv.Itoa(i+1))
  1104  		ks := keystore.NewKeyStore(ksPath, keystore.StandardScryptN, keystore.StandardScryptP)
  1105  		pwdStr := RandStringRunes(params.PasswordLength)
  1106  		ks.ImportECDSA(pk, pwdStr)
  1107  		WriteFile([]byte(pwdStr), path.Join(parentDir, "keystore"+strconv.Itoa(i+1)), crypto.PubkeyToAddress(pk.PublicKey).String())
  1108  	}
  1109  }
  1110  
  1111  func WriteFile(content []byte, parentFolder string, fileName string) {
  1112  	filePath := path.Join(outputPath, parentFolder, fileName)
  1113  	os.MkdirAll(path.Dir(filePath), os.ModePerm)
  1114  	ioutil.WriteFile(filePath, content, os.ModePerm)
  1115  	fmt.Println("Created : ", filePath)
  1116  }
  1117  
  1118  func indexGenType(genTypeFlag string, base string) int {
  1119  	// NOTE-Klaytn: genTypeFlag's default value is docker
  1120  	if base != "" && genTypeFlag == "" {
  1121  		genTypeFlag = base
  1122  	}
  1123  	for typeIndex, typeString := range Types {
  1124  		if genTypeFlag == typeString {
  1125  			return typeIndex
  1126  		}
  1127  	}
  1128  	return TypeNotDefined
  1129  }
  1130  
  1131  func findGenType(ctx *cli.Context) int {
  1132  	var genType int
  1133  	if ctx.Args().Present() {
  1134  		genType = indexGenType(ctx.Args()[0], "")
  1135  	} else {
  1136  		genType = indexGenType(ctx.String(genTypeFlag.Name), Types[0])
  1137  	}
  1138  
  1139  	if genType == TypeNotDefined {
  1140  		fmt.Printf("Wrong Type : %s\nSupported Types : [docker, local, remote, deploy]\n\n", genTypeFlag)
  1141  		cli.ShowSubcommandHelp(ctx)
  1142  		os.Exit(1)
  1143  	}
  1144  
  1145  	return genType
  1146  }
  1147  
  1148  func removeSpacesAndLines(b []byte) string {
  1149  	out := string(b)
  1150  	out = strings.Replace(out, " ", "", -1)
  1151  	out = strings.Replace(out, "\t", "", -1)
  1152  	out = strings.Replace(out, "\n", "", -1)
  1153  	return out
  1154  }
  1155  
  1156  func homiFlagsFromYaml(ctx *cli.Context) error {
  1157  	filePath := ctx.String(homiYamlFlag.Name)
  1158  	if filePath != "" {
  1159  		if err := altsrc.InitInputSourceWithContext(SetupCommand.Flags, altsrc.NewYamlSourceFromFlagFunc(homiYamlFlag.Name))(ctx); err != nil {
  1160  			return err
  1161  		}
  1162  	}
  1163  	return nil
  1164  }
  1165  
  1166  func BeforeRunHomi(ctx *cli.Context) error {
  1167  	if err := homiFlagsFromYaml(ctx); err != nil {
  1168  		return err
  1169  	}
  1170  	return nil
  1171  }