github.com/klaytn/klaytn@v1.12.1/cmd/utils/config.go (about) 1 // Modifications Copyright 2022 The klaytn Authors 2 // Copyright 2015 The go-ethereum Authors 3 // This file is part of go-ethereum. 4 // 5 // go-ethereum is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU 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 // go-ethereum 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 General Public License for more details. 14 // 15 // You should have received a copy of the GNU General Public License 16 // along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. 17 // 18 // This file is derived from cmd/utils/flags.go (2022/10/19). 19 // Modified and improved for the klaytn development. 20 21 package utils 22 23 import ( 24 "bufio" 25 "crypto/ecdsa" 26 "encoding/hex" 27 "errors" 28 "fmt" 29 "math/big" 30 "os" 31 "reflect" 32 "strconv" 33 "strings" 34 "time" 35 "unicode" 36 37 "github.com/Shopify/sarama" 38 "github.com/klaytn/klaytn/accounts" 39 "github.com/klaytn/klaytn/accounts/keystore" 40 "github.com/klaytn/klaytn/api/debug" 41 "github.com/klaytn/klaytn/blockchain" 42 "github.com/klaytn/klaytn/common" 43 "github.com/klaytn/klaytn/common/fdlimit" 44 "github.com/klaytn/klaytn/crypto" 45 "github.com/klaytn/klaytn/crypto/bls" 46 "github.com/klaytn/klaytn/datasync/chaindatafetcher" 47 "github.com/klaytn/klaytn/datasync/chaindatafetcher/kafka" 48 "github.com/klaytn/klaytn/datasync/chaindatafetcher/kas" 49 "github.com/klaytn/klaytn/datasync/dbsyncer" 50 "github.com/klaytn/klaytn/datasync/downloader" 51 "github.com/klaytn/klaytn/log" 52 "github.com/klaytn/klaytn/networks/p2p" 53 "github.com/klaytn/klaytn/networks/p2p/discover" 54 "github.com/klaytn/klaytn/networks/p2p/nat" 55 "github.com/klaytn/klaytn/networks/p2p/netutil" 56 "github.com/klaytn/klaytn/networks/rpc" 57 "github.com/klaytn/klaytn/node" 58 "github.com/klaytn/klaytn/node/cn" 59 "github.com/klaytn/klaytn/node/cn/filters" 60 "github.com/klaytn/klaytn/node/cn/tracers" 61 "github.com/klaytn/klaytn/node/sc" 62 "github.com/klaytn/klaytn/params" 63 "github.com/klaytn/klaytn/storage/database" 64 "github.com/klaytn/klaytn/storage/statedb" 65 "github.com/naoina/toml" 66 "github.com/urfave/cli/v2" 67 ) 68 69 const ( 70 ClientIdentifier = "klay" // Client identifier to advertise over the network 71 SCNNetworkType = "scn" // Service Chain Network 72 MNNetworkType = "mn" // Mainnet Network 73 gitCommit = "" 74 ) 75 76 // These settings ensure that TOML keys use the same names as Go struct fields. 77 var TomlSettings = toml.Config{ 78 NormFieldName: func(rt reflect.Type, key string) string { 79 return key 80 }, 81 FieldToKey: func(rt reflect.Type, field string) string { 82 return field 83 }, 84 MissingField: func(rt reflect.Type, field string) error { 85 link := "" 86 if unicode.IsUpper(rune(rt.Name()[0])) && rt.PkgPath() != "main" { 87 link = fmt.Sprintf(", see https://godoc.org/%s#%s for available fields", rt.PkgPath(), rt.Name()) 88 } 89 return fmt.Errorf("field '%s' is not defined in %s%s", field, rt.String(), link) 90 }, 91 } 92 93 type KlayConfig struct { 94 CN cn.Config 95 Node node.Config 96 DB dbsyncer.DBConfig 97 ChainDataFetcher chaindatafetcher.ChainDataFetcherConfig 98 ServiceChain sc.SCConfig 99 } 100 101 func LoadConfig(file string, cfg *KlayConfig) error { 102 f, err := os.Open(file) 103 if err != nil { 104 return err 105 } 106 defer f.Close() 107 108 err = TomlSettings.NewDecoder(bufio.NewReader(f)).Decode(cfg) 109 // Add file name to errors that have a line number. 110 if _, ok := err.(*toml.LineError); ok { 111 err = errors.New(file + ", " + err.Error()) 112 } 113 return err 114 } 115 116 func DefaultNodeConfig() node.Config { 117 cfg := node.DefaultConfig 118 cfg.Name = ClientIdentifier 119 cfg.Version = params.VersionWithCommit(gitCommit) 120 cfg.HTTPModules = append(cfg.HTTPModules, "klay", "shh", "eth") 121 cfg.WSModules = append(cfg.WSModules, "klay", "shh", "eth") 122 cfg.IPCPath = "klay.ipc" 123 return cfg 124 } 125 126 func MakeConfigNode(ctx *cli.Context) (*node.Node, KlayConfig) { 127 // Load defaults. 128 cfg := KlayConfig{ 129 CN: *cn.GetDefaultConfig(), 130 Node: DefaultNodeConfig(), 131 DB: *dbsyncer.DefaultDBConfig(), 132 ChainDataFetcher: *chaindatafetcher.DefaultChainDataFetcherConfig(), 133 ServiceChain: *sc.DefaultServiceChainConfig(), 134 } 135 136 // NOTE-Klaytn : klaytn loads the flags from yaml, not toml 137 // Load config file. 138 // if file := ctx.String(ConfigFileFlag.Name); file != "" { 139 // if err := LoadConfig(file, &cfg); err != nil { 140 // log.Fatalf("%v", err) 141 // } 142 // } 143 144 // Apply flags. 145 cfg.SetNodeConfig(ctx) 146 stack, err := node.New(&cfg.Node) 147 if err != nil { 148 log.Fatalf("Failed to create the protocol stack: %v", err) 149 } 150 cfg.SetKlayConfig(ctx, stack) 151 152 cfg.SetDBSyncerConfig(ctx) 153 cfg.SetChainDataFetcherConfig(ctx) 154 cfg.SetServiceChainConfig(ctx) 155 156 // SetShhConfig(ctx, stack, &cfg.Shh) 157 // SetDashboardConfig(ctx, &cfg.Dashboard) 158 159 return stack, cfg 160 } 161 162 func SetP2PConfig(ctx *cli.Context, cfg *p2p.Config) { 163 setNodeKey(ctx, cfg) 164 setNAT(ctx, cfg) 165 setListenAddress(ctx, cfg) 166 167 var nodeType string 168 if ctx.IsSet(NodeTypeFlag.Name) { 169 nodeType = ctx.String(NodeTypeFlag.Name) 170 } else { 171 nodeType = NodeTypeFlag.Value 172 } 173 174 cfg.ConnectionType = convertNodeType(nodeType) 175 if cfg.ConnectionType == common.UNKNOWNNODE { 176 logger.Crit("Unknown node type", "nodetype", nodeType) 177 } 178 logger.Info("Setting connection type", "nodetype", nodeType, "conntype", cfg.ConnectionType) 179 180 // set bootnodes via this function by check specified parameters 181 setBootstrapNodes(ctx, cfg) 182 183 if ctx.IsSet(MaxConnectionsFlag.Name) { 184 cfg.MaxPhysicalConnections = ctx.Int(MaxConnectionsFlag.Name) 185 } 186 logger.Info("Setting MaxPhysicalConnections", "MaxPhysicalConnections", cfg.MaxPhysicalConnections) 187 188 if ctx.IsSet(MaxPendingPeersFlag.Name) { 189 cfg.MaxPendingPeers = ctx.Int(MaxPendingPeersFlag.Name) 190 } 191 192 cfg.NoDiscovery = ctx.Bool(NoDiscoverFlag.Name) 193 194 cfg.RWTimerConfig = p2p.RWTimerConfig{} 195 cfg.RWTimerConfig.Interval = ctx.Uint64(RWTimerIntervalFlag.Name) 196 cfg.RWTimerConfig.WaitTime = ctx.Duration(RWTimerWaitTimeFlag.Name) 197 198 if netrestrict := ctx.String(NetrestrictFlag.Name); netrestrict != "" { 199 list, err := netutil.ParseNetlist(netrestrict) 200 if err != nil { 201 log.Fatalf("Option %q: %v", NetrestrictFlag.Name, err) 202 } 203 cfg.NetRestrict = list 204 } 205 206 common.MaxRequestContentLength = ctx.Int(MaxRequestContentLengthFlag.Name) 207 208 cfg.NetworkID, _ = getNetworkId(ctx) 209 } 210 211 // setNodeKey parses manually provided node key from command line flags, 212 // either loading it from a file or as a specified hex value. If neither flags 213 // were provided, this method sets cfg.PrivateKey = nil and node.Config.NodeKey() 214 // will handle the fallback logic. 215 func setNodeKey(ctx *cli.Context, cfg *p2p.Config) { 216 var ( 217 str = ctx.String(NodeKeyHexFlag.Name) 218 file = ctx.String(NodeKeyFileFlag.Name) 219 key *ecdsa.PrivateKey 220 err error 221 ) 222 switch { 223 case file != "" && str != "": 224 log.Fatalf("Options %q and %q are mutually exclusive", NodeKeyFileFlag.Name, NodeKeyHexFlag.Name) 225 case file != "": 226 if key, err = crypto.LoadECDSA(file); err != nil { 227 log.Fatalf("Option %q: %v", NodeKeyFileFlag.Name, err) 228 } 229 cfg.PrivateKey = key 230 case str != "": 231 if key, err = crypto.HexToECDSA(str); err != nil { 232 log.Fatalf("Option %q: %v", NodeKeyHexFlag.Name, err) 233 } 234 cfg.PrivateKey = key 235 } 236 } 237 238 // setBlsNodeKey parses manually provided bls secret key from the command line flags, 239 // either loading it from a file or as a specified hex value. If neither flags were 240 // provided, this method sets cfg.BlsKey = nil and node.Config.BlsNodeKey() will 241 // handle the fallback logic. 242 func setBlsNodeKey(ctx *cli.Context, cfg *node.Config) { 243 str := ctx.String(BlsNodeKeyHexFlag.Name) 244 file := ctx.String(BlsNodeKeyFileFlag.Name) 245 246 switch { 247 case file != "" && str != "": 248 log.Fatalf("Options %q and %q are mutually exclusive", BlsNodeKeyFileFlag.Name, BlsNodeKeyHexFlag.Name) 249 case file != "": 250 key, err := bls.LoadKey(file) 251 if err != nil { 252 log.Fatalf("Option %q: %v", BlsNodeKeyFileFlag.Name, err) 253 } 254 cfg.BlsKey = key 255 case str != "": 256 b, err := hex.DecodeString(str) 257 if err != nil { 258 log.Fatalf("Option %q: %v", BlsNodeKeyHexFlag.Name, err) 259 } 260 key, err := bls.SecretKeyFromBytes(b) 261 if err != nil { 262 log.Fatalf("Option %q: %v", BlsNodeKeyHexFlag.Name, err) 263 } 264 cfg.BlsKey = key 265 } 266 } 267 268 // setNAT creates a port mapper from command line flags. 269 func setNAT(ctx *cli.Context, cfg *p2p.Config) { 270 if ctx.IsSet(NATFlag.Name) { 271 natif, err := nat.Parse(ctx.String(NATFlag.Name)) 272 if err != nil { 273 log.Fatalf("Option %s: %v", NATFlag.Name, err) 274 } 275 cfg.NAT = natif 276 } 277 } 278 279 // setListenAddress creates a TCP listening address string from set command 280 // line flags. 281 func setListenAddress(ctx *cli.Context, cfg *p2p.Config) { 282 if ctx.IsSet(ListenPortFlag.Name) { 283 cfg.ListenAddr = fmt.Sprintf(":%d", ctx.Int(ListenPortFlag.Name)) 284 } 285 286 if ctx.Bool(MultiChannelUseFlag.Name) { 287 cfg.EnableMultiChannelServer = true 288 SubListenAddr := fmt.Sprintf(":%d", ctx.Int(SubListenPortFlag.Name)) 289 cfg.SubListenAddr = []string{SubListenAddr} 290 } 291 } 292 293 func convertNodeType(nodetype string) common.ConnType { 294 switch strings.ToLower(nodetype) { 295 case "cn", "scn": 296 return common.CONSENSUSNODE 297 case "pn", "spn": 298 return common.PROXYNODE 299 case "en", "sen": 300 return common.ENDPOINTNODE 301 default: 302 return common.UNKNOWNNODE 303 } 304 } 305 306 // setBootstrapNodes creates a list of bootstrap nodes from the command line 307 // flags, reverting to pre-configured ones if none have been specified. 308 func setBootstrapNodes(ctx *cli.Context, cfg *p2p.Config) { 309 var urls []string 310 switch { 311 case ctx.IsSet(BootnodesFlag.Name): 312 logger.Info("Customized bootnodes are set") 313 urls = strings.Split(ctx.String(BootnodesFlag.Name), ",") 314 case ctx.Bool(CypressFlag.Name): 315 logger.Info("Cypress bootnodes are set") 316 urls = params.MainnetBootnodes[cfg.ConnectionType].Addrs 317 case ctx.Bool(BaobabFlag.Name): 318 logger.Info("Baobab bootnodes are set") 319 // set pre-configured bootnodes when 'baobab' option was enabled 320 urls = params.BaobabBootnodes[cfg.ConnectionType].Addrs 321 case cfg.BootstrapNodes != nil: 322 return // already set, don't apply defaults. 323 case !ctx.IsSet(NetworkIdFlag.Name): 324 if NodeTypeFlag.Value != "scn" && NodeTypeFlag.Value != "spn" && NodeTypeFlag.Value != "sen" { 325 logger.Info("Cypress bootnodes are set") 326 urls = params.MainnetBootnodes[cfg.ConnectionType].Addrs 327 } 328 } 329 330 cfg.BootstrapNodes = make([]*discover.Node, 0, len(urls)) 331 for _, url := range urls { 332 node, err := discover.ParseNode(url) 333 if err != nil { 334 logger.Error("Bootstrap URL invalid", "kni", url, "err", err) 335 continue 336 } 337 if node.NType == discover.NodeTypeUnknown { 338 logger.Debug("setBootstrapNode: set nodetype as bn from unknown", "nodeid", node.ID) 339 node.NType = discover.NodeTypeBN 340 } 341 logger.Info("Bootnode - Add Seed", "Node", node) 342 cfg.BootstrapNodes = append(cfg.BootstrapNodes, node) 343 } 344 } 345 346 // setNodeConfig applies node-related command line flags to the config. 347 func (kCfg *KlayConfig) SetNodeConfig(ctx *cli.Context) { 348 cfg := &kCfg.Node 349 // ntp check enable with remote server 350 if ctx.Bool(NtpDisableFlag.Name) { 351 cfg.NtpRemoteServer = "" 352 } else { 353 cfg.NtpRemoteServer = ctx.String(NtpServerFlag.Name) 354 } 355 356 // disable unsafe debug APIs 357 cfg.DisableUnsafeDebug = ctx.Bool(UnsafeDebugDisableFlag.Name) 358 359 SetP2PConfig(ctx, &cfg.P2P) 360 setBlsNodeKey(ctx, cfg) 361 setIPC(ctx, cfg) 362 363 // httptype is http 364 // fasthttp type is deprecated 365 if ctx.IsSet(SrvTypeFlag.Name) { 366 cfg.HTTPServerType = ctx.String(SrvTypeFlag.Name) 367 368 if cfg.HTTPServerType == "fasthttp" { 369 logger.Warn("The fasthttp option is deprecated. Instead, the server will start with the http type") 370 cfg.HTTPServerType = "http" 371 } 372 } 373 374 setHTTP(ctx, cfg) 375 setWS(ctx, cfg) 376 setgRPC(ctx, cfg) 377 setAPIConfig(ctx) 378 setNodeUserIdent(ctx, cfg) 379 380 if dbtype := database.DBType(ctx.String(DbTypeFlag.Name)).ToValid(); len(dbtype) != 0 { 381 cfg.DBType = dbtype 382 } else { 383 logger.Crit("invalid dbtype", "dbtype", ctx.String(DbTypeFlag.Name)) 384 } 385 cfg.DataDir = ctx.String(DataDirFlag.Name) 386 cfg.ChainDataDir = ctx.String(ChainDataDirFlag.Name) 387 388 if ctx.IsSet(KeyStoreDirFlag.Name) { 389 cfg.KeyStoreDir = ctx.String(KeyStoreDirFlag.Name) 390 } 391 if ctx.IsSet(LightKDFFlag.Name) { 392 cfg.UseLightweightKDF = ctx.Bool(LightKDFFlag.Name) 393 } 394 if ctx.IsSet(RPCNonEthCompatibleFlag.Name) { 395 rpc.NonEthCompatible = ctx.Bool(RPCNonEthCompatibleFlag.Name) 396 } 397 } 398 399 // setHTTP creates the HTTP RPC listener interface string from the set 400 // command line flags, returning empty if the HTTP endpoint is disabled. 401 func setHTTP(ctx *cli.Context, cfg *node.Config) { 402 if ctx.Bool(RPCEnabledFlag.Name) && cfg.HTTPHost == "" { 403 cfg.HTTPHost = "127.0.0.1" 404 if ctx.IsSet(RPCListenAddrFlag.Name) { 405 cfg.HTTPHost = ctx.String(RPCListenAddrFlag.Name) 406 } 407 } 408 409 if ctx.IsSet(RPCPortFlag.Name) { 410 cfg.HTTPPort = ctx.Int(RPCPortFlag.Name) 411 } 412 if ctx.IsSet(RPCCORSDomainFlag.Name) { 413 cfg.HTTPCors = SplitAndTrim(ctx.String(RPCCORSDomainFlag.Name)) 414 } 415 if ctx.IsSet(RPCApiFlag.Name) { 416 cfg.HTTPModules = SplitAndTrim(ctx.String(RPCApiFlag.Name)) 417 } 418 if ctx.IsSet(RPCVirtualHostsFlag.Name) { 419 cfg.HTTPVirtualHosts = SplitAndTrim(ctx.String(RPCVirtualHostsFlag.Name)) 420 } 421 if ctx.IsSet(RPCConcurrencyLimit.Name) { 422 rpc.ConcurrencyLimit = ctx.Int(RPCConcurrencyLimit.Name) 423 logger.Info("Set the concurrency limit of RPC-HTTP server", "limit", rpc.ConcurrencyLimit) 424 } 425 if ctx.IsSet(RPCReadTimeout.Name) { 426 cfg.HTTPTimeouts.ReadTimeout = time.Duration(ctx.Int(RPCReadTimeout.Name)) * time.Second 427 } 428 if ctx.IsSet(RPCWriteTimeoutFlag.Name) { 429 cfg.HTTPTimeouts.WriteTimeout = time.Duration(ctx.Int(RPCWriteTimeoutFlag.Name)) * time.Second 430 } 431 if ctx.IsSet(RPCIdleTimeoutFlag.Name) { 432 cfg.HTTPTimeouts.IdleTimeout = time.Duration(ctx.Int(RPCIdleTimeoutFlag.Name)) * time.Second 433 } 434 if ctx.IsSet(RPCExecutionTimeoutFlag.Name) { 435 cfg.HTTPTimeouts.ExecutionTimeout = time.Duration(ctx.Int(RPCExecutionTimeoutFlag.Name)) * time.Second 436 } 437 if ctx.IsSet(RPCUpstreamArchiveENFlag.Name) { 438 rpc.UpstreamArchiveEN = ctx.String(RPCUpstreamArchiveENFlag.Name) 439 cfg.UpstreamArchiveEN = rpc.UpstreamArchiveEN 440 } 441 } 442 443 // setWS creates the WebSocket RPC listener interface string from the set 444 // command line flags, returning empty if the HTTP endpoint is disabled. 445 func setWS(ctx *cli.Context, cfg *node.Config) { 446 if ctx.Bool(WSEnabledFlag.Name) && cfg.WSHost == "" { 447 cfg.WSHost = "127.0.0.1" 448 if ctx.IsSet(WSListenAddrFlag.Name) { 449 cfg.WSHost = ctx.String(WSListenAddrFlag.Name) 450 } 451 } 452 453 if ctx.IsSet(WSPortFlag.Name) { 454 cfg.WSPort = ctx.Int(WSPortFlag.Name) 455 } 456 if ctx.IsSet(WSAllowedOriginsFlag.Name) { 457 cfg.WSOrigins = SplitAndTrim(ctx.String(WSAllowedOriginsFlag.Name)) 458 } 459 if ctx.IsSet(WSApiFlag.Name) { 460 cfg.WSModules = SplitAndTrim(ctx.String(WSApiFlag.Name)) 461 } 462 rpc.MaxSubscriptionPerWSConn = int32(ctx.Int(WSMaxSubscriptionPerConn.Name)) 463 rpc.WebsocketReadDeadline = ctx.Int64(WSReadDeadLine.Name) 464 rpc.WebsocketWriteDeadline = ctx.Int64(WSWriteDeadLine.Name) 465 rpc.MaxWebsocketConnections = int32(ctx.Int(WSMaxConnections.Name)) 466 } 467 468 // setIPC creates an IPC path configuration from the set command line flags, 469 // returning an empty string if IPC was explicitly disabled, or the set path. 470 func setIPC(ctx *cli.Context, cfg *node.Config) { 471 CheckExclusive(ctx, IPCDisabledFlag, IPCPathFlag) 472 switch { 473 case ctx.Bool(IPCDisabledFlag.Name): 474 cfg.IPCPath = "" 475 case ctx.IsSet(IPCPathFlag.Name): 476 cfg.IPCPath = ctx.String(IPCPathFlag.Name) 477 } 478 } 479 480 // setgRPC creates the gRPC listener interface string from the set 481 // command line flags, returning empty if the gRPC endpoint is disabled. 482 func setgRPC(ctx *cli.Context, cfg *node.Config) { 483 if ctx.Bool(GRPCEnabledFlag.Name) && cfg.GRPCHost == "" { 484 cfg.GRPCHost = "127.0.0.1" 485 if ctx.IsSet(GRPCListenAddrFlag.Name) { 486 cfg.GRPCHost = ctx.String(GRPCListenAddrFlag.Name) 487 } 488 } 489 490 if ctx.IsSet(GRPCPortFlag.Name) { 491 cfg.GRPCPort = ctx.Int(GRPCPortFlag.Name) 492 } 493 } 494 495 // setAPIConfig sets configurations for specific APIs. 496 func setAPIConfig(ctx *cli.Context) { 497 filters.GetLogsDeadline = ctx.Duration(APIFilterGetLogsDeadlineFlag.Name) 498 filters.GetLogsMaxItems = ctx.Int(APIFilterGetLogsMaxItemsFlag.Name) 499 } 500 501 // setNodeUserIdent creates the user identifier from CLI flags. 502 func setNodeUserIdent(ctx *cli.Context, cfg *node.Config) { 503 if identity := ctx.String(IdentityFlag.Name); len(identity) > 0 { 504 cfg.UserIdent = identity 505 } 506 } 507 508 // setKlayConfig applies klay-related command line flags to the config. 509 func (kCfg *KlayConfig) SetKlayConfig(ctx *cli.Context, stack *node.Node) { 510 // TODO-Klaytn-Bootnode: better have to check conflicts about network flags when we add Klaytn's `mainnet` parameter 511 // checkExclusive(ctx, DeveloperFlag, TestnetFlag, RinkebyFlag) 512 cfg := &kCfg.CN 513 raiseFDLimit() 514 515 ks := stack.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore) 516 setServiceChainSigner(ctx, ks, cfg) 517 setRewardbase(ctx, ks, cfg) 518 setTxPool(ctx, &cfg.TxPool) 519 520 if ctx.IsSet(SyncModeFlag.Name) { 521 cfg.SyncMode = *GlobalTextMarshaler(ctx, SyncModeFlag.Name).(*downloader.SyncMode) 522 if cfg.SyncMode != downloader.FullSync && cfg.SyncMode != downloader.SnapSync { 523 log.Fatalf("Full Sync or Snap Sync (prototype) is supported only!") 524 } 525 if cfg.SyncMode == downloader.SnapSync { 526 logger.Info("Snap sync requested, enabling --snapshot") 527 ctx.Set(SnapshotFlag.Name, "true") 528 } else { 529 cfg.SnapshotCacheSize = 0 // Disabled 530 } 531 } 532 533 if ctx.Bool(KESNodeTypeServiceFlag.Name) { 534 cfg.FetcherDisable = true 535 cfg.DownloaderDisable = true 536 cfg.WorkerDisable = true 537 } 538 539 if NetworkTypeFlag.Value == SCNNetworkType && kCfg.ServiceChain.EnabledSubBridge { 540 cfg.NoAccountCreation = !ctx.Bool(ServiceChainNewAccountFlag.Name) 541 } 542 543 cfg.NetworkId, cfg.IsPrivate = getNetworkId(ctx) 544 545 if dbtype := database.DBType(ctx.String(DbTypeFlag.Name)).ToValid(); len(dbtype) != 0 { 546 cfg.DBType = dbtype 547 } else { 548 logger.Crit("invalid dbtype", "dbtype", ctx.String(DbTypeFlag.Name)) 549 } 550 cfg.SingleDB = ctx.Bool(SingleDBFlag.Name) 551 cfg.NumStateTrieShards = ctx.Uint(NumStateTrieShardsFlag.Name) 552 if !database.IsPow2(cfg.NumStateTrieShards) { 553 log.Fatalf("%v should be power of 2 but %v is not!", NumStateTrieShardsFlag.Name, cfg.NumStateTrieShards) 554 } 555 556 cfg.OverwriteGenesis = ctx.Bool(OverwriteGenesisFlag.Name) 557 cfg.StartBlockNumber = ctx.Uint64(StartBlockNumberFlag.Name) 558 559 cfg.LevelDBCompression = database.LevelDBCompressionType(ctx.Int(LevelDBCompressionTypeFlag.Name)) 560 cfg.LevelDBBufferPool = !ctx.Bool(LevelDBNoBufferPoolFlag.Name) 561 cfg.EnableDBPerfMetrics = !ctx.Bool(DBNoPerformanceMetricsFlag.Name) 562 cfg.LevelDBCacheSize = ctx.Int(LevelDBCacheSizeFlag.Name) 563 564 cfg.RocksDBConfig.Secondary = ctx.Bool(RocksDBSecondaryFlag.Name) 565 cfg.RocksDBConfig.MaxOpenFiles = ctx.Int(RocksDBMaxOpenFilesFlag.Name) 566 if cfg.RocksDBConfig.Secondary { 567 cfg.FetcherDisable = true 568 cfg.DownloaderDisable = true 569 cfg.WorkerDisable = true 570 cfg.RocksDBConfig.MaxOpenFiles = -1 571 logger.Info("Secondary rocksdb is enabled, disabling fetcher, downloader, worker. MaxOpenFiles is forced to unlimited") 572 } 573 cfg.RocksDBConfig.CacheSize = ctx.Uint64(RocksDBCacheSizeFlag.Name) 574 cfg.RocksDBConfig.DumpMallocStat = ctx.Bool(RocksDBDumpMallocStatFlag.Name) 575 cfg.RocksDBConfig.CompressionType = ctx.String(RocksDBCompressionTypeFlag.Name) 576 cfg.RocksDBConfig.BottommostCompressionType = ctx.String(RocksDBBottommostCompressionTypeFlag.Name) 577 cfg.RocksDBConfig.FilterPolicy = ctx.String(RocksDBFilterPolicyFlag.Name) 578 cfg.RocksDBConfig.DisableMetrics = ctx.Bool(RocksDBDisableMetricsFlag.Name) 579 cfg.RocksDBConfig.CacheIndexAndFilter = ctx.Bool(RocksDBCacheIndexAndFilterFlag.Name) 580 581 cfg.DynamoDBConfig.TableName = ctx.String(DynamoDBTableNameFlag.Name) 582 cfg.DynamoDBConfig.Region = ctx.String(DynamoDBRegionFlag.Name) 583 cfg.DynamoDBConfig.IsProvisioned = ctx.Bool(DynamoDBIsProvisionedFlag.Name) 584 cfg.DynamoDBConfig.ReadCapacityUnits = ctx.Int64(DynamoDBReadCapacityFlag.Name) 585 cfg.DynamoDBConfig.WriteCapacityUnits = ctx.Int64(DynamoDBWriteCapacityFlag.Name) 586 cfg.DynamoDBConfig.ReadOnly = ctx.Bool(DynamoDBReadOnlyFlag.Name) 587 588 if gcmode := ctx.String(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" { 589 log.Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name) 590 } 591 cfg.NoPruning = ctx.String(GCModeFlag.Name) == "archive" 592 logger.Info("Archiving mode of this node", "isArchiveMode", cfg.NoPruning) 593 594 cfg.AnchoringPeriod = ctx.Uint64(AnchoringPeriodFlag.Name) 595 cfg.SentChainTxsLimit = ctx.Uint64(SentChainTxsLimit.Name) 596 597 cfg.TrieCacheSize = ctx.Int(TrieMemoryCacheSizeFlag.Name) 598 common.DefaultCacheType = common.CacheType(ctx.Int(CacheTypeFlag.Name)) 599 cfg.TrieBlockInterval = ctx.Uint(TrieBlockIntervalFlag.Name) 600 cfg.TriesInMemory = ctx.Uint64(TriesInMemoryFlag.Name) 601 cfg.LivePruning = ctx.Bool(LivePruningFlag.Name) 602 cfg.LivePruningRetention = ctx.Uint64(LivePruningRetentionFlag.Name) 603 604 if ctx.IsSet(CacheScaleFlag.Name) { 605 common.CacheScale = ctx.Int(CacheScaleFlag.Name) 606 } 607 if ctx.IsSet(CacheUsageLevelFlag.Name) { 608 cacheUsageLevelFlag := ctx.String(CacheUsageLevelFlag.Name) 609 if scaleByCacheUsageLevel, err := common.GetScaleByCacheUsageLevel(cacheUsageLevelFlag); err != nil { 610 logger.Crit("Incorrect CacheUsageLevelFlag value", "error", err, "CacheUsageLevelFlag", cacheUsageLevelFlag) 611 } else { 612 common.ScaleByCacheUsageLevel = scaleByCacheUsageLevel 613 } 614 } 615 if ctx.IsSet(MemorySizeFlag.Name) { 616 physicalMemory := common.TotalPhysicalMemGB 617 common.TotalPhysicalMemGB = ctx.Int(MemorySizeFlag.Name) 618 logger.Info("Physical memory has been replaced by user settings", "PhysicalMemory(GB)", physicalMemory, "UserSetting(GB)", common.TotalPhysicalMemGB) 619 } else { 620 logger.Debug("Memory settings", "PhysicalMemory(GB)", common.TotalPhysicalMemGB) 621 } 622 623 if ctx.IsSet(DocRootFlag.Name) { 624 cfg.DocRoot = ctx.String(DocRootFlag.Name) 625 } 626 if ctx.IsSet(ExtraDataFlag.Name) { 627 cfg.ExtraData = []byte(ctx.String(ExtraDataFlag.Name)) 628 } 629 630 cfg.SenderTxHashIndexing = ctx.Bool(SenderTxHashIndexingFlag.Name) 631 cfg.ParallelDBWrite = !ctx.Bool(NoParallelDBWriteFlag.Name) 632 cfg.TrieNodeCacheConfig = statedb.TrieNodeCacheConfig{ 633 CacheType: statedb.TrieNodeCacheType(ctx.String(TrieNodeCacheTypeFlag. 634 Name)).ToValid(), 635 NumFetcherPrefetchWorker: ctx.Int(NumFetcherPrefetchWorkerFlag.Name), 636 UseSnapshotForPrefetch: ctx.Bool(UseSnapshotForPrefetchFlag.Name), 637 LocalCacheSizeMiB: ctx.Int(TrieNodeCacheLimitFlag.Name), 638 FastCacheFileDir: ctx.String(DataDirFlag.Name) + "/fastcache", 639 FastCacheSavePeriod: ctx.Duration(TrieNodeCacheSavePeriodFlag.Name), 640 RedisEndpoints: ctx.StringSlice(TrieNodeCacheRedisEndpointsFlag.Name), 641 RedisClusterEnable: ctx.Bool(TrieNodeCacheRedisClusterFlag.Name), 642 RedisPublishBlockEnable: ctx.Bool(TrieNodeCacheRedisPublishBlockFlag.Name), 643 RedisSubscribeBlockEnable: ctx.Bool(TrieNodeCacheRedisSubscribeBlockFlag.Name), 644 } 645 646 if ctx.IsSet(VMEnableDebugFlag.Name) { 647 // TODO(fjl): force-enable this in --dev mode 648 cfg.EnablePreimageRecording = ctx.Bool(VMEnableDebugFlag.Name) 649 } 650 if ctx.IsSet(VMLogTargetFlag.Name) { 651 if _, err := debug.Handler.SetVMLogTarget(ctx.Int(VMLogTargetFlag.Name)); err != nil { 652 logger.Warn("Incorrect vmlog value", "err", err) 653 } 654 } 655 cfg.EnableInternalTxTracing = ctx.Bool(VMTraceInternalTxFlag.Name) 656 cfg.EnableOpDebug = ctx.Bool(VMOpDebugFlag.Name) 657 658 cfg.AutoRestartFlag = ctx.Bool(AutoRestartFlag.Name) 659 cfg.RestartTimeOutFlag = ctx.Duration(RestartTimeOutFlag.Name) 660 cfg.DaemonPathFlag = ctx.String(DaemonPathFlag.Name) 661 662 if ctx.IsSet(RPCGlobalGasCap.Name) { 663 cfg.RPCGasCap = new(big.Int).SetUint64(ctx.Uint64(RPCGlobalGasCap.Name)) 664 } 665 if ctx.IsSet(RPCGlobalEVMTimeoutFlag.Name) { 666 cfg.RPCEVMTimeout = ctx.Duration(RPCGlobalEVMTimeoutFlag.Name) 667 } 668 if ctx.IsSet(RPCGlobalEthTxFeeCapFlag.Name) { 669 cfg.RPCTxFeeCap = ctx.Float64(RPCGlobalEthTxFeeCapFlag.Name) 670 } 671 672 // Only CNs could set BlockGenerationIntervalFlag and BlockGenerationTimeLimitFlag 673 if ctx.IsSet(BlockGenerationIntervalFlag.Name) { 674 params.BlockGenerationInterval = ctx.Int64(BlockGenerationIntervalFlag.Name) 675 if params.BlockGenerationInterval < 1 { 676 logger.Crit("Block generation interval should be equal or larger than 1", "interval", params.BlockGenerationInterval) 677 } 678 } 679 if ctx.IsSet(BlockGenerationTimeLimitFlag.Name) { 680 params.BlockGenerationTimeLimit = ctx.Duration(BlockGenerationTimeLimitFlag.Name) 681 } 682 if ctx.IsSet(OpcodeComputationCostLimitFlag.Name) { 683 params.OpcodeComputationCostLimitOverride = ctx.Uint64(OpcodeComputationCostLimitFlag.Name) 684 } 685 686 if ctx.IsSet(SnapshotFlag.Name) { 687 cfg.SnapshotCacheSize = ctx.Int(SnapshotCacheSizeFlag.Name) 688 if cfg.StartBlockNumber != 0 { 689 logger.Crit("State snapshot should not be used with --start-block-num", "num", cfg.StartBlockNumber) 690 } 691 logger.Info("State snapshot is enabled", "cache-size (MB)", cfg.SnapshotCacheSize) 692 cfg.SnapshotAsyncGen = ctx.Bool(SnapshotAsyncGen.Name) 693 } else { 694 cfg.SnapshotCacheSize = 0 // snapshot disabled 695 } 696 697 // disable unsafe debug APIs 698 cfg.DisableUnsafeDebug = ctx.Bool(UnsafeDebugDisableFlag.Name) 699 cfg.StateRegenerationTimeLimit = ctx.Duration(StateRegenerationTimeLimitFlag.Name) 700 tracers.HeavyAPIRequestLimit = int32(ctx.Int(HeavyDebugRequestLimitFlag.Name)) 701 702 // Override any default configs for hard coded network. 703 // TODO-Klaytn-Bootnode: Discuss and add `baobab` test network's genesis block 704 /* 705 if ctx.Bool(TestnetFlag.Name) { 706 if !ctx.IsSet(NetworkIdFlag.Name) { 707 cfg.NetworkId = 3 708 } 709 cfg.Genesis = blockchain.DefaultBaobabGenesisBlock() 710 } 711 */ 712 // Set the Tx resending related configuration variables 713 setTxResendConfig(ctx, cfg) 714 } 715 716 // raiseFDLimit increases the file descriptor limit to process's maximum value 717 func raiseFDLimit() { 718 limit, err := fdlimit.Maximum() 719 if err != nil { 720 logger.Error("Failed to read maximum fd. you may suffer fd exhaustion", "err", err) 721 return 722 } 723 raised, err := fdlimit.Raise(uint64(limit)) 724 if err != nil { 725 logger.Warn("Failed to increase fd limit. you may suffer fd exhaustion", "err", err) 726 return 727 } 728 logger.Info("Raised fd limit to process's maximum value", "fd", raised) 729 } 730 731 // setServiceChainSigner retrieves the service chain signer either from the directly specified 732 // command line flags or from the keystore if CLI indexed. 733 func setServiceChainSigner(ctx *cli.Context, ks *keystore.KeyStore, cfg *cn.Config) { 734 if ctx.IsSet(ServiceChainSignerFlag.Name) { 735 account, err := MakeAddress(ks, ctx.String(ServiceChainSignerFlag.Name)) 736 if err != nil { 737 log.Fatalf("Option %q: %v", ServiceChainSignerFlag.Name, err) 738 } 739 cfg.ServiceChainSigner = account.Address 740 } 741 } 742 743 // setRewardbase retrieves the rewardbase either from the directly specified 744 // command line flags or from the keystore if CLI indexed. 745 func setRewardbase(ctx *cli.Context, ks *keystore.KeyStore, cfg *cn.Config) { 746 if ctx.IsSet(RewardbaseFlag.Name) { 747 account, err := MakeAddress(ks, ctx.String(RewardbaseFlag.Name)) 748 if err != nil { 749 log.Fatalf("Option %q: %v", RewardbaseFlag.Name, err) 750 } 751 cfg.Rewardbase = account.Address 752 } 753 } 754 755 // makeAddress converts an account specified directly as a hex encoded string or 756 // a key index in the key store to an internal account representation. 757 func MakeAddress(ks *keystore.KeyStore, account string) (accounts.Account, error) { 758 // If the specified account is a valid address, return it 759 if common.IsHexAddress(account) { 760 return accounts.Account{Address: common.HexToAddress(account)}, nil 761 } 762 // Otherwise try to interpret the account as a keystore index 763 index, err := strconv.Atoi(account) 764 if err != nil || index < 0 { 765 return accounts.Account{}, fmt.Errorf("invalid account address or index %q", account) 766 } 767 logger.Warn("Use explicit addresses! Referring to accounts by order in the keystore folder is dangerous and will be deprecated!") 768 769 accs := ks.Accounts() 770 if len(accs) <= index { 771 return accounts.Account{}, fmt.Errorf("index %d higher than number of accounts %d", index, len(accs)) 772 } 773 return accs[index], nil 774 } 775 776 func setTxPool(ctx *cli.Context, cfg *blockchain.TxPoolConfig) { 777 if ctx.IsSet(TxPoolNoLocalsFlag.Name) { 778 cfg.NoLocals = ctx.Bool(TxPoolNoLocalsFlag.Name) 779 } 780 if ctx.IsSet(TxPoolAllowLocalAnchorTxFlag.Name) { 781 cfg.AllowLocalAnchorTx = ctx.Bool(TxPoolAllowLocalAnchorTxFlag.Name) 782 } 783 if ctx.IsSet(TxPoolDenyRemoteTxFlag.Name) { 784 cfg.DenyRemoteTx = ctx.Bool(TxPoolDenyRemoteTxFlag.Name) 785 } 786 if ctx.IsSet(TxPoolJournalFlag.Name) { 787 cfg.Journal = ctx.String(TxPoolJournalFlag.Name) 788 } 789 if ctx.IsSet(TxPoolJournalIntervalFlag.Name) { 790 cfg.JournalInterval = ctx.Duration(TxPoolJournalIntervalFlag.Name) 791 } 792 if ctx.IsSet(TxPoolPriceLimitFlag.Name) { 793 cfg.PriceLimit = ctx.Uint64(TxPoolPriceLimitFlag.Name) 794 } 795 if ctx.IsSet(TxPoolPriceBumpFlag.Name) { 796 cfg.PriceBump = ctx.Uint64(TxPoolPriceBumpFlag.Name) 797 } 798 if ctx.IsSet(TxPoolExecSlotsAccountFlag.Name) { 799 cfg.ExecSlotsAccount = ctx.Uint64(TxPoolExecSlotsAccountFlag.Name) 800 } 801 if ctx.IsSet(TxPoolExecSlotsAllFlag.Name) { 802 cfg.ExecSlotsAll = ctx.Uint64(TxPoolExecSlotsAllFlag.Name) 803 } 804 if ctx.IsSet(TxPoolNonExecSlotsAccountFlag.Name) { 805 cfg.NonExecSlotsAccount = ctx.Uint64(TxPoolNonExecSlotsAccountFlag.Name) 806 } 807 if ctx.IsSet(TxPoolNonExecSlotsAllFlag.Name) { 808 cfg.NonExecSlotsAll = ctx.Uint64(TxPoolNonExecSlotsAllFlag.Name) 809 } 810 811 cfg.KeepLocals = ctx.Bool(TxPoolKeepLocalsFlag.Name) 812 813 if ctx.IsSet(TxPoolLifetimeFlag.Name) { 814 cfg.Lifetime = ctx.Duration(TxPoolLifetimeFlag.Name) 815 } 816 817 // PN specific txpool setting 818 if NodeTypeFlag.Value == "pn" { 819 cfg.EnableSpamThrottlerAtRuntime = !ctx.Bool(TxPoolSpamThrottlerDisableFlag.Name) 820 } 821 } 822 823 // getNetworkId returns the associated network ID with whether or not the network is private. 824 func getNetworkId(ctx *cli.Context) (uint64, bool) { 825 if ctx.Bool(BaobabFlag.Name) && ctx.Bool(CypressFlag.Name) { 826 log.Fatalf("--baobab and --cypress must not be set together") 827 } 828 if ctx.Bool(BaobabFlag.Name) && ctx.IsSet(NetworkIdFlag.Name) { 829 log.Fatalf("--baobab and --networkid must not be set together") 830 } 831 if ctx.Bool(CypressFlag.Name) && ctx.IsSet(NetworkIdFlag.Name) { 832 log.Fatalf("--cypress and --networkid must not be set together") 833 } 834 835 switch { 836 case ctx.Bool(CypressFlag.Name): 837 logger.Info("Cypress network ID is set", "networkid", params.CypressNetworkId) 838 return params.CypressNetworkId, false 839 case ctx.Bool(BaobabFlag.Name): 840 logger.Info("Baobab network ID is set", "networkid", params.BaobabNetworkId) 841 return params.BaobabNetworkId, false 842 case ctx.IsSet(NetworkIdFlag.Name): 843 networkId := ctx.Uint64(NetworkIdFlag.Name) 844 logger.Info("A private network ID is set", "networkid", networkId) 845 return networkId, true 846 default: 847 if NodeTypeFlag.Value == "scn" || NodeTypeFlag.Value == "spn" || NodeTypeFlag.Value == "sen" { 848 logger.Info("A Service Chain default network ID is set", "networkid", params.ServiceChainDefaultNetworkId) 849 return params.ServiceChainDefaultNetworkId, true 850 } 851 logger.Info("Cypress network ID is set", "networkid", params.CypressNetworkId) 852 return params.CypressNetworkId, false 853 } 854 } 855 856 func setTxResendConfig(ctx *cli.Context, cfg *cn.Config) { 857 // Set the Tx resending related configuration variables 858 cfg.TxResendInterval = ctx.Uint64(TxResendIntervalFlag.Name) 859 if cfg.TxResendInterval == 0 { 860 cfg.TxResendInterval = cn.DefaultTxResendInterval 861 } 862 863 cfg.TxResendCount = ctx.Int(TxResendCountFlag.Name) 864 if cfg.TxResendCount < cn.DefaultMaxResendTxCount { 865 cfg.TxResendCount = cn.DefaultMaxResendTxCount 866 } 867 cfg.TxResendUseLegacy = ctx.Bool(TxResendUseLegacyFlag.Name) 868 logger.Debug("TxResend config", "Interval", cfg.TxResendInterval, "TxResendCount", cfg.TxResendCount, "UseLegacy", cfg.TxResendUseLegacy) 869 } 870 871 func (kCfg *KlayConfig) SetChainDataFetcherConfig(ctx *cli.Context) { 872 cfg := &kCfg.ChainDataFetcher 873 if ctx.Bool(EnableChainDataFetcherFlag.Name) { 874 cfg.EnabledChainDataFetcher = true 875 876 if ctx.Bool(ChainDataFetcherNoDefault.Name) { 877 cfg.NoDefaultStart = true 878 } 879 if ctx.IsSet(ChainDataFetcherNumHandlers.Name) { 880 cfg.NumHandlers = ctx.Int(ChainDataFetcherNumHandlers.Name) 881 } 882 if ctx.IsSet(ChainDataFetcherJobChannelSize.Name) { 883 cfg.JobChannelSize = ctx.Int(ChainDataFetcherJobChannelSize.Name) 884 } 885 if ctx.IsSet(ChainDataFetcherChainEventSizeFlag.Name) { 886 cfg.BlockChannelSize = ctx.Int(ChainDataFetcherChainEventSizeFlag.Name) 887 } 888 if ctx.IsSet(ChainDataFetcherMaxProcessingDataSize.Name) { 889 cfg.MaxProcessingDataSize = ctx.Int(ChainDataFetcherMaxProcessingDataSize.Name) 890 } 891 892 mode := ctx.String(ChainDataFetcherMode.Name) 893 mode = strings.ToLower(mode) 894 switch mode { 895 case "kas": // kas option is not used. 896 cfg.Mode = chaindatafetcher.ModeKAS 897 cfg.KasConfig = makeKASConfig(ctx) 898 case "kafka": 899 cfg.Mode = chaindatafetcher.ModeKafka 900 cfg.KafkaConfig = makeKafkaConfig(ctx) 901 default: 902 logger.Crit("unsupported chaindatafetcher mode (\"kas\", \"kafka\")", "mode", cfg.Mode) 903 } 904 } 905 } 906 907 // NOTE-klaytn 908 // Deprecated: KASConfig is not used anymore. 909 func checkKASDBConfigs(ctx *cli.Context) { 910 if !ctx.IsSet(ChainDataFetcherKASDBHostFlag.Name) { 911 logger.Crit("DBHost must be set !", "key", ChainDataFetcherKASDBHostFlag.Name) 912 } 913 if !ctx.IsSet(ChainDataFetcherKASDBUserFlag.Name) { 914 logger.Crit("DBUser must be set !", "key", ChainDataFetcherKASDBUserFlag.Name) 915 } 916 if !ctx.IsSet(ChainDataFetcherKASDBPasswordFlag.Name) { 917 logger.Crit("DBPassword must be set !", "key", ChainDataFetcherKASDBPasswordFlag.Name) 918 } 919 if !ctx.IsSet(ChainDataFetcherKASDBNameFlag.Name) { 920 logger.Crit("DBName must be set !", "key", ChainDataFetcherKASDBNameFlag.Name) 921 } 922 } 923 924 // NOTE-klaytn 925 // Deprecated: KASConfig is not used anymore. 926 func checkKASCacheInvalidationConfigs(ctx *cli.Context) { 927 if !ctx.IsSet(ChainDataFetcherKASCacheURLFlag.Name) { 928 logger.Crit("The cache invalidation url is not set") 929 } 930 if !ctx.IsSet(ChainDataFetcherKASBasicAuthParamFlag.Name) { 931 logger.Crit("The authorization is not set") 932 } 933 if !ctx.IsSet(ChainDataFetcherKASXChainIdFlag.Name) { 934 logger.Crit("The x-chain-id is not set") 935 } 936 } 937 938 // NOTE-klaytn 939 // Deprecated: KASConfig is not used anymore. 940 func makeKASConfig(ctx *cli.Context) *kas.KASConfig { 941 kasConfig := kas.DefaultKASConfig 942 943 checkKASDBConfigs(ctx) 944 kasConfig.DBHost = ctx.String(ChainDataFetcherKASDBHostFlag.Name) 945 kasConfig.DBPort = ctx.String(ChainDataFetcherKASDBPortFlag.Name) 946 kasConfig.DBUser = ctx.String(ChainDataFetcherKASDBUserFlag.Name) 947 kasConfig.DBPassword = ctx.String(ChainDataFetcherKASDBPasswordFlag.Name) 948 kasConfig.DBName = ctx.String(ChainDataFetcherKASDBNameFlag.Name) 949 950 if ctx.Bool(ChainDataFetcherKASCacheUse.Name) { 951 checkKASCacheInvalidationConfigs(ctx) 952 kasConfig.CacheUse = true 953 kasConfig.CacheInvalidationURL = ctx.String(ChainDataFetcherKASCacheURLFlag.Name) 954 kasConfig.BasicAuthParam = ctx.String(ChainDataFetcherKASBasicAuthParamFlag.Name) 955 kasConfig.XChainId = ctx.String(ChainDataFetcherKASXChainIdFlag.Name) 956 } 957 return kasConfig 958 } 959 960 func makeKafkaConfig(ctx *cli.Context) *kafka.KafkaConfig { 961 kafkaConfig := kafka.GetDefaultKafkaConfig() 962 if ctx.IsSet(ChainDataFetcherKafkaBrokersFlag.Name) { 963 kafkaConfig.Brokers = ctx.StringSlice(ChainDataFetcherKafkaBrokersFlag.Name) 964 } else { 965 logger.Crit("The kafka brokers must be set") 966 } 967 kafkaConfig.TopicEnvironmentName = ctx.String(ChainDataFetcherKafkaTopicEnvironmentFlag.Name) 968 kafkaConfig.TopicResourceName = ctx.String(ChainDataFetcherKafkaTopicResourceFlag.Name) 969 kafkaConfig.Partitions = int32(ctx.Int64(ChainDataFetcherKafkaPartitionsFlag.Name)) 970 kafkaConfig.Replicas = int16(ctx.Int64(ChainDataFetcherKafkaReplicasFlag.Name)) 971 kafkaConfig.SaramaConfig.Producer.MaxMessageBytes = ctx.Int(ChainDataFetcherKafkaMaxMessageBytesFlag.Name) 972 kafkaConfig.SegmentSizeBytes = ctx.Int(ChainDataFetcherKafkaSegmentSizeBytesFlag.Name) 973 kafkaConfig.MsgVersion = ctx.String(ChainDataFetcherKafkaMessageVersionFlag.Name) 974 kafkaConfig.ProducerId = ctx.String(ChainDataFetcherKafkaProducerIdFlag.Name) 975 requiredAcks := sarama.RequiredAcks(ctx.Int(ChainDataFetcherKafkaRequiredAcksFlag.Name)) 976 if requiredAcks != sarama.NoResponse && requiredAcks != sarama.WaitForLocal && requiredAcks != sarama.WaitForAll { 977 logger.Crit("not supported requiredAcks. it must be NoResponse(0), WaitForLocal(1), or WaitForAll(-1)", "given", requiredAcks) 978 } 979 kafkaConfig.SaramaConfig.Producer.RequiredAcks = requiredAcks 980 return kafkaConfig 981 } 982 983 func (kCfg *KlayConfig) SetDBSyncerConfig(ctx *cli.Context) { 984 cfg := &kCfg.DB 985 if ctx.Bool(EnableDBSyncerFlag.Name) { 986 cfg.EnabledDBSyncer = true 987 988 if ctx.IsSet(DBHostFlag.Name) { 989 dbhost := ctx.String(DBHostFlag.Name) 990 cfg.DBHost = dbhost 991 } else { 992 logger.Crit("DBHost must be set !", "key", DBHostFlag.Name) 993 } 994 if ctx.IsSet(DBPortFlag.Name) { 995 dbports := ctx.String(DBPortFlag.Name) 996 cfg.DBPort = dbports 997 } 998 if ctx.IsSet(DBUserFlag.Name) { 999 dbuser := ctx.String(DBUserFlag.Name) 1000 cfg.DBUser = dbuser 1001 } else { 1002 logger.Crit("DBUser must be set !", "key", DBUserFlag.Name) 1003 } 1004 if ctx.IsSet(DBPasswordFlag.Name) { 1005 dbpasswd := ctx.String(DBPasswordFlag.Name) 1006 cfg.DBPassword = dbpasswd 1007 } else { 1008 logger.Crit("DBPassword must be set !", "key", DBPasswordFlag.Name) 1009 } 1010 if ctx.IsSet(DBNameFlag.Name) { 1011 dbname := ctx.String(DBNameFlag.Name) 1012 cfg.DBName = dbname 1013 } else { 1014 logger.Crit("DBName must be set !", "key", DBNameFlag.Name) 1015 } 1016 if ctx.Bool(EnabledLogModeFlag.Name) { 1017 cfg.EnabledLogMode = true 1018 } 1019 if ctx.IsSet(MaxIdleConnsFlag.Name) { 1020 cfg.MaxIdleConns = ctx.Int(MaxIdleConnsFlag.Name) 1021 } 1022 if ctx.IsSet(MaxOpenConnsFlag.Name) { 1023 cfg.MaxOpenConns = ctx.Int(MaxOpenConnsFlag.Name) 1024 } 1025 if ctx.IsSet(ConnMaxLifeTimeFlag.Name) { 1026 cfg.ConnMaxLifetime = ctx.Duration(ConnMaxLifeTimeFlag.Name) 1027 } 1028 if ctx.IsSet(DBSyncerModeFlag.Name) { 1029 cfg.Mode = strings.ToLower(ctx.String(DBSyncerModeFlag.Name)) 1030 } 1031 if ctx.IsSet(GenQueryThreadFlag.Name) { 1032 cfg.GenQueryThread = ctx.Int(GenQueryThreadFlag.Name) 1033 } 1034 if ctx.IsSet(InsertThreadFlag.Name) { 1035 cfg.InsertThread = ctx.Int(InsertThreadFlag.Name) 1036 } 1037 if ctx.IsSet(BulkInsertSizeFlag.Name) { 1038 cfg.BulkInsertSize = ctx.Int(BulkInsertSizeFlag.Name) 1039 } 1040 if ctx.IsSet(EventModeFlag.Name) { 1041 cfg.EventMode = strings.ToLower(ctx.String(EventModeFlag.Name)) 1042 } 1043 if ctx.IsSet(MaxBlockDiffFlag.Name) { 1044 cfg.MaxBlockDiff = ctx.Uint64(MaxBlockDiffFlag.Name) 1045 } 1046 if ctx.IsSet(BlockSyncChannelSizeFlag.Name) { 1047 cfg.BlockChannelSize = ctx.Int(BlockSyncChannelSizeFlag.Name) 1048 } 1049 } 1050 } 1051 1052 func (kCfg *KlayConfig) SetServiceChainConfig(ctx *cli.Context) { 1053 cfg := &kCfg.ServiceChain 1054 1055 // bridge service 1056 if ctx.Bool(MainBridgeFlag.Name) { 1057 cfg.EnabledMainBridge = true 1058 cfg.MainBridgePort = fmt.Sprintf(":%d", ctx.Int(MainBridgeListenPortFlag.Name)) 1059 } 1060 1061 if ctx.Bool(SubBridgeFlag.Name) { 1062 cfg.EnabledSubBridge = true 1063 cfg.SubBridgePort = fmt.Sprintf(":%d", ctx.Int(SubBridgeListenPortFlag.Name)) 1064 } 1065 1066 cfg.Anchoring = ctx.Bool(ServiceChainAnchoringFlag.Name) 1067 cfg.ChildChainIndexing = ctx.Bool(ChildChainIndexingFlag.Name) 1068 cfg.AnchoringPeriod = ctx.Uint64(AnchoringPeriodFlag.Name) 1069 cfg.SentChainTxsLimit = ctx.Uint64(SentChainTxsLimit.Name) 1070 cfg.ParentChainID = ctx.Uint64(ParentChainIDFlag.Name) 1071 cfg.VTRecovery = ctx.Bool(VTRecoveryFlag.Name) 1072 cfg.VTRecoveryInterval = ctx.Uint64(VTRecoveryIntervalFlag.Name) 1073 cfg.ServiceChainConsensus = ServiceChainConsensusFlag.Value 1074 cfg.ServiceChainParentOperatorGasLimit = ctx.Uint64(ServiceChainParentOperatorTxGasLimitFlag.Name) 1075 cfg.ServiceChainChildOperatorGasLimit = ctx.Uint64(ServiceChainChildOperatorTxGasLimitFlag.Name) 1076 1077 cfg.KASAnchor = ctx.Bool(KASServiceChainAnchorFlag.Name) 1078 if cfg.KASAnchor { 1079 cfg.KASAnchorPeriod = ctx.Uint64(KASServiceChainAnchorPeriodFlag.Name) 1080 if cfg.KASAnchorPeriod == 0 { 1081 cfg.KASAnchorPeriod = 1 1082 logger.Warn("KAS anchor period is set by 1") 1083 } 1084 1085 cfg.KASAnchorUrl = ctx.String(KASServiceChainAnchorUrlFlag.Name) 1086 if cfg.KASAnchorUrl == "" { 1087 logger.Crit("KAS anchor url should be set", "key", KASServiceChainAnchorUrlFlag.Name) 1088 } 1089 1090 cfg.KASAnchorOperator = ctx.String(KASServiceChainAnchorOperatorFlag.Name) 1091 if cfg.KASAnchorOperator == "" { 1092 logger.Crit("KAS anchor operator should be set", "key", KASServiceChainAnchorOperatorFlag.Name) 1093 } 1094 1095 cfg.KASAccessKey = ctx.String(KASServiceChainAccessKeyFlag.Name) 1096 if cfg.KASAccessKey == "" { 1097 logger.Crit("KAS access key should be set", "key", KASServiceChainAccessKeyFlag.Name) 1098 } 1099 1100 cfg.KASSecretKey = ctx.String(KASServiceChainSecretKeyFlag.Name) 1101 if cfg.KASSecretKey == "" { 1102 logger.Crit("KAS secret key should be set", "key", KASServiceChainSecretKeyFlag.Name) 1103 } 1104 1105 cfg.KASXChainId = ctx.String(KASServiceChainXChainIdFlag.Name) 1106 if cfg.KASXChainId == "" { 1107 logger.Crit("KAS x-chain-id should be set", "key", KASServiceChainXChainIdFlag.Name) 1108 } 1109 1110 cfg.KASAnchorRequestTimeout = ctx.Duration(KASServiceChainAnchorRequestTimeoutFlag.Name) 1111 } 1112 1113 cfg.DataDir = kCfg.Node.DataDir 1114 cfg.Name = kCfg.Node.Name 1115 }