OSDN Git Service

add bytom logs into files
[bytom/bytom.git] / config / config.go
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/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 }