github.com/klaytn/klaytn@v1.12.1/node/sc/config.go (about)

     1  // Modifications Copyright 2019 The klaytn Authors
     2  // Copyright 2017 The go-ethereum Authors
     3  // This file is part of go-ethereum.
     4  //
     5  // The go-ethereum library is free software: you can redistribute it and/or modify
     6  // it under the terms of the GNU Lesser General Public License as published by
     7  // the Free Software Foundation, either version 3 of the License, or
     8  // (at your option) any later version.
     9  //
    10  // The go-ethereum library is distributed in the hope that it will be useful,
    11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    13  // GNU Lesser General Public License for more details.
    14  //
    15  // You should have received a copy of the GNU Lesser General Public License
    16  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    17  //
    18  // This file is derived from eth/config.go (2018/06/04).
    19  // Modified and improved for the klaytn development.
    20  
    21  package sc
    22  
    23  import (
    24  	"crypto/ecdsa"
    25  	"fmt"
    26  	"os"
    27  	"os/user"
    28  	"path/filepath"
    29  	"runtime"
    30  	"strings"
    31  	"time"
    32  
    33  	"github.com/klaytn/klaytn/common"
    34  	"github.com/klaytn/klaytn/crypto"
    35  	"github.com/klaytn/klaytn/log"
    36  	"github.com/klaytn/klaytn/networks/p2p/discover"
    37  )
    38  
    39  const (
    40  	datadirMainChainBridgeNodes = "main-bridges.json" // Path within the datadir to the static node list
    41  )
    42  
    43  var logger = log.NewModuleLogger(log.ServiceChain)
    44  
    45  func DefaultServiceChainConfig() *SCConfig {
    46  	// DefaultConfig contains default settings for use on the Klaytn main net.
    47  	return &SCConfig{
    48  		NetworkId: 1,
    49  		MaxPeer:   1, // Only a single main-bridge and sub-bridge pair is allowed.
    50  	}
    51  }
    52  
    53  func init() {
    54  	home := os.Getenv("HOME")
    55  	if home == "" {
    56  		if user, err := user.Current(); err == nil {
    57  			home = user.HomeDir
    58  		}
    59  	}
    60  }
    61  
    62  type SCConfig struct {
    63  	// Name sets the instance name of the node. It must not contain the / character and is
    64  	// used in the devp2p node identifier. The instance name is "kscn". If no
    65  	// value is specified, the basename of the current executable is used.
    66  	Name string `toml:"-"`
    67  
    68  	// BridgeService
    69  	EnabledMainBridge bool
    70  	EnabledSubBridge  bool
    71  	DataDir           string
    72  
    73  	// Protocol options
    74  	NetworkId uint64 // Network ID to use for selecting peers to connect to
    75  
    76  	// Database options
    77  	SkipBcVersionCheck bool `toml:"-"`
    78  	DatabaseHandles    int  `toml:"-"`
    79  	LevelDBCacheSize   int
    80  	TrieCacheSize      int
    81  	TrieTimeout        time.Duration
    82  	TrieBlockInterval  uint
    83  	ChildChainIndexing bool
    84  
    85  	// Network
    86  	MainBridgePort string
    87  	SubBridgePort  string
    88  	MaxPeer        int
    89  
    90  	// ServiceChain
    91  	ServiceChainConsensus string
    92  	AnchoringPeriod       uint64
    93  	SentChainTxsLimit     uint64
    94  
    95  	ParentChainID                      uint64
    96  	VTRecovery                         bool
    97  	VTRecoveryInterval                 uint64
    98  	Anchoring                          bool
    99  	ServiceChainParentOperatorGasLimit uint64
   100  	ServiceChainChildOperatorGasLimit  uint64
   101  
   102  	// KAS
   103  	KASAnchor               bool
   104  	KASAnchorUrl            string
   105  	KASAnchorPeriod         uint64
   106  	KASAnchorOperator       string
   107  	KASAccessKey            string
   108  	KASSecretKey            string
   109  	KASXChainId             string
   110  	KASAnchorRequestTimeout time.Duration
   111  }
   112  
   113  // NodeName returns the devp2p node identifier.
   114  func (c *SCConfig) NodeName() string {
   115  	name := c.name()
   116  	// Backwards compatibility: previous versions used title-cased "Klaytn", keep that.
   117  	if name == "klay" || name == "klay-testnet" {
   118  		name = "Klaytn"
   119  	}
   120  	name += "/" + runtime.GOOS + "-" + runtime.GOARCH
   121  	name += "/" + runtime.Version()
   122  	return name
   123  }
   124  
   125  func (c *SCConfig) name() string {
   126  	if c.Name == "" {
   127  		progname := strings.TrimSuffix(filepath.Base(os.Args[0]), ".exe")
   128  		if progname == "" {
   129  			panic("empty executable name, set Config.Name")
   130  		}
   131  		return progname
   132  	}
   133  	return c.Name
   134  }
   135  
   136  // StaticNodes returns a list of node enode URLs configured as static nodes.
   137  func (c *SCConfig) MainBridges() []*discover.Node {
   138  	return c.parsePersistentNodes(filepath.Join(c.DataDir, datadirMainChainBridgeNodes))
   139  }
   140  
   141  func (c *SCConfig) parsePersistentNodes(path string) []*discover.Node {
   142  	// Short circuit if no node config is present
   143  	if c.DataDir == "" {
   144  		return nil
   145  	}
   146  	if _, err := os.Stat(path); err != nil {
   147  		return nil
   148  	}
   149  	// Load the nodes from the config file.
   150  	var nodelist []string
   151  	if err := common.LoadJSON(path, &nodelist); err != nil {
   152  		logger.Error(fmt.Sprintf("Can't load node file %s: %v", path, err))
   153  		return nil
   154  	}
   155  	// Interpret the list as a discovery node array
   156  	var nodes []*discover.Node
   157  	for _, url := range nodelist {
   158  		if url == "" {
   159  			continue
   160  		}
   161  		node, err := discover.ParseNode(url)
   162  		if err != nil {
   163  			logger.Error(fmt.Sprintf("Node URL %s: %v\n", url, err))
   164  			continue
   165  		}
   166  		nodes = append(nodes, node)
   167  	}
   168  	return nodes
   169  }
   170  
   171  // ResolvePath resolves path in the instance directory.
   172  func (c *SCConfig) ResolvePath(path string) string {
   173  	if filepath.IsAbs(path) {
   174  		return path
   175  	}
   176  	if c.DataDir == "" {
   177  		return ""
   178  	}
   179  	return filepath.Join(c.instanceDir(), path)
   180  }
   181  
   182  func (c *SCConfig) instanceDir() string {
   183  	if c.DataDir == "" {
   184  		return ""
   185  	}
   186  	return filepath.Join(c.DataDir, c.name())
   187  }
   188  
   189  func (c *SCConfig) getKey(path string) *ecdsa.PrivateKey {
   190  	keyFile := c.ResolvePath(path)
   191  	if key, err := crypto.LoadECDSA(keyFile); err == nil {
   192  		return key
   193  	}
   194  	// No persistent key found, generate and store a new one.
   195  	key, err := crypto.GenerateKey()
   196  	if err != nil {
   197  		logger.Crit("Failed to generate chain key", "err", err)
   198  	}
   199  	instanceDir := filepath.Join(c.DataDir, c.name())
   200  	if err := os.MkdirAll(instanceDir, 0o700); err != nil {
   201  		logger.Crit("Failed to make dir to persist chain key", "err", err)
   202  	}
   203  	keyFile = filepath.Join(instanceDir, path)
   204  	if err := crypto.SaveECDSA(keyFile, key); err != nil {
   205  		logger.Crit("Failed to persist chain key", "err", err)
   206  	}
   207  	return key
   208  }