11 log "github.com/sirupsen/logrus"
13 "github.com/vapor/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 Websocket *WebsocketConfig `mapstructure:"ws"`
32 // Default configurable parameters.
33 func DefaultConfig() *Config {
35 BaseConfig: DefaultBaseConfig(),
36 P2P: DefaultP2PConfig(),
37 Wallet: DefaultWalletConfig(),
38 Auth: DefaultRPCAuthConfig(),
39 Web: DefaultWebConfig(),
40 Websocket: DefaultWebsocketConfig(),
44 // Set the RootDir for all Config structs
45 func (cfg *Config) SetRoot(root string) *Config {
46 cfg.BaseConfig.RootDir = root
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
59 keyFile := rootify(cfg.P2P.NodeKeyFile, cfg.BaseConfig.RootDir)
60 buf := make([]byte, ed25519.PrivateKeySize*2)
61 fd, err := os.Open(keyFile)
64 if _, err = io.ReadFull(fd, buf); err == nil {
65 return string(buf), nil
69 log.WithField("err", err).Warning("key file access failed")
70 _, privKey, err := ed25519.GenerateKey(nil)
75 if err = ioutil.WriteFile(keyFile, []byte(privKey.String()), 0600); err != nil {
78 return privKey.String(), nil
81 //-----------------------------------------------------------------------------
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"`
88 //The ID of the network to json
89 ChainID string `mapstructure:"chain_id"`
92 LogLevel string `mapstructure:"log_level"`
94 // A custom human readable name for this node
95 Moniker string `mapstructure:"moniker"`
97 // TCP or UNIX socket address for the profiling server to listen on
98 ProfListenAddress string `mapstructure:"prof_laddr"`
100 Mining bool `mapstructure:"mining"`
102 // Database backend: leveldb | memdb
103 DBBackend string `mapstructure:"db_backend"`
105 // Database directory
106 DBPath string `mapstructure:"db_dir"`
108 // Keystore directory
109 KeysPath string `mapstructure:"keys_dir"`
111 ApiAddress string `mapstructure:"api_addr"`
113 VaultMode bool `mapstructure:"vault_mode"`
116 LogFile string `mapstructure:"log_file"`
118 // Cipher Service Provider
119 // CipherServiceProvider string `mapstructure:"csp"`
122 // Default configurable base parameters.
123 func DefaultBaseConfig() BaseConfig {
125 Moniker: "anonymous",
126 ProfListenAddress: "",
128 DBBackend: "leveldb",
130 KeysPath: "keystore",
134 func (b BaseConfig) DBDir() string {
135 return rootify(b.DBPath, b.RootDir)
138 func (b BaseConfig) KeysDir() string {
139 return rootify(b.KeysPath, b.RootDir)
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"`
159 // Default configurable p2p parameters.
160 func DefaultP2PConfig() *P2PConfig {
162 ListenAddress: "tcp://0.0.0.0:46656",
163 NodeKeyFile: "nodekey",
167 HandshakeTimeout: 30,
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"`
183 type RPCAuthConfig struct {
184 Disable bool `mapstructure:"disable"`
187 type WebConfig struct {
188 Closed bool `mapstructure:"closed"`
191 type WebsocketConfig struct {
192 MaxNumWebsockets int `mapstructure:"max_num_websockets"`
193 MaxNumConcurrentReqs int `mapstructure:"max_num_concurrent_reqs"`
196 // Default configurable rpc's auth parameters.
197 func DefaultRPCAuthConfig() *RPCAuthConfig {
198 return &RPCAuthConfig{
203 // Default configurable web parameters.
204 func DefaultWebConfig() *WebConfig {
210 // Default configurable wallet parameters.
211 func DefaultWalletConfig() *WalletConfig {
212 return &WalletConfig{
216 MaxTxFee: uint64(1000000000),
220 func DefaultWebsocketConfig() *WebsocketConfig {
221 return &WebsocketConfig{
222 MaxNumWebsockets: 25,
223 MaxNumConcurrentReqs: 20,
227 //-----------------------------------------------------------------------------
230 // helper function to make config creation independent of root dir
231 func rootify(path, root string) string {
232 if filepath.IsAbs(path) {
235 return filepath.Join(root, path)
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
246 switch runtime.GOOS {
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", "Bytom")
251 newPath := filepath.Join(home, "Library", "Application Support", "Bytom")
252 if !isFolderNotExists(oldPath) && isFolderNotExists(newPath) {
253 if err := os.Rename(oldPath, newPath); err != nil {
254 log.Errorf("DefaultDataDir: %v", err)
260 return filepath.Join(home, "AppData", "Roaming", "Bytom")
262 return filepath.Join(home, ".bytom")
266 func isFolderNotExists(path string) bool {
267 _, err := os.Stat(path)
268 return os.IsNotExist(err)
271 func homeDir() string {
272 if home := os.Getenv("HOME"); home != "" {
275 if usr, err := user.Current(); err == nil {