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