github.com/bytom/bytom@v1.1.2-0.20221014091027-bbcba3df6075/config/config.go (about)

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