github.com/Bytom/bytom@v1.1.2-0.20210127130405-ae40204c0b09/config/config.go (about)

     1  package config
     2  
     3  import (
     4  	"io"
     5  	"io/ioutil"
     6  	"os"
     7  	"os/user"
     8  	"path/filepath"
     9  	"runtime"
    10  
    11  	log "github.com/sirupsen/logrus"
    12  
    13  	"github.com/bytom/bytom/crypto/ed25519"
    14  )
    15  
    16  var (
    17  	// CommonConfig means config object
    18  	CommonConfig *Config
    19  )
    20  
    21  type Config struct {
    22  	// Top level options use an anonymous struct
    23  	BaseConfig `mapstructure:",squash"`
    24  	// Options for services
    25  	P2P       *P2PConfig       `mapstructure:"p2p"`
    26  	Wallet    *WalletConfig    `mapstructure:"wallet"`
    27  	Auth      *RPCAuthConfig   `mapstructure:"auth"`
    28  	Web       *WebConfig       `mapstructure:"web"`
    29  	Simd      *SimdConfig      `mapstructure:"simd"`
    30  	Websocket *WebsocketConfig `mapstructure:"ws"`
    31  }
    32  
    33  // Default configurable parameters.
    34  func DefaultConfig() *Config {
    35  	return &Config{
    36  		BaseConfig: DefaultBaseConfig(),
    37  		P2P:        DefaultP2PConfig(),
    38  		Wallet:     DefaultWalletConfig(),
    39  		Auth:       DefaultRPCAuthConfig(),
    40  		Web:        DefaultWebConfig(),
    41  		Simd:       DefaultSimdConfig(),
    42  		Websocket:  DefaultWebsocketConfig(),
    43  	}
    44  }
    45  
    46  // Set the RootDir for all Config structs
    47  func (cfg *Config) SetRoot(root string) *Config {
    48  	cfg.BaseConfig.RootDir = root
    49  	return cfg
    50  }
    51  
    52  // NodeKey retrieves the currently configured private key of the node, checking
    53  // first any manually set key, falling back to the one found in the configured
    54  // data folder. If no key can be found, a new one is generated.
    55  func (cfg *Config) NodeKey() (string, error) {
    56  	// Use any specifically configured key.
    57  	if cfg.P2P.PrivateKey != "" {
    58  		return cfg.P2P.PrivateKey, nil
    59  	}
    60  
    61  	keyFile := rootify(cfg.P2P.NodeKeyFile, cfg.BaseConfig.RootDir)
    62  	buf := make([]byte, ed25519.PrivateKeySize*2)
    63  	fd, err := os.Open(keyFile)
    64  	defer fd.Close()
    65  	if err == nil {
    66  		if _, err = io.ReadFull(fd, buf); err == nil {
    67  			return string(buf), nil
    68  		}
    69  	}
    70  
    71  	log.WithField("err", err).Warning("key file access failed")
    72  	_, privKey, err := ed25519.GenerateKey(nil)
    73  	if err != nil {
    74  		return "", err
    75  	}
    76  
    77  	if err = ioutil.WriteFile(keyFile, []byte(privKey.String()), 0600); err != nil {
    78  		return "", err
    79  	}
    80  	return privKey.String(), nil
    81  }
    82  
    83  //-----------------------------------------------------------------------------
    84  // BaseConfig
    85  type BaseConfig struct {
    86  	// The root directory for all data.
    87  	// This should be set in viper so it can unmarshal into this struct
    88  	RootDir string `mapstructure:"home"`
    89  
    90  	//The alias of the node
    91  	NodeAlias string `mapstructure:"node_alias"`
    92  
    93  	//The ID of the network to json
    94  	ChainID string `mapstructure:"chain_id"`
    95  
    96  	//log level to set
    97  	LogLevel string `mapstructure:"log_level"`
    98  
    99  	// A custom human readable name for this node
   100  	Moniker string `mapstructure:"moniker"`
   101  
   102  	// TCP or UNIX socket address for the profiling server to listen on
   103  	ProfListenAddress string `mapstructure:"prof_laddr"`
   104  
   105  	Mining bool `mapstructure:"mining"`
   106  
   107  	// Database backend: leveldb | memdb
   108  	DBBackend string `mapstructure:"db_backend"`
   109  
   110  	// Database directory
   111  	DBPath string `mapstructure:"db_dir"`
   112  
   113  	// Keystore directory
   114  	KeysPath string `mapstructure:"keys_dir"`
   115  
   116  	ApiAddress string `mapstructure:"api_addr"`
   117  
   118  	VaultMode bool `mapstructure:"vault_mode"`
   119  
   120  	// log file name
   121  	LogFile string `mapstructure:"log_file"`
   122  }
   123  
   124  // Default configurable base parameters.
   125  func DefaultBaseConfig() BaseConfig {
   126  	return BaseConfig{
   127  		Moniker:           "anonymous",
   128  		ProfListenAddress: "",
   129  		Mining:            false,
   130  		DBBackend:         "leveldb",
   131  		DBPath:            "data",
   132  		KeysPath:          "keystore",
   133  		NodeAlias:         "",
   134  		LogFile:           "log",
   135  	}
   136  }
   137  
   138  func (b BaseConfig) DBDir() string {
   139  	return rootify(b.DBPath, b.RootDir)
   140  }
   141  
   142  func (b BaseConfig) LogDir() string {
   143  	return rootify(b.LogFile, b.RootDir)
   144  }
   145  
   146  func (b BaseConfig) KeysDir() string {
   147  	return rootify(b.KeysPath, b.RootDir)
   148  }
   149  
   150  // P2PConfig
   151  type P2PConfig struct {
   152  	ListenAddress    string `mapstructure:"laddr"`
   153  	Seeds            string `mapstructure:"seeds"`
   154  	PrivateKey       string `mapstructure:"node_key"`
   155  	NodeKeyFile      string `mapstructure:"node_key_file"`
   156  	SkipUPNP         bool   `mapstructure:"skip_upnp"`
   157  	LANDiscover      bool   `mapstructure:"lan_discoverable"`
   158  	MaxNumPeers      int    `mapstructure:"max_num_peers"`
   159  	HandshakeTimeout int    `mapstructure:"handshake_timeout"`
   160  	DialTimeout      int    `mapstructure:"dial_timeout"`
   161  	ProxyAddress     string `mapstructure:"proxy_address"`
   162  	ProxyUsername    string `mapstructure:"proxy_username"`
   163  	ProxyPassword    string `mapstructure:"proxy_password"`
   164  	KeepDial         string `mapstructure:"keep_dial"`
   165  }
   166  
   167  // Default configurable p2p parameters.
   168  func DefaultP2PConfig() *P2PConfig {
   169  	return &P2PConfig{
   170  		ListenAddress:    "tcp://0.0.0.0:46656",
   171  		NodeKeyFile:      "nodekey",
   172  		SkipUPNP:         false,
   173  		LANDiscover:      true,
   174  		MaxNumPeers:      50,
   175  		HandshakeTimeout: 30,
   176  		DialTimeout:      3,
   177  		ProxyAddress:     "",
   178  		ProxyUsername:    "",
   179  		ProxyPassword:    "",
   180  	}
   181  }
   182  
   183  //-----------------------------------------------------------------------------
   184  type WalletConfig struct {
   185  	Disable  bool   `mapstructure:"disable"`
   186  	Rescan   bool   `mapstructure:"rescan"`
   187  	TxIndex  bool   `mapstructure:"txindex"`
   188  	MaxTxFee uint64 `mapstructure:"max_tx_fee"`
   189  }
   190  
   191  type RPCAuthConfig struct {
   192  	Disable bool `mapstructure:"disable"`
   193  }
   194  
   195  type WebConfig struct {
   196  	Closed bool `mapstructure:"closed"`
   197  }
   198  
   199  type SimdConfig struct {
   200  	Enable bool `mapstructure:"enable"`
   201  }
   202  
   203  type WebsocketConfig struct {
   204  	MaxNumWebsockets     int `mapstructure:"max_num_websockets"`
   205  	MaxNumConcurrentReqs int `mapstructure:"max_num_concurrent_reqs"`
   206  }
   207  
   208  // Default configurable rpc's auth parameters.
   209  func DefaultRPCAuthConfig() *RPCAuthConfig {
   210  	return &RPCAuthConfig{
   211  		Disable: false,
   212  	}
   213  }
   214  
   215  // Default configurable web parameters.
   216  func DefaultWebConfig() *WebConfig {
   217  	return &WebConfig{
   218  		Closed: false,
   219  	}
   220  }
   221  
   222  // Default configurable wallet parameters.
   223  func DefaultWalletConfig() *WalletConfig {
   224  	return &WalletConfig{
   225  		Disable:  false,
   226  		Rescan:   false,
   227  		TxIndex:  false,
   228  		MaxTxFee: uint64(1000000000),
   229  	}
   230  }
   231  
   232  // Default configurable web parameters.
   233  func DefaultSimdConfig() *SimdConfig {
   234  	return &SimdConfig{
   235  		Enable: false,
   236  	}
   237  }
   238  
   239  func DefaultWebsocketConfig() *WebsocketConfig {
   240  	return &WebsocketConfig{
   241  		MaxNumWebsockets:     25,
   242  		MaxNumConcurrentReqs: 20,
   243  	}
   244  }
   245  
   246  //-----------------------------------------------------------------------------
   247  // Utils
   248  
   249  // helper function to make config creation independent of root dir
   250  func rootify(path, root string) string {
   251  	if filepath.IsAbs(path) {
   252  		return path
   253  	}
   254  	return filepath.Join(root, path)
   255  }
   256  
   257  // DefaultDataDir is the default data directory to use for the databases and other
   258  // persistence requirements.
   259  func DefaultDataDir() string {
   260  	// Try to place the data folder in the user's home dir
   261  	home := homeDir()
   262  	if home == "" {
   263  		return "./.bytom"
   264  	}
   265  	switch runtime.GOOS {
   266  	case "darwin":
   267  		// In order to be compatible with old data path,
   268  		// copy the data from the old path to the new path
   269  		oldPath := filepath.Join(home, "Library", "Bytom")
   270  		newPath := filepath.Join(home, "Library", "Application Support", "Bytom")
   271  		if !isFolderNotExists(oldPath) && isFolderNotExists(newPath) {
   272  			if err := os.Rename(oldPath, newPath); err != nil {
   273  				log.Errorf("DefaultDataDir: %v", err)
   274  				return oldPath
   275  			}
   276  		}
   277  		return newPath
   278  	case "windows":
   279  		return filepath.Join(home, "AppData", "Roaming", "Bytom")
   280  	default:
   281  		return filepath.Join(home, ".bytom")
   282  	}
   283  }
   284  
   285  func isFolderNotExists(path string) bool {
   286  	_, err := os.Stat(path)
   287  	return os.IsNotExist(err)
   288  }
   289  
   290  func homeDir() string {
   291  	if home := os.Getenv("HOME"); home != "" {
   292  		return home
   293  	}
   294  	if usr, err := user.Current(); err == nil {
   295  		return usr.HomeDir
   296  	}
   297  	return ""
   298  }