OSDN Git Service

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