11 log "github.com/sirupsen/logrus"
13 "github.com/bytom/crypto/ed25519"
17 // CommonConfig means config object
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"`
33 // Default configurable parameters.
34 func DefaultConfig() *Config {
36 BaseConfig: DefaultBaseConfig(),
37 P2P: DefaultP2PConfig(),
38 Wallet: DefaultWalletConfig(),
39 Auth: DefaultRPCAuthConfig(),
40 Web: DefaultWebConfig(),
41 Simd: DefaultSimdConfig(),
42 Websocket: DefaultWebsocketConfig(),
46 // Set the RootDir for all Config structs
47 func (cfg *Config) SetRoot(root string) *Config {
48 cfg.BaseConfig.RootDir = root
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
61 keyFile := rootify(cfg.P2P.NodeKeyFile, cfg.BaseConfig.RootDir)
62 buf := make([]byte, ed25519.PrivateKeySize*2)
63 fd, err := os.Open(keyFile)
66 if _, err = io.ReadFull(fd, buf); err == nil {
67 return string(buf), nil
71 log.WithField("err", err).Warning("key file access failed")
72 _, privKey, err := ed25519.GenerateKey(nil)
77 if err = ioutil.WriteFile(keyFile, []byte(privKey.String()), 0600); err != nil {
80 return privKey.String(), nil
83 //-----------------------------------------------------------------------------
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"`
90 //The alias of the node
91 NodeAlias string `mapstructure:"node_alias"`
93 //The ID of the network to json
94 ChainID string `mapstructure:"chain_id"`
97 LogLevel string `mapstructure:"log_level"`
99 // A custom human readable name for this node
100 Moniker string `mapstructure:"moniker"`
102 // TCP or UNIX socket address for the profiling server to listen on
103 ProfListenAddress string `mapstructure:"prof_laddr"`
105 Mining bool `mapstructure:"mining"`
107 // Database backend: leveldb | memdb
108 DBBackend string `mapstructure:"db_backend"`
110 // Database directory
111 DBPath string `mapstructure:"db_dir"`
113 // Keystore directory
114 KeysPath string `mapstructure:"keys_dir"`
116 ApiAddress string `mapstructure:"api_addr"`
118 VaultMode bool `mapstructure:"vault_mode"`
121 LogFile string `mapstructure:"log_file"`
124 // Default configurable base parameters.
125 func DefaultBaseConfig() BaseConfig {
127 Moniker: "anonymous",
128 ProfListenAddress: "",
130 DBBackend: "leveldb",
132 KeysPath: "keystore",
137 func (b BaseConfig) DBDir() string {
138 return rootify(b.DBPath, b.RootDir)
141 func (b BaseConfig) KeysDir() string {
142 return rootify(b.KeysPath, b.RootDir)
146 type P2PConfig struct {
147 ListenAddress string `mapstructure:"laddr"`
148 Seeds string `mapstructure:"seeds"`
149 PrivateKey string `mapstructure:"node_key"`
150 NodeKeyFile string `mapstructure:"node_key_file"`
151 SkipUPNP bool `mapstructure:"skip_upnp"`
152 MaxNumPeers int `mapstructure:"max_num_peers"`
153 HandshakeTimeout int `mapstructure:"handshake_timeout"`
154 DialTimeout int `mapstructure:"dial_timeout"`
155 ProxyAddress string `mapstructure:"proxy_address"`
156 ProxyUsername string `mapstructure:"proxy_username"`
157 ProxyPassword string `mapstructure:"proxy_password"`
158 KeepDial string `mapstructure:"keep_dial"`
161 // Default configurable p2p parameters.
162 func DefaultP2PConfig() *P2PConfig {
164 ListenAddress: "tcp://0.0.0.0:46656",
165 NodeKeyFile: "nodekey",
168 HandshakeTimeout: 30,
176 //-----------------------------------------------------------------------------
177 type WalletConfig struct {
178 Disable bool `mapstructure:"disable"`
179 Rescan bool `mapstructure:"rescan"`
180 TxIndex bool `mapstructure:"txindex"`
181 MaxTxFee uint64 `mapstructure:"max_tx_fee"`
184 type RPCAuthConfig struct {
185 Disable bool `mapstructure:"disable"`
188 type WebConfig struct {
189 Closed bool `mapstructure:"closed"`
192 type SimdConfig struct {
193 Enable bool `mapstructure:"enable"`
196 type WebsocketConfig struct {
197 MaxNumWebsockets int `mapstructure:"max_num_websockets"`
198 MaxNumConcurrentReqs int `mapstructure:"max_num_concurrent_reqs"`
201 // Default configurable rpc's auth parameters.
202 func DefaultRPCAuthConfig() *RPCAuthConfig {
203 return &RPCAuthConfig{
208 // Default configurable web parameters.
209 func DefaultWebConfig() *WebConfig {
215 // Default configurable wallet parameters.
216 func DefaultWalletConfig() *WalletConfig {
217 return &WalletConfig{
221 MaxTxFee: uint64(1000000000),
225 // Default configurable web parameters.
226 func DefaultSimdConfig() *SimdConfig {
232 func DefaultWebsocketConfig() *WebsocketConfig {
233 return &WebsocketConfig{
234 MaxNumWebsockets: 25,
235 MaxNumConcurrentReqs: 20,
239 //-----------------------------------------------------------------------------
242 // helper function to make config creation independent of root dir
243 func rootify(path, root string) string {
244 if filepath.IsAbs(path) {
247 return filepath.Join(root, path)
250 // DefaultDataDir is the default data directory to use for the databases and other
251 // persistence requirements.
252 func DefaultDataDir() string {
253 // Try to place the data folder in the user's home dir
258 switch runtime.GOOS {
260 // In order to be compatible with old data path,
261 // copy the data from the old path to the new path
262 oldPath := filepath.Join(home, "Library", "Bytom")
263 newPath := filepath.Join(home, "Library", "Application Support", "Bytom")
264 if !isFolderNotExists(oldPath) && isFolderNotExists(newPath) {
265 if err := os.Rename(oldPath, newPath); err != nil {
266 log.Errorf("DefaultDataDir: %v", err)
272 return filepath.Join(home, "AppData", "Roaming", "Bytom")
274 return filepath.Join(home, ".bytom")
278 func isFolderNotExists(path string) bool {
279 _, err := os.Stat(path)
280 return os.IsNotExist(err)
283 func homeDir() string {
284 if home := os.Getenv("HOME"); home != "" {
287 if usr, err := user.Current(); err == nil {