OSDN Git Service

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