OSDN Git Service

fix_block_exist (#2007)
[bytom/bytom.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/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         Simd       *SimdConfig       `mapstructure:"simd"`
30         Websocket  *WebsocketConfig  `mapstructure:"ws"`
31         Federation *FederationConfig `mapstructure:"federation"`
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                 Websocket:  DefaultWebsocketConfig(),
44                 Federation: DefaultFederationConfig(),
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 alias of the node
93         NodeAlias string `mapstructure:"node_alias"`
94
95         // The ID of the network to json
96         ChainID string `mapstructure:"chain_id"`
97
98         // log level to set
99         LogLevel string `mapstructure:"log_level"`
100
101         // A custom human readable name for this node
102         Moniker string `mapstructure:"moniker"`
103
104         // TCP or UNIX socket address for the profiling server to listen on
105         ProfListenAddress string `mapstructure:"prof_laddr"`
106
107         Mining bool `mapstructure:"mining"`
108
109         // Database backend: leveldb | memdb
110         DBBackend string `mapstructure:"db_backend"`
111
112         // Database directory
113         DBPath string `mapstructure:"db_dir"`
114
115         // Keystore directory
116         KeysPath string `mapstructure:"keys_dir"`
117
118         ApiAddress string `mapstructure:"api_addr"`
119
120         VaultMode bool `mapstructure:"vault_mode"`
121
122         // log file name
123         LogFile string `mapstructure:"log_file"`
124
125         PrivateKeyFile string `mapstructure:"private_key_file"`
126         XPrv           *chainkd.XPrv
127         XPub           *chainkd.XPub
128
129         FederationFileName string `mapstructure:"federation_file"`
130 }
131
132 // Default configurable base parameters.
133 func DefaultBaseConfig() BaseConfig {
134         return BaseConfig{
135                 Moniker:            "anonymous",
136                 ProfListenAddress:  "",
137                 Mining:             false,
138                 DBBackend:          "leveldb",
139                 DBPath:             "data",
140                 KeysPath:           "keystore",
141                 NodeAlias:          "",
142                 LogFile:            "log",
143                 PrivateKeyFile:     "node_key.txt",
144                 FederationFileName: "federation.json",
145         }
146 }
147
148 func (b BaseConfig) DBDir() string {
149         return rootify(b.DBPath, b.RootDir)
150 }
151
152 func (b BaseConfig) LogDir() string {
153         return rootify(b.LogFile, b.RootDir)
154 }
155
156 func (b BaseConfig) KeysDir() string {
157         return rootify(b.KeysPath, b.RootDir)
158 }
159
160 func (b BaseConfig) FederationFile() string {
161         return rootify(b.FederationFileName, b.RootDir)
162 }
163
164 // P2PConfig
165 type P2PConfig struct {
166         ListenAddress    string `mapstructure:"laddr"`
167         Seeds            string `mapstructure:"seeds"`
168         SkipUPNP         bool   `mapstructure:"skip_upnp"`
169         LANDiscover      bool   `mapstructure:"lan_discoverable"`
170         MaxNumPeers      int    `mapstructure:"max_num_peers"`
171         HandshakeTimeout int    `mapstructure:"handshake_timeout"`
172         DialTimeout      int    `mapstructure:"dial_timeout"`
173         ProxyAddress     string `mapstructure:"proxy_address"`
174         ProxyUsername    string `mapstructure:"proxy_username"`
175         ProxyPassword    string `mapstructure:"proxy_password"`
176         KeepDial         string `mapstructure:"keep_dial"`
177 }
178
179 // Default configurable p2p parameters.
180 func DefaultP2PConfig() *P2PConfig {
181         return &P2PConfig{
182                 ListenAddress:    "tcp://0.0.0.0:46656",
183                 SkipUPNP:         false,
184                 LANDiscover:      true,
185                 MaxNumPeers:      50,
186                 HandshakeTimeout: 30,
187                 DialTimeout:      3,
188                 ProxyAddress:     "",
189                 ProxyUsername:    "",
190                 ProxyPassword:    "",
191         }
192 }
193
194 // -----------------------------------------------------------------------------
195 type WalletConfig struct {
196         Disable  bool   `mapstructure:"disable"`
197         Rescan   bool   `mapstructure:"rescan"`
198         TxIndex  bool   `mapstructure:"txindex"`
199         MaxTxFee uint64 `mapstructure:"max_tx_fee"`
200 }
201
202 type RPCAuthConfig struct {
203         Disable bool `mapstructure:"disable"`
204 }
205
206 type WebConfig struct {
207         Closed bool `mapstructure:"closed"`
208 }
209
210 type SimdConfig struct {
211         Enable bool `mapstructure:"enable"`
212 }
213
214 type WebsocketConfig struct {
215         MaxNumWebsockets     int `mapstructure:"max_num_websockets"`
216         MaxNumConcurrentReqs int `mapstructure:"max_num_concurrent_reqs"`
217 }
218
219 type FederationConfig struct {
220         FederationScript string         `json:"federation_script"`
221         Xpubs            []chainkd.XPub `json:"xpubs"`
222         Quorum           int            `json:"quorum"`
223 }
224
225 // Default configurable rpc's auth parameters.
226 func DefaultRPCAuthConfig() *RPCAuthConfig {
227         return &RPCAuthConfig{
228                 Disable: false,
229         }
230 }
231
232 // Default configurable web parameters.
233 func DefaultWebConfig() *WebConfig {
234         return &WebConfig{
235                 Closed: false,
236         }
237 }
238
239 // Default configurable wallet parameters.
240 func DefaultWalletConfig() *WalletConfig {
241         return &WalletConfig{
242                 Disable:  false,
243                 Rescan:   false,
244                 TxIndex:  false,
245                 MaxTxFee: uint64(1000000000),
246         }
247 }
248
249 // Default configurable web parameters.
250 func DefaultSimdConfig() *SimdConfig {
251         return &SimdConfig{
252                 Enable: false,
253         }
254 }
255
256 func DefaultWebsocketConfig() *WebsocketConfig {
257         return &WebsocketConfig{
258                 MaxNumWebsockets:     25,
259                 MaxNumConcurrentReqs: 20,
260         }
261 }
262
263 // Default configurable federation parameters.
264 func DefaultFederationConfig() *FederationConfig {
265         return &FederationConfig{
266                 Xpubs: []chainkd.XPub{
267                         xpub("2e171e9aed46633f3560cf4d207c4edb92e5ad6b6f63daee44aa0ed4c58f76fd4d0081f225d2b119ac398749dbc7aa113603bc7710693c54852d33b6b082daab"),
268                         xpub("896285b552bfe0647c0effaee41e5ce98a77981396455259792300cfbc0988bfb1a723488cedf0e73c3220e273fb6843abfbee025d7401b67bf81641b208dfc1"),
269                         xpub("aa5cb0d5d193a141ce66dd3448e8d74d73bed1131ea05b130c14c95ad04b0295f2d4d3f421ae10a2517f7431e0eca119fea509e0650bd20b4a64b856b5473f35"),
270                         xpub("98e6ab8c654bb31e0c432a2c9ff13a6e3419dcb8a1df94f2839f41d79e94b6ca7a68f60b793d947195f761187b37275fbeb345041d5ea3039c5d328b63e3d489"),
271                 },
272                 Quorum: 2,
273         }
274 }
275
276 func xpub(str string) (xpub chainkd.XPub) {
277         if err := xpub.UnmarshalText([]byte(str)); err != nil {
278                 log.Panicf("Fail converts a string to xpub")
279         }
280         return xpub
281 }
282
283 // -----------------------------------------------------------------------------
284 // Utils
285
286 // helper function to make config creation independent of root dir
287 func rootify(path, root string) string {
288         if filepath.IsAbs(path) {
289                 return path
290         }
291         return filepath.Join(root, path)
292 }
293
294 // DefaultDataDir is the default data directory to use for the databases and other
295 // persistence requirements.
296 func DefaultDataDir() string {
297         // Try to place the data folder in the user's home dir
298         home := homeDir()
299         if home == "" {
300                 return "./.bytom"
301         }
302         switch runtime.GOOS {
303         case "darwin":
304                 // In order to be compatible with old data path,
305                 // copy the data from the old path to the new path
306                 oldPath := filepath.Join(home, "Library", "Bytom")
307                 newPath := filepath.Join(home, "Library", "Application Support", "Bytom")
308                 if !isFolderNotExists(oldPath) && isFolderNotExists(newPath) {
309                         if err := os.Rename(oldPath, newPath); err != nil {
310                                 log.Errorf("DefaultDataDir: %v", err)
311                                 return oldPath
312                         }
313                 }
314                 return newPath
315         case "windows":
316                 return filepath.Join(home, "AppData", "Roaming", "Bytom")
317         default:
318                 return filepath.Join(home, ".bytom")
319         }
320 }
321
322 func isFolderNotExists(path string) bool {
323         _, err := os.Stat(path)
324         return os.IsNotExist(err)
325 }
326
327 func homeDir() string {
328         if home := os.Getenv("HOME"); home != "" {
329                 return home
330         }
331         if usr, err := user.Current(); err == nil {
332                 return usr.HomeDir
333         }
334         return ""
335 }