OSDN Git Service

4be5a257732721537254a79fbc89149d41ddb3bd
[bytom/vapor.git] / config / config.go
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/vapor/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         Federation *FederationConfig `mapstructure:"federation"`
31         CrossChain *CrossChainConfig `mapstructure:"cross_chain"`
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                 Websocket:  DefaultWebsocketConfig(),
43                 Federation: DefaultFederationConfig(),
44                 CrossChain: DefaultCrossChainConfig(),
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) PrivateKey() *chainkd.XPrv {
58         if cfg.XPrv != nil {
59                 return cfg.XPrv
60         }
61
62         filePath := rootify(cfg.PrivateKeyFile, cfg.BaseConfig.RootDir)
63         fildReader, err := os.Open(filePath)
64         if err != nil {
65                 log.WithField("err", err).Panic("fail on open private key file")
66         }
67
68         defer fildReader.Close()
69         buf := make([]byte, 128)
70         if _, err = io.ReadFull(fildReader, buf); err != nil {
71                 log.WithField("err", err).Panic("fail on read private key file")
72         }
73
74         var xprv chainkd.XPrv
75         if _, err := hex.Decode(xprv[:], buf); err != nil {
76                 log.WithField("err", err).Panic("fail on decode private key")
77         }
78
79         cfg.XPrv = &xprv
80         xpub := cfg.XPrv.XPub()
81         cfg.XPub = &xpub
82         return cfg.XPrv
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         Mining bool `mapstructure:"mining"`
105
106         // Database backend: leveldb | memdb
107         DBBackend string `mapstructure:"db_backend"`
108
109         // Database directory
110         DBPath string `mapstructure:"db_dir"`
111
112         // Keystore directory
113         KeysPath string `mapstructure:"keys_dir"`
114
115         ApiAddress string `mapstructure:"api_addr"`
116
117         VaultMode bool `mapstructure:"vault_mode"`
118
119         // log file name
120         LogFile string `mapstructure:"log_file"`
121
122         PrivateKeyFile string `mapstructure:"private_key_file"`
123         XPrv           *chainkd.XPrv
124         XPub           *chainkd.XPub
125
126         // Federation file name
127         FederationFileName string `mapstructure:"federation_file"`
128 }
129
130 // Default configurable base parameters.
131 func DefaultBaseConfig() BaseConfig {
132         return BaseConfig{
133                 Moniker:            "anonymous",
134                 ProfListenAddress:  "",
135                 Mining:             false,
136                 DBBackend:          "leveldb",
137                 DBPath:             "data",
138                 KeysPath:           "keystore",
139                 LogFile:            "log",
140                 PrivateKeyFile:     "node_key.txt",
141                 FederationFileName: "federation.json",
142         }
143 }
144
145 func (b BaseConfig) DBDir() string {
146         return rootify(b.DBPath, b.RootDir)
147 }
148
149 func (b BaseConfig) LogDir() string {
150         return rootify(b.LogFile, b.RootDir)
151 }
152
153 func (b BaseConfig) KeysDir() string {
154         return rootify(b.KeysPath, b.RootDir)
155 }
156
157 func (b BaseConfig) FederationFile() string {
158         return rootify(b.FederationFileName, b.RootDir)
159 }
160
161 // P2PConfig
162 type P2PConfig struct {
163         ListenAddress    string `mapstructure:"laddr"`
164         Seeds            string `mapstructure:"seeds"`
165         SkipUPNP         bool   `mapstructure:"skip_upnp"`
166         LANDiscover      bool   `mapstructure:"lan_discoverable"`
167         MaxNumPeers      int    `mapstructure:"max_num_peers"`
168         HandshakeTimeout int    `mapstructure:"handshake_timeout"`
169         DialTimeout      int    `mapstructure:"dial_timeout"`
170         ProxyAddress     string `mapstructure:"proxy_address"`
171         ProxyUsername    string `mapstructure:"proxy_username"`
172         ProxyPassword    string `mapstructure:"proxy_password"`
173         KeepDial         string `mapstructure:"keep_dial"`
174         Compression      string `mapstructure:"compression_backend"`
175 }
176
177 // Default configurable p2p parameters.
178 func DefaultP2PConfig() *P2PConfig {
179         return &P2PConfig{
180                 ListenAddress:    "tcp://0.0.0.0:56656",
181                 SkipUPNP:         false,
182                 LANDiscover:      true,
183                 MaxNumPeers:      20,
184                 HandshakeTimeout: 30,
185                 DialTimeout:      3,
186                 ProxyAddress:     "",
187                 ProxyUsername:    "",
188                 ProxyPassword:    "",
189                 Compression:      "snappy",
190         }
191 }
192
193 //-----------------------------------------------------------------------------
194 type WalletConfig struct {
195         Disable  bool   `mapstructure:"disable"`
196         Rescan   bool   `mapstructure:"rescan"`
197         TxIndex  bool   `mapstructure:"txindex"`
198         MaxTxFee uint64 `mapstructure:"max_tx_fee"`
199 }
200
201 type RPCAuthConfig struct {
202         Disable bool `mapstructure:"disable"`
203 }
204
205 type WebConfig struct {
206         Closed bool `mapstructure:"closed"`
207 }
208
209 type WebsocketConfig struct {
210         MaxNumWebsockets     int `mapstructure:"max_num_websockets"`
211         MaxNumConcurrentReqs int `mapstructure:"max_num_concurrent_reqs"`
212 }
213
214 type FederationConfig struct {
215         Xpubs  []chainkd.XPub `json:"xpubs"`
216         Quorum int            `json:"quorum"`
217 }
218
219 type CrossChainConfig struct {
220         AssetWhitelist string `mapstructure:"asset_whitelist"`
221 }
222
223 // Default configurable rpc's auth parameters.
224 func DefaultRPCAuthConfig() *RPCAuthConfig {
225         return &RPCAuthConfig{
226                 Disable: false,
227         }
228 }
229
230 // Default configurable web parameters.
231 func DefaultWebConfig() *WebConfig {
232         return &WebConfig{
233                 Closed: false,
234         }
235 }
236
237 // Default configurable wallet parameters.
238 func DefaultWalletConfig() *WalletConfig {
239         return &WalletConfig{
240                 Disable:  false,
241                 Rescan:   false,
242                 TxIndex:  false,
243                 MaxTxFee: uint64(1000000000),
244         }
245 }
246
247 func DefaultWebsocketConfig() *WebsocketConfig {
248         return &WebsocketConfig{
249                 MaxNumWebsockets:     25,
250                 MaxNumConcurrentReqs: 20,
251         }
252 }
253
254 func DefaultFederationConfig() *FederationConfig {
255         return &FederationConfig{
256                 Xpubs: []chainkd.XPub{
257                         xpub("580daf48fa8962100047cb1391da890bb7f2c849fdbc9b368cb4394a4c7cbb0977e2e7ebbf055dc0ef90af6a0d2af01ce7ec56b735d016aab597815ec48552e5"),
258                         xpub("f3f6bcf61b65fa9d1566455a5688ca8b395efdc22e654963134b5e5cb0a45d8be522d21abc384a73177a7b9d64eba915fcfe2862d86a508a3c46dc410bdd72ad"),
259                         xpub("53559612f2b7bcada18948b7de39d63947a0e2bd7336d07db1350c54ba5743996b84bf9d18ff7a2457e1a5c70ce5013e4a3b62666ddb03294c53051d5f5c70c0"),
260                         xpub("7c88cc58adfc71818b08308d43c29de22460b0ea6895449cbec6e458d7dc09e0aea243fa5075ee6621da0d805bd047f6bb207329c5bd2ca3253b172fb323b512"),
261                 },
262                 Quorum: 2,
263         }
264 }
265
266 func DefaultCrossChainConfig() *CrossChainConfig {
267         return &CrossChainConfig{}
268 }
269
270 func xpub(str string) (xpub chainkd.XPub) {
271         if err := xpub.UnmarshalText([]byte(str)); err != nil {
272                 log.Panicf("Fail converts a string to xpub")
273         }
274         return xpub
275 }
276
277 //-----------------------------------------------------------------------------
278 // Utils
279
280 // helper function to make config creation independent of root dir
281 func rootify(path, root string) string {
282         if filepath.IsAbs(path) {
283                 return path
284         }
285         return filepath.Join(root, path)
286 }
287
288 // DefaultDataDir is the default data directory to use for the databases and other
289 // persistence requirements.
290 func DefaultDataDir() string {
291         // Try to place the data folder in the user's home dir
292         home := homeDir()
293         if home == "" {
294                 return "./.vapor"
295         }
296         switch runtime.GOOS {
297         case "darwin":
298                 return filepath.Join(home, "Library", "Application Support", "Vapor")
299         case "windows":
300                 return filepath.Join(home, "AppData", "Roaming", "Vapor")
301         default:
302                 return filepath.Join(home, ".vapor")
303         }
304 }
305
306 func isFolderNotExists(path string) bool {
307         _, err := os.Stat(path)
308         return os.IsNotExist(err)
309 }
310
311 func homeDir() string {
312         if home := os.Getenv("HOME"); home != "" {
313                 return home
314         }
315         if usr, err := user.Current(); err == nil {
316                 return usr.HomeDir
317         }
318         return ""
319 }