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 ¶ms.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 ¶ms.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 ¶ms.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 ¶ms.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 ¶ms.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: ¶ms.ChainConfig{ 360 ChainID: big.NewInt(10000), 361 DeriveShaImpl: 2, 362 Governance: ¶ms.GovernanceConfig{ 363 GoverningNode: nodeAddrs[0], 364 GovernanceMode: "single", 365 Reward: ¶ms.RewardConfig{ 366 MintingAmount: mintingAmount, 367 Ratio: "34/54/12", 368 UseGiniCoeff: true, 369 DeferredTxFee: true, 370 }, 371 }, 372 Istanbul: ¶ms.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: ¶ms.ChainConfig{ 402 ChainID: big.NewInt(1000), 403 DeriveShaImpl: 2, 404 Istanbul: ¶ms.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: ¶ms.ChainConfig{ 451 ChainID: big.NewInt(2019), 452 DeriveShaImpl: 2, 453 Governance: ¶ms.GovernanceConfig{ 454 GoverningNode: nodeAddrs[0], 455 GovernanceMode: "single", 456 Reward: ¶ms.RewardConfig{ 457 MintingAmount: mintingAmount, 458 Ratio: "34/54/12", 459 UseGiniCoeff: false, 460 DeferredTxFee: true, 461 }, 462 }, 463 Istanbul: ¶ms.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 }