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  }