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