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  }