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